边缘检测
- 前言
- 1.基本概念
- 1) 滤波
- 2) 计算梯度
- 3) 非极大值抑制
- 4) 双阈值检测
- 2.opencv中的边缘检测
- 效果展示
- 分析对比
- 3.结尾
前言
在之前的文章中我们介绍了使用膨胀和腐蚀、计算图像梯度的方式来获取图像的轮廓,本篇文章将介绍另外一种可以获取图像轮廓的方法——边缘检测
1.基本概念
首先我们来看一下边缘检测的基本过程
1) 滤波
使用高斯滤波器,以平滑图像,滤除噪声
H即为高斯分布的卷积核,初看上去似乎这个矩阵似乎很莫名其妙,但其实他的特征很明显,中间的数值要比周围的大,因为高斯滤波使用的卷积核是满足高斯分布,即正态分布的(是的,高斯分布就是正态分布)
关于高斯滤波的细节请参考之前的文章:opencv-python常用函数解析及参数介绍(三)——图像滤波
2) 计算梯度
计算图像中每个像素点的梯度强度和方向。
我们以3x3的sobel算子为例计算梯度
在之前的文章中我们知道,sobel的梯度因为算子可以分成Sx和Sy,所以梯度也可以分为两个梯度,一个是Gx,更加侧重左右的偏差,即侧重竖直方向的边缘,而Gy更加侧重上下的偏差,即侧重水平方向的边缘,那么我们得到了x方向的梯度Gx,y方向的梯度Gy,那么总梯度应该为
G
x
2
+
G
y
2
\sqrt{Gx^2+Gy^2}
Gx2+Gy2
这里我们只求得了梯度的大小,那么如何计算梯度的方向呢
我们已经知道了x方向的梯度大小为Gx,y方向的梯度大小为Gy
假设梯度方向与
x
轴方向的夹角为
θ
则
t
a
n
θ
=
G
y
G
x
即
:
θ
=
a
r
c
t
a
n
(
G
y
G
x
)
假设梯度方向与x轴方向的夹角为 \theta \\则tan\theta = \frac{Gy}{Gx} \\ 即:\theta = arctan(\frac{Gy}{Gx})
假设梯度方向与x轴方向的夹角为θ则tanθ=GxGy即:θ=arctan(GxGy)
关于图像梯度的计算的详细细节可以参照上一篇博客:opencv-python常用函数解析及参数介绍(六)——图像梯度
3) 非极大值抑制
顾名思义就是抑制不是极大值的值,应用非极大值(Non-Maximum Suppression)抑制,以消除边缘检测带来的杂散响应。
在本问题中可以理解为只选用最大的梯度。
4) 双阈值检测
应用双阈值(Double-Threshold)检测来确定真实的和潜在的边缘。
其细节上表现为,设置两个阈值,一个阈值决定下限,另一个阈值决定上限,超过阈值上限的梯度可以理所应当的被认为是边缘,低于下限的梯度被认为不是边缘,而对应在上下限直接的范围梯度,应该看与他相连的梯度是不是已经被认为是边缘,如果已经被认为是边缘了,那么与边缘相连的也一定是边缘。
2.opencv中的边缘检测
上述的过程似乎有些复杂,幸好,在opencv中我们可以使用cv2.Canny进行边缘检测,我们只需设置双阈值检测中需要的上下限就好
效果展示
我们假设有一张名为kl.png的图片
为了展示方便,我们依然先编写一个展示函数
def cv_show(img,name):
cv2.imshow(name,img)
cv2.waitKey()
cv2.destroyAllWindows()
对这张图片进行边缘检测的效果如下
img=cv2.imread("kl.png",cv2.IMREAD_GRAYSCALE)
v1=cv2.Canny(img,80,150)
cv_show(v1,'res')
分析对比
与上篇文章中直接使用梯度当做边缘的效果相比似乎是更好的,那么这是为什么呢?其主要的区别就是从双阈值检测,因为我们进行了双阈值检测,在这个过程中当某一个点上的梯度小于设置的下限时就会被丢弃,即立即判断这个点不是边缘,所以相比之下,结果看起来会更干净(因为直接使用梯度作为边缘时一些较小梯度的点仍然会被保留)
当我们把下限设置成0时,即不对梯度的下限做限制,我们可以清晰的看到有些本不属于边缘的位置被当成了边缘
img=cv2.imread("kl.png",cv2.IMREAD_GRAYSCALE)
v1=cv2.Canny(img,0,150)
cv_show(v1,'res')
下面我们来对上下限进行修改,然后做一下对比
img=cv2.imread("kl.png",cv2.IMREAD_GRAYSCALE)
v1=cv2.Canny(img,0,150)
v2=cv2.Canny(img,50,150)
v3=cv2.Canny(img,50,200)
res = np.hstack((v1,v2,v3))
cv_show(cv2.resize(res, (1500, 500)),'res')
从这个对比中我们可以得到一个结论,上限相同时,降低下限,会导致被直接判断成非边界的点减少,从而得到更多的边缘,下限相同时,升高上限,会使得直接被判断成边界的点减少,同时也会影响到与被判断成边界的点相连的点,产生更少的边缘
3.结尾
关于边缘检测所需的内容,如果感兴趣可以参照之前的一个博客边缘检测生成(伪)手绘线稿风格的视频简易版教程自己生成一个边缘检测的(伪)线稿视频,关于图像的处理所用的全都是本专栏介绍过的知识