• 【opencv实践】边缘检测


    边缘检测:

    一、canny算子

    Canny边缘检测根据对信噪比与定位乘积进行测度,得到最优化逼近算子,也就是Canny算子。类似与 LoG 边缘检测方法,也属于先平滑后求导数的方法。

    二、canny算法描述

    1.首先进行高斯平滑滤波;

    2、然后计算像素点的梯度(利用sobel算子)

    3、计算幅值和夹角

    4、非极大值抑制(NMS)幅值和夹角,如下图所示,就是比较梯度方向前后像素梯度的大小。

    上图中左右图:g1、g2、g3、g4都代表像素点,很明显它们是c的八领域中的4个,左图中c点是我们需要判断的点,蓝色的直线是它的梯度方向,也就是说c如果是局部极大值,它的梯度幅值M需要大于直线与g1g2和g2g3的交点,dtmp1和dtmp2处的梯度幅值。但是dtmp1和dtmp2不是整像素,而是亚像素,也就是坐标是浮点的,那怎么求它们的梯度幅值呢?线性插值,例如dtmp1在g1、g2之间,g1、g2的幅值都知道,我们只要知道dtmp1在g1、g2之间的比例,就能得到它的梯度幅值,而比例是可以靠夹角计算出来的,夹角又是梯度的方向。

        写个线性插值的公式:设g1的幅值M(g1),g2的幅值M(g2),则dtmp1可以很得到:

            M(dtmp1)=w*M(g2)+(1-w)*M(g1)  

           其中w=distance(dtmp1,g2)/distance(g1,g2)      

        distance(g1,g2) 表示两点之间的距离。实际上w是一个比例系数,这个比例系数可以通过梯度方向(幅角的正切和余切)得到。

    5、双阈值选取

    • 将低于阈值的所有值赋零,得到图像的边缘阵列 

    • 阈值τ取得太低->假边缘
    • 阈值τ取得太高->部分轮廊丢失

     Canny算法中减少假边缘数量的方法是采用双阈值法。选择两个阈值,根据高阈值得到一个边缘图像,这样一个图像含有很少的假边缘,但是由于阈值较高,产生的图像边缘可能不闭合,为解决这样一个问题采用了另外一个低阈值。
            在高阈值图像中把边缘链接成轮廓,当到达轮廓的端点时,该算法会在断点的8邻域点中寻找满足低阈值的点,再根据此点收集新的边缘,直到整个图像边缘闭合。

     三、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,表示应用Sobel算子的孔径大小,默认值3
    •  第六个参数,bool类型的L2gradient,一个计算图像梯度幅值的标识,默认值false
    注意:两个阈值中较小的值用于边缘连接,较大的值用来控制强边缘的初始段,推荐高低阈值比为2:1到3:1之间

     四、opencv中的实现

    1、图像灰度化;

    2、高斯滤波(blur)

    3、计算梯度

    4、用双阈值方法检测和连接边缘

     
    #include <opencv2/core/core.hpp>
    #include <opencv2/imgproc/imgproc.hpp>
    #include <opencv2/highgui/highgui.hpp>
    #include <math.h>
    using namespace cv;
    int main(int argc, char *argv[])
    {
        Mat img = imread("lena.jpg", CV_LOAD_IMAGE_COLOR);
        if(img.empty())
           return -1;
        Mat src_gray,src_blur,dst;
        cvtColor(img,src_gray,CV_BGR2GRAY);
        blur(src_gray,src_blur,Size(3,3));
        Canny(src_blur,dst,30,200);
        namedWindow( "lena", CV_WINDOW_AUTOSIZE );
        imshow("lena", img);
        imshow("canny",dst);
        waitKey(0);
        return 0;
    }
     

     

  • 相关阅读:
    execvp
    Linux系统调用getrlimit()与setrlimit()函数详解
    Va_start及Vsprintf应用
    waitpid()
    sdut 2408 Pick apples 夜
    poj 1273 Drainage Ditches 夜
    poj 1408 Fishnet 夜
    poj 1113 Wall 夜
    poj 1584 A Round Peg in a Ground Hole 夜
    poj 3007 Organize Your Train part II 夜
  • 原文地址:https://www.cnblogs.com/abella/p/10616079.html
Copyright © 2020-2023  润新知