【OpenCV新手教程之十二】OpenCV边缘检测:Canny算子,Sobel算子,Laplace算子,Scharr滤波器合辑.pdf
《【OpenCV新手教程之十二】OpenCV边缘检测:Canny算子,Sobel算子,Laplace算子,Scharr滤波器合辑.pdf》由会员分享,可在线阅读,更多相关《【OpenCV新手教程之十二】OpenCV边缘检测:Canny算子,Sobel算子,Laplace算子,Scharr滤波器合辑.pdf(23页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、【OpenCV 新手教程之十二】OpenCV 边缘检測:Canny 算子,Sobel 算子,Laplace 算子,Scharr 滤波器合辑本系列文章由浅墨_毛星云 出品,转载请注明出处。文章链接:http:/ 版本号:2.4.9本篇文章中,我们将一起学习OpenCV 中边缘检測的各种算子和滤波器Canny 算子,Sobel 算子,Laplace 算子以及 Scharr 滤波器。文章中包括了五个浅墨为大家准备的具体凝视的博文配套源码。在介绍四块知识点的时候分别一个,以及最后的综合演示样例中的一个。文章末尾提供配套源码的下载。依旧是是放出一些程序执行截图吧:效果图看完,我们来唠唠嗑。首先,须要说明
2、的是,浅墨这篇文章最后的演示样例代码是採用两周前刚刚公布的 2.4.9 来书写的。里面的lib 都已经改成了 2.4.9 版本号的。假设大家须要执行的话,要么配置好 2.4.9.要么把浅墨在 project 中包括的末尾数字为 249 的各种 lib 改成之前的 248 或者你相应的 OpenCV 版本号。不然会提示:LINK:fatal error LNK1181:无法打开输入文件“opencv_calib3d248.lib”之类的错误。OpenCV 2.4.9 的配置和之前的 2.4.8 差点儿相同,假设还是不太清楚,具体能够參考浅墨改动过的相应 2.4.9 版的配置文章:【OpenCV
3、新手教程之中的一个】安装 OpenCV:OpenCV2.4.8 或 2.4.9+VS 开发环境配置第二,给大家分享一个OpenCV 中写代码时节约时间的小常识。事实上 OpenCV 中,不用 namedWindow,直接 imshow 就能够显示出窗体。大家看下文的演示样例代码就能够发现,浅墨在写代码的时候并没实用 namedWindow,遇到想显示出来的 Mat 变量直接imshow。我们通常是为了规范,才先用 namedWindow 创建窗体,再 imshow 出它来,由于我们还有须要用到指定窗体名称的地方,比方用到 trackbar 的时候。而普通情况想显示一个 Mat 变量的图片的话,
4、直接 imshow 就能够啦。OK,開始正文吧一、关于边缘检測在具体介绍之前,先来一起看看边缘检測的一般步骤吧。(?此处强度应指图像亮度强)1)滤波:边缘检測的算法主要是基于图像强度的一阶和二阶导数,但导数通常对噪声非常敏感,因此必须採用滤波器来改善与噪声有关的边缘检測器的性能。常见的滤波方法主要有高斯滤波,即採用离散化的高斯函数产生一组归一化的高斯核(具体见“高斯滤波原理及其编程离散化实现方法”一文),然后基于高斯核函数对图像灰度矩阵的每一点进行加权求和(具体程序实现见下文)。2)增强:增强边缘的基础是确定图像各点邻域强度的变化值。增强算法能够将图像灰度点邻域强度值有显著变化的点凸显出来。在
5、具体编程实现时,可通过计算梯度幅值来确定。3)检測:经过增强的图像,往往邻域中有非常多点的梯度值比較大,而在特定的应用中,这些点并非我们要找的边缘点,所以应该採用某种方法来对这些点进行取舍。实际project中,经常使用的方法是通过阈值化方法来检測。另外,须要注意,下文中讲到的 Laplace 算子,sobel 算子和 Scharr算子都是带方向的,所以,演示样例中我们分别写了X方向,Y方向和终于合成的的效果图。OK,正餐開始,召唤 canny算子。:)二、canny 算子篇2.1 canny 算子相关理论与概念解说2.1.1 canny 算子简单介绍Canny 边缘检測算子是 John F.
6、Canny于 1986 年开发出来的一个多级边缘检測算法。更为重要的是 Canny 创立了边缘检測计算理论(Computational theory ofedge detection),解释了这项技术是怎样工作的。Canny 边缘检測算法以 Canny 的名字命名,被非常多人推崇为当今最优的边缘检測的算法。当中,Canny 的目标是找到一个最优的边缘检測算法,让我们看一下最优边缘检測的三个主要评价标准:1.低错误率:标识出尽可能多的实际边缘,同一时候尽可能的降低噪声产生的误报。2.高定位性:标识出的边缘要与图像中的实际边缘尽可能接近。3.最小响应:图像中的边缘仅仅能标识一次,而且可能存在的图像
7、噪声不应标识为边缘。为了满足这些要求 Canny 使用了变分法,这是一种寻找满足特定功能的函数的方法。最优检測使用四个指数函数项的和表示,可是它非常近似于高斯函数的一阶导数。2.1.2 Canny边缘检測的步骤1.消除噪声。普通情况下,使用高斯平滑滤波器卷积降噪。例如以下显示了一个 size=5 的高斯内核演示样例:2.计算梯度幅值和方向。此处,依照Sobel滤波器的步骤。.运用一对卷积阵列(分别作用于 x和 y 方向):.使用下列公式计算梯度幅值和方向:梯度方向近似到四个可能角度之中的一个(一般为 0,45,90,135)3.非极大值抑制。这一步排除非边缘像素,仅仅保留了一些细线条(候选边缘
8、)。4.滞后阈值。最后一步,Canny 使用了滞后阈值,滞后阈值须要两个阈值(高阈值和低阈值):.假设某一像素位置的幅值超过 高 阈值,该像素被保留为边缘像素。.假设某一像素位置的幅值小于低 阈值,该像素被排除。.假设某一像素位置的幅值在两个阈值之间,该像素仅仅在连接到一个高于 高 阈值的像素时被保留。tips:对于 Canny 函数的使用,推荐的高低阈值比在 2:1 到 3:1 之间。很多其它的细节,能够參考 canny 算子的 wikipedia:http:/en.wikipedia.org/wiki/Canny_edge_detectorcanny 边缘检測的原理讲述,课參看这篇博文:h
9、ttp:/ 算子的中文 wikipedia:http:/zh.wikipedia.org/wiki/Canny%E7%AE%97%E5%AD%902.2 OpenCV 中 Canny 函数具体解释Canny 函数利用 Canny 算法来进行图像的边缘检測。C+:voidCanny(InputArray image,OutputArray edges,double threshold1,double threshold2,int apertureSize=3,bool L2gradient=false)第一个參数,InputArray 类型的 image,输入图像,即源图像,填 Mat 类的对象
10、就可以,且需为单通道 8 位图像。第二个參数,OutputArray 类型的 edges,输出的边缘图,须要和源图片有一样的尺寸和类型。第三个參数,double 类型的 threshold1,第一个滞后性阈值。第四个參数,double类型的 threshold2,第二个滞后性阈值。第五个參数,int类型的 apertureSize,表示应用 Sobel 算子的孔径大小,其有默认值 3。第六个參数,bool 类型的 L2gradient,一个计算图像梯度幅值的标识,有默认值 false。须要注意的是,这个函数阈值 1 和阈值 2 两者的小者用于边缘连接,而大者用来控制强边缘的初始段,推荐的高低阈
11、值比在 2:1 到 3:1之间。调用演示样例:/加载原始图 Mat src=imread(1.jpg);/project 文件夹下应该有一张名为 1.jpg 的素材图 Canny(src,src,3,9,3);imshow(【效果图】Canny 边缘检測,src);如上三句,就有结果出来,非常好用。2.3调用 Canny 函数的实例代码OpenCV 中调用 Canny 函数的实例代码例如以下:/-【头文件包括部分】-/描写叙述:包括程序所依赖的头文件/-#include#include#include/-【命名空间声明部分】-/描写叙述:包括程序所使用的命名空间/-using namespac
12、ecv;/-【main()函数】-/描写叙述:控制台应用程序的入口函数,我们的程序从这里開始/-int main()/加载原始图 Mat src=imread(1.jpg);/project 文件夹下应该有一张名为 1.jpg 的素材图 Mat src1=src.clone();/显示原始图 imshow(【原始图】Canny 边缘检測,src);/-/一、最简单的 canny 使用方法,拿到原图后直接用。/-Canny(src,src,150,100,3);imshow(【效果图】Canny 边缘检測,src);/-/二、高阶的 canny 使用方法,转成灰度图,降噪,用canny,最后将得
13、到的边缘作为掩码,拷贝原图到效果图上,得到彩色的边缘图/-Mat dst,edge,gray;/【1】创建与 src 同类型和大小的矩阵(dst)dst.create(src1.size(),src1.type();/【2】将原图像转换为灰度图像 cvtColor(src1,gray,CV_BGR2GRAY);/【3】先用使用 3x3 内核来降噪 blur(gray,edge,Size(3,3);/【4】执行Canny算子Canny(edge,edge,3,9,3);/【5】将g_dstImage内的全部元素设置为 0 dst=Scalar:all(0);/【6】使用 Canny算子输出的边缘
14、图 g_cannyDetectedEdges 作为掩码,来将原图 g_srcImage 拷到目标图 g_dstImage 中 src1.copyTo(dst,edge);/【7】显示效果图 imshow(【效果图】Canny 边缘检測 2,dst);waitKey(0);return 0;执行效果图:三、sobel 算子篇3.1 sobel 算子相关理论与概念解说3.1.1 基本概念Sobel 算子是一个主要用作边缘检測的离散微分算子(discrete differentiation operator)。它 Sobel 算子结合了高斯平滑和微分求导,用来计算图像灰度函数的近似梯度。在图像的不论
15、什么一点使用此算子,将会产生相应的梯度矢量或是其法矢量。sobel 算子的 wikipedia:http:/zh.wikipedia.org/wiki/%E7%B4%A2%E8%B2%9D%E7%88%BE%E7%AE%97%E5%AD%90sobel 算子相关概念,还能够參看这篇博文:http:/ sobel 算子的计算过程我们假设被作用图像为 I.然后进行例如以下的操作:1.分别在 x 和 y 两个方向求导。.水平变化:将 I 与一个奇数大小的内核进行卷积。比方,当内核大小为 3 时,的计算结果为:.垂直变化:将:I 与一个奇数大小的内核进行卷积。比方,当内核大小为 3 时,的计算结果为:
16、2.在图像的每一点,结合以上两个结果求出近似梯度:另外有时,也可用以下更简单公式取代:3.2 OpenCV 中 Sobel 函数具体解释Sobel 函数使用扩展的 Sobel 算子,来计算一阶、二阶、三阶或混合图像差分。C+:void Sobel(InputArraysrc,/输入图 OutputArray dst,/输出图 int ddepth,/输出图像的深度 int dx,int dy,int ksize=3,double scale=1,doubledelta=0,int borderType=BORDER_DEFAULT);第一个參数,InputArray 类型的 src,为输入图像
17、,填 Mat 类型就可以。第二个參数,OutputArray 类型的 dst,即目标图像,函数的输出參数,须要和源图片有一样的尺寸和类型。第三个參数,int 类型的 ddepth,输出图像的深度,支持例如以下src.depth()和ddepth的组合:若src.depth()=CV_8U,取 ddepth=-1/CV_16S/CV_32F/CV_64F若 src.depth()=CV_16U/CV_16S,取 ddepth=-1/CV_32F/CV_64F若src.depth()=CV_32F,取 ddepth=-1/CV_32F/CV_64F若src.depth()=CV_64F,取 dde
18、pth=-1/CV_64F第四个參数,int 类型 dx,x 方向上的差分阶数。第五个參数,int类型 dy,y 方向上的差分阶数。第六个參数,int 类型ksize,有默认值 3,表示 Sobel 核的大小;必须取 1,3,5 或7。第七个參数,double 类型的 scale,计算导数值时可选的缩放因子,默认值是 1,表示默认情况下是没有应用缩放的。我们能够在文档中查阅 getDerivKernels 的相关介绍,来得到这个參数的很多其它信息。第八个參数,double类型的 delta,表示在结果存入目标图(第二个參数 dst)之前可选的 delta 值,有默认值 0。第九个參数,int
19、类型的 borderType,我们的老朋友了(万年是最后一个參数),边界模式,默认值为BORDER_DEFAULT。这个參数能够在官方文档中 borderInterpolate 处得到更具体的信息。普通情况下,都是用 ksize x ksize 内核来计算导数的。然而,有一种特殊情况当 ksize 为 1 时,往往会使用 3 x 1 或者 1 x 3的内核。且这种情况下,并没有进行高斯平滑操作。一些补充说明:1.当内核大小为 3 时,我们的 Sobel 内核可能产生比較明显的误差(毕竟,Sobel 算子仅仅是求取了导数的近似值而已)。为解决这一问题,OpenCV 提供了 Scharr函数,但该
20、函数仅作用于大小为 3 的内核。该函数的运算与Sobel 函数一样快,但结果却更加精确,其内核是这种:2.由于 Sobel 算子结合了高斯平滑和分化(differentiation),因此结果会具有很多其它的抗噪性。大多数情况下,我们使用sobel 函数时,取【xorder=1,yorder=0,ksize=3】来计算图像 X 方向的导数,【xorder=0,yorder=1,ksize=3】来计算图像 y 方向的导数。计算图像 X 方向的导数,取【xorder=1,yorder=0,ksize=3】情况相应的内核:而计算图像 Y 方向的导数,取【xorder=0,yorder=1,ksize
21、=3】相应的内核:3.3 调用 Sobel 函数的实例代码调用 Sobel 函数的实例代码例如以下。这里仅仅是教大家怎样使用 Sobel 函数,就没有先用一句cvtColor 将原图;转化为灰度图,而是直接用彩色图操作。/-【头文件包括部分】-/描写叙述:包括程序所依赖的头文件/-#include#include#include/-【命名空间声明部分】-/描写叙述:包括程序所使用的命名空间/-using namespacecv;/-【main()函数】-/描写叙述:控制台应用程序的入口函数,我们的程序从这里開始/-int main()/【0】创建 grad_x 和 grad_y 矩阵 Mat
22、grad_x,grad_y;Mat abs_grad_x,abs_grad_y,dst;/【1】加载原始图 Mat src=imread(1.jpg);/project 文件夹下应该有一张名为 1.jpg 的素材图/【2】显示原始图 imshow(【原始图】sobel 边缘检測,src);/【3】求 X 方向梯度 Sobel(src,grad_x,CV_16S,1,0,3,1,1,BORDER_DEFAULT);convertScaleAbs(grad_x,abs_grad_x);imshow(【效果图】X 方向 Sobel,abs_grad_x);/【4】求 Y 方向梯度 Sobel(src
23、,grad_y,CV_16S,0,1,3,1,1,BORDER_DEFAULT);convertScaleAbs(grad_y,abs_grad_y);imshow(【效果图】Y 方向 Sobel,abs_grad_y);/【5】合并梯度(近似)addWeighted(abs_grad_x,0.5,abs_grad_y,0.5,0,dst);imshow(【效果图】总体方向 Sobel,dst);waitKey(0);return 0;执行截图例如以下:四、Laplace 算子篇4.1 Laplace 算子相关理论与概念解说Laplacian 算子是 n 维欧几里德空间中的一个二阶微分算子,定
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- OpenCV新手教程之十二 OpenCV 新手 教程 十二 边缘 检测 Canny 算子 Sobel Laplace Scharr 滤波器
链接地址:https://www.taowenge.com/p-60814490.html
限制150内