OpenCV之Canny边缘检测(C++实现)

canny算子简介

首先看一下最有边缘检测的三个主要评价标准:

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

为了满足这些要求,canny使用的变分法,这是一种寻找满足特定功能的函数的方法。最优检测用4个指数函数项的和表示,但是它非常近似于高斯函数的一阶导数。

canny边缘检测的步骤

第一步:消除噪声

一般情况下,使用高斯平滑滤波器降噪,以size=5的高斯核为例:

OpenCV之Canny边缘检测(C++实现)_第1张图片

第二步:计算幅值和方向

运用一对卷积阵列分别作用于x和y方向(这一步与sobel滤波器的操作相同)

OpenCV之Canny边缘检测(C++实现)_第2张图片

使用以下公式计算梯度幅值和方向

OpenCV之Canny边缘检测(C++实现)_第3张图片

梯度的方向一般取4个可能的角度之一:0度,45度,90度,180度

第三步:非极大值抑制

这一步排除非边缘像素,基本保留了一些细线条(候选边缘)。

第四步:滞后阈值

这是最后一步,canny使用了滞后阈值,滞后阈值需要两个阈值,分别是高阈值和低阈值:

  • 如果某一像素位置的幅值超过高阈值,该像素被保留为边缘像素;
  • 如果某一像素位置的幅值小于低阈值,该像素被排除;
  • 如果某一像素位置的幅值在两个阈值之间,该像素仅仅在连接到一个高于高阈值的像素时被保留。

对canny函数,高阈值与低阈值的比值最好是2:1和3:1之间。

canny边缘检测:Canny() 函数

函数原型:

void Canny(InputArray image, OutputArray edges, double threshold1, double threshold2, int apertureSize=3, bool L2gradient=false)

参数详解:

  • 第一个参数:InputArray类型的image,输入图像,Mat对象节课,需为单通道8位图像。
  • 第二个参数:OutputArray类型的edges,输出的边缘图,需要和输入图像有相同的尺寸和类型。
  • 第三个参数:double类型的threshold1,第一个滞后性阈值。
  • 第四个参数:double类型的threshold2,第二个滞后性阈值。
  • 第五个参数:int类型的apertureSize,表示算子的孔径的大小,默认值时3.
  • 第六个参数:bool类型的L2gradient,一个计算图像梯度复制的标识,默认false。

需要注意的是,阈值1和阈值2两者中比较小的值用于边缘连接,较大的值用来控制边缘的初始段,推荐高低阈值比在2:1和3:1之间。

代码示例:

#include 
#include 
#include 
#include 
#include 

using namespace std;
using namespace cv;
int main() {
    Mat srcImage, grayImage;
    srcImage = imread("/Users/dwz/Desktop/cpp/1.jpg");
    Mat srcImage1 = srcImage.clone();
    cvtColor(srcImage, grayImage, COLOR_BGR2GRAY);
    Mat dstImage, edge;

    blur(grayImage, grayImage, Size(3,3));
    Canny(grayImage, edge, 150, 100, 3);

    dstImage.create(srcImage1.size(), srcImage1.type());
    dstImage = Scalar::all(0);
    srcImage1.copyTo(dstImage, edge);
    imwrite("canny.jpg", dstImage);

    return 0;
}

输入:

OpenCV之Canny边缘检测(C++实现)_第4张图片

输出:

OpenCV之Canny边缘检测(C++实现)_第5张图片

 

OpenCV之Canny边缘检测(C++实现)_第6张图片

你可能感兴趣的:(C++,opencv,图像处理,计算机视觉,opencv,c++)