OpenCV 中的图像处理 007_Canny 边缘探测

本文主要内容来自于 OpenCV-Python 教程OpenCV 中的图像处理 部分,这部分的全部主要内容如下:

目标

在本章中,我们将学习关于

  • Canny 边缘检测的概念
  • OpenCV 中为此提供的函数:cv.Canny()

理论

Canny 边缘检测是一个流行的边缘检测算法。它由 John F. Canny 开发

  1. 这是一个多阶段算法,我们将浏览每个阶段。
  2. 降噪
    由于边缘检测容易受到图像中噪声的影响,因此第一步是使用 5x5 高斯滤波器去除图像中的噪声。我们在前面的章节中已经看到了这一点。
  3. 寻找图像的强度梯度
    然后在水平和垂直方向上使用 Sobel 核对平滑后的图像进行滤波,以获得水平方向 ( G x G_x Gx) 和垂直方向 ( G y G_y Gy) 的一阶导数。从这两张图像中,我们可以找到每个像素的边缘梯度和方向,如下所示:
    E d g e _ G r a d i e n t    ( G ) = G x 2 + G y 2 A n g l e    ( θ ) = tan ⁡ − 1 ( G y G x ) Edge\_Gradient \; (G) = \sqrt{G_x^2 + G_y^2} \\ Angle \; (\theta) = \tan^{-1} \bigg(\frac{G_y}{G_x}\bigg) Edge_Gradient(G)=Gx2+Gy2 Angle(θ)=tan1(GxGy)
    梯度方向始终垂直于边缘。它被舍入到代表垂直、水平和两个对角线方向的四个角度之一。
  4. 非最大抑制
    在获得梯度幅度和方向后,对图像进行全面扫描以去除可能不构成边缘的任何不需要的像素。为此,在每个像素处,检查像素是否是其邻域中沿梯度方向的局部最大值。检查下图:
    image
    A点在边缘上(垂直方向)。梯度方向垂直于边缘。点 B 和 C 在梯度方向上。因此点 A 与点 B 和 C 一起检查来看下它是否是局部最大值。如果是,则将考虑让它进入下一阶段,否则,将其抑制(置零)。
    简而言之,我们得到的结果是具有 “薄边” 的二值图像。
  5. 迟滞阈值
    这个阶段决定哪些所有的边都是真正的边,哪些不是。为此我们需要两个阈值,minValmaxVal。任何强度梯度大于 maxVal 的边缘肯定是边缘,低于 minVal 的边缘肯定是非边缘,因此丢弃。位于这两个阈值之间的那些根据它们的连通性被分类为边缘或非边缘。如果它们连接到 “确定边缘” 像素,则它们被认为是边缘的一部分。 否则,它们也会被丢弃。 见下图:
    image
    边缘 A 在 maxVal 之上,因此被认为是 “确定边缘”。尽管边缘 C 在 maxVal 之下,它连接到了边缘 A,因而也被认为是有效的边缘,且我们得到了完整的曲线。但边缘 B,尽管它在 minVal 之上,且与边缘 C 位于同一片区域,它没有连接到任何 “确定边缘”,因而它被丢弃。因此,我们必须相应地选择 minValmaxVal 以获得正确的结果,这一点非常重要。
    在假设边缘是长线的情况下,这个阶段还去除了小像素噪声。

所以我们最终得到的是图像中的强边缘。

OpenCV 中的 Canny 边缘检测

OpenCV 把上面所有的东西都放进一个函数里,cv.Canny()。我们将看到如何使用它。第一个参数是我们的输入图像。第二个和第三个参数分别是我们的 minValmaxVal。第四个参数是 aperture_size。它是用于寻找图像梯度的 Sobel 内核的大小。其默认为 3。最后一个参数是 L2gradient,它指定了寻找梯度幅度的方程。如果它为 True,它使用上面提到的更精确的方程,否则它使用这个函数: E d g e _ G r a d i e n t    ( G ) = ∣ G x ∣ + ∣ G y ∣ Edge\_Gradient \; (G) = |G_x| + |G_y| Edge_Gradient(G)=Gx+Gy。它的默认值为 False

import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt


def canary_edge_detection():
    cv.samples.addSamplesDataSearchPath("/media/data/my_multimedia/opencv-4.x/samples/data")
    img = cv.imread(cv.samples.findFile('messi5.jpg'))
    edges = cv.Canny(img, 100, 200)
    plt.subplot(121), plt.imshow(img, cmap='gray')
    plt.title('Original Image'), plt.xticks([]), plt.yticks([])
    plt.subplot(122), plt.imshow(edges, cmap='gray')
    plt.title('Edge Image'), plt.xticks([]), plt.yticks([])
    plt.show()


if __name__ == "__main__":
    canary_edge_detection()

来看如下的结果:
image

其它资源

  1. Wikipedia 中的 Canny 边缘探测

  2. Canny 边缘探测教程 by Bill Green, 2002.

练习

编写一个小应用来寻找 Canny 边缘探测,其阈值可以使用两个轨迹栏来改变。这样,你可以了解阈值的影响。

参考文档

Canny Edge Detection

Done.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值