OpenCV实战系列Canny边缘检测

OpenCV实战系列Canny边缘检测

分享人工智能技术干货,专注深度学习与计算机视觉领域!

OpenCV为我们提供了一个非常方便的边缘检测接口Canny函数,该函数的命名是以其发明者Jhon F.Canny命名的,自1986年被发明后该算法就一直很受欢迎,其不容易受噪声的干扰,它的双阈值法可以分别检测到强边缘和弱边缘,并且仅当弱边缘与强边缘相连时,才将弱边缘包含在输出结果中,这就保障了检测到真正的弱边缘。Canny算法不仅效果好,其使用也非常简便,仅需一行代码即可实现边缘检测,一般其工作原理如下:

1) 使用高斯滤波器对图像进行平滑去噪;

2) 计算输入图像梯度;

3) 在边缘上使用非极大值抑制(NMS)进行过滤;

4) 在检测到的边缘上使用双阈值法去除假阳性;

5) 分析所有的边缘及其之间的连接,以保留真正的边缘并消除不明显的边缘;


该接口的定义及其形参说明如下:

Canny(image, threshold1, threshold2, edges=None, apertureSize=None, L2gradient=None)

image: 输入的8bit图像

threshold1: 阈值1

threshold2: 阈值2

edges: 输出的边缘图像,8bit单通道,宽高与输入图像一致

apertureSize: Sober算子核大小

L2gradient: 是否使用更精确的方式计算梯度,True使用,否则不用


Canny函数还有另外一种接口定义,其说明如下:

Canny(dx, dy, threshold1, threshold2[, edges[, L2gradient]])

dx: 输入图像在x方向的导数:16-bit(CV_16SC1或CV_16SC3)

dy: 输入图像在y方向的导数:16-bit(CV_16SC1或CV_16SC3)

threshold1: 同上

threshold2: 同上

edges: 同上

L2gradient: 同上


一般来说,梯度小于阈值1则认为不是边缘,梯度大于阈值2则认为是强边缘,而介于阈值1和阈值2之间的则认为是弱边缘,只有弱边缘与强边缘相连,算法才会视该像素点为边缘进行保留,否则就不是从而抛弃掉。

而对于L2gradient参数,其将计算图像梯度方式导向不同的公式,一般会存在如下两种情况:

True:

False:


我们以如下摩天轮来举例说明Canny边缘检测算法的一般使用示例:

示例代码如下:

# -*- coding:utf-8 -*-
#!/usr/bin/env python
import cv2
def detect_edges(img_path):
    img_gray = cv2.imread(img_path, cv2.CV_LOAD_IMAGE_GRAYSCALE)
    img_edges = cv2.Canny(img_gray, 150, 250)