说明:图像分割就是把图像分成若干个特定的、具有独特性质的区域并提出感兴趣目标的技术和过程。它是由图像处理到图像分析的关键步骤。现有的图像分割方法主要分以下几类:基于阈值的分割方法、基于区域的分割方法、基于边缘的分割方法以及基于特定理论的分割方法等。从数学角度来看,图像分割是将数字图像划分成互不相交的区域的过程。图像分割的过程也是一个标记过程,即把属于同一区域的像索赋予相同的编号。(来自百度百科)
概念:将嵌在一幅图像的恒定区域或亮度几乎不变的区域里的孤立点的检测,就是点检测。可以用点检测的模板来将孤立的点检测出来:这个模板的作用就是当模板中心是孤立点时,模板的相应最强,而在非模板中心时,相应为零。
在MATLAB中进行点检测操作,基本语法为:
g = abs(imfilter(tofloat(f),w))>=T; %g是包含检测点的图像;f是输入图像;w是点检测模板
运用上面的语法编写实验代码:
f = imread('C:\Users\Public\Pictures\Sample Pictures\Fig0903(a).tif');
subplot(121),imshow(f);
w = [-1 -1 -1;-1 8 -1;-1 -1 -1];
g = abs(imfilter(tofloat(f),w));
T = max(g(:)); %在滤波后图像中选择的最大值
g = g >=T;
subplot(122),imshow(g);
点检测的另一种方法是在大小为m×n的所有邻点中寻找一些点,最大值和最小值的差超出了T的值,可以用函数ordfilt2进行操作:
g = ordfilt2(f,m*n,ones(m,n))-ordfilt2(f,1,ones(m,n));
g = g>=T;
线检测比点检测更加复杂一些,模板如图所示:
同样的,当检测的线是在中间那行或者是由“2”组成的行或列中,则此时的相应最大,其他部分的相应为零。
编写实验代码:
f = imread('C:\Users\Public\Pictures\Sample Pictures\Fig0513(a).tif');
subplot(231),imshow(f),title('原始图像');
w = [2 -1 -1;-1 2 -1;-1 -1 2];
g = imfilter(tofloat(f),w);
subplot(232),imshow(g,[]),title('45°处理后的图像');
gtop = g(1:120,1:120);
gtop = pixeldup(gtop,4);
subplot(233),imshow(gtop,[]),title('左上角放大的图像');
gbot = g(end -119:end,end -119:end);
gbot = pixeldup(gbot,4);
subplot(234),imshow(gbot,[]),title('右下角放大的图像');
g =abs(g);
subplot(235),imshow(g,[]),title('绝对值的图像');
T =max(g(:));
g =g >=T;
subplot(236),imshow(g),title('所有点满足g>=T的图像');
实验分析: 在进行45°的边缘检测中,只能够检测到45°或者135°的边缘,并在matlab中进行显示,发现在第二幅图中,45°的边缘检测并不是清楚的看出45°的边缘,而只能看到由点组成的边缘,这是因为原图像中基本没有呈对角线的线条,因此并不能显示对角线的边缘。绝对值的图像是将图像变成了二值图像(只有黑与白),比灰度图像更加清晰看出检测到的线条边缘。
以上两种方法在图像分割中很重要,但是所常用的方法是边缘检测,这种方法是检测亮度的不连续性。这样的不连续是用一阶和二阶导数来检测的。
首先,我们先介绍二阶函数的梯度向量公式:
这个向量的幅值可以简化为如下形式:通常使用梯度的幅值或近似值来作为“梯度”。
梯度向量的基本性质是:梯度向量指向(x,y)坐标处f的最大变化率方向。
最大变化率处发生的角度是:
在图像处理工具箱中,可以使用函数edge来作为边缘估计器。
[g,t] = edge(f,'method',parameters)
[g,t] = edge(f,'sobel',T,dir) %T是阈值,dir是边缘检测首选方向:'horizontal'、'vertical'、‘both’
[g,t] = edge(f,'prewitt',T,dir) %T是阈值,dir是边缘检测首选方向:'horizontal'、'vertical'、‘both’
[g,t] = edge(f,'roberts',T,dir) %T是阈值,dir是边缘检测首选方向:'horizontal'、'vertical'、‘both’
这样会得到两种效果:一种是平滑图像,减少了噪声;另一种是计算拉普拉斯,从而产生双边缘图像,然后在双边缘之间定位由发现的零交叉组成的边缘。
调用语法为:
[g,t] = edge(f,'log',T,sigma) %T是阈值,sigma是标准差,默认为2
[g,t] = edge(f,'zerocross',T,H) %T是阈值
[g,t] = edge(f,'canny',T,sigma) %T是向量=[T1,T2];sigma是标准差,默认为1
编写实验代码:
f = imread('C:\Users\Public\Pictures\Sample Pictures\Fig0309(a).tif');
subplot(231),imshow(f),title('原始图像');
[gv,t] = edge(f,'sobel','vertical');
subplot(232),imshow(gv),title('默认阈值垂直的sobel图像');
t
gv = edge(f,'sobel',0.15,'vertical');
subplot(233),imshow(gv),title('阈值0.15垂直的sobel图像')
gboth = edge(f,'sobel',0.15);
subplot(234),imshow(gboth),title('阈值为0.15垂直水平的sobel图像')
wneg45 = [-2 -1 0;-1 0 1;0 1 2];
gneg45 = imfilter(tofloat(f),wneg45,'replicate');
T =0.3*max(abs(gneg45(:)));
gneg45 = gneg45>=T;
subplot(235),imshow(gneg45),title('阈值45°边缘图像')
实验分析: 当参数是默认垂直的sobel边缘检测时,得到边缘细节是垂直的,水平的边缘线是没有能够检测出来的。当加入参数0.15之后,之前能够检测到的细节却不能够检测出来了,是因为这已经超出了阈值的范围;当采用垂直水平的边缘检测,将之前没有能够检测出的水平线能够检测并显示出来了;当所检测的边缘线是45°的时候,该算法只能够检测到45°或135°的边缘线条,并显示出来。
将sobel、Log和canny边缘检测算子进行比较,编写实验代码:
f = tofloat(f);
subplot(221),imshow(f),title('原始图像')
[gSobel_dafault,ts] = edge(f,'sobel');
[gLog_dafault,tlog] = edge(f,'log');
[gCanny_dafault,tc] = edge(f,'canny');
subplot(222),imshow(gSobel_dafault),title('默认的sobel图像');
subplot(223),imshow(gLog_dafault),title('默认的log图像');
subplot(224),imshow(gCanny_dafault),title('默认的canny图像');
gSobel_best = edge(f,'sobel',0.05);
gLog_best = edge(f,'log',0.003,2.25);
gCanny_best = edge(f,'canny',[0.04 0.1],1.5);
subplot(222),imshow(gSobel_best),title('最好效果的sobel图像');
subplot(223),imshow(gLog_best),title('最好效果的log图像');
subplot(224),imshow(gCanny_best),title('最好效果的canny图像');
实验分析: 同样的一幅图像,使用默认的sobel边缘检测得到的图像中线条是比较其他两种是比较少的,而且获取的边缘细节不是很完整,缺失了很多重要的细节,比如说草地上的细节等。但是在最佳的sobel边缘检测中,所得到的图像是比较完整的,线条细节基本上都被获取并显示出来,相比较其他两种方法,所得到的边缘细节是最完整的。在canny边缘检测中,默认参数的canny检测是最好的,所获得细节是最多的,其边缘基本都可以完整的检测到。
在理想情况下,只能产生边缘上的像素,为了更好的得到边缘特性,因此下面介绍霍夫变换的线检测方法。
霍夫变换:是一种特征检测(feature extraction),被广泛应用在图像分析(image analysis)、计算机视觉(computer vision)以及数位影像处理(digital image processing)。霍夫变换是用来辨别找出物件中的特征,例如:线条。他的算法流程大致如下,给定一个物件、要辨别的形状的种类,算法会在参数空间(parameter space)中执行投票来决定物体的形状,而这是由累加空间(accumulator space)里的局部最大值(local maximum)来决定。(来自百度百科)
霍夫变换的原理:
我们将用极坐标系来表示直线。此时,直线的表达式为:
将其化简为:
一般来说,一条直线能够通过在平面θ-ρ 寻找交于一点的曲线数量来进行检测。 越多曲线交于一点也就意味着这个交点表示的直线由更多的点组成.。一般来说我们可以通过设置直线上点的阈值来定义多少条曲线交于一点,此时认为检测到了一条直线。霍夫线变换要做的就是:它追踪图像中每个点对应曲线间的交点。 如果交于一点的曲线的数量超过了 阈值, 那么可以认为这个交点所代表的参数对 (θ, ρ) 在原图像中为一条直线。
在图像处理工具箱中提供了以下函数:
函数hough实现了所描述的概念;
函数houghpeaks寻找霍夫变换的峰值(累加单元的高计数);
函数houghlines在原图像上提取线段。
[H,theta,rho] = hough(f)
或 [H,theta,rho] = hough(f,'ThetaRes',val1,'RhoRes',val2)
其中,H是霍夫变换矩阵,theta和rho是ρ和θ值向量。f是二值图像,val1是0-90的标量,指定沿θ轴霍夫变换的间距(默认为1);val2是0 编写实验代码: 调用语法: 其中,val1可以从0到Inf变换,默认是0.5*max(H(:)),val2是指定量围绕峰值的邻域大小。 其中,theta和rho是来自函数hough的输出,peaks是来自houghpeaks的输出。val1指定了与相同的霍夫变换相关的两条线段的距离。当两条线段之间的鹅咀里小于指定的值时,则把线段合并为一条线段(默认20);val2指定合并的线是保留还是去掉,如果合并的线比val2指定的值短,则丢掉(默认是40)。 编写实验代码: 一般情况下,一张图片分为前景和背景,我们感兴趣的一般的是前景部分,所以我们一般使用阈值将前景和背景分割开来,使我们感兴趣的图像的像素值为1,不感兴趣的我0,有时一张图我们会有几个不同的感兴趣区域(不在同一个灰度区域),这时我们可以用多个阈值进行分割,这就是阈值处理。 一般选取阈值就是图像直方图的视觉检测。将区分度大的两个灰度级部分之间进行划分,取T为阈值来分开它们。在此基础上学习一种自动地选择阈值的算法,方法如下: 编写实验代码: Otsu’s方法的最佳方法是选择阈值k,最大类间方差σ2(k)来定义的: 调用的语法是: 编写实验代码: (基本全局算法)一般来说,高SM值说明灰度分成两类的可能性比较高。 噪声可以影响阈值的选择,当噪声不能够在源头减少,在阈值处理之前可以将图像进行平滑处理,这样可以更好地进行阈值处理。 编写实验代码: 实验分析: 当加入高斯噪声的图像,所显示的直方图并不能使用阈值处理进行分割图像,所以经过otsu’s全局阈值处理操作后发现,原始图像和噪声并不能够分离开。当使用平滑滤波器进行图像改善之后,从其直方图看出,可以使用阈值处理进行分割图像了,所以最后的效果图显示,图像与噪声分割开来,因此可以使用otsu’s全局阈值处理对图像进行操作。 边缘改进的阈值处理:主要是处理那些位于或接近物体和背景间边缘的像素,使得这些像素分离开的操作。 具体算法过程如下: 用自定义的函数percentile2i来计算灰度值I的对应指定的百分比: 编写实验一代码:基于梯度边缘信息改进全局阈值处理 编写实验二代码:用拉普拉斯边缘信息改进全局阈值处理 实验分析: 在之前的学习知道,拉普拉斯算法是用于图像的锐化,把图像的边缘提取出来。在这个部分中,用拉普拉斯边缘信息改进全局阈值处理也是一样的,首先将原始图像的边缘提取出来,然后将原始图像与已标记好的图像进行相乘,得到的就是实验中所需要的图像,最终图像就如边缘改进结果那样,修改边缘信息提取出来,再用阈值进行处理。 当背景照明高度不均匀时,需要进行阈值处理的难度就增大,为了解决这个问题,运用局部统计的可变阈值处理的算法进行解决。我们用一幅图像中每个点的邻域中像素的标准差和均值,这是局部对比度和平均灰度的描述子。 用于执行局部阈值处理,可以用下面的函数来操作: 编写实验代码: 实验分析: 观察原图像发现,图像可以分为三种灰度级,发现除了细胞核的部分,细胞核与细胞的灰度级差别并不是很大,因此当我们使用全局阈值处理时,不能将里面的细胞核与细胞分离开,得到的阈值处理如otsu方法分割图像所示。当实验使用局部可变的阈值处理时,计算出图像的局部标准差,可以将细胞与细胞核分离开,因此当再次使用阈值处理时可以完整的将细胞与细胞核分离开,获得最终的处理结果。 移动平均是一种局部阈值处理方法,该方法以一幅图像的扫描行计算移动平均为基础。移动平均分割能减少光照偏差,且计算简单。当感兴趣的物体与图像尺寸相比较小(或较细)时,基于移动平均的阈值处理会工作的很好。打印图像和手写文本图像满足这一条件。 移动平均需要计算图像中每一个点,因此分割用下面的表示式: 可以用如下的函数movingthresh来进行移动平均的操作: 编写实验代码: 实验分析: 实验之前就说过,移动平均的图像阈值处理适用于处理打印图像和手写文本图像这种类型。对比房子的移动平均处理看出,最后所获得的图像不是实验所需要的图像,因此这种方法并不适用于这种图像处理。在处理手写文本图像的时候,经过局部移动平均阈值处理后,所获得的结正是我们所需要的。 分割的目的是把图像分成一块一块的区域,是基于像素特性的分布,通过阈值处理完成的。 令R表示整个图像区域,分割是把R分成n个子区域的处理,分割必须满足下面5条原则: 区域生长(region growing) 是指将成组的像素或区域发展成更大区域的过程。从种子点的集合开始,从这些点的区域增长是通过将与每个种子点有相似属性像强度、灰度级、纹理颜色等的相邻像素合并到此区域。 在区域生长中的主要问题如下: 在图像处理工具中使用函数regiongrow进行区域生长的操作: 编写实验代码: 这个操作是区域生长的反操作,是将图像中的区域分离或合并这些区域。令R表示整个图像,选择属性P,这个操作将R连续地细分为越来越小的象限区域。如果P(R)=TRUE,就把图像分成4象限;如果对每个4象限来说,P都是FALSE,再细分象限就为子象限,以此类推划分下去,直到无法进一步合并的时候停止分离。这种方法也称作四叉树。(如图所示) 为了在四叉树分解中得到实际的四叉区域像素值,使用函数qtgetblk: 用函数splitmerge来计算两个区域的合并: predicate函数是用户自定义的,用于考察该区域的是否符合要求: 用代码编写以上过程: 分水岭算法主要用于图像的分割,如果目标物体是连接在一起的,则分割起来会很困难。此时经常采用分水岭分割算法,会得到比较好的效果。分水岭分割算法把图像看成一幅地形图,亮度比较强的区域像素值较大,亮度暗的区域像素值比较小,通过寻找汇水盆地和分水岭界线对图像进行分割。分水岭的计算过程是一个迭代标注过程。分水岭比较经典的计算方法是L. Vincent提出的。在该算法中,分水岭计算分两个步骤,一个是排序过程,一个是淹没过程。首先对每个像素的灰度级进行从低到高排序,然后在从低到高实现淹没过程中,对每一个局部极小值在h阶高度的影响域采用先进先出(FIFO)结构进行判断及标注。 注意:分割结果必须要根据种子区域,以减小过分割造成的影响。 最常用的分水岭变换分割的是距离变换,主要是用于二值图像的处理,它是指从每个像素到最接近零值的像素的距离。 计算距离变换的负分水岭变换,调用函数watershed: 编写实验代码为: 梯度处理是在分水岭变换之前的预处理,它将沿着物体的边缘有较高的像素值,而在其他地方的像素值比较低。 编写实验代码: 实验分析: 观察两组图像,当梯度的分水岭分割时,所获得的图像基本上满足实验的效果,但由于严重的过度分割后,图像已不再是需要得到的效果,使得图像分割没有意义了。使用平滑梯度图像的分水岭分割后,虽然产生了一些缺陷(图像上被一些类似噪声污染),但没有影响图像的分割效果。基于梯度的分水岭分割法是修改梯度函数使得集水盆只响应想要探测的目标,再对梯度图像进行阈值处理,以消除灰度的微小变化产生的过度分割。 当直接用梯度进行分水岭变换时,容易造成过度分割,为了改善这样的情况,采用基于标记符的方式进行分割。 编写实验代码: 实验分析: 当直接使用梯度幅度方法进行分割处理时,发现图像过度分割非常严重,而这样的分割是没有意义的,并不是我们所需要的。当采用控制标记符分水岭分割算法时,能调整过度分割的界限,设置内部标记符和外部标记符,把所需要的内外部标记符联合起来,再次进行分割,因此可以得到我们所需要的分割效果。f = zeros(101,101);
f(1,1) = 1;f(101,1) = 1;f(1,101) = 1;
f(101,101) = 1;f(51,51) = 1;
H = hough(f)
imshow(H,[])
[H,theta,rho] = hough(f);
imshow(H,[],'XData',theta,'YData',rho,'InitialMagnification','fit')
axis on,axis normal
xlabel('\theta'),ylabel('\rho')
实验分析: 三条曲线(直线也可以考虑为曲线)在±45°处的交点指出:f中有两组三个共线的点。两条曲线在(ρ,θ)=(0,-90)、(-100,-90)、(0,0)和(100,0)处的交点指出:有4组位于垂直线和水平线上的共线点。(需要将图像放大以方便观察其坐标)
peaks = houghpeaks(H,NumPeaks)
或 peaks = houghpeaks(H,‘Threshold’,val1,'NHoodSize',val2)
这个过程的基本思想是:通过把峰值的直接邻域中的霍夫变换单元置0来清理峰值。
调用函数:lines = houghlines(f,theta,rho,peaks)
或lines = houghlines(f,'FillGap',val1,'MinLength',val2)
f = imread('C:\Users\Public\Pictures\Sample Pictures\Fig1006(a).tif');
subplot(131),imshow(f),title('原始图像');
[H,theta,rho] = hough(f,'ThetaRes',0.2)
subplot(132),imshow(H,[ ],'XData',theta,'YData',rho,'InitialMagnification','fit')
axis on,axis normal
xlabel('\theta'),ylabel('\rho')
peaks =houghpeaks(H,5);
hold on
plot(theta(peaks(:,2)),rho(peaks(:,1)),'linestyle','none','marker','s','color','w')
lines = houghlines(f,theta,rho,peaks);
subplot(133),imshow(f);
for k = 1:length(lines)
xy = [lines(k).point1;lines(k).point2];
plot(xy(:,1),xy(:,2),'LineWidth',4,'Color',[0.8 0.8 0.8]);
end
(三)阈值处理
(1)基础知识
单个阈值:
两个阈值:
示意图如下:
(2)基本全局阈值处理
f = imread('C:\Users\Public\Pictures\Sample Pictures\Fig0309(a).tif');
f = imnoise(f,'gaussian');
count = 0;
T = mean2(f);
done = false;
while ~done
count = count+1;
g = f>T;
Tnext = 0.5*(mean(f(g))+mean(f(~g)));
done = abs(T-Tnext)<0.5;
T =Tnext;
end
count
T
g = im2bw(f,T/255);
subplot(131),imshow(f),title('带噪声的图像');
subplot(132),imhist(f),title('图像的直方图');
subplot(133),imshow(g),title('全局阈值分割的结果')
实验分析: count是表示含有的灰度级数目,则T表示阈值。当我们对图像进行噪声处理时,基本全局阈值分割出来的结果也会或多或少带有一些噪声,使得图像并不是很美观。因此下面的方法将对含有噪声的图像进行修改。(3)使用Otsu’s方法的最佳全局阈值处理
当设置的方差越大,则完全分割一幅图像的阈值就会越接近。公式中的k就是我们所要寻找的最佳阈值,当k不唯一时,则将所有的最佳阈值进行取平均值即可。[T,SM] = graythresh(f) %SM是可分性度量,T是归一化的阈值
f = imread('C:\Users\Public\Pictures\Sample Pictures\Fig0309(a).tif');
f = imnoise(f,'gaussian');
[T,SM] = graythresh(f)
T*255
f2 = imread('C:\Users\Public\Pictures\Sample Pictures\Fig1014(a).tif');
subplot(221),imshow(f2),title('原始图像');
subplot(222),imhist(f2),title('原始图像直方图');
count = 0;
T = mean2(f2);
done = false;
while ~done
count = count+1;
g = f2>T;
Tnext = 0.5*(mean(f2(g))+mean(f2(~g)));
done = abs(T-Tnext)<0.5;
T =Tnext;
end
g = im2bw(f2,T/255);
subplot(223),imshow(g,[]),title('用基本全局算法分割结果')
[T,SM] = graythresh(f2);
SM
T*255
g = im2bw(f2,T);
subplot(224),imshow(g),title('用Otsu’s算法分割结果')
实验分析: 可以看出,用基本全局阈值处理时细胞的分割效果并不是很好,没有能够分割清楚,是由于前景和背景的灰度级比较相近而不能够完全分离开,因此当使用了otsu’s算法进行分割时,可以完全将细胞(前景)和背景分割开来。尽管分离度的度量值比较低,但是还是可以准确地从背景中提取细胞。(4)使用图像平滑改进全局阈值处理
f = imread('C:\Users\Public\Pictures\Sample Pictures\Fig0513(a).tif');
subplot(241),imshow(f),title('原始图像');
fn = imnoise(f,'gaussian',0,0.038);
subplot(242),imshow(fn),title('具有高斯噪声的图像');
subplot(243),imhist(fn),title('具有高斯噪声的直方图');
Tn = graythresh(fn);
gn = im2bw(fn,Tn);
subplot(244),imshow(gn),title('用otsu’s分割的图像');
w = fspecial('average',5);
fa = imfilter(fn,w,'replicate');
subplot(245),imshow(fa),title('平滑后的图像');
subplot(246),imhist(fa),title('平滑后的直方图');
Ta = graythresh(fa);
ga =im2bw(fa,Ta);
subplot(247),imshow(ga),title('平滑后并用otsu’s分割的图像');
(5)使用边缘改进全局阈值处理
I = percentile2i(h,p)
f = tofloat(imread('C:\Users\Public\Pictures\Sample Pictures\Fig1013(a).tif'));
subplot(231),imshow(f),title('原图像');
subplot(232),imhist(f),title('原图像直方图');
sx = fspecial('sobel');
sy = sx';
gx = imfilter(f,sx,'replicate');
gy = imfilter(f,sy,'replicate');
grad = sqrt(gx.*gx+gy.*gy);
grad = grad/max(grad(:));
h =imhist(grad);
Q = percentile2i(h,0.999);
markerImage = grad>Q;
subplot(233),imshow(markerImage),title('以99.9%进行阈值处理后的梯度幅值图像');
fp = f.*markerImage;
subplot(234),imshow(fp),title('原图像与梯度幅值乘积的图像');
hp = imhist(fp);
hp(1) = 0;
subplot(235),bar(hp),title('原图像与梯度幅值乘积的直方图');
T = otsuthresh(hp);
T*(numel(hp)-1)
g = im2bw(f,T);
subplot(236),imshow(g),title('改进边缘后的图像')
实验分析: 原始图像本身具有高斯噪声,由其直方图单峰可以知道,此时的图像分割是不可能进行操作的,使用基本全局阈值处理是失败的。因此,实验只能够用梯度幅值处理后,将图像进行明显的灰度级分离,把阈值处理接近模式的中点,这样就可以得到基本完美的图像分割。f = tofloat(imread('C:\Users\Public\Pictures\Sample Pictures\Fig1017(a).tif'));
subplot(231),imshow(f),title('原始图像');
subplot(232),imhist(f),title('原始图像的直方图');
hf = imhist(f);
[Tf SMf] = graythresh(f);
gf = im2bw(f,Tf);
subplot(233),imshow(gf),title('对原始图像进行分割的图像');
w= [-1 -1 -1;-1 8 -1;-1 -1 -1];
lap = abs(imfilter(f,w,'replicate'));
lap = lap/max(lap(:));
h = imhist(lap);
Q = percentile2i(h,0.995);
markerImage = lap >Q;
fp = f.*markerImage;
subplot(234),imshow(fp),title('标记图像与原图像的乘积');
hp = imhist(fp);
hp(1) =0;
subplot(235),bar(hp)
T = otsuthresh(hp);
g = im2bw(f,T);
subplot(236),imshow(g),title('修改边缘后的阈值处理图像')
(6)基于局部统计的可变阈值处理
为了计算局部标准差,使用函数stdfilt进行操作:g = stdfilt(f,nhood);
为了计算局部均值,可以用函数localmean进行操作:function mean = localmean(f,nhood)
if nargin ==1
nhood = ones(3)/9;
else
nhood = nhood/sum(nhood(:));
end
mean = imfilter(tofloat(f),nhood,'replicate');
function g = localthresh(f,nhood,a,b,meantype)
f = tofloat(f);
SIG = stdfilt(f,nhood);
if nargin == 5 && strcmp(meantype,'global')
MEAN = mean2(f);
else
MEAN = localmean(f,nhood);
end
g = (f > a*SIG) & (f > b*MEAN);
[TGlobal] = graythresh(f);
gGlobal = im2bw(f,TGlobal);
subplot(131),imshow(gGlobal),title('用otsu方法分割的图像');
g = localthresh(f,ones(3),30,1.5,'global');
SIG = stdfilt(f,ones(3));
subplot(132),imshow(SIG,[]),title('局部标准差图像');
subplot(133),imshow(g),title('局部阈值处理后的图像');
(7)使用移动平均的图像阈值处理
其中,K是[0,1]范围内的常数,mxy是输入图像的移动平均function g = movingthresh(f, n, K)
f = tofloat(f);
[M, N] = size(f);
if (n < 1) || (rem(n, 1) ~= 0)
error('n must be an integer >= 1.')
end
if K < 0 || K > 1
error('K must be a fraction in the range [0, 1].')
end
f(2:2:end, :) = fliplr(f(2:2:end, :));
f = f'; % Still a matrix.
f = f(:)'; % Convert to row vector for use in function filter.
maf = ones(1, n)/n; % The 1-D moving average filter.
ma = filter(maf, 1, f); % Computation of moving average.
g = f > K * ma;
g = reshape(g, N, M)';
g(2:2:end, :) = fliplr(g(2:2:end, :));
f = imread('C:\Users\Public\Pictures\Sample Pictures\Fig1019(a).tif');
subplot(131),imshow(f),title('原始图像');
T =graythresh(f);
g1 = im2bw(f,T);
subplot(132),imshow(g1),title('用otsu全局阈值分割后的图像');
g2 = movingthresh(f,20,0.5);
subplot(133),imshow(g2),title('用移动平均局部阈值分割后的图像');
(四)基于区域的分割
(1)基本表达式
(2)区域生长
(1)表示区域的初始化种子的选择:在区域生长过程中,这些不同区域点合适属性的选择。
(2)基于图像具体属性的像素生长不一定是好的分割。在区域生长过程中,不应该使用连通性或邻接信息。
(3)相似性:相似性表示在灰度级中观察在两个空间邻接像素之间或像素集合的平均灰度级间的最小差分,它们将产生不同的区域。如果这个差分比相似度阈值小,则像素属于相同的区域。
(4)区域面积:最小面积阈值与像素中的最小区域大小有关。在分割的图像中,没有区域比这个阈值小,它由用户定义。(来自百度百科)[g,NR,SI,TI] = regiongrow(f,S,T) %f是被分割图像,S/T可以是数组或标量,范围是[0,1]内
f = imread('C:\Users\Public\Pictures\Sample Pictures\Fig0309(a).tif');
subplot(221),imshow(f),title('原始图像');
[g,NR,SI,TI]=regiongrow(f,255,65);%种子的像素值为255,65为阈值
subplot(222),imshow(SI),title('种子点的图像');
subplot(223),imshow(TI),title('所有通过阈值测试的像素');
subplot(224),imshow(g),title('对种子点进行8连通分析后的结果');
(3)区域分离和聚合
在图像处理工具箱中使用函数qtdecomp 进行四叉树分解的处理:z = qtdecomp(f,@split_test,parameters) %split_test用来决定某个区域是否进行分离
[vals,r,c] = qtgetblk(f,z,m) %vals是数组,r和c事行列坐标的向量,z是返回的稀疏矩阵
g = splitmerge(f,mindim,@predicate) %mindim是分解中允许的最小块
flag = predicate(region)
f = imread('C:\Users\Public\Pictures\Sample Pictures\Fig1023(a).tif');
subplot(231),imshow(f),title('原始图像');
g32 = splitmerge(f,32,@predicate) %使用最小块为32进行分割
subplot(232),imshow(g32),title('使用最小块为32进行分割图像');
g16 = splitmerge(f,16,@predicate) %使用最小块为16进行分割
subplot(233),imshow(g16),title('使用最小块为16进行分割图像');
g8= splitmerge(f,8,@predicate) %使用最小块为8进行分割
subplot(234),imshow(g8),title('使用最小块为8进行分割图像');
g4 = splitmerge(f,4,@predicate) %使用最小块为4进行分割
subplot(235),imshow(g4),title('使用最小块为4进行分割图像');
g2 = splitmerge(f,2,@predicate) %使用最小块为2进行分割
subplot(236),imshow(g2),title('使用最小块为2进行分割图像');
(五)使用分水岭变换的分割
(1)使用距离变换的分水岭分割
距离变换函数为:D = bwdist(f)
L = watershed(A,conn)
f = imread('C:\Users\Public\Pictures\Sample Pictures\Fig0513(a).tif');
subplot(231),imshow(f),title('原始图像');
g = im2bw(f,graythresh(f)); %把图像变换成二值图像
subplot(232),imshow(g),title('二值图像');
gc = ~g;
subplot(233),imshow(gc),title('补的图像');
D = bwdist(gc);
subplot(234),imshow(D),title('距离变换图像');
L = watershed(-D);
w = L == 0;
subplot(235),imshow(w),title('负分水岭脊的图像');
g2 = g&-w;
subplot(236),imshow(g2),title('黑色重叠后的图像');
(2)使用梯度的分水岭分割
f = imread('C:\Users\Public\Pictures\Sample Pictures\Fig1014(a).tif');
subplot(221),imshow(f),title('原始图像');
h = fspecial('sobel');
fd = tofloat(f);
g = sqrt(imfilter(fd,h,'replicate').^2+imfilter(fd,h,'replicate').^2);
subplot(222),imshow(g,[]),title('梯度和分水岭分割幅度图像');
L =watershed(g);
wr = L == 0;
subplot(223),imshow(wr),title('严重分割过分割后图像');
g2 = imclose(imopen(g,ones(3,3)),ones(3,3));
L2 = watershed(g2);
wr2 = L2 == 0;
f2 = f;
f2(wr2) = 255;
subplot(224),imshow(f2),title('平滑梯度图像后的分水岭变换');
(3)控制标记符的分水岭分割
f = imread('C:\Users\Public\Pictures\Sample Pictures\Fig1028(a).tif');
subplot(241),imshow(f),title('原始图像');
h = fspecial('sobel');
fd = tofloat(f);
g = sqrt(imfilter(fd,h,'replicate').^2+imfilter(fd,h,'replicate').^2);
L =watershed(g);
wr = L == 0;
subplot(242),imshow(wr),title('梯度幅度图像进行分水岭变换图像');
rm = imregionalmin(g); %计算图像中所有的局部小区域的位置
subplot(243),imshow(rm),title('梯度幅值的局部小区域图像');
im = imextendedmin(f,2); %用于计算比临近点更暗的图像中“低点”的集合
fim = f;
fim(im) = 175;
subplot(244),imshow(f,[]),title('内部标记符图像');
Lim = watershed(bwdist(im));
em = Lim == 0;
subplot(245),imshow(em,[]),title('外部标记符图像');
g2 = imimposemin(g,im|em); %用来修改一幅图像,使得其只在指定的位置处取得局部最小值
subplot(246),imshow(g2),title('修改后的梯度幅值图像');
L2 = watershed(g2);
f2 = f;
f2(L2 == 0) = 255;
subplot(247),imshow(f2),title('最后的分割图像');