前言
Canny边缘检测算法是—种特别常用且性能优秀的边缘检测算法,相比于普通的边缘检测算法,Canny算法具有不容易受图像噪声干扰、能够检测到真正的弱边缘和拥有较高的检测精度的优点,同时图像的真实边缘只返回一个边缘点即单像素边缘。
Canny边缘检测步骤
- 转化为灰度图像,然后高斯模糊
- 计算梯度大小和方向
- 非极大值抑制,每条边理应只有一个响应
- 双阈值边界跟踪,分离强边缘和弱边缘
高斯模糊
边缘属于图像中的高频信号,但噪声也属于高频信号,因此可以先对图像做一次高斯模糊,抑制噪声,虽然边缘也会被抑制,但后期连接弱边缘时,被抑制的边缘还可能被重置为强边缘,而被抑制的噪声因为孤立而不被认为强边缘。
高斯模糊原理可查看link。
计算梯度大小和方向
梯度定义如下所示:
这分别是图像在(x, y)点处x方向和y方向上的偏导数即梯度,从上面的表达式可以看出来,图像的梯度相当于2个相邻像素之间的差值。图像梯度的原理可查看link1和link2。
这样就形成了一个简单的检测算子[-1,1],拿此算子遍历整个图像就可以得到x方向的边缘。(y方向与此类同)
一般均采用sobel算子计算x方向和y方向上的梯度。sobel算子分为垂直方向和水平方向两个模板,模板如下:
利用模板和图像进行卷积得到x方向和y方向上的梯度:
梯度大小和梯度方向计算:
梯度的大小表示像素点(x, y)的梯度幅值F(x, y),梯度幅值计算公式如下:
实际应用中,为了减少计算量,常采用绝对值来简化计算:
梯度方向为:
非极大值抑制
非极大值抑制的目的在于细化边缘,将原有粗略边缘检测图中的宽边细化为真正的边缘,从而可以更好的凸显物体的轮廓。
非极大值抑制是在像素的3×3邻域上,比较该像素点和其梯度正负方向的像素点的梯度强度,梯度方向与边缘方向是垂直的,如果该像素点梯度强度最大则保留,否则抑制(删除,即置为0)。
事实上图像是离散的,q’和r’并不存在,这时有两种办法,1)线性插值,通过p、q两点的线性插值求得q’,r’同理可得。2)取相近点作为极大值,即取q点取代q’点。
双阈值法确定图像边缘
双阈值检测分为两个步骤:
1)通过选取强弱阈值,将梯度幅值低与弱阈值的点置为0,大于强阈值的保留并标记为255。
2)对于梯度幅值大于弱阈值但又小于高阈值的点,通过判断它的8邻域是否存在大于强阈值的点,若存在,则保留并置为255,若不存在,则舍弃并置为0。
自适应双阈值的Canny边缘检测
自适应阈值的改进Canny算法改进过程为:在求出梯度幅值 后,跟据公式求出梯度均值和梯度标准差来求解阈值。求解公式如下:
还有另外一种简单的方式,得到的效果也不错:
def auto_canny(image, sigma=0.33):
# 计算单通道像素强度的中位数
v = np.median(image)
# 选择合适的lower和upper值,然后应用它们
lower = int(max(0, (1.0 - sigma) * v))
upper = int(min(255, (1.0 + sigma) * v))
edged = cv2.Canny(image, lower, upper)
return edged