一、Image thresholding : imread()、graythresh()、im2bw()
1. 读入图像
I = imread(‘filename’):通过文件名导入图像I(注意必须在同一文件夹)
level = graythresh(I): 找出并返回图像I(必须是灰度图) 的合适阈值level
I_bw = im2bw(I, level): 将图像I(必须是灰度图)通过计算好的阈值level 转化为二值图 I_bw
二、Background Estimation
1. Estimate for the gray level of the background : strel()
给你一张图,让你找出这张图的背景,就需要用到: SE = strel(shape, parameters)
举例:se = strel('disk',15) 创建半径15的圆盘
tips: 由于该函数有些复杂且学习笔记篇幅有限,有关该函数更多信息可移步下面两个链接: https://ww2.mathworks.cn/help/images/ref/strel.html#bu7pnvx-1 https://blog.csdn.net/hyaqian123/article/details/79924627
2. background subtraction : imsubtract()、imopen()、strel()
Z = imsubtract(X, Y):简单说就是图像X每个像素灰度值 减去图像Y每个像素灰度值,返回一个图像Z。 更详细信息可移步 https://ww2.mathworks.cn/help/images/ref/imsubtract.html?s_tid=doc_ta
J = imopen(I,SE) :在灰度或二值图像上执行形态开放图像I,返回打开的图像J。 SE是由返回的单个结构元素对象 strel或offsetstrel功能。形态学开放操作是侵蚀,随后是扩张,使用相同的结构元素进行两种操作。
那么imopen()、strel()这两个函数如何结合呢? imopen(I, strel(shape, parameters))
举例:下面的一张图片摘自MATLAB中国,链接 https://ww2.mathworks.cn/help/images/ref/imopen.html tips: 代码 imshow(原件); 是翻译问题,应是 imshow(original);
;
大概了解其工作原理后,我们看下面的应用:
BG = imopen(I, strel('disk', 15)) 即取出 原图I 的 背景BG。
3. Thresholding on Background Removed Image
我们图像处理一般要将 rice.png 这种灰度图转化为二值图(即black-white黑白图)。
那么我们联系之前学过的可以想到两种处理方法;
(1)一种是之前直接阈值处理函数
k = graythresh(I); I_bw = im2bw(I, k);
(2)另一种是2. background subtraction 提到的先背景减法处理,再转化为二值图 BG = imopen(I, strel(‘disk’, 15)); % 取BG I2 = msubtract(I, BG); % 做减法,得到图像I2 level = graythresh(I2); % 得到阈值level I_bw = im2bw(I2, level) % 得到二值图I_bw
绘出图像进行对比——
tips:
我们可以看到 I直接阈值处理 的图像有一些米粒部分由于像素值较小,低于阈值而被误认为是背景而被二值化成黑色,只留下了白色点;先做背景减法再二值化 的图像中米粒则比较完好。
代码如下:
I = imread('rice.png');
subplot(2,2,1);
imshow(I); title('原图I');
%内置function直接处理
level = graythresh(I);
bw = im2bw(I, level);
subplot(2,2,2);
imshow(bw); title('I直接阈值处理');
%提取背景
BG = imopen(I, strel('disk', 15));
subplot(2,2,3);
imshow(BG); title('I的BG');
%原图 - 背景
I2 = imsubtract(I, BG); level = graythresh(I2);
bw2 = im2bw(I2, level);
subplot(2,2,4);
imshow(bw2); title('I - BG');
三、Connected-component labeling
连接和边界问题是图像问题的重点。
我们先认识一下label是什么,它不仅仅是坐标轴的标签,还可以是一幅二值图中像素连通集的标号(从上到下,从左到右给连通集标号1,2,3,……)(连通区域可能可以联合成连通集)
比如我们如果按照8连通的标准去给 rice.png 的米粒数数,那就是有99个连通集,你可以认为有99个米粒(若米粒连在一起、图像边缘处米粒size过小算不算一粒米等的细分问题另当别论)
1. Built in Connected-component labeling Algorithm : bwlabel()、find()、mean()、size()
(1)L = bwlabel(BW, conn):返回图像BW的标签矩阵L, conn指定连接方式。
conn指定的连接方式有两种:4连通、8连通(若无第二个参数conn,则默认8连通) [L, num] = bwlabel(BW, nonn):这里num就是返回的BW中连通集的个数。
老规矩,更详细信息请见 https://ww2.mathworks.cn/help/images/ref/bwlabel.html?s_tid=doc_ta
(2)location = find(V == key):在矩阵V中寻找值key,返回其位置(位置按照从左到右、从上到下的顺序)。
该函数用法多样,提供下面链接供参考: https://ww2.mathworks.cn/help/matlab/ref/find.html?s_tid=doc_ta
(3) M = mean(A): 返回 A 沿大小不等于 1 的第一个数组维度的元素的均值。
如果 A 是向量,则 mean(A) 返回元素均值。
如果 A 为矩阵,那么 mean(A) 返回包含每列均值的行向量。
如果 A 是多维数组,则 mean(A) 沿大小不等于 1 的第一个数组维度计算,并将这些元素视为向量。此维度会变为 1,而所有其他维度的大小保持不变。
该函数用法多样,提供下面链接供参考: https://ww2.mathworks.cn/help/matlab/ref/mean.html?s_tid=doc_ta
(4) sz = size(A, n):n 取1或者2,返回矩阵A的第一维度(行cow)或者第二维度(列column)。
该函数用法多样,提供下面链接供参考: https://ww2.mathworks.cn/help/matlab/ref/size.html
OKOK~
上面我们已经找到了较好的将rice.png转化为二值图的方式
现在我们有两个问题:
one 米粒的最大size是多少?
two 米粒的平均size是多少?
解决的代码如下:
I = imread('rice.png');
BG = imopen(I, strel('disk', 15));
I2 = imsubtract(I, BG); level = graythresh(I2);
BW = im2bw(I2, level);
%%%%%%%% 上面是找背景BG的代码 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
[labeled, numObjects] = bwlabel(BW, 8); % labeled是BW的标记矩阵,numObjects是连通集的数量
num=zeros(1,numObjects); % 创建1 x numObjects大小的全零矩阵num
for i=1:size(BW,1) % for 行i(图BW的)
for j = 1:size(BW,2) % for 列j(图BW的)
for k = 1:numObjects
if labeled(i,j)==k % 如果矩阵labeled坐标(i,j)处 == k,就将矩阵num的k位置的值++
num(k)=num(k)+1; % 想一想,其实该位置的值是遍历中该label出现的次数,也就代表了size
end
end
end
end
largest=find(num==max(num)); % 矩阵num中找出最大值的位置,即最大size的位置
s=mean(num); % s是平均size
得出的数据如下:
2. Object Properties : regionprops()
STATS = regionprops(L, properties):若properties为字符串’basic’,则属性:‘Area’,'Centroid’和’BoundingBox’将被计算。
用 rice.png 解释一下三个属性: Area: 米粒大小 Centroid: 米粒中心坐标 BoundingBox: 能框住米粒的最小矩形的左上角坐标、右下角坐标 [x_left,y_left,x_right,y_right]
该函数用法多样,提供下面链接供参考: https://ww2.mathworks.cn/help/images/ref/regionprops.html?requestedDomain=zh
我们用该函数对之前rice.png 的label 进行查看信息
I = imread('rice.png');
BG = imopen(I, strel('disk', 15));
I2 = imsubtract(I, BG); level = graythresh(I2);
BW = im2bw(I2, level);
[labeled, numObjects] = bwlabel(BW, 8);
%%%%% 上面的都是前面的代码 %%%%%%%%%
graindata = regionprops(labeled, 'basic'); % 根据矩阵labeled 绘制一张basic信息表
graindata(51); % 查看信息表中标号为51的basic信息
下面是得到的graindata——(1-28)
3. Interactive Selection : bwselect()
bwselect(BW):可以与二值图进行互动,挑选你想要的元素。
先上一段代码——
I = imread('rice.png');
BG = imopen(I, strel('disk', 15));
I2 = imsubtract(I, BG);
BW = im2bw(I2, graythresh(I2));
ObjI = bwselect(BW);
imshow(ObjI);
接下来看好了:
这是原图:
我们用鼠标左键点击我们想要的米粒,下图米粒上有彩色米字形的,即我们选中的米粒:
接下来我们鼠标移到图像外边,但还在Figure里面的灰色区域并用鼠标右击灰色区域,接下来就是见证奇迹的时刻!
本笔记多采自YouTubeMATLAB教学视频
|
请发表评论