美文网首页
[OpenCV官方教程中文版-段力辉译]-Canny边缘检测

[OpenCV官方教程中文版-段力辉译]-Canny边缘检测

作者: 六千宛 | 来源:发表于2021-07-15 14:25 被阅读0次

    Canny边缘检测是一种非常流行的边缘检测算法,是John Canny在1986年提出的。它是一个多阶段的算法,即由多个步骤构成。

    • 图像降噪
      Canny 边缘检测是一种非常流行的边缘检测算法,是 John F.Canny 在1986 年提出的。它是一个有很多步构成的算法,我们接下来会逐步介绍。
    • 计算图像梯度
      由于边缘检测很容易受到噪声影响,所以第一步是使用 5x5 的高斯滤波器去除噪声,这个前面我们已经学过了。对平滑后的图像使用 Sobel 算子计算水平方向和竖直方向的一阶导数(图像梯度)(Gx 和 Gy)。根据得到的这两幅梯度图(Gx 和 Gy)找到边界的梯度和方向,公式如下:


      image.png

      梯度的方向一般总是与边界垂直。梯度方向被归为四类:垂直,水平,和两个对角线。

    • 非极大值抑制
      在获得梯度的方向和大小之后,应该对整幅图像做一个扫描,去除那些非边界上的点。对每一个像素进行检查,看这个点的梯度是不是周围具有相同梯度方向的点中最大的。如下图所示:


      image.png
    • 阈值筛选
      现在要确定那些边界才是真正的边界。这时我们需要设置两个阈值:minVal 和 maxVal。当图像的灰度梯度高于 maxVal 时被认为是真的边界,那些低于 minVal 的边界会被抛弃。如果介于两者之间的话,就要看这个点是否与某个被确定为真正的边界点相连,如果是就认为它也是边界点,如果不是就抛弃。如下图:


      image.png

      A 高于阈值 maxVal 所以是真正的边界点,C 虽然低于 maxVal 但高于minVal 并且与 A 相连,所以也被认为是真正的边界点。而 B 就会被抛弃,因为他不仅低于 maxVal 而且不与真正的边界点相连。所以选择合适的 maxVal和 minVal 对于能否得到好的结果非常重要。在这一步一些小的噪声点也会被除去,因为我们假设边界都是一些长的线段。

    原型

    OpenCV-Python中Canny函数的原型为:

    edge = cv2.Canny(image, threshold1, threshold2[, edges[, apertureSize[, L2gradient ]]]) 
    

    必要参数:

    • 第一个参数是需要处理的原图像,该图像必须为单通道的灰度图;
    • 第二个参数是阈值1;
    • 第三个参数是阈值2。
      在 OpenCV 中只需要一个函数:cv2.Canny(),就可以完成以上几步。让我们看如何使用这个函数。这个函数的第一个参数是输入图像。第二和第三个分别是 minVal 和 maxVal。第三个参数设置用来计算图像梯度的 Sobel卷积核的大小,默认值为 3。最后一个参数是 L2gradient,它可以用来设定求梯度大小的方程。如果设为 True,就会使用我们上面提到过的方程,否则使用方程:Edge−Gradient(G) = |G2x| + |G2y| 代替,默认值为 False。

    使用

    Canny函数的使用很简单,只需指定最大和最小阈值即可。如下:

    #coding=utf-8
    import cv2
    import numpy as np  
    img = cv2.imread("D:/lion.jpg", 0)  # 由于Canny只能处理灰度图,所以将读取的图像转成灰度图
    img = cv2.GaussianBlur(img,(3,3),0) # 用高斯平滑处理原图像降噪。若效果不好可调节高斯核大小
    canny = cv2.Canny(img, 50, 150)     # 调用Canny函数,指定最大和最小阈值,其中apertureSize默认为3。
    cv2.imshow('Canny', canny)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    
    image.png

    处理结果如下:
    分别为高斯核为(1,1)和(3, 3)的效果图:


    image.png
    image.png

    更多
    这个程序只是静态的,下面是可以在运行时调整阈值大小的程序。其代码如下:

    import cv2
    import numpy as np
    def CannyThreshold(lowThreshold):
        detected_edges = cv2.GaussianBlur(gray,(3,3),0)
        detected_edges =cv2.Canny(detected_edges,lowThreshold,lowThreshold*ratio,apertureSize = kernel_size)
        dst = cv2.bitwise_and(img,img,mask = detected_edges)  # just add some colours to edges from original image.
        cv2.imshow('canny demo',dst)
    lowThreshold = 0
    max_lowThreshold = 100
    ratio = 3
    kernel_size = 3
    img = cv2.imread('D:/lion.jpg')
    gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
    cv2.namedWindow('canny demo')
    cv2.createTrackbar('Min threshold','canny demo',lowThreshold, max_lowThreshold, CannyThreshold)
    CannyThreshold(0)  # initialization
    if cv2.waitKey(0) == 27:
        cv2.destroyAllWindows()
    

    效果图如下:


    image.png

    相关文章

      网友评论

          本文标题:[OpenCV官方教程中文版-段力辉译]-Canny边缘检测

          本文链接:https://www.haomeiwen.com/subject/wxvqultx.html