Canny边缘检测与轮廓提取_第1页
Canny边缘检测与轮廓提取_第2页
Canny边缘检测与轮廓提取_第3页
Canny边缘检测与轮廓提取_第4页
Canny边缘检测与轮廓提取_第5页
已阅读5页,还剩20页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、目录摘要IAbstractII1 绪论12 设计内容与OpenCV简介22.1 设计任务内容22.2 OpenCV简介23 理论分析33.1 边缘检测33.1.1 图像的边缘33.1.2 边缘检测的基本步骤33.2 轮廓提取44 边缘检测的算法比较54.1 Reborts算子54.2 Sobel算子54.3 Prewitt 算子64.4 Kirsch 算子74.5 LOG算子74.6 Canny算子85 实验仿真105.1算法设计105.2 实验结果116 分析与总结12参考文献13附录14摘要边缘检测是图像处理和计算机视觉中的基本问题,它的目的是标识出数字图像中亮度变化明显的点。图像经过边沿

2、检测处理之后,不仅大幅度地减少了数据量,并且剔除了可以认为不相关的信息,保留了图像重要的结构属性。事实上,边缘存在于图像的不规则结构和不平稳现象中,也即存在于信号的突变点处,这些点给出了图像轮廓的位置。这些轮廓常常是我们在图像边缘检测时,所需要的非常重要的一些特征条件,这就需要我们对一幅图像检测并提取出它的边缘。可用于图像边缘检测和轮廓提取的方法有很多,其中包括有常见的Robert 边缘算子、Prewitt 边缘算子、Sobel 边缘算子等等。本文首先将会从数字图像处理的角度,对几种边缘检测算法进行详细的分析,然后会并选择其中一种边缘检测算法进行实验。考虑到以后进一步的学习,本文将会使用ope

3、nCV对算法进行实现。最后,本文将会把实验获得的实际效果,与理论分析的结果进行比对,并以此对本次实验进行总结。关键字:边缘检测 轮廓提取 图像处理 openCVAbstractEdge detection is the basic problem in image processing and computer vision, its purpose is to identify the digital image brightness changes in the obvious points.Image after edge detection processing, not only g

4、reatly reduces the amount of data, and eliminated can think irrelevant information, keep the structure of the image important attribute.Edge of image, in fact, exist in the image of the irregular structure and unstable phenomenon, which exists in the abrupt change point of the signal, the point the

5、location of the image contour is presented.These contours are often in image edge detection, we need some important characteristics of the condition, this needs us to the edge of an image detection and extract it.There are so many method can be used in image edge detection and contour extraction, in

6、cluding common Robert edge operator, Prewitt edge operator, Sobel edge operator and so on.At first, this paper will, from the perspective of digital image processing and analysis of several kinds of edge detection algorithms in detail, and then select one of the edge detection algorithm for experime

7、nts.After considering the further study, this paper implemented the algorithm will use openCV.Finally, this article will obtain the actual effect of the experiment, and compares the results of theoretical analysis, and then to summarize this experiment.Keywords: Edge detection Contour extraction Ima

8、ge processing openCV1 绪论数字图像处理技术的迅猛发展,其应用前景得到了不可限量的扩展,如今各行各业都在积极发展与图像相关的技术。其应用逐渐凸显其魅力,其应用如医学影像、航天航空、无人驾驶、自动导航、工业控制、导弹制导、文化艺术等。边缘检测在图像处理和计算机视觉等领域骑着重要的作用,是图像分析、模式识别、目标检测与分割等的前期处理。前期边缘检测的好坏,直接影响后期更高级处理的精度。自从1986年John Canny提出了最优边缘检测算子的三条准则并推导出了一个近似实现。但是在实际中,真正实现这一目标尚有较大的难度。这是因为:(1)实际图像一般都含有噪声,并且噪声的分布信息业

9、是未知的,同时噪声和边缘都属于高频信息,在进行滤波的同时,虽然能够在一定程度上抑制噪声,却也丢失了边缘信息。(2)由于场景、光照条件的边缘等原因,同一场景在不同光照条件下得到的边缘可能也是不同的,设置的阈值也可能是不同的。针对这些问题,如何进行改进,并得到较理想的边缘检测算子是有必要的。另一方面,轮廓提取技术是图像分割、目标区域识别区域行状提取等图像分析处理领域十分重要的基础。寻求非接触、精度高、具有综合分析能力的识别方法来代替人工目测,解决图像表面的模式识别和测量问题,是图像加工行业面临的一大难题,也是值得我们长期探讨的科研课题。2 设计内容与OpenCV简介2.1 设计任务内容针对一幅图像

10、,利用边缘检测算子(如Robert算子、Sobel算子、Prewitt算子、Laplace算子、Kirsch算子和Marr算子)检测出图像的边缘,然后采取轮廓提取算法得到封闭的二值图像轮廓。2.2 OpenCV简介OpenCV的全称是:Open Source Computer Vision Library,是一个基于开源发行的跨平台计算机视觉库,可以运行在Linux、Windows和Mac OS操作系统上。它轻量级而且高效由一系列 C 函数和少量 C+ 类构成,同时提供了Python、Ruby、MATLAB等语言的接口,实现了图像处理和计算机视觉方面的很多通用算法。相对于matlab而言,Op

11、enCV操作起来较为复杂,需要一定C+编程基础,对没有语言基础的初学者而言较为困难。但是OpenCV有很多不容忽视的优点:(1) 具有更强大的数字图像处理能力;(2) 具有良好的可移植性;(3) 由于是一个C+的类库,因此在实际中运用更加广泛。考虑到上述因素,此次试验将选择OpenCV作为开发工具。3 理论分析3.1 边缘检测3.1.1 图像的边缘在数字图像中,边缘是指图像局部变化最显著的部分,边缘主要存在于目标与目标,目标与背景之间,是图像局部特性的不连续性,如灰度的突变、纹理结构的图标、颜色的图标等。尽管图像的边缘点产生的原因各不相同,但他们都是图形上灰度不连续或灰度几句辩护的点,图像边缘

12、分为阶跃状、斜坡状和屋顶状。从成因上看,一般图像边缘主要由四个方面的因素形成:(1)图像灰度在表面法向变化的不连续造成的边缘;(2)图像对像素在空间上不一致形成的边缘;(3)在光滑的表面上由于颜色的不一致形成的边缘;(4)物体的光影造成的边缘。图像边缘提取的作用有:(1)改良图像质量;(2)分离对象;(3)理解和重构视觉场景;(4)识别特征。3.1.2 边缘检测的基本步骤(1)滤波:边缘检测主要基于导数计算,会受到噪声的影响,可以通过设计滤波器来降低噪声,但滤波器在降低噪声的同时也会导致边缘精度的损失。(2)增强:增强算法将邻域中灰度有显著变化的点突出显示。一般通过计算梯度幅值来完成。(3)检

13、测:在有些图像中梯度幅值较大的并不是边缘点。最简单的边缘检测是梯度幅值阈值判定。(4)定位:精确确定边缘的位置。3.2 轮廓提取图像的轮廓作为图像的一种基本特征,经常被应用到较高层次的图像应用中去。它在图像识别,图像分割,图像增强以及图像压缩等的领域有广泛应用,也是图像处理的基础。图像的轮廓往往携带着一幅图像的大部分信息。而轮廓即在于图像的不规则结构和不稳定上,也存在于信号的突变点处,这些点给出了图像轮廓的位置,这些轮廓常常是我们在图像边缘检测时所需的非常重要的特征条件,因而这就需要我们对一幅图像检测并提取出它的轮廓。经典的轮廓提取技术大都基于微分运算。首先通过平滑来滤除图像中的噪声,然后进行

14、一阶微分或二阶微分运算,求得梯度最大值或二阶导数的过零点,最后选取适当的阈值来提取边界。本次课设所用的轮廓提取算法非常简单,就是掏空内部点:如果原图中有一点为黑,且它的8个相邻点都是黑色时(此时该点是内部点),则将该点删除。要注意的是,我们处理的虽然是二值图,但实际上是256级灰度图,不过只用到了0和255两种颜色。4 边缘检测的算法比较特征提取作为图像边缘检测的一个重要内容,发展了众多的方法。这些方法经过实践的检验,成为了经典的内容。经典的边缘检测算子包括:Roberts算子、Prewitt算子、Sobel算子、Log算子、Canny算子等,这些经典的边缘提取算子在使用时都是使用预定义的边缘

15、模型去匹配。4.1 Reborts算子Reboerts算子是一种利用局部差分来寻找边缘的算子,Roberts 梯度算子所采用的是对角方向相邻两像素值之差,算子形式如下:Roberts梯度算子对应的卷积模版为: 用以上两个卷积算子与图像运算后,可求出图像的梯度幅值 G ( x,y),然后选择适当的阈值 ,若 G ( x,y),则 (i ,j)为边缘点,否则,判断 (i ,j)为非边缘点。由此得到一个二值图像 g (i,j),即边缘图像。Roberts 算子采用的是用对角线方向上相邻两像素的差近似梯度幅值来检测边缘,它的定位精度高,对于水平和垂直方向的边缘,检测效果较好,而对于有一定倾角的斜边缘,

16、检测效果则不理想,存在着许多的漏检。另外,在含噪声的情况下,Roberts 算子不能有效的抑制噪声,容易产生一些伪边缘。因此,该算子适合于对低噪声且具有陡峭边缘的图像提取边缘。4.2 Sobel算子Sobel算子在边缘检测算子扩大了其模版,在边缘检测的同时尽量削弱了噪声。其模版大小为33,其将方向差分运算与局部加权平均相结合来提取边缘。在求取图像梯度之前,先进行加权平均,然后进行未分,加强了对噪声的一致。Sobel算子所对应的卷积模版为:图像中的每个像素点和以上水平和垂直两个卷积算子做卷积运算后,再计算得到梯度幅值 G ( x,y),然后选取适当的阈值 ,若 G ( x,y),则 (i ,j)

17、为边缘点,否则,判断 (i ,j)为非边缘点。由此得到一个二值图像 g (i,j),即边缘图像。Sobel 算子在空间上比较容易实现,不但产生较好的边缘检测效果,同时,由于其引入了局部平均,使其受噪声的影响也较小。若使用较大的邻域,抗噪性会更好,但也增加了计算量,并且得到的边缘比较粗。在对精度要求不是很高的场合下,Sobel 算子是一种较为常用的边缘检测算法。4.3 Prewitt 算子同 Sobel 算子相似,Prewitt 算子也是一种将方向的差分运算和局部平均相结合的方法,也是取水平和垂直两个卷积核来分别对图像中各个像素点做卷积运算,所不同的是,Sobel 算子是先做加权平均然后再微分,

18、Prewitt 算子是先平均后求微分,其对应的卷积模版为: (2.3.8)图像中的每个像素点和以上水平和垂直两个卷积算子做卷积运算后,再计算得到梯度幅值 G ( x,y),然后选取适当的阈值 ,若 G ( x,y),则 (i,j)为边缘点,否则,判断 (i,j)为非边缘点。由此得到一个二值图像 g (i,j),即边缘图像。在此基础上,有人提出了改进的Prewitt算子,将其扩展到八个方向,依次用这些边缘模板去检测图像,与被检测区域最为相似的样板给出最大值。用这个最大值作为算子的输出值 P i ,j,这样就可将边缘像素检测出来。Prewitt 算子通过对图像上的每个像素点的八方向邻域的灰度加权差

19、之和来进行检测边缘,对噪声有一定抑制作用,抗噪性较好,但由于采用了局部灰度平均,因此容易检测出伪边缘,并且边缘定位精度较低。4.4 Kirsch 算子Kirsch 算子是一种 33 的非线性方向算子。其基本思想是希望改进取平均值的过程,从而尽量使边缘两侧的像素各自与自己同类的像素取平均值,然后再求平均值之差,来减小由于取平均值所造成的边缘细节丢失。通常采用八方向 Kirsch 模板的方法进行检测,取其中最大的值作为边缘强度,而将与之对应的方向作为边缘方向。常用的八方向 Kirsch 模板如下所示: 实际的应用中,通常都是利用简单的卷积核来计算方向差分的,不同的算子对应着不同的卷积核。它们在图像

20、的像素点上所产生的两个方向的偏导数用均方值或者绝对值求和的形式来近似代替梯度幅值,然后选取一个合适的阈值,用所得到的梯度幅值和所设定的阈值进行比较来判断边缘点。若大于所取的阈值,则判断为边缘点;否则,判断为非边缘点。很显然,在提取边缘的过程中,阈值的选取特别重要,尤其在含噪图像中,阈值的选择要折衷考虑噪声造成的伪边缘和有效边缘的丢失。4.5 LOG算子LOG算子基本思想是:先在一定的范围内做平滑滤波,然后再利用差分算子来检测在相应尺度上的边缘。滤波器的选择要考虑以下两个因素:其一是滤波器在空间上要求平稳,即要求空间位置误差 x要小;其二是平滑滤波器本身要求是带通滤波器,并且在有限的带通内是平稳

21、的,即要求频域误差 要小。根据信号处理中的测不准原理, x 和 是相互矛盾的,而达到测不准下限的滤波器就是高斯滤波器。Marr 和 Hildreth 提出的这种差分算子是各向同性的拉普拉斯二阶差分算子。该边缘检测器的基本特征是:(1) 所用的平滑滤波器是高斯滤波器(2) 增强步骤采用的是二阶导数(即二维拉普拉斯函数)(3) 边缘检测的判据是二阶导数过零点并且对应一阶导数的极大值该方法的特点是先用高斯滤波器与图像进行卷积,既平滑了图像又降低了噪声,使孤立的噪声点和较小的结构组织被滤除。然而由于对图像的平滑会导致边缘的延展,因此只考虑那些具有局部梯度极大值的点作为边缘点,这可以用二阶导数的零交叉来

22、实现。拉普拉斯函数可用作二维二阶导数的近似,因为它是一种标量算子。为了避免检测出非显著的边缘,所以应该选择一阶导数大于某一阈值的零交叉点来作为边缘点。实际应用中,常用的LOG算子的模版为:这说明, 高斯平滑运算不但可以滤除噪声,还会导致图像中的边缘和其它尖锐不连续部分模糊,而模糊程度取决于空间尺度因子 的大小。 越大,高斯滤波对噪声的滤除效果越好,但同时也会丢失重要的边缘信息,影响到边缘检测器的性能。如果 较小,又可能导致平滑作用不完全而留有较多的噪声。因此在实际应用中,要根据情况选择适当的。4.6 Canny算子1986年,Canny从边缘检测算子应该满足的三个准则出发,推导出了最优边缘检测

23、算子Canny算子,该算子是目前理论上相对最完善的一种边缘检测算法。Canny提出的评价边缘检测性能优劣的三个准则分别是:(1)好的信噪比准则。即将非边缘点判为边缘点的概率要低,将边缘点判为非边缘点的概率要低;(2)好的定位性能准则。即检测出的边缘点要尽可能在实际边缘的中心;(3)单边缘响应准则。即单一边缘具有唯一响应,单一边缘产生的多个响应的概率要低,并且对虚假边缘的响应应得到最大抑制。利用Canny算子检测边缘的算法如下:(1)用式所示的高斯函数h(r)对图像进行平滑滤波,去除图像中的噪声。(2)在每一点计算出局部梯度和边缘方向,可以利用Sobel算子、Roberts算子等来计算。边缘点定

24、义为梯度方向上其强度局部最大的点。(3)对梯度进行“非极大值抑制”。(4)双阐值化和边缘连接。5 实验仿真5.1算法设计通过以上各种边缘检测算法之间的比较可知,Canny算子使用两个阈值检测强信号和弱信号边缘,如果它们被连接到边缘,那么输出只包含弱边缘。因此,此方法更适合用于检测真实得弱边缘,本次实验决定采用Canny算子,算法具体步骤如下:(1) 求图像与高斯平滑滤波器卷积:(2) 使用一阶有限差分计算偏导数的两个阵列P与Q:(3) 幅值和方位角:(4) 非极大值抑制(NMS ) :细化幅值图像中的屋脊带,即只保留幅值局部变化最大的点。将梯度角的变化范围减小到圆周的四个扇区之一,方向角和幅值

25、分别为:非极大值抑制通过抑制梯度线上所有非屋脊峰值的幅值来细化Mi,j,中的梯度幅值屋脊这一算法首先将梯度角i,j的变化范围减小到圆周的四个扇区之一,如图5-1所示: 图5-1 圆周四个扇脚5.2 实验结果通过算法的设计,得到的图像如图5-2、图5-3和图5-4所示。其中图5-2为原图,图5-3为边缘检测后得到的图像,图5-4为对图5-3进行轮廓提取所得的图像。 图5-2 原图像图5-3 边缘检测 图5-4 轮廓提取6 分析与总结由实验结果可知,Canny算子采用高斯函数对图像作平滑处理,因此具有较强的抑制噪声能力,同样该算子也会将一些高频边缘平滑掉,造成边缘丢失。Canny算子也存在不足之处

26、,一是为了得到较好的边缘检测结果,它通常需要使用较大的滤波尺度,这样容易丢失一些细节;二是Canny算子的双阈值要人为的选取,不能够自适应。通过此次课设让我对OpenCV有了一定的理解,尽管许多内部函数还不知道,程序设计也只是一知半解,但对以后的学习有了较好的指引。不仅在知识学习上有较多的收获,在学习态度和方法上也起到了端正和提高作用,为了寻求知识的那份执著。这次课程设计给我们提供了一个应用自己所学知识的机会,从到图书馆查找资料到对程序的设计和仿真,都对我们所学的知识进行了检验。让我明白了设计系统程序的一些基本思想 。总体来说,这次课程设计让我受益匪浅。在摸索该如何设计程序使之实现所需功能的过

27、程中,虽然很困难,但也很有趣,培养了我的设计思维,锻炼了操作能力。在让我体会到了设计的艰辛的同时,更让我体会到成功的喜悦和快乐。参考文献1 Canny. A Computational Approach to Edge Detection, IEEE Trans. on Pattern Analysis and Machine Intelligence, 8(6), pp. 679-698 (1986).2 刘泉编.通信电子线路.武汉理工出版社.2007年3 樊昌信等编.通信原理.国防工业出版社.2007年4 数字信号处理.科学出版社.2007年5 于仕琪等编.OpenCV教程(基础篇).20

28、06年 附录关键代码如下:void Canny( InputArray _src, OutputArray _dst, double low_thresh, double high_thresh, int aperture_size, bool L2gradient ) Mat src = _src.getMat(); CV_Assert( src.depth() = CV_8U ); _dst.create(src.size(), CV_8U); Mat dst = _dst.getMat(); if (!L2gradient & (aperture_size & CV_CANNY_L2_G

29、RADIENT) = CV_CANNY_L2_GRADIENT) /backward compatibility if (aperture_size & 1) = 0 | (aperture_size != -1 & (aperture_size 7) CV_Error(CV_StsBadFlag, ); const int cn = src.channels(); cv:Mat dx(src.rows, src.cols, CV_16SC(cn); cv:Mat dy(src.rows, src.cols, CV_16SC(cn); cv:Sobel(src, dx, CV_16S, 1,

30、0, aperture_size, 1, 0, cv:BORDER_REPLICATE); cv:Sobel(src, dy, CV_16S, 0, 1, aperture_size, 1, 0, cv:BORDER_REPLICATE); if (low_thresh high_thresh) std:swap(low_thresh, high_thresh); if (L2gradient) low_thresh = std:min(32767.0, low_thresh); high_thresh = std:min(32767.0, high_thresh); if (low_thre

31、sh 0) low_thresh *= low_thresh; if (high_thresh 0) high_thresh *= high_thresh; int low = cvFloor(low_thresh); int high = cvFloor(high_thresh); int* mag_buf3; mag_buf0 = (int*)(uchar*)buffer; mag_buf1 = mag_buf0 + mapstep*cn; mag_buf2 = mag_buf1 + mapstep*cn; memset(mag_buf0, 0, /* cn* */mapstep*size

32、of(int); uchar* map = (uchar*)(mag_buf2 + mapstep*cn); memset(map, 1, mapstep); memset(map + mapstep*(src.rows + 1), 1, mapstep); int maxsize = std:max(1 10, src.cols * src.rows / 10); std:vector stack(maxsize); uchar *stack_top = &stack0; uchar *stack_bottom = &stack0; #define CANNY_PUSH(d) *(d) =

33、uchar(2), *stack_top+ = (d) #define CANNY_POP(d) (d) = *-stack_top / calculate magnitude and angle of gradient, perform non-maxima supression. / fill the map with one of the following values: / 0 - the pixel might belong to an edge / 1 - the pixel can not belong to an edge / 2 - the pixel does belon

34、g to an edge for (int i = 0; i 0) + 1 + 1; if (i src.rows) short* _dx = dx.ptr(i); short* _dy = dy.ptr(i); if (!L2gradient) for (int j = 0; j src.cols*cn; j+) _normj = std:abs(int(_dxj) + std:abs(int(_dyj); else for (int j = 0; j 1) for(int j = 0, jn = 0; j src.cols; +j, jn += cn) int maxIdx = jn; f

35、or(int k = 1; k _normmaxIdx) maxIdx = jn + k; _normj = _normmaxIdx; _dxj = _dxmaxIdx; _dyj = _dymaxIdx; _norm-1 = _normsrc.cols = 0; else memset(_norm-1, 0, /* cn* */mapstep*sizeof(int); / at the very beginning we do not have a complete ring / buffer of 3 magnitude rows for non-maxima suppression if

36、 (i = 0) continue; uchar* _map = map + mapstep*i + 1; _map-1 = _mapsrc.cols = 1; int* _mag = mag_buf1 + 1; / take the central row ptrdiff_t magstep1 = mag_buf2 - mag_buf1; ptrdiff_t magstep2 = mag_buf0 - mag_buf1; const short* _x = dx.ptr(i-1); const short* _y = dy.ptr(i-1); if (stack_top - stack_bo

37、ttom) + src.cols maxsize) int sz = (int)(stack_top - stack_bottom); maxsize = maxsize * 3/2; stack.resize(maxsize); stack_bottom = &stack0; stack_top = stack_bottom + sz; int prev_flag = 0; for (int j = 0; j src.cols; j+) #define CANNY_SHIFT 15 const int TG22 = (int)(0.*(1 low) int xs = _xj; int ys

38、= _yj; int x = std:abs(xs); int y = std:abs(ys) CANNY_SHIFT; int tg22x = x * TG22; if (y _magj-1 & m = _magj+1) goto _ocv_canny_push; else int tg67x = tg22x + (x tg67x) if (m _magj+magstep2 & m = _magj+magstep1) goto _ocv_canny_push; else int s = (xs ys) _magj+magstep2-s & m _magj+magstep1+s) goto _

39、ocv_canny_push; prev_flag = 0; _mapj = uchar(1); continue;_ocv_canny_push: if (!prev_flag & m high & _mapj-mapstep != 2) CANNY_PUSH(_map + j); prev_flag = 1; else _mapj = 0; / scroll the ring buffer _mag = mag_buf0; mag_buf0 = mag_buf1; mag_buf1 = mag_buf2; mag_buf2 = _mag; / now track the edges (hysteresis thresholding) while (stack_top stack_bottom) uchar* m; if (stack_top - stack_bottom) + 8 maxsize) int sz = (int)(stack_top - stack_bottom); maxsize = maxsize * 3/2; stack.resize(maxsize); stack_bottom = &stack0; stack_top = stack_bottom + sz; CANNY_POP(m); if (!m-1) CANNY

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论