zoukankan      html  css  js  c++  java
  • OpenCV-C++ Canny算法介绍

    注意:文章原理还很不完善,仅供本人学习使用;

    Canny理论原理

    Canny边缘检测器是由John F. Canny在1986年提出,Canny被称为最优检测器,其目标满足以下三个主要标准:

    • 低错误率:对已有的边界能够有很好的检测;
    • 良好的定位:即检测到的边缘像素和实际边缘像素之间的距离必须最小化;
    • 最小响应:即每边只有一个响应;

    Canny算法主要包含以下五个步骤:

    过滤噪声

    使用高斯滤波器去噪,高斯核如下图所示:

    计算图像梯度

    首先,在图像利用Sobel算子计算x, y两个方向的梯度:

    其次,计算梯度的强度和方向:

    其中,梯度的方向被四舍五入到[0, 45, 90, 135]这几个角度;

    非最大值抑制算子(NMS)

    抑制那些梯度不够大的像素点,只保留最大的像素点,从而达到瘦边的目的;

    双阈值算法检测边缘和连接边缘

    经过NMS算法后,设置两个阈值(T_1, T_2),通常(T_1)(T_2)(1/2)或者(1/3);

    • 梯度值大于(T_2)的像素点称为强边缘,保留作为图像边缘;
    • 梯度值小于(T_1)的像素点不是边缘,舍弃;
    • 针对梯度值大于(T_1),小于(T_2)的像素点,称为弱边缘;

    针对弱边缘,需要进一步判定其是否的真正的边缘像素点;判别的方法就是,当弱边缘像素点周围8个领域内存在强边缘像素时,则该弱边缘变成强边缘点,否则不是边缘点;

    OpenCV Canny使用

    CannyAPI的介绍:

    void Canny( InputArray image, OutputArray edges,
               double threshold1, double threshold2,
               int apertureSize = 3, bool L2gradient = false );
    
    • src输入图像,必须是8-bits;
    • edges输出的图像边缘
    • threshold1, threshold2对应于上述的(T_1, T_2);
    • apertureSizeSobel算子的大小;
    • L2gradient表示计算梯度值时是否使用(L2)(就是默认的计算方式);

    如果设置L2gradient=True,则梯度值的计算方式为:

    [G = |G_x| + |G_y| ]

    使用方式:

    #include <iostream>
    #include <opencv2/opencv.hpp>
    
    using namespace std;
    using namespace cv;
    
    /**
     * 边缘处理
    */
    
    Mat src, srcBlur, srcGray;
    const int MAX_THRESHOLD = 255;
    int t1_value = 50;
    char output_wind[] = "output";
    
    void Canny_Demo(int, void*);
    
    int main(){
        // 读取图像
        src = imread("/home/chen/dataset/lena.jpg");
        if (src.empty()){
            cout << "could not load image." << endl;
            return -1;
        }
        namedWindow("src", WINDOW_AUTOSIZE);
        imshow("src", src); 
    
        GaussianBlur(src, srcBlur, Size(3, 3), 0, 0);
        cvtColor(srcBlur, srcGray, COLOR_BGR2GRAY);
    
        namedWindow(output_wind, WINDOW_AUTOSIZE);
        createTrackbar("Threshold: ", output_wind, &t1_value, MAX_THRESHOLD, Canny_Demo);
        Canny_Demo(0, 0);
    
        waitKey(0); 
        return 0;
    }
    
    void Canny_Demo(int, void*){
        Mat edgeOutput;
        Canny(srcGray, edgeOutput, t1_value, t1_value*2, 3, false);
        imshow(output_wind, edgeOutput);
    }
    

    Reference:

  • 相关阅读:
    [NOIp2016] 天天爱跑步
    状压DP小拼盘
    DP × KMP
    KMP算法 详解+模板
    [NOI2014] 起床困难综合症
    [洛谷P3391] 文艺平衡树 (Splay模板)
    START
    【C】单链表的实现
    【数据结构】动态顺序表
    C语言实现扫雷程序
  • 原文地址:https://www.cnblogs.com/chenzhen0530/p/14690472.html
Copyright © 2011-2022 走看看