OpenCV3-Python边缘检测详细介绍
admin 于 2018年04月18日 发表在 计算机视觉

OpenCV提供许多边缘检测滤波函数,包括Laplacian()、Sobel()以及Scharr(),这些滤波函数都会将非边缘区域转为黑色,将边缘区域转为白色或其它饱和颜色,但是这些函数很容易将噪声识别为边缘。缓解这个问题的方法就是边缘检测之前,对图像进行模糊处理。

OpenCV提供了很多模糊滤波函数,包括blur()(简单算术平均)、medianBlur()(中值滤波)以及GaussianBlur()(高斯滤波)等。尽管边缘检测滤波函数和模糊滤波函数的参数由很多,但总会有一个ksize参数,它是一个奇数,表示滤波核的宽和高(以像素为单位)。

(1) 中值滤波器:

中值滤波对消除椒盐噪声非常有效,能够克服线性滤波器带来的图像细节模糊等弊端,能够有效保护图像边缘信息,是非常经典的平滑噪声处理方法。在光学测量条纹图像的香味分析处理方法中有特殊作用,但在条纹中心分析方法中作用不大。

(2) Laplacian边缘检测函数

dst = cv2.Laplacian(src, ddepth[, dst[, ksize[, scale[, delta[, borderType]]]]])  

前两个是必须的参数:

第一个参数是需要处理的图像;

第二个参数是图像的深度,-1表示采用的是与原图像相同的深度。目标图像的深度必须大于等于原图像的深度;

其后是可选的参数:

dst不用解释了;

ksize是算子的大小,必须为1、3、5、7。默认为1。

scale是缩放导数的比例常数,默认情况下没有伸缩系数;

delta是一个可选的增量,将会加到最终的dst中,同样,默认情况下没有额外的值加到dst中;

borderType是判断图像边界的模式。这个参数默认值为cv2.BORDER_DEFAULT。

应用举例:

main.py 内容:

def strokeEdges(src,blurKsize=7, edgeKsize=5):
    if blurKsize >= 3:
	#中值滤波
        blurredSrc = cv2.medianBlur(src, blurKsize) 
	#转换为彩色图像转换为灰度图像
        graySrc = cv2.cvtColor(blurredSrc, cv2.COLOR_BGR2GRAY) 
    else:
        graySrc = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY)

    #Laplacian边缘检测函数
    cv2.Laplacian(graySrc, cv2.CV_8U, graySrc, ksize = edgeKsize)

    #在得到Laplacian()函数的结果后,需要将其转换成黑色边缘和白色背景的图像。然后
    #将其归一化(使像素值在0-1之间),并乘以源图像以便将边缘变黑。
    normalizedInverseAlpha = (1.0/255)*(255-graySrc)

    #拆分通道为单通道,获取各个通道的灰度值
    channels = cv2.split(src)
    for channel in channels:
        channel[:] = channel * normalizedInverseAlpha

    #合并单通道为多通道
    dst = cv2.merge(channels)
    return graySrc,dst

img = cv2.imread("./00.png")
lapsrc,result = strokeEdges(img)
cv2.imshow("img",img)
cv2.imshow("lapsrc",lapsrc)
cv2.imshow("result",result)
cv2.waitKey()
cv2.destroyAllWindows()

运行结果:

(3) 定制内核做卷积

OpenCV预定义的许多滤波器(滤波函数)都会使用核。核即是一组权重,它决定如何通过邻近像素点来计算新的像素点。核也称为卷积矩阵,它对一个区域的像素做调和(mix up)或卷积运算。

通常基于核的滤波器(滤波函数)被称为卷积滤波器(滤波函数),卷积矩阵是一个二维数组,有奇数行、奇数列,中心元素对应于感兴趣的像素。

如:

kernel = numpy.array([[-1, -1, -1],
                     [-1,  9, -1],
                     [-1, -1, -1]])

感兴趣的像素权重为9,其邻近像素权重为-1。对于感兴趣的像素来说,新像素值是用当前像素值乘以9.然后减去8个邻近像素值。

应用举例:

filters.py 内容:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Sat Apr  7 22:58:11 2018

@author: lu
"""

import cv2
import numpy

#一般的卷积滤波器
class VConvolutionFilter(object):
    
    def __init__(self, kernel):
        self._kernel = kernel
    
    def apply(self, src):
        dst = cv2.filter2D(src, -1, self._kernel)
        return dst

#特定锐化滤波器,权重和为1
class SharpenFilter(VConvolutionFilter):
    
    def __init__(self):
        kernel = numpy.array([[-1, -1, -1],
                              [-1,  9, -1],
                              [-1, -1, -1]])
        VConvolutionFilter.__init__(self, kernel)

#边缘检测核,把边缘转化为白色,非边缘转为黑色,权重和为0
class FindEdgesFilter(VConvolutionFilter):
    
    def __init__(self):
        kernel = numpy.array([[-1, -1, -1],
                              [-1,  8, -1],
                              [-1, -1, -1]])

        VConvolutionFilter.__init__(self, kernel)

#模拟滤波器,通常权重应该为1,而且邻近像素权重为正      
class BlurFilter(VConvolutionFilter): 
    
    def __init__(self):
        kernel = numpy.array([[0.04, 0.04, 0.04, 0.04, 0.04],
                              [0.04, 0.04, 0.04, 0.04, 0.04],
                              [0.04, 0.04, 0.04, 0.04, 0.04],
                              [0.04, 0.04, 0.04, 0.04, 0.04],
                              [0.04, 0.04, 0.04, 0.04, 0.04]])
        VConvolutionFilter.__init__(self, kernel)

#同时具有模糊(正的权重)和锐化(负的权重),产生一种脊状或浮雕的效果
class EmbossFilter(VConvolutionFilter):
    
    def __init__(self):
        kernel = numpy.array([[-2, -1, 0],
                              [-1,  1, 1],
                              [ 0,  1, 2]])
        VConvolutionFilter.__init__(self, kernel)

main.py 内容:

import matplotlib.pyplot as plt  
import cv2
import filters

#读取图像
img = cv2.imread("./00.png")

#特定锐化滤波器
filt = filters.SharpenFilter()
result1 = filt.apply(img)

#边缘检测滤波器
filt = filters.FindEdgesFilter()
result2 = filt.apply(img)

#模拟滤波器
filt = filters.BlurFilter()
result3 = filt.apply(img)

#模糊+锐化滤波器
filt = filters.EmbossFilter()
result4 = filt.apply(img)

plt.figure(figsize=(10,10)) #参数figsize设置画布大小

plt.subplot(221)  
plt.title('SharpenFilter') 
plt.imshow(result1) 

plt.subplot(222)  
plt.title('FindEdgesFilter')
plt.imshow(result2) 

plt.subplot(223)  
plt.title('BlurFilter')
plt.imshow(result3) 

plt.subplot(224)  
plt.title('EmbossFilter') 
plt.imshow(result4) 

plt.show()

运行结果:

(4) Canny边缘检测

OpenCV中提供了非常方便的边缘检测函数Canny,直接调用即可,近一步详细介绍访问这里

cv2.Canny(image, threshold1, threshold2[, edges[, apertureSize[, L2gradient ]]])   

必要参数:

第一个参数是需要处理的原图像,该图像必须为单通道的灰度图

第三个参数是阈值2,一般用来检测图像中明显的边缘,但一般会出现断断续续的状况,需要结合调整第二个参数阈值1来将一些间断的边缘连接起来。

应用举例:

main.py 内容:

img = cv2.imread("./00.png",0)
result = cv2.Canny(img, 200, 300)

cv2.imshow("Original",img)
cv2.imshow("Canny",result)
cv2.waitKey()
cv2.destroyAllWindows()

运行结果:

下一篇:《OpenCV3-Python轮廓检测流程介绍》

参考:

http://www.cnblogs.com/naaoveGIS/

注意:本站所有文章除特别说明外,均为原创,转载请务必以超链接方式并注明作者出处。 标签:python,opencv3