Canny图像边缘检测(OpenCV)

  • C++ API说明

void cv::Canny    (    

InputArray    image,    (输入图像:8-bit)
OutputArray    edges,    (输出边缘图像:单通道,8-bit,size与输入图像一致)
double    threshold1,    (阈值1)
第一个滞后性阈值【低阈值】。值越大,找到的边缘越少
double    threshold2,    (阈值2)第二个滞后性阈值【高阈值】。
int    apertureSize=3,    (Sober算子大小)
bool    L2gradient=false  (是否采用更精确的方式计算图像梯度)
)          


void cv::Canny    (    

InputArray    dx,    (输入图像在x方向的导数:16-bit(CV_16SC1或CV_16SC3))
InputArray    dy,    (输入图像在y方向的导数:16-bit(CV_16SC1或CV_16SC3))
OutputArray    edges,    (输出边缘图像:单通道,8-bit,size与输入图像一致)
double    threshold1,    (阈值1)
第一个滞后性阈值【低阈值】。值越大,找到的边缘越少
double    threshold2,    (阈值2)第二个滞后性阈值【高阈值】。
bool    L2gradient=false (是否采用更精确的方式计算图像梯度)

)    

        
# xgrad = cv.Sobel(gray, cv.CV_16SC1, 1, 0) #x方向梯度

2 # ygrad = cv.Sobel(gray, cv.CV_16SC1, 0, 1) #y方向梯度

 3# edge_output = cv.Canny(xgrad, ygrad, 50, 150)

4edge_output = cv.Canny(gray, 50, 150)
注:其中第4行代码可以用1、2、3行代码代替!两种方法效果一样。

  • 原理

JohnCanny于1986年提出Canny算子,是一个多级边缘检测算法。它与Marr(LoG)边缘检测方法类似,也属于是先平滑后求导数的方法。被很多人认为是边缘检测的最优算法, 最优边缘检测的评价标准主要有三个:

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

它是一个多阶段的算法,即由多个步骤构成。

1.图像降噪 

消除噪声。 使用高斯平滑滤波器卷积降噪。 下面是一个 size = 5 的高斯内核:


2.计算图像梯度 

 计算梯度幅值和方向。计算图像梯度可以得到图像的边缘,因为边缘也是灰度变化明显,梯度灰度变化也明显。这一步可以检测到可能的边缘。由于灰度变化大的地方可能是边缘,也可能不是边缘,但这一步将所有可能是边缘的地方集合。 此处使用Sobel滤波器:

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

                  

在上面的三个模板中,Gx为水平x方向的模板,Gy为 垂直y方向的模板,K为领域标记矩阵。

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

梯度方向近似得到四个可能角度一般是 0, 45, 90, 135。 

3.非极大值抑制 

非极大值 抑制。 这一步排除非边缘像素, 仅仅保留了一些细线条(候选边缘)。灰度变化的地方通常比较集中,将局部范围内梯度方向上灰度变化最大的保留下来,其它的不保留,这样处理可以剔除掉很多不是边缘的点。将宽边缘(多个像素)变成一个单(单像素)边缘。即“宽边缘”变成“单边缘”。
4.双阈值筛选或者滞后阈值

  最后一步,通过非极大值抑制后,仍然有很多的可能边缘点,进一步的设置一个双阈值,即低阈值(low)、高阈值(high)。

  1. 某一像素的灰度值超过high 阈值, 该像素被保留为边缘像素。
  2. 某一像素的灰度值小于low 阈值, 该像素被排除。
  3. 如果某一像素的灰度值在两个阈值之间,该像素仅仅在连接到一个高于high阈值的像素时被保留。

Canny 推荐的 : 阈值比在 2:1 到3:1之间。

最后看代码效果:

#include "opencv.hpp"
using namespace cv;

void main()
{
    Mat src = imread("2019_04_13.jpg", IMREAD_COLOR);

    Mat gray;
    cvtColor(src , gray, CV_BGR2GRAY);

    Mat canny;
    Canny(gray,  canny, 60, 180);

}

参考:

http://www.opencv.org.cn/opencvdoc/2.3.2/html/doc/tutorials/imgproc/imgtrans/canny_detector/canny_detector.html

https://blog.csdn.net/dieju8330/article/details/82814529

猜你喜欢

转载自blog.csdn.net/qq_30460949/article/details/89278654