经过实验对比后,发现canny算子实现边缘检测出的图像最优,其次是sobel算子,所以今天在这里着重编写下canny算子。
首先,最优边缘检测的三个主要评价标准是:
低错误率: 标识出尽可能多的实际边缘,同时尽可能的减少噪声产生的误报;
高定位性: 标识出的边缘要与图像中的实际边缘尽可能接近;
最小响应: 图像中的边缘只能标识一次。
canny边缘检测算法的步骤为:
1.消除噪声。 使用高斯平滑滤波器卷积降噪。 下面显示了一个 的高斯内核示例:
2.计算梯度幅值和方向。 此处,按照Sobel滤波器的步骤:
运用一对卷积阵列 (分别作用于 x和 y方向):
使用下列公式计算梯度幅值和方向:
梯度方向近似到四个可能角度之一(一般 0, 45, 90, 135)
3.非极大值抑制。 这一步排除非边缘像素, 仅仅保留了一些细线条(候选边缘)。
4.滞后阈值: 最后一步,Canny 使用了滞后阈值,滞后阈值需要两个阈值(高阈值和低阈值):
a.如果某一像素位置的幅值超过 高 阈值, 该像素被保留为边缘像素。
b.如果某一像素位置的幅值小于 低 阈值, 该像素被排除。
c.如果某一像素位置的幅值在两个阈值之间,该像素仅仅在连接到一个高于 高 阈值的像素时被保留。
Canny 推荐的高:低 阈值比在 2:1 到3:1之间。
以上就是使用canny检测边缘的步骤,在opencv开发环境下使用canny算子检测边缘实现起来较为简便,因为opencv函数库中已经对canny函数进行了封装。
Canny(g_tmpImage, g_tmpImage, g_nCannyLowThreshold, g_nCannyLowThreshold * 3);
其中,g_tmpImage为平滑去躁后的灰度图像(在使用前先利用cvtColor(src,dst,COLOR_RGB2GRAY将原图像转化为灰度图像,再利用blur(src,dst,Size(3, 3))用均值滤波器进行平滑去躁);
第二个g_tmpImage为输出图像;
g_nCannyLowThreshold为设置的低阈值;
g_nCannyLowThreshold表示阈值比为3:1。
createTrackbar("Canny Parameters: ", "[Edge Detector]", &g_nCannyLowThreshold, 120, on_CannyType);//创建滚动条检测可以寻找处理后图像现实最佳的低阈值
实现canny算子检测边缘实现代码如下:
与此同时也给出了sobel边缘检测代码。sobel算子是针对图像3*3邻域的处理,其原理是先后在水平方向和垂直方向上对邻域灰度求差分,然后取两个差分的较大值或其中较大者,通常我们使用两个差分的较大者。用S(C)表示sobel算子的结果,有如下公式:S(C)=max{|(N0+N1*2+N2)-(N4+N5*2+N6)|-|(N0+N7*2+N6)-(N2+N3*2+N4)|}
N0 |
N1 |
N2 |
N7 |
C |
N3 |
N6 |
N5 |
N4 |
具体算法实现参考上述代码。
最终显示图片效果如下所示
canny算子:
sobel算子: