• opencv(10)图像变换之边缘检测


    1.sobel算子

    
    
    

    sobel算子利用多项式计算导数的近似值,其计算公式和3*3模版如下,sobel算子结合了一些滤波的效果,对噪声有一定的鲁棒性。

    1 2

    opencv提供了进行sobel算子的函数,函数如下:

    void cvSobel( const CvArr* src, CvArr* dst, int xorder, int yorder, int aperture_size=3 );

    src :输入图像. 单通道,8位或者浮点
    dst: 输出图像. 单通道,如果是8位图像,为了防止溢出,输出必须是IPL_DEPTH_16S类型

    xorder:  x 方向上的差分阶数
    yorder : y 方向上的差分阶数  可以是0 1 2
    aperture_size  :扩展 Sobel 核的大小,必须是 1, 3, 5 或 7。 除了尺寸为 1, 其它情况下, aperture_size ×aperture_size 可分离内核将用来计算差分。对 aperture_size=1的情况, 使用 3x1 或 1x3 内核 (不进行高斯平滑操作)。这里有一个特殊变量 CV_SCHARR (=-1),对应 3x3 Scharr 滤波器,可以给出比 3x3 Sobel 滤波更精确的结果。

    3

    sobel算子使用大核计算到导数更加的逼近,小核对噪声更加敏感,当计算X,Y方向的梯度的时候,精确度还可以,但是使用Y/X计算图像梯度方向的时候,精度就很差,尤其是小核的时候。所以opencv提供了scharr滤波器来解决这个问题,计算梯度的准确率会比sobel 3*3的效果好。

    2.拉普拉斯算子

    拉普拉斯算子的是对拉普拉斯函数的离散模拟,函数形式如下,opencv中利用二次sobel算子来实现,先利用sobel算子计算X Y方向的差分,然后再求和。

    4

    opencv中的实现函数:

    void cvLaplace( const CvArr* src, CvArr* dst, int aperture_size=3 );参数和cvsobel函数类似。注意的拉普莱斯中对过零问题做了处理,将二阶差分为0 ,一阶差分算子响应低的边缘点滤除掉。3.CANNY算子void cvCanny( const CvArr* image, CvArr* edges, double threshold1,double threshold2, int aperture_size=3 );canny的步骤如下step1:用高斯滤波器平滑图象;step2:用一阶偏导的有限差分来计算梯度的幅值和方向;step3:对梯度幅值进行非极大值抑制;
    step4:用双阈值算法检测和连接边缘。
    image:canny只接受单通道图像double threshold1,double threshold2为canny算子中采用的两个最大阈值和最小阈值,一个像素的梯度大于最大阈值被认定为边缘,如果小于最小阈值则被抛弃,如果介于二者之间,主要当期与高于上限阈值的连接时才会被认定为接受。也可以采用自适应的阈值算法,可以参考:自适应阈值算法aperture:计算一阶偏导的时候opencv采用sobel算子,这个参数为sobel的内核大小。默认为3*3

     
     

    测试代码:

       1: IplImage *Image1;
       2: Image1 = cvLoadImage("7.jpg");
       3: IplImage *ImageGray = cvCreateImage(cvGetSize(Image1),IPL_DEPTH_8U,1);
       4: IplImage *SobelDstImg= cvCreateImage(cvGetSize(Image1),IPL_DEPTH_16S,1);
       5: IplImage *ImageGray2 = cvCreateImage(cvGetSize(Image1),IPL_DEPTH_8U,1);
       6: cvCvtColor(Image1,ImageGray,CV_BGR2GRAY);
       7:  
       8: cvNamedWindow("src");
       9: cvShowImage("src",ImageGray);
      10:  
      11: cvSobel(ImageGray,SobelDstImg,1,1,3 );
      12: cvConvertScaleAbs(SobelDstImg,ImageGray2);
      13:  
      14: cvNamedWindow("sobel");
      15: cvShowImage("sobel",ImageGray2);
      16:  
      17: cvLaplace(ImageGray,SobelDstImg,3);
      18: cvConvertScaleAbs(SobelDstImg,ImageGray2);
      19:  
      20: cvNamedWindow("Laplace");
      21: cvShowImage("Laplace",ImageGray2);
      22:  
      23: cvCanny(ImageGray,ImageGray2,50,100,3);
      24:  
      25: cvNamedWindow("Canny");
      26: cvShowImage("Canny",ImageGray2);
      27:  
      28: cvCanny(ImageGray,ImageGray2,100,150,3);
      29:  
      30: cvNamedWindow("Canny2");
      31: cvShowImage("Canny2",ImageGray2);
      32:  
      33: cvWaitKey();

    测试图像:

    5

    6

    sobel检测效果没有canny好,拉普拉斯产生了双边缘,canny不同的阈值得到的结果也有很大的差别。

  • 相关阅读:
    玩转 SpringBoot 2 快速整合 | FreeMarker篇
    微服务简单说
    玩转 SpringBoot 2 快速整合 | JSP 篇
    SpringBoot中获取微信用户信息从未如此简单!
    玩转 SpringBoot 2 快速整合 Filter
    oc语言的Foundation框架(学习笔记1)
    【PyInstaller安装及使用】将py程序转换成exe可执行程序
    【Django】Apache上运行单个Django项目,mod_wsgi配置
    【Django】基于Django架构网站代码的目录结构
    拖延症与自控力
  • 原文地址:https://www.cnblogs.com/zsb517/p/2554212.html
Copyright © 2020-2023  润新知