图像边缘检测基于最小二乘法的椭圆边缘检测matlab源码
Posted MatlabQQ1575304183
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了图像边缘检测基于最小二乘法的椭圆边缘检测matlab源码相关的知识,希望对你有一定的参考价值。
经典椭圆检测方法
椭圆检测算法经过多年的研究发展,已经基本形成一个较完整的体系。它们大致可以分为三类即投票(聚类)、最优化、基于弧段的方法。
投票(聚类)方法
椭圆因为有中心位置坐标、长短轴长度、倾斜角五个参数,标准霍夫变换有较强的鲁棒性,但对内存要求高,运算效率低,不太现实。霍夫变换类算法以霍夫变换为算法基础,经过不同国家研究人员多年的不懈努力研究,如今已衍生出很多改进算法,它们各有优劣。随机霍夫变换算法相对标准霍夫变换计算速度有较大提升,但检测相互遮挡的椭圆时准确度低。
随机hough变换椭圆检测算法
随机椭圆检测结合使用了了最小二乘法和Hough变换算法。第一步预处理,获得较理想的边缘图。第二步随机选取三个点,取这三点为中心相同大小的邻域中所有点,用最小二乘法把它们拟合成一个椭圆。如图2-3所示。第三步从边缘点中再随机选取第四个点,判断此点是否在拟合出的圆上。若是,则认为该椭圆是真实椭圆的可能性较大,接着收集证据,验证该椭圆的真实性。
算法具体过程如下(从第二步开始):
1.把边缘检测得到的点收进集合V中,失败计数器f初始值设为0。设定5个阈值,分别是能容忍的失败次数最大值Tf,检测进行时对V中边缘点数量的要求阈值Tem,随机选取的三点之间两两距离最小值Ta,随机选取的第四点到可能椭圆边界距离的最大值Td,以及椭圆残缺比率阈值Tr。
2.np表示集合V中剩余的点的数量,当np小于Tem时或当失败次数f大于Tf时停止检测,算法终止;否则从V中随机取四点,并从V中删除这四点。
3.若用来求解椭圆参数的三个点两两之间距离都大于Ta,拟合出椭圆,计算第四个点到该椭圆边界的距离,若距离小于Td,执行第4步;若不满足两者之一,将这四个点返回到V中,失败次数加一,回到第2步执行。
4.设E为第3步拟合出来的椭圆,初始化满足阈值Td的点的个数num。遍历V中点,计算并判断它们到椭圆E的边界的距离是否小于Td,若是则num=num+1,并将该点从V中除去,直到遍历完成。
5.若num>=Tr*K,其中K为椭圆E的周长,那么跳转到第6步;否则认为椭圆E不是真实的椭圆,将第4步和第2步中删除的num+4个点返回V中,并跳转到第2步。
6.认为椭圆E是一个真实存在的椭圆,f置0,并跳转到第2步。
随机hough变换的优缺点如下:
第一,由于该算法是基于最小二乘法,所以一方面检测结果往往比真实椭圆小而且对噪声敏感,但是另一方面当预处理效果较好时检测精度很高。
第二,由于该算法基于随机采样,所以一方面可能会有所选点距离较近的情况造成拟合出的椭圆偏差较大,但是另一方面因为随机采样的灵活性检测速度提升了。
第三,一方面当参数选取的较好时检测又快有准确;另一方面,由于该算法严格由参数Ta,Td,Tr控制而且这些参数不易取到合适值,所以会出现不合适的参数不仅增加计算量,而且增加误检机会的情况。
最优化方法
最优化类方法优点在其精度上,缺点是其一次只能处理一个图形,即此前要对图像信息进行分类分离。AndrewFitzgibb等人提出了直接最小二乘法椭圆拟合算法。该方法能保证拟合出来的一定是椭圆。但该方法受到孤立点和噪声点的影响。目前最优化算法多与其他算法一起结合使用。
基于弧段的方法
基于边界聚类的椭圆检测方法结合使用了基于弧段的方法和最小二乘法。从边界图提取圆弧,再经过过滤、聚类,最终用最小二乘法拟合出椭圆。该方法能有效应对多个椭圆、椭圆相互遮挡和椭圆部分缺损等复杂情况,因而引起了广泛的注意。
边界聚类算法流程
边界聚类算法属于从下往上结构的算法。算法步骤主要分为三步,分别是预处理,边界聚类和直接最小二乘法拟合椭圆三个过程。流程图如下所示:
预处理
预处理第一步是进行灰度变换。灰度化常用的方法也就是依据亮度方程来实现的,即依据人眼对不同颜色的敏感度不同,对RGB分量以不同系数的加权平均。
第二是降噪。去噪手段对应于噪声的两种分类主要有两种。噪声功率谱符合高斯函数时用可以用高斯平滑模板平滑。由于脉冲干扰等产生的噪声(即椒盐噪声)可以采用中值滤波去除。
第三步是边界检测。通常图像中边界点都是图像中亮度梯度比较大的点,这些点包含了我们检测要用到的图像特征信息。边界检测最常用的方法是Canny算法。该算法主要分四个部分。一、降噪。方法是让原始图像和所用的高斯模板作卷积,模板在使用前指定了标准差。 二、寻找亮度梯度。Canny算法使用4个模板检测边缘的方向,,它们分别是水平、垂直、主对角线和副对角线方向;遍历圆图上的每个像素点,让原始图像中以该点为中心以该模板为窗口内的所有点与该模板作卷积,我们就从原图获得了各个点亮度梯度图和亮度梯度的方向。三、非极大值抑制。该过程目的是获得单像素的候选边缘,主要操作是将非零像素点所在的区域进行细化。具体过程如下:对于图3-2中一点P(x,y),计算P点梯度方向与其8-连通邻域点所组成的正方形的交点 (x1,y1)和(x2,y2)。如图2-5,交点坐标通过插值法得到。如果中间点的值大于这两个交点值,那么P点值不变,如若不然置零。四、滞后阈值操作。它需要设置两个阈值t1与t2。t1等于边界像素数除以总像素数,这些点称之为强边缘像素。t2等于t1除以2, t2和 t1之间的点称之为弱边缘像素。最后通过将8-连通的弱像素集成到强像素,再把它们连接起来,得到边界图。
第四步是二值化。二值化的效果几乎完全取决于分割阈值的选取。所以自动寻找最佳分割阈值的方法就显得十分关键。找到图片二值化的一个合适的分割阈值的一种方法是按图像的灰度特性,将图像分成背景和目标两部分,背景和目标之间的类间方差最大的分割意味着错分概率最小。MATLAB 的Graythresh函数就是使用该方法来获得一个自适应阈值作为二值化的分割依据。
第五步,二值化后,因为椭圆弧附近的非相关像素会严重影响检测结果,因此为了大幅度减少非相关像素,本文用形态学的腐蚀操作来得到细化的边界。
边界像素连接
采用Kovesi的边界连接算法,以8-邻域连通准则从上至下,从左至右扫描二值图像,将边界像素连接为有向边界列。然后采用边界列中像素数阈值条件去除像素数较小的集合。因为若边界列像素数少于阈值数,则很有可能是噪声或背景,应当删除。具体步骤如下:
1.以8-邻域连通准则从上至下,从左至右扫描二值图像,按连通区域对图像中的像素点聚类。
2.寻找每一个连通域中边界像素中所有的结束点和分叉点(分叉点是三条以上曲线的交点)并存储。
3.以这些结束点和分叉点为结束标志,让每一个连通域中的像素点集合分割为遇到结束点和连接点就断开的小集合。
4.删除这些集合中像素数小于某一阈值的部分。
线段列提取
因为图像光栅化难以获得准确的切线,而后续过程需要用到圆弧的切线,所以要进行线段拟合,即用多段折线代替原来的圆弧。具体步骤如下:
1.取边界像素连接成的第i条有向边界列,判断是否超过边界列总数目total,若不是进行步骤2,若是终止算法。
2.判断该边界列是否已经完成处理,若为否则进行第3步;若是则i=i+1,重新进行步骤2.
3.从其中第三个点开始,计算第一个点到这个点(记为点j)的连线方程,并依次判断第一个点和该点之间的所有点到该连线的距离,若所有距离均小于某一阈值,则j=j+1,重新进行步骤3,否则该有向边界列从该处断开,前面部分只保留第一个点和第j个点,前面j个点构成的连线用第一点和第j点之间的直线连线代替;后面部分仍然记为边界列i,
4.判断步骤3中断开的有向边界列后面部分像素数是否小于某阈值,若是则删除掉,否则不处理。最后跳转到步骤1。
完成这一个过程后一个连通域的的像素点构成的曲线就变成了其中部分像素点构成的一条折线。经过这个过程虽然像素信息损失了一部分,但是求取圆弧切线的精度从某种意义上说提高了,因为没有了光栅化效应。而且数据少了处理变得简单。再采用线段数阈值条件去除较短的线段列。若线段数数少于阈值数,则很有可能是噪声或背景或者进行拟合时误差过大,因此须删除。
线段列旋转方向统一
本文将所有线段列旋转方向统一为逆时针方向。
假设图3-4中的黑点为线段列中的点,箭头代表线段列的方向,P1(x1,y1),P2(x2,y2),P3(x3,y3)为线段列中连续的三个像素,像素都引入z坐标,且令其为0,则P1(x1,y1,0),P2(x2,y2,0),P3(x3,y3,0),空间向量
向量积
对一个线段列中除去首尾两个点的所有点像P2点一样计算并判别和存储,若小于0的次数最多,则认为线段列的旋转方向是顺时针,将线段列中的点逆序处理;若大于0的次数最多,则认为线段列的旋转方向是逆时针。
凹点和角点检测
在确定线段列的旋转方向为逆时针方向后,检测凹点和角点方法同前面统一线段列旋转方向类似,对一个线段列中除去首尾两个点的所有点计算P1P2×P2P3并判断向量积第三个分量的大小,若小于0,则P2为凹点。因为边界波动可能引入冗余凹点也即因边界检测误差可能错判一些正常点为凹点而进修分割会导致检测率下降,所以增加一个角度判断过程,即前面向量积为0并且P1P2和P2P3的夹角大于某阈值,才为凹点,这样选择合适的阈值可保证凹点检测的准确性。若向量积大于0且P1P2和P2P3的夹角大于另一阈值,则认为该点角度变化过大,是角点,线段列有很大可能性不是椭圆弧,而有可能是三角形、矩形等图形的边角,因此从该点分割该线段列。分割完成后,过滤掉含点数较少的线段列,即可除掉部分非椭圆弧。留下的线段列认为是椭圆弧,参加后续的聚类。如图3-5所示,左上角的P2很可能是凹点,右下角的P2很可能是角点。
圆弧聚类
圆弧聚类是将属于同一椭圆但是分开的两条或多条椭圆弧进行聚类。在进行聚类前,首先要判断弧段的完整度。一般用弧段的首尾端点P1,P3与中点P2构成的两向量P2P1,P2P3的夹角的大小来进行判断。夹角越小,一般该椭圆弧越完整,夹角越大,一般认为椭圆弧缺损越严重。设定一个阈值,当夹角小于该阈值时认为该弧段已经足够完整,仅仅靠该弧段上的点就可以较准确地拟合出真实存在的椭圆,因此该弧段不需要参与后面的聚类过程。如果希望该阈值自适应,在划分待聚类椭圆弧和不须聚类的弧(较完整弧)之前,先要确定该阈值。用直接最小二乘法拟合该弧所在的椭圆,若较圆,为了减小的误差,应使阈值夹角稍微大一些,如90度;若该弧所在的椭圆较扁,应使阈值夹角稍微小一些,如60度。接下来才根据该自适应阈值进行对圆弧判断。当大于阈值时认为该弧段上的点过少,不足以拟合出准确的椭圆,需要找到和该弧段属于同一椭圆的弧段然后用它们所有的点一起拟合出一个椭圆。经过此判断过程,椭圆弧就被分成两组。把需要参加聚类的椭圆弧按照含点数的数目由多到少进行排列,下面的过程都按照数目多的弧段优先的顺序进行。
对于待聚类的椭圆弧,先要定义其搜索区域,由于椭圆是封闭图形,所以整个椭圆可以确定是在其任何一部分弧和弧两端点的切线所在的射线包围起来的区域里面,属于该椭圆的其他弧以确定是在该弧对应的弦和弧两端点的切线所在的射线包围起来的区域里面。这就是我们搜索的区域。在图中a1的搜索区域也就是射线l1,l2,弦l3和图像边缘范围内的区域,在这个区域里面找弧,可以缩小搜寻的范围,提高效率。判断一条弧是否在待聚类椭圆弧的搜索区域里面我们只需取这条弧的首末端点j3,j4是否在搜索区域。方法是分别求过这两点同时平行于待聚类椭圆弧对应弦l3的直线和切线的交点,若交点分别有两个,交点都在射线上且这两个端点在对应两个交点之间则该弧段在搜索区域内。图中明显a2,a3,a4在a1的搜索区域内而a5不在。
待聚类椭圆弧找到待配对的圆弧后用两种约束条件判断它们到底是否属于同一椭圆。约束一是利用一个椭圆任意两段弧弧中点之间的距离大于一个弧中点到另一个弧首末端点连线的中点之间的距离,在图中即为
用来去除图中a2类型的椭圆弧。右图(b)不满足,左图(a)同时满足这两个关系,进入下一步,再用约束二进行判断。
约束二是点到拟合椭圆边界距离条件。我们只需要让两条线段列中的点一起参与椭圆拟合,按照下面公式计算所有这些点到拟合出椭圆边界的距离。设置一距离阈值,当d_i小于该阈值认为该点落在该椭圆上,否则该点不在这个椭圆上。统计d_i中小于某一阈值的点的数量,若大于某一比例(比例阈值),则认为这两条弧属于同一椭圆,否则不属于同一椭圆。判定后将属于同一椭圆的弧段聚类到一起。
其中
如上图(a)中的参与拟合的点较多都落在拟合的椭圆上,所以有较大可能满足约束二条件;(b)中大多数拟合点点离拟合出的椭圆边界有一定距离,有较大可能不满足约束条件二。
如果希望这两个阈值改为自适应的,方法是先拟合出椭圆,判断椭圆大小。若椭圆较小,应适当降低限制,即增大距离阈值,减小比例阈值;若椭圆较大,应适当提高限制,即减小距离阈值,增大比例阈值。本算法中选取的是,若椭圆的短轴小于50则距离阈值为0.05,比例阈值设为0.7;否则前者取0.03,后者取0.8。
再配对
聚类后的弧和较完整弧或者两个较完整弧可能属于同一椭圆但是在前面的步骤它们只是被分开了并没有配对,所以有必要增加再匹配过程,增加检测准确度。匹配方法还是约束条件二的方法。因为该方法和原算法的去伪过程相似,所以经过该方法后无需再去伪。
直接最小二乘法椭圆拟合
前面的很多步骤都删除了像素点较少的集合,或者用少数点代替了边界列中的很多点,或者是分割后再删除点数较少的集合的,这些操作到椭圆拟合这一步实际上基本上去除了所有的背景和噪声,甚至包括一部分有用信息。所以即使对噪声和孤立点敏感的直接最小二乘法也可以用来拟合椭圆,而且因为该方法对椭圆缺损不敏感,所以非常适合。
clc;
clear all;
im=imread('1.jpg');
im0=rgb2gray(im);%变彩色为黑白
im1=medfilt2(im0,[3 3]);%中值滤波函数
BW = edge(im1,'sobel'); %边缘检测,边缘为1,其余为0
[imx,imy]=size(BW);%获取矩阵行数和列数
L = bwlabel(BW,8);% Calculating connected components
mx=max(max(L))
% There will be mx connected components.Here U can give a value between 1 and mx for L or in a loop you can extract all connected components
% If you are using the attached car image, by giving 1,2,3 to L you can extract the number plate completely.
[r,c] = find(L==3);
rc = [r c];
[sx sy]=size(rc);
n1=ones(imx,imy);%zeros
for i=1:sx
x1=rc(i,1);
y1=rc(i,2);
n1(x1,y1)=0;
end % Storing the extracted image in an array
figure,imshow(n1);
title('边缘提取');
[S]=ellipsefit(c,r)
a=S.Phi;
jdg(S.Xc,S.Yc,S.A,S.B,a,n1)%plot ellipse
完整代码添加QQ1575304183
以上是关于图像边缘检测基于最小二乘法的椭圆边缘检测matlab源码的主要内容,如果未能解决你的问题,请参考以下文章
图像边缘检测基于matlab模拟退火算法图像边缘检测含Matlab源码 2398期