欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Canny图像边缘检测

程序员文章站 2024-01-28 11:30:04
...
  • 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 (是否采用更精确的方式计算图像梯度)
)   

Parameters
image	8-bit input image.
edges	output edge map; single channels 8-bit image, which has the same size as image .
threshold1	first threshold for the hysteresis procedure.
threshold2	second threshold for the hysteresis procedure.
apertureSize	aperture size for the Sobel operator.
L2gradient	a 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 ).
1 # 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)
4  edge_output = cv.Canny(gray, 50, 150)
注:其中第4行代码可以用1、2、3行代码代替!两种方法效果一样。

原理

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

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

步骤 

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

1.图像降噪 

消除噪声。 使用高斯平滑滤波器卷积降噪。 下面是一个 Canny图像边缘检测 的高斯内核:

Canny图像边缘检测


2.计算图像梯度 

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

         a.运用一对卷积阵列 (分别作用于 Canny图像边缘检测 和 Canny图像边缘检测 方向):

                  Canny图像边缘检测Canny图像边缘检测Canny图像边缘检测

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

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

Canny图像边缘检测

梯度方向近似得到四个可能角度一般是 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);

}

Canny图像边缘检测

 

Canny图像边缘检测

参考:

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