第11章 表示与描述
11.1 背景知识
11.1.1 单元数组与结构
-
单元数组
单元数组提供了一种将各种类型的对象(如数字,字符,矩阵和其他单元数组)组合在一个变量名下的方法。
例如:
a = [1 2 3]; c = {'qwe',a,52}; disp(c) %输出为:'qwe' [1x3 double] [52]
用{}来表示下标
a = [1 2 3]; c = {'qwe',a,52}; disp(c{2}); disp(c{2}(2));
用()可以获得单元数组元素的信息(基本元素则直接输出)
a = [1 2 3]; c = {'qwe',a,52}; c(1) % 输出 'qwe' c(2) % 输出 '[1x3 douuble]'
这种方法同样适用于size函数
size(c(2)) ans = 1 1 size(c{2}) ans = 1 3
celldisp 递归输出单元数组的信息(就是会输出单元数组里的元素数据而不是元素信息)
a = [1 2 3]; c = {'qwe',a,52}; celldisp(c); % 输出 c{1} = qwe c{2} = 1 2 3 c{3} = 52 disp(c); % 输出'qwe' [1x3 double] [52]
函数cellfun使用语法:
D = cellfun(‘fname’,C)
将函数fname应用于单元数组C的元素,返回结果为双精度数组D。数组D中的每个元素包含有由fname返回的与C中元素相对应的值。输出数组D与单元数组C的大小相同。
D = cellfun('length',c) D = 3 3 1
-
结构
就允许将不同的数据收集在一起组成一个单一变量而言,结构类似于单元数组。然而,与单元数组不同的是,单元是通过数字来访问的,而结构的元素则是通过称为域的名称进行访问的。例如:
s.a = 1; s.b = 2; s % 输出 s = a:1 b:2
11.1.2 本章中使用的其他一些MATLAB和IPT函数
-
函数imfill。用fB和fI来表示二值图像和灰度图像。若输出是二值图像,则我们用gB 来表示它;否则将简单地表示为g。语法为:
gB = imfill(fB,locations,conn)
f = imread('c:\图像\洞.tif'); g = imfill(f); figure,imshow(f) figure,imshow(g)
图像1为原图像
图像2为填充后的图像
-
bwlabe(f)将二值图像分区(可以用来计数)
f = imread('c:\图像\菌落.tif'); f = im2bw(f); f = imfill(f, 4, 'holes'); [g, n] = bwlabel(f); [w, h] = size(g); l = zeros(w, h); sw = sqrt(n); sh = n / sw; for i=1:n [c, r] = find(g(:) == i); % l = zeros(w, h); % 这句话让每次读取都独立显示 l(c) = 1; subplot(floor(sw), ceil(sh), i), imshow(l), title(i); end
-
sortrows对向量进行升序排序
z = sortrows(S)
参量S必须是矩阵或列向量。函数sortrows只与np x 2数组一起使用。若一些行的第一坐标相同,则按第二坐标升序排序。若想既对数组S的行排序,又要去除重复行,则可使用函数unique,其语法如下所示:
[z,m,n] = unique(S,‘rows’)
其中z是排序后无重复行的数组,m和n是z = S(m,:)和S = z(n,:)。例如,若S =[1 2;6 5;1 2;4 3],则z = [1 2;4 3;6 5],m = [ 3;4;2]和n = [1;3;1;2]。注意z是按升序排列的,m指示最初数组的哪些行被保留。
通常,有必要对数组行进行向上,向下或侧移指定位置数的位移操作,为此我们使用函数circshift:
z = circshift(S,[ud lr])
其中ud是S向上或向下移位的元素数。若ud为证,则移位操作向下;否则向上。类似地,若lr为正,则移位操作向右移动lr个元素;否则向左。若只需要向上和向下的移位操作,则可以使用以下的简单方法:
z = circshift(S,ud)
若S是一幅图像,则circshift就是我们所熟悉的对图像进行的卷动操作(向上或向下)或平移操作(向左或向右)。
11.1.3 一些基本的M函数
- boundaries(f,conn,dir)跟踪f的外部边界
f = imread('c:\图像\菌落.tif');
f = imfill(f,4,'holes');
g = boundaries(f, 4, 'cw');
d = cellfun('length', g);
[max_d, k] = max(d);
v = g{k(1)};
[w, h] = size(f);
l = zeros(w, h);
l(v(:,1), v(:,2)) = 1;
subplot(1, 2, 1), imshow(f), title('原图');
subplot(1, 2, 2), imshow(l), title('边界最长的');
11.2 表示
11.2.1 链码
-
函数fchcode的语法为
c = fchcode(b,conn,dir)
该函数计算一个保存在数组b中的np x 2个已排序边界点集的Freeman链码。输出c是一个包含以下域的结构,其中包含在圆括号中的数字表示数组大小:
参数conn指定代码的连接方式;其值可以是4或8(默认)。仅当边界不包括对角转换时,值设为4才是有效的
参数dir指定输出代码的方向:若设为’same’,则代码的方向与b中的点的方向相同。若设定为’reverse’,则代码的方向与b中的点的方向相反。默认为’same’。因此,写为c=fchcode(b,conn)时将使用默认方向,而写为c = fchcode(b)时则使用默认的连接方式和方向。
图像1为噪声图像;
图像2是用9 x 9平均掩模平滑后的图像
图像3是经阈值处理后的图像
图像4是二值图像的边界
图像5是二次取样后的边界(经过膨胀处理后)
图像6是连接图像5中的点的效果
11.2.2 使用最小周长多边形的多边形近似
在这里插入图片描述
-
按上面所说MMP就是最小周长的多边形,SKlansky方法则根据上述四个特性(规则)来进行寻找。
接着就是寻找一个区域的MMP的步骤:
-
MPP算法实现中用到的一些M函数
**Q = qtdecomp(B,threshold,[mindim maxdim])**将图像分割成等大小的部分方块
f = imread('c:\图像\洞.tif'); h = fspecial('average', 9); f = imfilter(f, h, 'replicate'); f = im2bw(f, 0.5); l = f(1:512, 1:512); b = bwperim(l, 8); Q = qtdecomp(b, 0, 2); [vals, r, c] = qtgetblk(b, Q, 2); l = zeros(512, 512); for i=1:length(r) l(r(i), c(i)) = vals(1, 1, i); l(r(i) + 1, c(i)) = vals(2, 1, i); l(r(i), c(i) + 1) = vals(1, 2, i); l(r(i) + 1, c(i) + 1) = vals(2, 2, i); end subplot(1, 2, 1), imshow(f), title('原图'); subplot(1, 2, 2), imshow(l), title('分块后');
-
计算MPP的M函数
[x,y] = minperpoly(B,cellsize)
其中,B是一幅输入二值图像,它包含单个区域或边界,而cellsize是细胞联合体中用于形成边界的方形单元大小。列向量x和y包含MPP顶点的x坐标和y坐标。
f = imread('img20.tif'); subplot(3, 3, 1), imshow(f), title('原图'); B = im2bw(f); subplot(3, 3, 2), imshow(B), title('二值图'); b = boundaries(B, 4, 'cw'); b = b{1}; [M, N] = size(B); bim = bound2im(b, M, N, min(b(:, 1)), min(b(:, 2))); subplot(3, 3, 3), imshow(imdilate(bim, ones(3, 3))), title('boundaries'); [x, y] = minperpoly(B, 2); b = connectpoly(x, y); bim= bound2im(b, M, N, xmin, ymin); subplot(3, 3, 4), imshow(imdilate(bim, ones(3, 3))), title('MMP 2'); [x, y] = minperpoly(B, 3); b = connectpoly(x, y); bim= bound2im(b3, M, N, xmin, ymin); subplot(3, 3, 5), imshow(imdilate(bim, ones(3, 3))), title('MMP 3'); [x, y] = minperpoly(B, 4); b = connectpoly(x, y); bim= bound2im(b, M, N, xmin, ymin); subplot(3, 3, 6), imshow(imdilate(bim, ones(3, 3))), title('MMP 4'); [x, y] = minperpoly(B, 8); b = connectpoly(x, y); bim = bound2im(b, M, N, xmin, ymin); subplot(3, 3, 7), imshow(imdilate(bim, ones(3, 3))), title('MMP 8');
11.2.3标记
-
标记是边界的一维函数的表示。
signature(b, x0, y0) 用于查找给定边界的标记
该函数的b需要必须是像素宽的边界,如boundaries获得的边界
- cart2pol(X, Y) 将笛卡尔坐标转换为极坐标
11.2.4 边界片段
11.2.5 骨骼
f = imread('c:\图像\骨骼1.tif');
figure,imshow(f)
f = im2double(f);
h = fspecial('gaussian',25,15);
g = imfilter(f,h,'replicate');
figure,imshow(g);
g = im2bw(g,1.5*graythresh(g));
figure,imshow(g);
s = bwmorph(g,'skel',Inf);
figure,imshow(s);
s1 = bwmorph(s,'spur',8);
figure,imshow(s1);
s1 = bwmorph(s,'spur',7);
figure,imshow(s1);
s2 = bwmorph(s1,'spur',7);
figure,imshow(s2);
图像1为分割后的人类的染色体
图像2为使用25 x 25高斯空间掩模(sig = 15)平滑图像f后的结果;
图像3是经过阈值处理后的图像
图像4为骨骼
图像5为应用8次去除毛刺的算法后的骨骼
图像6为再应用7次去除毛刺算法后的骨骼