引子:如何计算下图中米粒的个数及各米粒的大小?
1.进行二值化(背景-->黑,前景(米粒)-->白)
2.计算连通的白色区域数(米粒数)
3.计算每个区域包含多少个像素(米粒大小)
#二值化结果:见下图
问题:
1.背景中存在噪点(没有米粒的地方出现了白色的像素)
2.一些米粒消失了
原因:
打光不均匀,上半部分比下半部分亮
导致上半部分的背景被误判为前景(问题1)
下半部分的前景被误判为背景(问题2)
解决方法:进行背景估计,得到背景,然后从原图中剪掉背景
>> I = imread('rice.png');
>> BG = imopen(I,strel('disk',15));
>> imshow(BG);%结果见下图1
>> I2 = imsubtract(I,BG);
>> imshow(I2)%结果见下图2
>> bw2=im2bw(I2,graythresh(I2));
>> imshow(bw2)%结果见下图3
一.图像二值化(Image Binarization)
1.基本原理:
1.找到灰度阈值(Gray Scale Thresholding),记为T
2.将灰度大于T的像素变为白色,灰度小于T的像素变为黑色
3.处理后即得到"二值图像"(Binary Image)
2.方法:
(1)计算灰度阈值:
[<T>[,<EM>]] = graythresh(<I>):使用Otsu方法计算灰度图的全局灰度阈值
#(???)Otsu方法(即最大类间方差法)选择1个阈值,使阈值化的黑白像素的类内方差最小化
#全局阈值T可与imbinarize()结合使用以将灰度图转换为二值图像
#参数说明:
I:指定灰度图
T:返回得到的全局灰度阈值
EM:返回有效性度量
#实例:
>> I = imread('coins.png');
>> level = graythresh(I)
level = 0.4941
>> BW = imbinarize(I,level);
>> imshowpair(I,BW,'montage')%结果见下图
(2)进行二值化:
<BW> = imbinarize(<I>[,<method>]):通过阈值化将2/3维灰度图像二值化
#参数说明:
I:指定2/3维灰度图像
method:指定寻找阈值的ff;默认为Otsu方法
#详情参见官方文档
BW:返回二值图像
<BW> = imbinarize(<I>,<T>):功能同上,不过是手动指定阈值
#参数说明:BW,I同上
T:指定阈值
<BW> = imbinarize(<I>,"adaptive"[,"<Name>",<Value>]):使用键值对组控制阈值,创建二值图像
#参数说明:BW,I同上
Name,Value:指定键值对,用于控制自适应阈值的各个方面
#实例:
>> I = imread('coins.png');
>> BW = imbinarize(I);
>> figure
>> imshowpair(I,BW,'montage')%结果见下图1
>> I = imread('rice.png');
>> BW = imbinarize(I, 'adaptive');
>> figure
>> imshowpair(I,BW,'montage')%结果见下图2
%对前景比背景暗的图像进行二值化:
>> I = imread('printedtext.png');
>> figure
>> imshow(I)%结果见下图3
>> title('Original Image')
>> BW = imbinarize(I,'adaptive','ForegroundPolarity','dark','Sensitivity',0.4);
>> figure
>> imshow(BW)%结果见下图4
>> title('Binary Version of Image')
%使用全局阈值对三维体进行二值化:
>> load mristack;
>> V = mristack;
>> figure
>> slice(double(V),size(V,2)/2,size(V,1)/2,size(V,3)/2)%查看3维图像的切片,结果见下图5
>> colormap gray
>> shading interp
>> J = imbinarize(V);
>> figure
>> slice(double(J),size(J,2)/2,size(J,1)/2,size(J,3)/2)%查看3维二值图像的切片,结果见下图6
>> colormap gray
>> shading interp
<BW> = im2bw(<I>,<level>):基于阈值将灰度图转换为二值图像(不推荐)
#参数说明:
I:指定灰度图
level:指定阈值;为[0,1]内的标量
灰度>level的像素替换为白色,灰度≤level的像素替换为黑色
BW:返回二值图像
<BW> = im2bw(<X>,<map>,<level>):基于阈值将索引图像转换为二值图像(不推荐)
#参数说明:BW,level同上
X:指定索引图像
map:指定颜色图
<BW> = im2bw(<RGB>,<level>):将于阈值将真彩色图像转换为二值图像(不推荐)
#参数说明:BW,level同上
RGB:指定真彩色图像
注意:如果输入不是灰度图像,则先将图像转换为灰度图像,再通过阈值将灰度图像转换为二值图像
#实例:
>> load trees
>> BW = im2bw(X,map,0.4);
>> imshow(X,map);%结果见下图1
>> figure;
>> imshow(BW);%结果见下图2
3.不利用内置函数进行二值化:
I = imread('rice.png');
[h,w] = size(I);%获得图片的高度(height)/宽度(width)
level = 100;%输入阈值
for i = 1 : h
for j = 1 : w
if I(i,j) > level%若大于阈值,则转换为白色
I(i,j) = 1;
else%否则转换为黑色
I(i,j) = 0;
end
end
end
I = uint8(I * 255);%转为位图
imshow(I)%结果见下图
二.背景估计(Background Estimation)
1.对图像进行开运算:
对灰度图像进行形态学开运算:<J> = imopen(<I>,<SE>)
<J> = imopen(<I>,<nhood>)
#后者等效于imopen(I,strel(nhood))
#即使用同样的结构元素先对图像进行腐蚀操作后进行膨胀操作;常用于获得背景
#参数说明:
I:指定灰度图像
SE:由strel()/offsetstrel()返回的单个构造元素对象
nhood:用于指定结构元素邻域的矩阵,由0/1构成
#imopen()通过floor((size(nhood)+1)/2)确定邻域的中心元素
J:返回处理后的图像
2.对图像进行减运算:
从图像的每个像素中减去指定量:Z = imsubtract(X,Y)
#常用于从图像中去除背景
#参数说明:
X:指定原图像
Y:指定要减去的量;为scalar/matrix
Z:返回处理后的图像
三.连通区域分析(Connected-Component Labeling/Analysis)
1.概述
(1)连通区域:
在图像中,每个像素周围有8个相邻像素.常见的邻接关系有2种:4邻接与8邻接.对4邻接来说,某个像素有4个邻接像素(上下左右);对8邻接来说,每个像素则有8个邻接
像素(多了通过对角相邻的像素)
如果像素点A与B邻接且二者的值相同,则称A与B"连通";并且若A与B连通,B与C连通,则A与C连通.从视觉上看来,彼此连通的点形成了1个区域.这样1个由所有彼此连
通的前景像素点构成的图像区域,称为1个"连通区域"(Connected Component).如下图中包含3个4连通区域或2个8连通区域
(2)连通区域分析:
背景像素仍标记为原来的值(如0);而将前景像素分为不同的连通区域,相同连通区域中的点标记为相同的值,不同连通区域中的点则标记为不同的值(如1,2...).连通区域
标记算法有很多种,有的可以1次遍历图像完成标记,有的则需要2次或更多次遍历,这就造成了不同的算法时间效率的差别
2.连通区域标记
(1)进行连通区域标记:
对二值图像进行连通区域标记:[L,n] = bwlabel(BW[,conn])
#参数说明:
BW:指定二值图像
conn:指定连通性;为4(4联通)/8(默认值;8联通)
L:返回标记矩阵
#背景像素会被标记为0,前景像素依据所在连通区域会被标记为1,2...
n:返回联通区域的数量
#实例:
>> [L,n] = bwlabel(bw2);
>> L
L =
1 至 25 列
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 15 15 15 15
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 15 15 15 15 15
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 15 15 15 15 15
...%此处省略
0 0 0 0 0 0
0 0 0 0 0 0
>> n
n =
99
(2)将标记矩阵转换为RGB图像:
将标记矩阵转换为RGB图像:RGB = label2rgb(L[,cmap,zerocolor,order,'OutputFormat',outputFormat])
#参数说明:
L:指定标记矩阵
cmap:指定标记与RGB颜色间的映射关系;为'jet' (默认值)/matrix(包含3列)/function
zerocolor:指定背景像素(被标记为0)的RGB颜色;为str/vector(长度为3;默认为[1,1,1])
order:指定RGB颜色与标记对应的顺序;为'noshuffle'(默认值)/'shuffle'
outputFormat:指定返回的RGB数据的格式;为'image'(默认值)/'triplets'
RGB:返回RGB图像
#实例:
>> RGB=label2rgb(L);
>> imshow(RGB)%结果见下图
3.连通区域操作
(1)查看连通区域属性:
查看各个连通区域的属性:stats = regionprops([output,]BW[,I,properties])
stats = regionprops([output,]CC[,I,properties])
stats = regionprops([output,]L[I,properties])
#虽然regionprops()也接受3维图像,但对3维图像来说,跟推荐regionprops3(),因为可获得更多信息
#参数说明:
output:指定返回值的类型
BW:指定二值图像
#返回其中每个8连通区域的指定属性
CC:指定由bwconncomp()返回的结构体
#返回其中每个连通区域的指定属性
L:指定测量标注图像
#返回其中每个标注区域的指定属性
I:指定灰度图像
#返回其中每个标注区域的指定属性,由BW/CC/L标识I中的区域
#可不指定I而指定properties
properties:指定要查看的属性;为str,默认为'Area'/'Centroid'/'BoundingBox'
stats:返回指定属性的测量值
(2)选择物体:
选择二值图像中的指定物体:[x,y,BW2,idx,xi,yi] = bwselect(BW,c,r[,n])
#参数说明:
BW:指定二值图像
c,r:选择BW(r,c)所在的物体;均为num/array
n:指定连通性;为4/8
BW2:返回指定物体构成的二值图像