Canny 是1986年提出的图像边缘检测经典算法,本文记录相关内容与 OpenCV 实现。
通常情况下边缘检测的目的是在保留原有图像属性的情况下,显著减少图像的数据规模。
John F. 在提出Canny 的同时,提出了边缘检测的三大准则:
Canny边缘检测算法可以分为以下5个步骤:
边缘方向 | 梯度方向 | 角度范围 |
---|---|---|
水平 | 垂直 | $ \theta_{M} \in[0,22.5) \cup(-22.5,0] \cup(157.5,180] \cup(-180,157.5] $ |
135° | 45° | $ \theta_{M} \in[22.5,67.5) \cup[-157.5,-112.5) $ |
垂直 | 水平 | $ \theta_{M} \in[67.5,112.5] \cup[-112.5,-67.5] $ |
45° | 135° | $ \theta_{M} \in(112.5,157.5] \cup[-67.5,-22.5] $ |
一般的边缘检测算法用一个阀值来滤除噪声或颜色变化引起的小的梯度值,而保留大的梯度值。Canny算法应用双阀值,即一个高阀值和一个低阀值来区分边缘像素。如果边缘像素点梯度值大于高阀值,则被认为是强边缘点。如果边缘梯度值小于高阀值,大于低阀值,则标记为弱边缘点。小于低阀值的点则被抑制掉。
至此,强边缘点可以认为是真的边缘。弱边缘点则可能是真的边缘,也可能是噪声或颜色变化引起的。为得到精确的结果,后者引起的弱边缘点应该去掉。通常认为真实边缘引起的弱边缘点和强边缘点是连通的,而又噪声引起的弱边缘点则不会。所谓的滞后边界跟踪算法检查一个弱边缘点的8连通领域像素,只要有强边缘点存在,那么这个弱边缘点被认为是真是边缘保留下来。
官方文档 使用 Sobel 算子运算
cv2.Canny(image, threshold1, threshold2[, edges[, apertureSize[, L2gradient]]]) ->edges
参数 | 说明 |
---|---|
image | uint8 格式单通道图像 |
edges | 输出边缘图; 单通道8位图像,与图像大小相同。 |
threshold1 | 低阈值 |
threshold2 | 高阈值 |
apertureSize | cv2.Canny()内部调用的Sobel导数算子所用的aperturel的大小,默认为3,可选值[3, 5, 7] |
L2gradient | 是否使用精度高但速度慢的 $L_2$ 范数计算方向梯度,默认为 False |
否则使用 L_1 范数计算:
img = mt.cv_rgb_imread('img1.jpg', gray=True)
res = cv2.Canny(img, 17430, 30000, apertureSize=7)
PIS(img, res)