Matlab数字图像处理(四)——图像分割

一、基本介绍

图像分割使图像被划分成或分隔成具有相近特征的区域。图像分割常用边缘和纹理作为特征,区域内图像的灰度色调或纹理应该均匀一致,没有孔洞,相邻区域的特征差异明显。本次实验要求采用区域增长法和大津法, 实现图像分割。

二、算法原理

(1)区域增长法算法原理

​ 区域增长是一种区域分割方法。假定区域的数目以及在每个区域中种子点的位置已知,则从该已知点开始,加上与已知点相似的邻近点形成一个区域,相似性准则可以是灰度级、彩色、组织、梯度或其它特性;相似性的测度可以由所确定的阈值来判定。从满足检测准则的点开始,在各个方向上生长区域,如果其邻近点满足检测准则就并入区域中; 重复这一过程,直到没有可接受的邻近点后,区域增长过程终止。

(2)大津法算法原理

OTSU算法也称最大类间差法,有时也称之为大津算法,由大津于1979年提出,被认为是图像分割中阈值选取的最佳算法,计算简单,不受图像亮度和对比度的影响,因此在数字图像处理上得到了广泛的应用
​ 大津法是按图像的灰度特性,将图像分成背景和前景两部分。因方差是灰度分布均匀性的一种度量,背景和前景之间的类间方差越大,说明构成图像的两部分的差别越大,当部分前景错分为背景或部分背景错分为前景都会导致两部分差别变小。因此,使类间方差最大的分割意味着错分概率最小,但是大津法这种全局阈值分割的方法受光照不均的影响较大。

三、实验内容

1、针对cameraman.jpg 这幅测试图像,运用区域增长法进行分割,通过调整criterion的值,分析分割结果的差异和好坏

【代码】
主函数TEST.m代码:

input=imread('cameraman.jpg');
[row,col]=size(input);
seg=reshape(1:row*col,row,col);
criterion=2;
connectivity=8;
[seg,seg_arr,reg_info]=region_grow1(input,seg,criterion,connectivity);
seg=uint16(seg);
imshow(hsteq(seg));

补充后的region_grow1.m的部分代码:

%更改标签值等于c_lab的区域的均值
reg_info(c_lab).crt=(reg_info(c_lab).size*reg_info(c_lab).crt+reg_info(n_lab).size*reg_info(n_lab).crt)/(reg_info(c_lab).size+reg_info(n_lab).size);

【结果】
四连通时:
img
【分析】
直接观察分割后的图像及其直方图,可以发现其灰度值分布较不均匀,视觉效果不是很好,于是对三幅图像进行直方图均衡化。
可以看出在四连通时,criterion分别取值2,4,6,8,10时,criterion越大,效果越好。但是三种处理条件下得到的图像都有严重的伪轮廓,而且前两个图像的人像边界较模糊,但是有较多的背景中的细节。当criterion=10时效果较好,能在视觉上区分人像和背景,但是人像和图像上部、左下部分的背景灰度值较相近,区分度也不大。
【结果】
八连通时:
img
  邻域连通采用八连通时当可以发现,人像的轮廓较清晰,并模糊了背景中的细节。但是,在criterion=4和criterion=8时虽然能视觉区分人像和背景,但是会发现人像的衣摆部分和身后的背景灰度值较相近,在这部分区分度不如criterion=10时好,
  总而言之,八连通的效果比四连通的好(相同条件下,四连通结果中人像和背景的相似程度大于八连通结果);随着criterion的值增大,背景细节减少,主体分割效果更好;同时,虽然八连通有较少的伪轮廓出现,但是还是会存在人像灰度值和背景灰度值相近的情况。

2、针对rice.jpg这幅图像,运用大津法和区域增长法进行分割,并自动统计大米的数量。请展示Matlab程序和分割后的图像。比较两种方法的效果。

(1)大津法实现图像分割并数出米粒的数量

1.1大津法实现图像分割

【代码】
以下是一段在Matlab中实现大津法的程序,即一个使用OTSU算法提取图像阈值的函数,输入参数为一个图像,返回分割该图像的最佳阈值,并依据此阈值对图像进行分割。

%OTSU阈值法
clear;clc;
I = imread('rice.JPG');
imshow(I);title('原图像')
I = double(I);
[M,N] = size(I);
T = min(I(:)):max(I(:));    %获得所有可能的阈值
g = [];
for i = 1:length(T)
	 C1 = I(I>=T(i));
	 C2 = I(I<T(i));
	 w1 = numel(C1)/(M*N);    %计算C1的权重
	 w2 = numel(C2)/(M*N);    %计算C2的权重
	 u1 = mean(C1);           %C1平均灰度
	 u2 = mean(C2);           %C2平均灰度
	 g(i) = w1*w2*(u1-u2)^2;  %类间方差
end
max_T = T(g==max(g));        %使用g中的最大值的标号作为T的索引
I(I>=max_T) = 255;           %进行阈值分割
I(I<max_T) = 0;
figure(2);imshow(logical(I));title('OTSU法分割结果');     %图像显示
level=(max_T-1)/255          %输出阈值

同时,在Matlab中也提供了graythresh函数,该函数也是基于大津法来获取最佳阈值,调用如下:
【结果】
使用自己编写的OTSU阈值法程序分割结果:

close all;
I=imread('rice.jpg');
imshow(I),title('原图');
level=graythresh(I);
BW=im2bw(I,level);
figure(2);imshow(BW);title('调用Matlab的graythresh函数分割结果');

【结果】
使用自己编写的OTSU阈值法程序分割结果:
img
调用Matlab自带的graythresh函数分割结果:
img
查看两个程序计算出的阈值:
自己编写的大津法程序:
level =
0.5137
Gragthresh()计算出的阈值:
level =
0.5137
【分析】
查看计算出的阈值,发现自己编写的大津法代码与gragthresh()计算出的阈值大体上完全一致。

1.2数出米粒的数量

对二值化后的图像使用imlabel函数实现数出米粒数量
【代码】

clear el
I=imread('rice.jpg');
level=graythresh(I);
BW=im2bw(I,level);
[L ,Ne]=bwlabel(double(BW),4);
imshow(BW);title(['The number of rice:',num2str(Ne)]);

【结果】
img
【分析】
发现米粒的数量明显偏多,推测是因为米粒破碎,导致将较小的区域也标记为了米粒,出现了米粒偏多的情况,因此需要对于连通域的大小进行限制。改进后的代码如下:

I=imread('rice.jpg');
level=graythresh(I);
BW=im2bw(I,level);
[L Ne]=bwlabel(double(BW),4);
prop=regionprops(L,'Area');
total=0;
imshow(BW);hold on
for n=1:size(prop,1)
    if prop(n).Area>20
        total=total+1;
    end
end
hold on
title(['The number of rice:',num2str(total)])
disp(total);

【结果】
img
【分析】
可以明显的发现,下方处的米粒分割得并不好,米粒出现了破碎的情况,导致计数的结果少于实际结果,这是因为rice.jpg这张图片的背景光照不均匀,在底部背景灰度值与米粒的灰度值较为接近,所以分割效果并不理想,针对这点做出改进。

1.3去除背景后数出米粒的数

【代码】

clear
close all
i= imread('rice.jpg');                  %读入图片
figure(1);imshow(i);title('原图');
BG=imopen(i,strel('disk',15));          % 获取图片的背景
figure(2);                           
imshow(BG);title('图像背景');
i2=imsubtract(i,BG);                    %减去图像背景
figure(3);
imshow(i2);title('减去背景后的图像');
level=graythresh(i2);
bw2=im2bw(i2,level);
[labeled,numObjects]=bwlabel(bw2,8);
prop=regionprops(labeled,'Area');
t=max(max(labeled));  %大米粒计数总数为t
total=0;
figure(4);imshow(bw2);hold on
for n=1:size(prop,1)
    if prop(n).Area>20
        total=total+1;
    end
end
hold on; title(['The number of rice:',num2str(total)]);disp(total);

【结果】
img
【分析】
数米粒的结果仍偏少,推测是因为筛掉了周围的点导致的数量偏少,去除筛除连通域的代码。代码如下:

clear
close all
i= imread('rice.jpg');                  %读入图片
figure(1);imshow(i);title('原图');
BG=imopen(i,strel('disk',15));          % 获取图片的背景
figure(2);                           
imshow(BG);title('图像背景');
i2=imsubtract(i,BG);                    %减去图像背景
figure(3);
imshow(i2);title('减去背景后的图像');
level=graythresh(i2);
bw2=im2bw(i2,level);
[labeled,numObjects]=bwlabel(bw2,8);
t=max(max(labeled));  %大米粒计数总数为t
figure(4);
imshow(bw2);title(['The number of rice:',num2str(t)]);disp(t);

【结果】
img
【分析】
数米粒的大体步骤是:首先进行开运算,因为结构元素为半径为十五的圆,因此这次的开运算可以等价于将米粒全部消除,只留下背景,然后用原图减去背景,减少背景对大津法的影响,使用bwlabel函数统计连通域个数并返回分类的标签图。

三、实验总结与思考

(1)关于bwlabel函数

[L,num] = bwlabel(BW,n)
返回一个和BW大小相同的L矩阵,包含了标记了BW中每个连通区域的类别标签,这些标签的值为1、2…num(连通区域的个数)。n的值为4或8,表示是按4连通寻找区域,还是8连通寻找,默认为8。num返回的就是BW中连通区域的个数,可以理解成一幅图像中可以分成几块连通区域。

(2)关于图像的背景影响

因为大津法受背景的影响较大,因此在使用大津法进行图像分割前,消除背景的影响对分割并计算米粒的个数起到了重要的作用,同时此环节对于其他的图像分割任务也是十分必要的,感觉和遥感图像的处理中大气校正这一环节有相似之处。当然在复杂的任务中,采取这种非常简单的方式来消除背景影像无疑是不恰当的,但对于本次实验中较简单的米粒这一图像,可以做出合理的推断,在使用区域生长法之前去除背景也对米粒的提取有很大的帮助。
下面做一个对比:
【代码】

input=imread('rice.jpg');
BG=imopen(input,strel('disk',15));                             
input1=imsubtract(input,BG);  
[row,col]=size(input);
seg=reshape(1:row*col,row,col);
criterion=11;
connectivity=8;
[seg,seg_arr,reg_info]=region_grow1(input1,seg,criterion,connectivity);
seg=uint16(seg);
imshow(histeq(seg));title('criterion=11,connectivity=8');

【结果】
img
【分析】
左图为criterrion为11,八连通未消除背景影响的分割结果。右图为criterrion为11,八连通消除背景影响的分割结果。可以发现较未消除背景影响的分割结果,消除背景影响后的分割的效果有了较大的提高。

posted @ 2022-05-16 22:01  Weltㅤ  阅读(3792)  评论(0编辑  收藏  举报