Canny边缘检测

0.参考

Canny 边缘检测 — OpenCV 2.3.2 documentation

OpenCV-Python教程(8、Canny边缘检测)_sunny2038的专栏-CSDN博客

1.原理

Canny 边缘检测算法 是 John F. Canny 于 1986年开发出来的一个多级边缘检测算法,也被很多人认为是边缘检测的 最优算法, 最优边缘检测的三个主要评价标准是:

  • 低错误率: 标识出尽可能多的实际边缘,同时尽可能的减少噪声产生的误报。
  • 高定位性: 标识出的边缘要与图像中的实际边缘尽可能接近。
  • 最小响应: 图像中的边缘只能标识一次。

2.步骤

(1)消除噪声。

使用高斯平滑滤波器卷积降噪。 下面显示了一个 size=5的高斯内核示例:

K = \dfrac{1}{159}\begin{bmatrix}           2 & 4 & 5 & 4 & 2 \\           4 & 9 & 12 & 9 & 4 \\           5 & 12 & 15 & 12 & 5 \\           4 & 9 & 12 & 9 & 4 \\           2 & 4 & 5 & 4 & 2                   \end{bmatrix}

(2)计算梯度幅值和方向。

        此处,按照Sobel滤波器的步骤:

        a.运用一对卷积阵列 (分别作用于 x 和y  方向):

G_{x} = \begin{bmatrix} -1 & 0 & +1  \\ -2 & 0 & +2  \\ -1 & 0 & +1 \end{bmatrix}  G_{y} = \begin{bmatrix} -1 & -2 & -1  \\ 0 & 0 & 0  \\ +1 & +2 & +1 \end{bmatrix}

        b.使用下列公式计算梯度幅值和方向:

\begin{array}{l} G = \sqrt{ G_{x}^{2} + G_{y}^{2} } \\ \theta = \arctan(\dfrac{ G_{y} }{ G_{x} }) \end{array}

        梯度方向近似到四个可能角度之一(一般 0, 45, 90, 135)

(3)非极大值抑制

        这一步排除非边缘像素,仅仅保留了一些细线条(候选边缘)

(4)滞后阈值

        最后一步,Canny 使用了滞后阈值,滞后阈值需要两个阈值(高阈值和低阈值):

        a.如果某一像素位置的幅值超过高阈值,该像素被保留为边缘像素。
        b.如果某一像素位置的幅值小于低阈值,该像素被排除。
        c.如果某一像素位置的幅值在两个阈值之间,该像素仅仅在连接到一个高于高闽值的像素时被保留。
        Canny 推荐的高低阈值比在2:1到3:1之间。

3.Canny函数接口

cv.Canny(	
            image, 
            threshold1, 
            threshold2[, edges[, apertureSize[, L2gradient]]]	
)

->	edges
cv.Canny(	
            dx, 
            dy, 
            threshold1, 
            threshold2[, edges[, L2gradient]]	
) 

->	edges

Parameters

image       需要处理的原图像,该图像必须为单通道的灰度图;

dx

16-bit x derivative of input image (CV_16SC1 or CV_16SC3).
dy16-bit y derivative of input image (same type as dx).
edgesoutput edge map; single channels 8-bit image, which has the same size as image .
threshold1first threshold for the hysteresis procedure.
threshold2second threshold for the hysteresis procedure.
L2gradienta flag, indicating whether a more accurate L2 norm =(dI/dx)2+(dI/dy)2−−−−−−−−−−−−−−−−√ should be used to calculate the image gradient magnitude ( L2gradient=true ), or whether the default L1 norm =|dI/dx|+|dI/dy| is enough ( L2gradient=false ).

其中较大的阈值2用于检测图像中明显的边缘,但一般情况下检测的效果不会那么完美,边缘检测出来是断断续续的。所以这时候用较小的第一个阈值用于将这些间断的边缘连接起来。
可选参数中apertureSize就是Sobel算子的大小。而L2gradient参数是一个布尔值,如果为真,则使用更精确的L2范数进行计算(即两个方向的倒数的平方和再开放),否则使用L1范数(直接将两个方向导数的绝对值相加)。

具体的算法可参见清华大学出版社的《图像处理与计算机视觉算法及应用(第2版) 》第二章,其中有Canny算法的详细描述及实现。

函数返回一副二值图,其中包含检测出的边缘。

4.测试代码

Canny函数内部并没有对图像进行很好地降噪,因此为了保证结果更准确,我们在调用Canny函数前常常会先通过高斯滤波降噪。

import cv2
import numpy as np
# 获取照片路径
path=r"C:\Users\Nobody\Desktop\Hand.JPG"
# 读取灰度照片
img=cv2.imread(path,0)
# 缩放
img1=cv2.resize(img,None,fx=0.5,fy=0.5)
# 高斯滤波
img_gaus=cv2.GaussianBlur(img1,(3,3),0)
# canny算子
img_canny=cv2.Canny(img_gaus,50,160)

imgs=np.hstack([img1,img_gaus,img_canny])
cv2.imshow('multi pic',imgs)
cv2.waitKey()

结果输出:

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值