OpenCV——边缘检测Canny算子

边缘检测Canny算子

该算法不容易受到噪声的影响,能够识别图像中的弱边缘和强边缘,并结合强弱边缘的位置关系,综和给出图像整体的边缘信息。Canny边缘检测算法是目前最优越的边缘检测算法之一,该方法的检测过程分为以下5个步骤:

  • Step1:使用高斯滤波平滑图像,减少图像中噪声。一般情况下使用式所示的5×5的高斯滤波器。

在这里插入图片描述

  • Step2:计算图像中每个像素的梯度方向和幅值。首先通过Sobel算子分别检测图像X方向的边缘和Y方向的边缘,之后利用式(5.24)计算梯度的方向和幅值。

在这里插入图片描述

为了简便,梯度方向常取值0°、45°、90°和135°这个四个角度之一。 

  • Step3:应用非极大值抑制算法消除边缘检测带来的杂散响应。首先将当前像素的梯度强度与沿正负梯度方向上的两个像素进行比较,如果当前像素的梯度强度与另外两个像素梯度强度相比最大,则该像素点保留为边缘点,否则该像素点将被抑制。
  • Step4:应用双阈值法划分强边缘和弱边缘。将边缘处的梯度值与两个阈值进行比较,如果某像素的梯度幅值小于较小的阈值,则会被去除掉;如果某像素的梯度幅 值大于较小阈值但小于较大阈值,则将该像素标记为弱边缘;如果某像素的梯度幅值大于较大阈值,则将该像素标记为强边缘。
  • Step5:消除孤立的弱边缘。在弱边缘的8邻域范围寻找强边缘,如果8邻域内存在强边缘,则保留该弱边缘,否则将删除弱边缘,最终输出边缘检测结果。
void Canny( InputArray image, OutputArray edges,
                         double threshold1, double threshold2,
                         int apertureSize = 3, bool L2gradient = false );

 

  • image:输入图像,必须是CV_8U的单通道或者三通道图像。
  • edges:输出图像,与输入图像具有相同尺寸的单通道图像,且数据类型为CV_8U。
  • threshold1:第一个滞后阈值。
  • threshold2:第二个滞后阈值。
  • apertureSize:Sobel算子的直径。
  • L2gradient:计算图像梯度幅值方法的标志,幅值的两种计算方式如式(5.25)所示。

在这里插入图片描述 

该函数利用Canny算法提取图像中的边缘信息。第一个参数是需要提取边缘的输入图像,目前只支持数据类型为CV_8U的图像,输入图像可以是灰度图像或者彩色图像。第二个参数是边缘检测结果的输出图像,图像是数据类型为为CV_8U的单通道灰度图像。函数第三个和第四个参数是Canny算法中用于区分强边缘和弱边缘的两个阈值,两个参数不区分较大阈值和较小阈值,函数会自动比较区分两个阈值的大小,不过一般情况下,较大阈值与较小阈值的比值在2:1到3:1之间。函数最后一个参数是计算梯度幅值方法的选择标志,无特殊需求的情况下,使用默认值即可。

简单示例

 

//
// Created by smallflyfly on 2021/6/15.
//

#include "opencv2/opencv.hpp"
#include "opencv2/highgui.hpp"
#include "utils.hpp"

#include 

using namespace std;
using namespace cv;

int main() {

    Mat im = imread("test.jpg", IMREAD_GRAYSCALE);
    if (im.empty()) {
        cerr << "image file read error" << endl;
        return -1;
    }
    resize(im, im, Size(0, 0), 0.5, 0.5);

    Mat result11, result12, result21, result22, result31, result32, result41, result42;
    Canny(im, result11, 100, 200);
    Canny(im, result12, 100, 200, 3, true);

    Canny(im, result21, 20, 50);
    Canny(im, result22, 20, 50, 3, true);

    // gauss blur
    Mat imGauss;
    GaussianBlur(im, imGauss, Size(5, 5), 5);
    Canny(imGauss, result31, 20, 50);
    Canny(imGauss, result32, 20, 50, 3, true);

    Canny(imGauss, result41, 100, 200);
    Canny(imGauss, result42, 100, 200, 3, true);

    showImage("result11", result11);
    showImage("result12", result12);
    showImage("result21", result21);
    showImage("result22", result22);
    showImage("result31", result31);
    showImage("result32", result32);
    showImage("result41", result41);
    showImage("result42", result42);

    waitKey(0);
    destroyAllWindows();

    return 0;
}

 

你可能感兴趣的:(Opencv)