图像分割

  • (一)点、线和边缘检测
    • (1)点检测
    • (2)线检测
    • (3)使用函数edge的边缘检测
  • (二)使用霍夫变换的线检测
  • (三)阈值处理
    • (1)基础知识
    • (2)基本全局阈值处理
    • (3)使用Otsu's方法的最佳全局阈值处理
    • (4)使用图像平滑改进全局阈值处理
    • (5)使用边缘改进全局阈值处理
    • (6)基于局部统计的可变阈值处理
    • (7)使用移动平均的图像阈值处理
  • (四)基于区域的分割
    • (1)基本表达式
    • (2)区域生长
    • (3)区域分离和聚合
  • (五)使用分水岭变换的分割
    • (1)使用距离变换的分水岭分割
    • (2)使用梯度的分水岭分割
    • (3)控制标记符的分水岭分割

说明:图像分割就是把图像分成若干个特定的、具有独特性质的区域并提出感兴趣目标的技术和过程。它是由图像处理到图像分析的关键步骤。现有的图像分割方法主要分以下几类:基于阈值的分割方法、基于区域的分割方法、基于边缘的分割方法以及基于特定理论的分割方法等。从数学角度来看,图像分割是将数字图像划分成互不相交的区域的过程。图像分割的过程也是一个标记过程,即把属于同一区域的像索赋予相同的编号。(来自百度百科)

(一)点、线和边缘检测

(1)点检测

概念:将嵌在一幅图像的恒定区域或亮度几乎不变的区域里的孤立点的检测,就是点检测。可以用点检测的模板来将孤立的点检测出来:这个模板的作用就是当模板中心是孤立点时,模板的相应最强,而在非模板中心时,相应为零。

在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)线检测

线检测比点检测更加复杂一些,模板如图所示:

同样的,当检测的线是在中间那行或者是由“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°的边缘,而只能看到由点组成的边缘,这是因为原图像中基本没有呈对角线的线条,因此并不能显示对角线的边缘。绝对值的图像是将图像变成了二值图像(只有黑与白),比灰度图像更加清晰看出检测到的线条边缘。

(3)使用函数edge的边缘检测

以上两种方法在图像分割中很重要,但是所常用的方法是边缘检测,这种方法是检测亮度的不连续性。这样的不连续是用一阶和二阶导数来检测的。
首先,我们先介绍二阶函数的梯度向量公式:

这个向量的幅值可以简化为如下形式:通常使用梯度的幅值或近似值来作为“梯度”。

梯度向量的基本性质是:梯度向量指向(x,y)坐标处f的最大变化率方向。
最大变化率处发生的角度是:

在图像处理工具箱中,可以使用函数edge来作为边缘估计器。

[g,t] = edge(f,'method',parameters)

下面分别介绍表格中的边缘检测算子:

  1. sobel边缘检测算子

    调用语法是:
[g,t] = edge(f,'sobel',T,dir)  %T是阈值,dir是边缘检测首选方向:'horizontal'、'vertical'、‘both’
  1. prewitt边缘检测算子

    调用语法为:(较容易产生噪声)
[g,t] = edge(f,'prewitt',T,dir)  %T是阈值,dir是边缘检测首选方向:'horizontal'、'vertical'、‘both’
  1. Roberts边缘检测算子

    调用语法为:
[g,t] = edge(f,'roberts',T,dir)  %T是阈值,dir是边缘检测首选方向:'horizontal'、'vertical'、‘both’
  1. LoG检测算子
    高斯函数:

    这个公式表示的是平滑函数。如果此函数和图像进行卷积,则图像会变得模糊,且模糊的程度是由σ决定的。这个函数的拉普拉斯算法是:

    这个函数称为LoG算子。原理是:由于求二阶导数是线性操作,所以用这个函数卷积这幅图像与先用平滑函数对图像卷积,再对结果进行拉普拉斯计算的结果是一样的。

这样会得到两种效果:一种是平滑图像,减少了噪声;另一种是计算拉普拉斯,从而产生双边缘图像,然后在双边缘之间定位由发现的零交叉组成的边缘。

调用语法为:

[g,t] = edge(f,'log',T,sigma)  %T是阈值,sigma是标准差,默认为2
  1. 零交叉检测算子
    这种算子与LoG方法类似,不同之处在于卷积使用特殊的滤波函数H来完成的。
    调用语法为:
[g,t] = edge(f,'zerocross',T,H)  %T是阈值
  1. Canny检测算子
    这种算子是edge函数中最强的边缘检测算子
    (1)图像用指定了标准差σ的高斯滤波器来平滑,用来减少噪声;
    (2)局部梯度和边缘方向在每个点都进行计算。边缘点被定义为梯度方向上局部强度最大的点。
    (3)在(2)中决定的边缘点在梯度幅度图像上给出脊。然后算法追踪所有脊的顶部,设置所有的不在脊的顶部的像素为零。因此在输出中给出一条细线,这是非最大值抑制处理。脊像素使用称为“滞后阈值”的技术进行阈值处理,这种技术以使用两个阈值为基础,即T1和T2,且T1<T2。值大于T2的脊像素称为强边缘像素,T1和T2之间的脊像素称为弱边缘像素。
    (4)算法用合并8连接的弱像素点到强像素点的方法执行边缘连接。
    调用语法为:
[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在原图像上提取线段。

  1. 函数hough
    调用函数:
 [H,theta,rho] = hough(f)   或 [H,theta,rho] = hough(f,'ThetaRes',val1,'RhoRes',val2)

其中,H是霍夫变换矩阵,theta和rho是ρ和θ值向量。f是二值图像,val1是0-90的标量,指定沿θ轴霍夫变换的间距(默认为1);val2是0<val2<hypot(size(I,2),size(I,2))的实际量,指定沿ρ轴的霍夫变换的间距(默认为1)。

编写实验代码:

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 normalxlabel('\theta'),ylabel('\rho')


实验分析: 三条曲线(直线也可以考虑为曲线)在±45°处的交点指出:f中有两组三个共线的点。两条曲线在(ρ,θ)=(0,-90)、(-100,-90)、(0,0)和(100,0)处的交点指出:有4组位于垂直线和水平线上的共线点。(需要将图像放大以方便观察其坐标)

  1. 函数houghpeaks:寻找霍夫变换的峰值(累加单元的高计数)

调用语法:

peaks = houghpeaks(H,NumPeaks)
或 peaks = houghpeaks(H,‘Threshold’,val1,'NHoodSize',val2)

其中,val1可以从0到Inf变换,默认是0.5*max(H(:)),val2是指定量围绕峰值的邻域大小。
这个过程的基本思想是:通过把峰值的直接邻域中的霍夫变换单元置0来清理峰值。

  1. 函数houghlines:当峰值在霍夫变换中被识别出来,则可用此函数来决定线的起始点和终点。
    调用函数:
lines = houghlines(f,theta,rho,peaks)
或lines = houghlines(f,'FillGap',val1,'MinLength',val2)

其中,theta和rho是来自函数hough的输出,peaks是来自houghpeaks的输出。val1指定了与相同的霍夫变换相关的两条线段的距离。当两条线段之间的鹅咀里小于指定的值时,则把线段合并为一条线段(默认20);val2指定合并的线是保留还是去掉,如果合并的线比val2指定的值短,则丢掉(默认是40)。

编写实验代码:

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)基础知识

一般情况下,一张图片分为前景和背景,我们感兴趣的一般的是前景部分,所以我们一般使用阈值将前景和背景分割开来,使我们感兴趣的图像的像素值为1,不感兴趣的我0,有时一张图我们会有几个不同的感兴趣区域(不在同一个灰度区域),这时我们可以用多个阈值进行分割,这就是阈值处理。
单个阈值:

两个阈值:

示意图如下:

(2)基本全局阈值处理

一般选取阈值就是图像直方图的视觉检测。将区分度大的两个灰度级部分之间进行划分,取T为阈值来分开它们。在此基础上学习一种自动地选择阈值的算法,方法如下:

  1. 针对全局阈值选择初始估计值T;
  2. 用T分割图像,G1是所有灰度值大于T的像素组成,G2是所有灰度值小于等于T的像素组成;
  3. 分别计算G1和G2区域内的平均灰度值m1和m2;
  4. 计算出新的阈值,取他们的m1和m2平均值数;
  5. 重复步骤2.-4.,直到在连续的重复中,T的差异比预先设定的参数小为止;
  6. 使用函数im2bw分割图像:g = im2bw(f,T/den)

编写实验代码:

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;
endcount
Tg = im2bw(f,T/255);
subplot(131),imshow(f),title('带噪声的图像');
subplot(132),imhist(f),title('图像的直方图');
subplot(133),imshow(g),title('全局阈值分割的结果')



实验分析: count是表示含有的灰度级数目,则T表示阈值。当我们对图像进行噪声处理时,基本全局阈值分割出来的结果也会或多或少带有一些噪声,使得图像并不是很美观。因此下面的方法将对含有噪声的图像进行修改。

(3)使用Otsu’s方法的最佳全局阈值处理

Otsu’s方法的最佳方法是选择阈值k,最大类间方差σ2(k)来定义的:
当设置的方差越大,则完全分割一幅图像的阈值就会越接近。公式中的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

(基本全局算法)一般来说,高SM值说明灰度分成两类的可能性比较高。

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分割的图像');

实验分析: 当加入高斯噪声的图像,所显示的直方图并不能使用阈值处理进行分割图像,所以经过otsu’s全局阈值处理操作后发现,原始图像和噪声并不能够分离开。当使用平滑滤波器进行图像改善之后,从其直方图看出,可以使用阈值处理进行分割图像了,所以最后的效果图显示,图像与噪声分割开来,因此可以使用otsu’s全局阈值处理对图像进行操作。

(5)使用边缘改进全局阈值处理

边缘改进的阈值处理:主要是处理那些位于或接近物体和背景间边缘的像素,使得这些像素分离开的操作。

具体算法过程如下:

  1. 用一种边缘查找方式计算图像的模板的值。
  2. 通过百分比指定阈值。由于计算的边缘模板值中有很多噪声,所以可以将计算值排序,并选择百分比相对高的值(大于百分下的值的阈值)作为阈值。
  3. 根据指定的阈值,对第一步的图像边缘的值进行选择。使高于阈值的像素点值为1,低于的值为零,由此选择出部分边缘点的二值图像(模板)。
  4. 用刚才计算出来的模板与原图像相乘,获得一幅新的图像。
  5. 对新的图像使用otsu进行分割。

用自定义的函数percentile2i来计算灰度值I的对应指定的百分比:

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 ==1nhood = ones(3)/9;
elsenhood = 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);
elseMEAN = 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('局部阈值处理后的图像');

实验分析: 观察原图像发现,图像可以分为三种灰度级,发现除了细胞核的部分,细胞核与细胞的灰度级差别并不是很大,因此当我们使用全局阈值处理时,不能将里面的细胞核与细胞分离开,得到的阈值处理如otsu方法分割图像所示。当实验使用局部可变的阈值处理时,计算出图像的局部标准差,可以将细胞与细胞核分离开,因此当再次使用阈值处理时可以完整的将细胞与细胞核分离开,获得最终的处理结果。

(7)使用移动平均的图像阈值处理

移动平均是一种局部阈值处理方法,该方法以一幅图像的扫描行计算移动平均为基础。移动平均分割能减少光照偏差,且计算简单。当感兴趣的物体与图像尺寸相比较小(或较细)时,基于移动平均的阈值处理会工作的很好。打印图像和手写文本图像满足这一条件。

移动平均需要计算图像中每一个点,因此分割用下面的表示式:

其中,K是[0,1]范围内的常数,mxy是输入图像的移动平均

可以用如下的函数movingthresh来进行移动平均的操作:

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)基本表达式

令R表示整个图像区域,分割是把R分成n个子区域的处理,分割必须满足下面5条原则:

(2)区域生长

区域生长(region growing) 是指将成组的像素或区域发展成更大区域的过程。从种子点的集合开始,从这些点的区域增长是通过将与每个种子点有相似属性像强度、灰度级、纹理颜色等的相邻像素合并到此区域。

在区域生长中的主要问题如下:
(1)表示区域的初始化种子的选择:在区域生长过程中,这些不同区域点合适属性的选择。
(2)基于图像具体属性的像素生长不一定是好的分割。在区域生长过程中,不应该使用连通性或邻接信息。
(3)相似性:相似性表示在灰度级中观察在两个空间邻接像素之间或像素集合的平均灰度级间的最小差分,它们将产生不同的区域。如果这个差分比相似度阈值小,则像素属于相同的区域。
(4)区域面积:最小面积阈值与像素中的最小区域大小有关。在分割的图像中,没有区域比这个阈值小,它由用户定义。(来自百度百科)

在图像处理工具中使用函数regiongrow进行区域生长的操作:

[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)区域分离和聚合

这个操作是区域生长的反操作,是将图像中的区域分离或合并这些区域。令R表示整个图像,选择属性P,这个操作将R连续地细分为越来越小的象限区域。如果P(R)=TRUE,就把图像分成4象限;如果对每个4象限来说,P都是FALSE,再细分象限就为子象限,以此类推划分下去,直到无法进一步合并的时候停止分离。这种方法也称作四叉树。(如图所示)

在图像处理工具箱中使用函数qtdecomp 进行四叉树分解的处理:

z = qtdecomp(f,@split_test,parameters)  %split_test用来决定某个区域是否进行分离

为了在四叉树分解中得到实际的四叉区域像素值,使用函数qtgetblk:

[vals,r,c] = qtgetblk(f,z,m)  %vals是数组,r和c事行列坐标的向量,z是返回的稀疏矩阵

函数splitmerge来计算两个区域的合并

g = splitmerge(f,mindim,@predicate)  %mindim是分解中允许的最小块

predicate函数是用户自定义的,用于考察该区域的是否符合要求

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进行分割图像');

(五)使用分水岭变换的分割

分水岭算法主要用于图像的分割,如果目标物体是连接在一起的,则分割起来会很困难。此时经常采用分水岭分割算法,会得到比较好的效果。分水岭分割算法把图像看成一幅地形图,亮度比较强的区域像素值较大,亮度暗的区域像素值比较小,通过寻找汇水盆地和分水岭界线对图像进行分割。分水岭的计算过程是一个迭代标注过程。分水岭比较经典的计算方法是L. Vincent提出的。在该算法中,分水岭计算分两个步骤,一个是排序过程,一个是淹没过程。首先对每个像素的灰度级进行从低到高排序,然后在从低到高实现淹没过程中,对每一个局部极小值在h阶高度的影响域采用先进先出(FIFO)结构进行判断及标注。

注意:分割结果必须要根据种子区域,以减小过分割造成的影响。

(1)使用距离变换的分水岭分割

最常用的分水岭变换分割的是距离变换,主要是用于二值图像的处理,它是指从每个像素到最接近零值的像素的距离。

距离变换函数为:D = bwdist(f)

计算距离变换的负分水岭变换,调用函数watershedL = 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('最后的分割图像');

实验分析: 当直接使用梯度幅度方法进行分割处理时,发现图像过度分割非常严重,而这样的分割是没有意义的,并不是我们所需要的。当采用控制标记符分水岭分割算法时,能调整过度分割的界限,设置内部标记符和外部标记符,把所需要的内外部标记符联合起来,再次进行分割,因此可以得到我们所需要的分割效果。

十六、数字图像处理之图像分割相关推荐

  1. [Python图像处理] 三十四.数字图像处理基础与几何图形绘制万字详解(推荐)

    该系列文章是讲解Python OpenCV图像处理知识,前期主要讲解图像入门.OpenCV基础用法,中期讲解图像处理的各种算法,包括图像锐化算子.图像增强技术.图像分割等,后期结合深度学习研究图像识别 ...

  2. 《OpenCv视觉之眼》Python图像处理十六:Opencv图像处理实战一之图像中的硬币检测

    本专栏主要介绍如果通过OpenCv-Python进行图像处理,通过原理理解OpenCv-Python的函数处理原型,在具体情况中,针对不同的图像进行不同等级的.不同方法的处理,以达到对图像进行去噪.锐 ...

  3. MATLAB画三维墨西哥草帽图,数字图像处理之图像分割-20210401063921.ppt-原创力文档...

    第六章 图像分割;主要内容;6.1 图像分割概述;;6.1 图像分割概述;图像分割的目的把图像分解成构成它的部件和对象:有选择性地定位感兴趣对象在图像中的位置和范围.;从简到难,逐级分割控制背景环境, ...

  4. 数字图像处理:图像分割 人工智能算法在图像处理中的应用

    人工智能算法在图像处理中的应用 人工智能算法包括遗传算法.蚁群算法.模拟退火算法和粒子群算法等,在图像边缘检测.图像分割.图像识别.图像匹配.图像分类等领域有广泛应用.本文首先介绍常用人工智能算法的的 ...

  5. 第10章 Python 数字图像处理(DIP) - 图像分割 基础知识 标准差分割法

    This Chapter is all about image segmentation. I still not finished whole chapter, but here try to pu ...

  6. 系统学习数字图像处理之图像分割

    图像分割,有区域法,直接确定边界,边缘检测法,大多数算法基于灰度的不连续性(边缘检测)和相似性(阈值处理,区域生长,区域分裂,区域聚合). 边缘分类:台阶边缘,斜坡边缘,屋顶边缘,一阶导数会产生粗边缘 ...

  7. 7/16数字图像处理之图像分割

    图像分割 概述 间断检测 点检测 线检测 边缘检测 图像分割的方法: 边缘检测 阈值处理 基本全局阈值处理 使用Otsu's方法的最佳全局阈值处理 基于局部统计的可变阈值处理 阈值处理 基于区域的分割 ...

  8. 基于matlab的数字图像处理软件设计

    文章目录 1.总体功能概述 2.功能介绍 2.1基本操作 2.2图像类型变换 2.3图形几何变换 2.4图像变换 2.5图像添加噪声 2.6图像复原 2.7图像增强 2.8图像分割 2.9图像编码 2 ...

  9. 【图像处理】数字图像处理笔记

    文章目录 直方图处理 滤波器 图像复原 形态学图像处理 灰度形态学--多使用平坦结构元(SE)[数字图像处理P428 图像分割 1.canny边缘检测[数字图像处理P463] 图像的表征 特征描述子 ...

最新文章

  1. android View.isShown() 和 getVisibility() 的区别
  2. python零基础入门建模_python基础教程之Python 建模步骤|python基础教程|python入门|python教程...
  3. 压铸行业龙头广东鸿图携手用友U9实现数智化升级
  4. cp分解实现_如何用贝叶斯高斯张量分解修复缺失数据?(Jupyter notebook - Python)
  5. Linux-No.04 Linux 设置定时任务发送邮件功能
  6. SQL Server索引视图以(物化视图)及索引视图与查询重写
  7. Mac 启动时屏幕上的特殊图像标识都是什么意思
  8. 分享6个国内优秀Java后台管理框架的开源项目,建议收藏!
  9. SCU4487 king's trouble I(深搜DFS)
  10. C#实现在图片上添加文字和二维码
  11. 正激电路:半桥(波形解释)
  12. 使用记录6_发布微信小游戏
  13. mysql根据字符转行
  14. 为什么手机充电这么慢?别用错数据线
  15. 输出从顶点Vi到Vj的所有简单路径
  16. c语言动态分配内存keil,keil5中结构体分配内存问题
  17. 前端技术:Vue+elementUI 饿了吗UI+CRUD,创建图书管理系统
  18. 【压测】压力测试ab的用法【原创】.md
  19. 视频教程-EXCEL VBA编程(excel办公高手必经之路)-Office/WPS
  20. Oracle 层级数据计算方式start with connect by

热门文章

  1. 苹果手机怎么追踪定位
  2. 我要每人送一块高端鼠标垫,包邮…
  3. marquee demo
  4. 不知道怎么编辑图片?只需三步就可以学会
  5. [转载]Qualcomm Wlan Country Code
  6. 错误:ssh:could not resolve ....
  7. 极光推送JPush---自定义提示音
  8. AnolisOS 8 安装 epel源
  9. html小球碰撞源代码,JS实现小球的弹性碰撞效果
  10. 【bzoj1017】[JSOI2008]魔兽地图DotR