c#用canny算子做边缘提取_干货 | 边缘检测

   最近小可爱们有没有等我们的技术推等到望穿秋水啊?大家日思夜想的技术推来啦。今天我们来一起学习一下opencv里面一个重要方面:边缘检测。

01.什么是边缘检测

     边缘检测是图像处理计算机视觉中的基本问题,边缘检测的目的是标识数字图像中亮度变化明显的点。图像属性中的显著变化通常反映了属性的重要事件和变化。

       这些包括:

(i)深度上的不连续

(ii)表面方向不连续

(iii)物质属性变化

(iv)场景照明变化 

  边缘检测是图像处理和计算机视觉中,尤其是特征提取中的一个研究领域。图像边缘检测大幅度地减少了数据量,并且剔除了可以认为不相关的信息,保留了图像重要的结构属性。

02.边缘检测的步骤

   它的步骤简单来说可以分成三种:

(1)滤波边缘检测的 算法 主要是基于图像强度的一阶和二阶导数,但导数通常对噪声很敏感,因此必须采用滤波器来改善与噪声有关的边缘检测的性能。常见的滤波方法主要有 高斯滤波,即采用离散化的高斯函数产生一组归一化的高斯核(具体见“高斯滤波原理及其编程离散化实现方法”一文),然后基于高斯核函数对图像灰度矩阵的每一点进行加权和(具体程序见下文)

 (2)增强 :增强边缘 的基础是确定图像各点邻域强度的变化值。增强算法可以将图像灰度点邻域强度值有显著变化的点凸显出来。在具体编程实现时,可通过计算梯度幅值来确定。

(3)检测: 经过增强的图像,往往邻域中有很多点的梯度值比较大,而在特定的应用中,这些点并不是我们想要的找的边缘点,所以应该采用某种方法来对这些点进行取舍。在实际工程中,常用的方法是 通过阈值化方法来检测。

03.Canny算子

    Canny算子在opencv中是最常用来进行边缘检测的,接下来我们就简要介绍一下它。

     Canny边缘检测算子是John F.Canny于 1986 年开发出来的一个多级边缘检测算法。更为重要的是 Canny 创立了边缘检测计算理论,解释了这项技术是如何工作的。Canny边缘检测算法以Canny的名字命名,被很多人推崇为当今最优的边缘检测的算法。

    其中,Canny 的目标是找到一个最优的边缘检测算法,最优边缘检测的三个主要评价标准是:

  1 低错误率:标识出尽可能多的实际边缘,同时尽可能的减少噪声产生的误报

  2 高定位性:标识出的边缘要与图像中的实际边缘尽可能接近

  3 最小响应:图像中的边缘只能标识一次,并且可能存在的图像噪声不应标识为边缘

04.如何利用Canny算子进行检测

利用Canny算法进行图像的边缘检测:

1 void Canny (InputArray image,OutputArray edges , double threshold1,

2 Threshold2 ,int apertureSize = 3,bool  L2gradient = false);

注解:

·第一个参数,InputArray类型的image,输入图像,即源图像,填Mat类的对象即可,且需为单通道8位图像.

·第二个参数,OutputArray类型edges,输出的边缘图,需要和源图片有一样的尺寸和类型.

·第三个参数,double类型threshold1,第一个滞后性阈值.

·第四个参数,double类理的threshold2,第二个滞后性阀值.

·第五个参数,int类型的apertureSize,表示应用Sobel算子的孔径大小,其有默认值3.

·第六个参数,bool类型的L2gradient,一个计算图像梯度幅值的标识,有默认值false.

 (需要注意的是,这个函数阈值1和阈值2两者的小者用于边缘连接,而大者用来控制强边缘的初始段,推荐的高低阈值比在2:1到3:1之间)

05.函数实例

使用示例:

1 // 输入原始图

2  Mat src = inread (“1.jpg”)

3 Canny ( src , src , 3,9,3);

4 inshow  (“[效果图]边缘检测”,src);

如上三句,就有结果出来,非常好用。

▲向上滑动

函数示例:

#include

#include

#include

#include

#include

 using namespace std;

using namespace cv;

 /*------------------------------

          【1】Canny算子

---------------------------------*/

int main()

{

    //载入原始图

    Mat src = imread("1.jpg");

    Mat src1 = src.clone();

    //Mat src2 = src.clone();

   //显示原始图

    imshow("【原始图】Canny边缘检测", src);

   /*----------------------------

 // (1) 最简单的canny用法,拿到原图后直接用

    -----------------------------------*/

    Canny(src,src,150,100,3);

    imshow("【效果图】Canny边缘检测", src);

   /*---------------------------------------

   //(2)高阶的canny用法,转成灰度图,降噪,   用Canny,   最后得到的边缘作为掩码,拷贝原 图到效果图上,得到 彩色的边缘图

    ----------------------------------*/

    Mat dst, edge, gray;

    //(1)创建与src 同类型和大小的矩阵

    dst.create(src1.size(),src1.type());

   //(2)将原图转换为灰度图像

  cvtColor(src1,gray,CV_BGR2GRAY);

  //(3)使用3*3内核来降噪

    blur(gray,edge,Size(3,3));

  //(4)运行Canny算子

    Canny(edge,edge,3,9,3);

  //(5)将g_dstImage内的元素设为0

    dst = Scalar::all(0);

  //(6)使用Canny算子输出的边源:

g_canny DetectEdges作为掩码,将g_srcImage拷到目标图g_dstImage中,

src1.copyTo(dst,edge);

 //(7)显示效果图

   imshow("【效果图】Canny边缘检测2", dst);

     waitKey();

    return 0;

}

示例图如下

原图是这样的

fbe379dd5e81603250bb0d0efd87c114.png

检测完后的效果图。

a3bf668c3bb91d55774d9df7a0cee32e.png

     可以看出这个算法非常细腻地把图里面的轮廓都给找出来了。

     不过,有时候过于细腻也不好,这时候就需要调整参数或者采用其他算法,比如sobel算法和拉普拉斯算法。嘻嘻,这些就等下次再来介绍咯。

aad7291e05209ce95b42948d714f42f5.png

文案/ 谢函瀚

排版/胡文博

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值