图像分割是指将图像中具备特殊意义的不一样区域划分开来, 这些区域互不相交,每一个区域知足灰度、纹理、彩色等特征的某种类似性准则。图像分割是图像分析过程当中最重要的步骤之一,分割出的区域能够做为后续特征提取的目标对象。算法
本文主要包括如下内容 数组
图像的边缘是图像的最基本特征,边缘点是指图像中周围像素灰度有阶跃变化或屋顶变化的那些像素点,即灰度值导数较大或极大的地方。图像属性中的显著变化一般反映了属性 的重要意义和特征。
边缘检测是图像处理和计算机视觉中的基本问题,其用途在于标识数字图像中亮度变化明显的点。咱们曾在5.5节中讨论了一些能够用于加强边缘的图像锐化方法,本节介绍如何 将它们用于边缘检测。此外,还将介绍一种专门用千边缘检测的Canny算子 bash
边缘检测能够大幅度地减小数据量, 而且剔除那些被认为不相关的信息, 保留图像重要的结构属性。
markdown
边缘检测方法的分类
一般可将边缘检测的算法分为两类: 基于查找的算法和基于零穿越的算法。除此以外.还有Canny边缘检测算法、统计判别方法等。 函数
基于—阶导数的边缘检测算子包括Roberts算子、Sobel算子、Prewitt算子等,它们都是梯度算子;基于二阶导数的边缘检测算子主要是高斯—拉普拉斯边缘检测算子. 优化
Roberts算子利用局部差分算子寻找边缘,边缘定位精度较高,但容易丢失一部分边缘,同时因为图像没通过平滑处理,所以不具有抑制噪声的能力。该算子对具备陡峭边缘且含噪声小的图像效果较好。
Sobel算子和Prewitt算子都考虑了邻域信息,至关于对图像先作加权平滑处理,而后再作微分运算,所不一样的是平滑部分的权值有些差别,所以对噪声具备必定的抑制能力,但不能彻底排除检测结果中出现的虚假边缘。虽然这两个算子边缘定位效果不错,但检测出的边缘容易出现多像素宽度。 ui
高斯一拉普拉斯算子
spa
Canny边缘检测算子
前面介绍的几种都是基于微分方法的边缘检测算法,他们都只有在图像不含噪声或者首先经过平滑去除噪声的前提下才能正常应用。
在图像边缘检测中,抑制噪声和边缘精肯定位是没法同时知足的,一些边缘检测算法经过平滑滤波去除噪声的同时,也增长了边缘定位的不肯定性;而提升边缘检测算子对边缘敏感性的同时,也提升了对噪声的敏感性。Canny算子力图在抗噪声干扰和精肯定位之间寻求最佳折衷方案。
显然,只要固定了k, 就固定了极大值的个数。
有了这3个准则,寻找最优的滤波器的问题就转化为泛函的约束优化问题了,公式的解能够由高斯的一阶导数去逼近。
Canny边缘检测的基本思想就是首先对图像选择必定的Gauss滤波器进行平滑滤波,而后采用非极值抑制技术进行处理获得最后的边缘图像。其步骤为:
3d
Matlab的IPT函数edge能够方便地实现9.2.2小节的几种边缘检测方法, 该函数的做用 是检测灰度图像中的边缘, 并返回一个带有边缘信息的二值图像, 其中黑色表示背景, 白色 表示原图像中的边缘部分. code
基于高斯一拉普拉斯算子的边缘检测
使用edge函数进行基于高斯-拉普拉斯算子的边缘检测的调用语法为:
BW = edge(I,’log’,thresh,sigma);
第2个参数为’log’表示采用高斯拉普拉斯算子.
thresh是敏感度阈值参数,任何灰度值低于此阈值的边缘将不会被检测到. 其默认值是空矩阵D, 此时算法会自动计算阈值. 若是将thresh设为0, 则输出的边缘图像将包含围绕全部物体的闭合的轮廓线, 由于这样的运算会包括输入图像中全部的过零点
sigma指定生成高斯滤波器所使用的标准差.默认时,标准差值为2. 滤镜大小n * n,n的计算方法为n=ceil(sigma * 3) x 2+1.
基干Canny算子的边缘检测
BW = edge(I,’canny’,thresh,sigma);
第2个参数为’canny’表示采用canny算子.
thresh是敏感度阈值参数, 其默认值是空矩阵[]. 与前面的算法不一样, Canny算法的敏感度阈值是一个列向量, 由于须要为算法指定阈值的上下限. 在指定阈值矩阵时,第1个元素是阈值下限,第2个元素为阈值上限.若是只指定一个阈值元素,则这个直接指定的值会被做为阈值上限,而它与0.4的积会被做为阈值下限。若是阈值参数没有指定, 算法会自行肯定敏感度阈值的上、下限。
sigma指定生成平滑使用的高斯滤波器的标准差.默认时,标准差值为1滤镜大小nxn, n的计算方法为n=ceil(sigma x 3) x 2+1.
intensity = imread('circuit.tif');
bw1 = edge(intensity,'sobel');
bw2 = edge(intensity,'prewitt');
bw3 = edge(intensity,'roberts');
bw4 = edge(intensity,'log');
bw5 = edge(intensity,'canny');
subplot(3,2,1); imshow(intensity); title('a');
subplot(3,2,2); imshow(bw1); title('b');
subplot(3,2,3); imshow(bw2); title('c');
subplot(3,2,4); imshow(bw3); title('d');
subplot(3,2,5); imshow(bw4); title('e');
subplot(3,2,6); imshow(bw5); title('f');
从图中能够看出, 不一样算法获得的结果存在很大差别, 下面进行简要的分析
注意:以上验证结杲及分析是基于阶跃变化假设进行的,但真实的灰度变化不必定都是阶跃的,有可能发生在很宽的灰度范围上, 且存在灰度的起落. 所以,咱们应当根据工程实际对各类算子作以比较后加以选用.
9.2节介绍了一些边缘检测的有效方法。但实际中因为噪声和光照不均等因素,使得在不少状况下得到的边缘点不连续,必须经过边缘链接将它们转换为有意义的边缘。通常的作 法是对通过边缘检测的图像进一步使用链接技术,从而将边缘像素组合成完整的边缘。
霍夫(Hough)变换是一个很是重要的检测间断点边界形状的方法。它经过将图像坐标空间变换到参数空间,来实现直线和曲线的拟合。
注意:因为原图中的直线每每具备必定宽度,实际上至关于多条参数极其接近的单像素宽直线,它们对应参数空间中相邻的多个累加器单元. 所以每找到一个当前最大的峰值点后,须要将该点及其附近点清零,以防算法检测出多条极其邻近的“假”直线.
这种利用二维累加器的离散化方法大大简化了Hough变换的计算.参数空间a-b上的细分程度决定了最终找到直线上点的共线精度。上述的二维累加数组A组也经常被称为Hough 矩阵。
注意:使用直角坐标表示直线, 当直线为一条垂直直线或者接近垂直直线时,该直线的斜率为无限大或者接近无限大,从而没法在参数空间a-b中表示出来. 为了解决这一问题,能够采用极坐标系.
极坐标参数空间
Hough变换一样适用千方程已知的曲线检测。图像坐标空间中的一条已知曲线方程也能够创建其相应的参数空间。由此,图像坐标空间中的一点,在参数空间中就能够映射为相应 的轨迹曲线或者曲面。若参数空间中对应各个间断点的曲线或者曲面可以相交,就可以找到参数空间的极大值以及对应的参数:若参数空间中对应各个间断点的曲线或者曲面不能相交, 则说明间断点不符合某已知曲线.
Rough变换作曲线检割时,最重要的是写出团像坐标空间到参数空间的变换公式。例如,对于已知的圆方程, 其直角坐标的通常方程为:
其中(a, b)为圆心坐标,r为圆的半径, 它们为图像的参数。那么, 参数空间能够表示为(a, b, r), 图像坐标空间中的一个圆对应参数空间中的一点。
具体计算时, 与前面讨论的方法相同.只是数组累加器为三维A(a, b, r)。计算过程是让a、b在取值范围内增长, 解出知足上式的r值, 每计算出一个(a, b, r)值, 就对数组元素A(a, b, r)加一.计算结束后, 找到的最大的A(a, b, r)所对应的a、b、r就是所求的圆的参数。
与直线检测同样, 曲线检测也能够经过极坐标形式计算。
求出参考点后,整个目标的边界就能够肯定了
经过Hough变换在二值图像中检测直线须要3个步骤。
(I)利用hough()函数执行霍夫变换, 获得霍夫矩阵。
(2)利用hougbpeaks()函数在霍夫矩阵中寻找峰值点。
(3)利用houghlines()函数在以前2步结果的基础上获得原二值图像中的直线信息。
利用Hough变换对Matlab示例图片 circuit.tif进行直线检测,显示Hough矩阵 和检测到的峰值,并在原图中标出符合要求的全部直线段.
I = imread('circuit.tif');
rotI = imrotate(I,33,'crop');
BW = edge(rotI,'canny');
[H,T,R]=hough(BW);
imshow(H,[],'XData',T,'YData',R,'InitialMagnification','fit');
xlabel('\theta'),ylabel('rho');
axis on,axis normal,hold on;
P = houghpeaks(H,5,'threshold',ceil(0.3*max(H(:))));
x = T(P(:,2)); y = R(P(:,1));
plot(x,y,'s','color','white');
lines = houghlines(BW,T,R,P,'FillGap',5,'MinLength',7);
figure,imshow(rotI),hold on;
max_len = 0;
for k = 1 : length(lines)
xy = [lines(k).point1;lines(k).point2];
plot(xy(:,1),xy(:,2),'LineWidth',2,'Color','green');
plot(xy(1,1),xy(1,2),'x','LineWidth',2,'Color','yellow');
plot(xy(2,1),xy(2,2),'x','LineWidth',2,'Color','red');
len = norm(lines(k).point1-lines(k).point2);
if(len > max_len)
max_len = len;
xy_long = xy;
end
end
plot(xy_long(:,1),xy_long(:,2),'LineWidth',2,'Color','cyan');
经过此列可发如今houghpeaks函数执行后, 咱们共获得了5个峰值, 然而图的结果中却出现了8条直线段, 这正是houghlines函数中’FillGap’参数的做用。 将FillGap设定为80能够合井本来共线(有相同的