图像处理OpenCV算法04

8、边缘检测

      大多数边缘检测算子是基于方向差分卷积核求卷积的方法,通常有四种方式来衡量最后输出的边缘强度。(1)取对应位置绝对值的和:    ,(2)取对应位置平方和的开方:,(3)取对应位置绝对值的最大值:,(4)插值法: 。

      Roberts算子卷积核:

        

      Prewitt算子卷积核:

        

        

      Sobel算子卷积核:

        

      Sobel算子是在一个坐标轴方向上进行非归一化的高斯平滑,在另一个坐标轴方向上进行差分处理。n*n的Sobel算子是由高斯平滑算子和差分算子Full卷积而得到的。

      Scharr算子卷积核有水平方向、垂直方向、45度方向、135度方向,和Prewitt算子的卷积核类似,但在数字上变成了3,10,3。

      Kirsch算子:图像与每一个核进行卷积,然后去绝对值作为对应方向上的边缘强度的量化,对8个卷积结果去绝对值,然后在对应位置取最大值作为最后输出的边缘强度,超过255进行截断。

        

      Robinson算子和Kirsch算子一样。

        

      通过np.array()构建卷积核,通过signal.convolve2d()对图像和卷积核进行卷积计算。

 

      在边缘检测中常用的边缘检测算子是Canny算子、Laplacian算子、高斯差分边缘检测、Marr-Hildreth边缘检测。下面将对以上四种边缘检测的算法实现进行简单的过程思路介绍。

 

      Canny边缘检测

      Canny算子在Sobel算子、Prewitt等算子没有充分利用边缘的梯度方向,最后输出的二值图只是简单的利用阈值进行处理,如果阈值过大会损失很多边缘信息,如果阈值过小会出现噪声。针对这两个缺点,Canny算子进行了改进,基于边缘梯度方形的非极大值抑制,双阈值的滞后阈值处理。

      Canny边缘检测算法实现思想如下:

      (1)图像分别于Sobel算子的水平方向和垂直方向上的卷积核卷积得到dx和dy(像素点大小有正负),然后利用平方和的开方得到边缘强度

      (2)利用dx和dy计算出梯度方向,angle=arctan2(dy,dx),即对每一个位置(r,c),angle(r,c)=arctan2(dy(r,c),dx(r,c))代表该位置的梯度方向,一般用角度表示,即angle(r,c)在[0,180]和[-180,0]之间。

      通过angle=np.arctan2(dy,dx)/np.pi*180计算梯度方向。

      (3)对每一个位置进行非极大值抑制的处理,非极大值抑制操作返回的仍然是一个矩阵。在边缘强度图像magnitude,判断magnitude(r,c)左边点的梯度方向angle(r,c)=arctan2(dy(r,c),dx(r,c)),根据该梯度方向在该点绘制一条斜线,比较该点的像素值与斜线穿过该点的“右上方和左下方”的像素值的大小进行比较,如果magnitude(r,c)大于这两个点的值,则成为极大值,否则为非极大值。

      (4)双阈值的滞后阈值处理,经过第三步的非极大值抑制处理后的边缘强度图,一般需要阈值化处理,常用的方法是全局阈值分割和局部自适应阈值分割。这里用到的滞后阈值处理设置了两个阈值,高阈值和低阈值。边缘强度大于高阈值的那些店作为确定的边缘点;边缘强度低于低阈值的那些点立即被剔除;边缘强度在低阈值和高阈值之间的那些点,按照只有这些点能按某一路径与确定边缘点相连接时,才可以作为边缘点被接受。

 

      Laplacian边缘检测

      二维函数f(x,y)的Laplacian变换,

        

      将其推广到离散的二维数组(矩阵),即矩阵的拉普拉斯变换是矩阵与拉普拉斯核的卷积。

        

      图像矩阵与拉普拉斯核的卷积本质上是计算任意位置上的值与其水平方向和垂直方向上四个相邻点平均值之间的差值。拉普拉斯的缺点对噪声产生较大的影响,误将噪声作为边缘;优点只有一个卷积核,其计算成本比其他算子低。拉普拉斯其他常用形式的算子如下:

        

      拉普拉斯核内所有值得和必须等于0,这样就使得在恒等灰度值区域不会产生错误的边缘,上述几种形式的拉普拉斯算子是不可分离的。

 

      高斯拉普拉斯边缘检测

      对二维高斯函数:

        

      进行拉普拉斯变换:

        

      Python语言的LOG卷积核构建:

    H,W=size

    r,c=np.mgrid[0:5:1,0:5:1]

    r-=(H-1)/2

    c-=(W-1)/2

    sigma2=pow(sigma,2.0)

    norm2=np.power(r,2.0)+np.power(c,2.0)

    LoGKernel=(norm2/sigma2-2)*np.exp(-norm2/(2*sigma2))

      最后对高斯拉普拉斯后的结果进行二值化处理。

 

      高斯差分边缘检测

      二维高斯函数:

        

      对σ进行一阶偏导如下:

        

      其和高斯拉普拉斯有如下关系:

        

      根据一阶导数的定义,二维高斯函数对σ进行一阶偏导可以这样表示:

        

      根据上面两个公式,可以得到高斯拉普拉斯的近似值:

        

      当k=0.95时,高斯拉普拉斯核高斯差分的近似值相等。

      最后对高斯差分后的结果进行二值化处理。

      高斯卷积gauss(x,y,σ):

    H,W=size

    xr,xc=np.mgrid[0:1,0:W]

    xc-=(W-1)/2

    xk=np.exp(-np.power(xc,2.0))

    I_xk=signal.convolve2d(I,xk,’same’,’symm’)

    yr,yc=np.mgrid[0:H,0:1]

    yr-=(H-1)/2

    yk=np.exp(-np.power(yr,2.0))

    I_xk_yk=signal.convolve2d(I_xk,yk,’same’,’symn’)

    I_xk_yk*=1.0/(2*np.pi*pow(sigma,2.0))

 

      Marr-Hildreth边缘检测

      Marr-Hildreth边缘检测只是将高斯差分和高斯拉普拉斯检测最后一步的阈值化处理改成寻找过零点位置的操作。过零点操作,对于函数f(x),求一阶导数,其一阶导数的最大值点就是其二阶导数的零点位置,使得二阶导数等于0,也就是边缘强度最大值处。

      一般通过以下两种方式来寻找过零点:

        

      方式1中,对于这四种情况只要有一种情况出现异号,该位置(r,c)就是过零点,即为边缘点,即将该位置的输出标记为白色,通过两个位置的像素点相乘来判断是否是异号。

      方式2中,对于这四个领域的均值,只要任意两个均值是异号,该位置(r,c)就是过零点,即为边缘点,将该位置的输出值设为白色,首先利用mean函数来计算每个区域的均值,然后通过判断min(fourmean)*max(fourmean)是否异号来判断是否是边缘点。

猜你喜欢

转载自blog.csdn.net/zx520113/article/details/80889251