Canny算法

边缘检测算法:Canny算法

该算法不容易受到噪声的影响,能够识别图像中的弱边缘和强边缘,并结合强弱边缘的位置关系,综合给出图像整体的边缘信息

Canny边缘检测算法目前是最优越的边缘检测算法之一,该方法的检测过程分为以下5步

第一步:使用高斯滤波平滑图像,减少图像中噪声,在一般情况下,使用5x5的高斯滤波器

第二步:计算图像中每个像素的梯度方向和幅值,首先通过Sobel算子分别检测图像X方向的边缘和Y方向的边缘

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

第三步:应用非极大值抑制算法消除边缘检测带来的杂散响应,首先,将当前像素的梯度强度与沿正负梯度方向上的两个像素

进行比较,如果当前像素的梯度强度与另外两个像素梯度强度相比最大,那么该像素点保留位边缘点,否则被抑制

第四步:应用双阈值法划分强边缘和弱边缘,将边缘处的梯度值与两个阈值进行比较,如果某像素的梯度幅值小于较小的阈值

那么会被去除;如果某像素的梯度幅值大于较小幅值、小于较大阈值,那么将该像素标记为弱边缘;如果某像素的梯度

幅值大于较大阈值,那么将该像素标记为强边缘

第五步:消除孤立的弱边缘。在弱边缘的8邻域范围寻找强边缘,如果8领域内存在强边缘,就保留该弱边缘, 否则将删除弱边缘

最终输出边缘检测结果

OpenCV4提供了Canny()函数实现Canny算法检测图像中的边缘

Canny()函数原型:

void Canny(InputArray image,
           OuputArray edges,
           double threshold1,
           double threshold2,
           int apertureSize = 3,
           bool L2gradient = false
           )
  • image:输入图像,必须是CV_8U的单通道或者三通道图像
  • edges:输出图像,与输入图像具有相同的单通道图像,且数据类型为CV_8U
  • threshold1:第一个滞后阈值
  • threshold2:第二个滞后阈值
  • apertureSize:Sobel算子的直径
  • L2gradient:计算图像梯度幅方法的标志(两种)

该函数利用Canny算法提取图像中的边缘信息,第一个参数是需要提取边缘的输入图像,目前只支持数据类型为CV_8U的图像

输入图像可以是灰度图像或者彩色图像,第二个参数是边缘检测结果的输出图像,图像是数据类型为CV_8U的单通道灰度图像

第三、四个参数是Canny算法中用于区分强边缘和弱边缘的两个阈值,两个参数不区分较大阈值和较小阈值,函数自动区分大小

一般情况下较大阈值与较小阈值的比值在2:1到3:1之间

示例:

#include <iostream>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int main()
{
    //读取图像,黑白图像边缘检测结果较为明显
    Mat img = imread("E:\\CLion\\opencv_xin\\SG\\SG_0.jpg",IMREAD_ANYDEPTH);
    if (img.empty())
    {
        cout << "error" << endl;
        return -1;
    }
    Mat resultHigh,resultLow,resultG;
    //高阈值检测图像边缘
    Canny(img,resultHigh,100,200,3);
    //低阈值检测图像边缘
    Canny(img,resultLow,20,40,3);
    //高斯模糊后检测图像边缘
    GaussianBlur(img,resultG,Size(3,3),5);
    Canny(resultG,resultG,100,200,3);
    //显示图像
    imshow("resultHigh",resultHigh);
    imshow("resultLow",resultLow);
    imshow("resultG",resultG);
    waitKey(0);
    return 0;
}

注:较高的阈值会降低噪声信息对图像提取边缘结果的影响,但是同时也会减少结果种的边缘结果

results matching ""

    No results matching ""