【图像处理】OpenCV中的边缘检测

【图像处理】OpenCV中的边缘检测

  • 部分参考来源
  • 边缘检测的算子
    • 边缘定义及类型
    • 图像边缘描述
    • 边缘检测算子类别
      • 一阶微分算子:Roberts 、Sobel 、Prewitt
      • 二阶微分算子:Laplacian、Log/Marr
      • 非微分边缘检测算子:Canny
      • 方向算子:Kirsch(8个3 * 3模板),Nevitia (12个5 * 5模板)
  • OpenCV中的Canny边缘检测函数
  • 结语

部分参考来源

https://blog.csdn.net/tigerda/article/details/61192943

边缘检测的算子

边缘定义及类型

定义:边缘是不同区域的分界线,是周围(局部)像素有显著变化的像素的集合,有幅值与方向两个属性。这个不是绝对的定义,主要记住局部特征以及周围像素显著变化产生边缘。

轮廓和边缘的关系:一般认为轮廓是对物体的完整边界的描述,边缘点一个个连接起来构成轮廓。边缘可以是一段边缘,而轮廓一般是完整的。人眼视觉特性,看物体时一般是先获取物体的轮廓信息,再获取物体中的细节信息,比如看到几个人站在那,我们一眼看过去马上能知道的是每个人的高矮胖瘦,然后才获取脸和衣着等信息。

类型:简单分为4种类型,阶跃型屋脊型斜坡型脉冲型,其中阶跃型和斜坡型是类似的,只是变化的快慢不同,同样,屋脊型和脉冲型也是如此。
【图像处理】OpenCV中的边缘检测_第1张图片
上图中,(a)和(b)可认为是阶跃或斜坡型,(c)脉冲型,(d)屋脊型,阶跃与屋脊的不同在于阶跃上升或下降到某个值后持续下去,而屋脊则是先上升后下降

图像边缘描述

我们更多关注的是阶跃和屋脊型边缘,边缘用微分算子来刻画
【图像处理】OpenCV中的边缘检测_第2张图片 在数学中,函数的变化率由导数来刻画,图像我们看成二维函数,其上面的像素值变化,当然也可以用导数来刻画,当然图像是离散的,那我们换成像素的差分来实现

对于阶跃型边缘,其一阶导数具有极大值,极大值点对应二阶导数的过零点,也就是,准确的边缘的位置是对应于一阶导数的极大值点,或者二阶导数的过零点(注意不仅仅是二阶导数为0值的位置,而且是正负值过渡的零点)。

故边缘检测算子的类型当然就存在一阶和二阶微分算子

边缘检测算子类别

常见边缘检测算子:Roberts 、Sobel 、Prewitt、Laplacian、Log/Marr、Canny、Kirsch、Nevitia

一阶微分算子:Roberts 、Sobel 、Prewitt

算子模板及写成差分的形式:

  • Roberts:
    在这里插入图片描述
    (a)是像素坐标系 u u u方向移动的卷积核心,(b)是像素坐标系 v v v方向移动的卷积核。下同
    2x2的卷积核决定左上像素点的结果
    Δ x f ( x , y ) = f ( x , y ) − f ( x + 1 , y + 1 ) \Delta_xf(x,y) =f(x,y)-f(x+1,y+1) Δxf(x,y)=f(x,y)f(x+1,y+1)
    Δ y f ( x , y ) = f ( x + 1 , y ) − f ( x , y + 1 ) \Delta_yf(x,y)=f(x+1,y)-f(x,y+1) Δyf(x,y)=f(x+1,y)f(x,y+1)

  • Sobel:
    【图像处理】OpenCV中的边缘检测_第3张图片
    3x3的卷积核决定中心像素点的结果
    Δ x f ( x , y ) = [ f ( x + 1 , y + 1 ) + 2 f ( x , y + 1 ) + f ( x − 1 , y + 1 ) ] − [ f ( x − 1 , y − 1 ) + 2 f ( x , y − 1 ) + f ( x + 1 , y − 1 ) ] \Delta_xf(x,y) =[f(x+1,y+1)+2f(x,y+1)+f(x-1,y+1)]-[f(x-1,y-1)+2f(x,y-1)+f(x+1,y-1)] Δxf(x,y)=[f(x+1,y+1)+2f(x,y+1)+f(x1,y+1)][f(x1,y1)+2f(x,y1)+f(x+1,y1)]
    Δ y f ( x , y ) = [ f ( x + 1 , y + 1 ) + 2 f ( x + 1 , y ) + f ( x + 1 , y − 1 ) ] − [ f ( x − 1 , y − 1 ) + 2 f ( x − 1 , y ) + f ( x − 1 , y + 1 ) ] \Delta_yf(x,y)=[f(x+1,y+1)+2f(x+1,y)+f(x+1,y-1)]-[f(x-1,y-1)+2f(x-1,y)+f(x-1,y+1)] Δyf(x,y)=[f(x+1,y+1)+2f(x+1,y)+f(x+1,y1)][f(x1,y1)+2f(x1,y)+f(x1,y+1)]

  • Prewitt:

【图像处理】OpenCV中的边缘检测_第4张图片

在这里插入图片描述

  • 各向同性Sobel算子模板:
    【图像处理】OpenCV中的边缘检测_第5张图片

如何计算边缘幅值与方向?以Sobel算子为例。 3 ∗ 3 3 * 3 33 Sobel两个方向的算子在图像上滑动,模板与其覆盖的图像 3 ∗ 3 3 * 3 33区域 9 9 9个像素进行卷积,求和后得到此方向的边缘检测幅值,水平和竖直方向算子的卷积结果:
【图像处理】OpenCV中的边缘检测_第6张图片
总幅值:
在这里插入图片描述
总方向:
在这里插入图片描述
G G G的计算有时简化为:
在这里插入图片描述

在这里插入图片描述

二阶微分算子:Laplacian、Log/Marr

算子模板:
Laplacian:
【图像处理】OpenCV中的边缘检测_第7张图片
Log/Marr:
【图像处理】OpenCV中的边缘检测_第8张图片

非微分边缘检测算子:Canny

经典的Canny边缘检测算法通常都是从高斯模糊开始,到基于双阈值实现边缘连接结束
但是在实际工程应用中,考虑到输入图像都是彩色图像,最终边缘连接之后的图像要二值化输出显示,所以完整的Canny边缘检测算法实现步骤如下:

  1. 彩色图像转换为灰度图像
  2. 对图像进行高斯模糊
  3. 计算图像梯度(使用Sobel算子),根据梯度计算图像边缘幅值与角度
  4. 非最大信号压制处理(边缘细化,消除边缘检测带来的杂散效应)
  5. 双阈值边缘连接处理
    如果当前梯度值大于给定的maxVal,判断为边界;如果当前梯度值小于minVal则舍弃;如果当前梯度值在给定的最大值和最小值之间,如果其周围的点是边界点,那么当前点保留,否则舍弃。当minVal和maxVal越小时,所保留的边缘信息更多
  6. 二值化图像输出结果

方向算子:Kirsch(8个3 * 3模板),Nevitia (12个5 * 5模板)

这两个算子是利用多个方向的子模板进行分别计算,最后取幅值最大的那个为最终边缘幅值方向即最大幅值对应的那个方向

OpenCV中的Canny边缘检测函数

edge = cv2.Canny(image, threshold1, threshold2)
  • image:源图像
  • threshold1:阈值1(minVal)
  • threshold2:阈值2(maxVal)

其中,较大的阈值2用于检测图像中明显的边缘,但一般情况下检测的效果不会那么完美,边缘检测出来是断断续续的。所以这时候用较小的第一个阈值用于将这些间断的边缘连接起来

函数返回的是二值图,包含检测出的边缘

结语

如果您有修改意见或问题,欢迎留言或者通过邮箱和我联系。
如果我的文章对您有帮助,转载请注明出处。

你可能感兴趣的:(图像处理)