文章目录
首先,我们知道:
- 边缘是图像的重要特征之一;
- 图像边缘是数字图像的高频成分,也就是像素值变化较为剧烈的点,亮度变化比较大的点,对应图像梯度的极值;
- 边缘检测包括一阶微分算子,例如:
Prewitt
算子、Sobel
算子(x,y
方向);二阶微分算子,例如:Laplace
算子、LoG
高斯-拉普拉斯算子(Laplace of Gaussian)
;还有Canny
边缘检测。
后面,我们详细的学习下,canny
边缘检测算法的原理,和为什么要这样做,一套究竟。文末放视频参考链接,可结合视频共同学习。
一、canny边缘检测点步骤
检测步骤如下:
- 应用高斯滤波器,平滑图像,滤除噪声点(降噪,噪声点也是像素变化急剧的点,属于高频部分,提前去除,降低后续在边缘部分,引入不必要的边缘)
- 计算图像中每个像素点的梯度大小和方向(梯度)
- 使用非极大值抑制(
Non-Maximum Suppression, NMS
),以消除边缘检测、目标检测带来的杂散响应,即对待测边缘或目标,应尽可能有唯一的准确响应(非极大值抑制) - 应用双阈值检测,确定真实和潜在的边缘(双阈值检测)
- 通过抑制孤立的弱边缘,完成边缘检测。
一个个的,听着挺高大上,那一步步的,都是为啥这么干呢?下面我们一一娓娓道来
1.1、如何和为什么计算每个像素点的梯度大小和方向?
上图,是计算一个像素点的梯度大小和方向,需要用到的滤波器和计算公式,其中:
Gx-x
方向的滤波算子(竖直方向)Gy-y
方向的滤波算子(水平方向)G
-梯度幅值大小θ
-梯度方向
下面,就是lena
图,和经过计算得到的梯度图,左边原图,每一个点表示的是像素值,右侧的梯度图,每一个点表示的是梯度幅值。尽管表示的都是图,但是代表的意义,是不同的:
自问下,为什么我们要计算梯度的幅值和方向呢?
- 我们前面提到,边是图像中像素值变化比较大的点,而梯度的幅值就是衡量像素变化率的大小;
- 梯度的方向,是用来干什么呢?前面滤波器时候我们知道,过一个像素点,有很多的方向,我们要找到一个方向,是梯度变化最大的方向。因为只有在梯度方向上,是这个像素点变化最为剧烈的。
1.2、怎么还引入非极大值抑制(Non-Maximum Suppression,NMS)?
仔细观察梯度图,我们会发现:
- 相比于原始图像,梯度图像显得简单了很多,但是大致的轮廓还是看的清楚;
- 边缘的区域,有一种朦朦胧胧的素描感,不是棱角分明的感觉,边缘白色区域是有渐变色的。
这不是我们需要的边缘。我们希望在与白色边缘垂直的梯度方向上,只留下一个最大的像素点,将其他的像素点消除掉,置为 0。这也就是我们要引入非极大值抑制的最根本原因。
那么,问题又来了,该如何将目标像素点留下来,其他的给去除掉呢?那就用非极大值抑制。
非极大值抑制应用在边缘细化技术。渐变图像中每个像素的算法步骤是:
- 将当前像素的边缘强度(幅值),与正梯度方向和负梯度方向上的像素的边缘强度进行比较。
- 如果当前像素的边缘强度(幅值),与具有相同方向的掩模中的其他像素相比是最大的(即,指向y方向的像素,则将其与其上方和下方的像素进行比较,垂直轴),该值将被保留。否则,该值将被抑制。
在上图右侧的示意图里面:
- 蓝色斜线表示的就是梯度方向,其中
C
点恰好在像素点上,θ
为梯度角; - 梯度方向在其他两个水平方向上面,没有落在像素点上,例如其中
g1、g2
上点,该点的幅值是线性插值的方式计算得到的,参与到非极大值抑制中去。
1.3、双阈值检测-边缘的连接
尽管经过非极大值抑制,使得部分非必要的点给去除了,但是还会存在部分点区域,或者点是孤立,这部分的点还需要进一步的去处掉,于是,就引入了双阈值检测。
听到双阈值,就首先肯定是有两个大小不一样的,一个小阈值minVal
和一个大阈值maxVal
。一般open CV
建议,minVal=50
,maxVal=minVal*3
。那么:
- 大与
maxVal
的肯定是边 - 小于
minVal
的肯定不是边 - 介于
minVal
和maxVal
的,就是需要我们需要连接的部分。也是最复杂的部分,单独聊下过程。
介于minVal
和maxVal
连接过程:
- 首先将肯定是边的点,押入栈内;
- 然后比较站内元素,其
8邻域
点各个点,是否存在;如果存在,那么这个点压入栈内; - 继续
步骤 2
的过程,直到栈空位置,这样就将潜在是边的点,全部连接到一起了。
这样,就得到了最终检测结果,如下所示:
二、代码实现
从第一章节的讲解,若要实现canny
边缘检测算法,那么猜测下大概需要以下这些功能:
- 滤波,降噪,去除噪声;
- 梯度检测,得到每个像素点的梯度大小和方向;
- 非极大值抑制,去除部分不利梯度
- 双阈值检测
代码详情解析部分,待进一步学习讲解。敬请期待。相信文本中肯定还是有什么不准确的地方的,欢迎小伙伴评论区指出
参考视频:
- 视频地址1: canny edge detection(canny边缘检测)
- 视频地址2:Canny边缘检测原理