第十一章(1至2节) 表示与描述

来源:互联网 发布:红叶知弦调教 编辑:程序博客网 时间:2024/05/18 14:42

1. 背景知识

1.1 单元数组与结构

单元数组其实第二章有所接触,它提供了一种将各种类型的对象(如数字、字符、矩阵和其他单元数组)组合在一个变量名下的方法。假设有三个实体:(1)一幅238*315的 uint8类图像f;(2)一个以3*2数组的行的形式出现的二维坐标序列b;(3)一个包含两个字符名称char_array={‘area’,’centroid’}的单元数组。这三个相异实体可以使用单元数组组织到一个变量C中:C={f,b,char_array}

 C={f,a,char_array};>> CC =   1 列    [238x315 uint8]  2 列    [3x2 double]  3

如果要获得具体值,可以用花括号,如果要获得变量的描述,可以用圆括号。
单元数组包含的是变量的副本,而不是指向这些变量的指针。
假设我们要写一个函数,该函数输出一幅图像的平均亮度、维数、行的平均亮度和列的平均亮度,则可以使用标准方法按一下形式写函数。

代码如下:

function[AI,dim,AIrows,AIcols]=image_states(f)dim=size(f);AI=mean2(f);AIrows=mean(f,2);AIcols=mean(f);

1.2 本章使用的其他一些MATLAB和IPT函数

函数imfill对于二值图像和灰度图像作用不同。在输入二值图像的背景像素上从参数指定的点的开始,执行填充操作(即将背景像素值设为1)。

代码实例:

b=imread('finger.jpg');>> fb=logical(b);>> gb=imfill(fb,4,'holes');subplot(1,2,1),imshow(b);>> title('原图');title('将location设为4的结果');

效果图像:

这里写图片描述

函数find和bwlabel一起使用,返回构成某个指定对象的像素的坐标向量。若[gb,num]=bwlabel(fB)产生了多个连接区域,则使用以下语法可以获得第二个区域的坐标:

[r,c]=find(g==2)

在本章中,区域或者边界的二维坐标被组织成np*2数组的形式,其中每行是一个(x,y)坐标对,np是区域或边界中的点的数目。在某些情况下,有必要对数组进行排序。为此,可使用函数sortrows。

代码示例:

>> S=[1 2;7 3;2 4];>> z=sortrows(S)z =     1     2     2     4     7     3

该函数按升序对数组S的行进行排序。参量S必须是矩阵或列向量。若想对数组S的行排序,又要去除重复行,则可使用函数unique。

代码示例:

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,n]=unique(S,'rows')z =     1     2     4     3     6     5m =     1     4     2n =     1     3     1     2

z是排序后无重复行的数组,m和n是z=S(m,:),S=z(n,:)。注意z是按升序排列的,m指示最初数组的哪些行被保留。通常,有必要对数组行进行向上、向下或侧移指定位置数的移位操作,为此我们使用函数circshift:
代码如下:

z=cirshift(S,[ud lr])
z=circshift(S,[1,2])z =     4     3     1     2     6     5     1     2S =     1     2     6     5     1     2     4     3

若ud是S向上或向下移位的元素数。若ud为正,则移位操作向下;否则向上。类似的,若lr为正,则移位操作向右移动lr个元素;否则向左。

1.3 一些基本的m函数

函数boundaries

边界已被表示为np*2数组,数组中的每一行表示一个二维的坐标对。大部分这种函数会自动地将大小为2*np的坐标数组转换为大小为np*2的数组。

代码实例:

f2=logical(b);>> B=boundaries(f2);>> d=cellfun('length',B);>> [max_d,k]=max(d);v=B{k(1)};

向量v包含输入图像中最长边界的坐标,k是对应的区域数;数组v的大小为np*2。若最大边界多于一条,则最后一条命令简单地选出最大长度边界中的第一个。因为使用函数boundaries计算出的每个边界中第一个点和最后一个点相同,所以行v(1,:)和行v(end,:)相同。
而函数bound2eight会从b中去除一些像素。函数bound2im生成一幅二值图像g,该图像的大小为M*N,边界点为1,背景值为0。当对边界进行操作时,计算连接两点的一条直线的整数坐标是一个基本工具。

2. 表示

2.1 链码

链码通过一个指定长度与方向的直线段的连接序列来表示一个编号方案加以编码,如图

这里写图片描述

典型情况下,这一表示建立在线段的4连接或者8连接之上。每条线段的方向通过一个编号方案加以编码,基于这种方式的链码称为Freeman链码。一条边界的链码取决于起点。然而,代码可以通过将起点处理为方向数的循环序列和重新定义起点的方法进行归一化,因此,产生的数字序列形成一个最小幅值的整数。有一个函数fchcode,该函数计算一个保存在数组b中的np*2个已排序边界点集的Freeman链码。下面的例子是获得对象的边界的链码和一阶差分。
使用9*9平均掩模的处理结果g:

b=imread('E:\matlab书中资源\素材图片\dipum_images_ch11\Fig1102(a)(noisy_circular_stroke).tif');>> imshow(b);>> h=fspecial('average',9);>> g=imfilter(b,h,'replicate');

把g经阈值处理后获得的二值图像

g=im2bw(g,0.5);

获取该图像的边界使用函数boundaries。

B=boundaries(g);

接下来的代码为

>> cn=connectpoly(s(:,1),s(:,2));>> g2=bound2im(cn,M,N,min(cn(:,1)),min(cn(:,2)));>> subplot(2,3,6),imshow(g2);>> title('连接点后的结果');d=cellfun('length',B);>> [max_d,k]=max(d);>> b=B{1};>> [M N]=size(g);>> g=bound2im(b,M,N,min(b(:,1)),min(b(:,2)));>> subplot(2,3,4),imshow(g);>> title('二值图像的边界');>> [s,su]=bsubsamp(b,50);g2=bound2im(s,M,N,min(s(:,1)),min(s(:,2)));>> subplot(2,3,5),imshow(g2);>> title('二次取样后的边界');>> cn=connectpoly(s(:,1),s(:,2));n=connectpoly(s(:,1),s(:,2));>> g2=bound2im(cn,M,N,min(cn(:,1)),min(cn(:,2)));>> subplot(2,3,6),imshow(g2);>> title('连接点后的结果');

效果如下:

这里写图片描述

2.2 使用最小周长多边形的多边形近似

假设我们用一组级联的单元来包围一条边界,如下图,这将有助于边界的可视化,就像对应于单元条的内外边界的两堵墙,对象边界可以被看成是包围两堵墙的区域间的橡皮条。Sklansky方法使用一个所谓的“细胞联合体”或者“细胞马赛克”,对我们来说,它是一组用于包围边界的方形元素的集合。

这里写图片描述

查找一个区域的MPP的如下步骤:

  1. 获取细胞联合体。
  2. 获取细胞联合体的内部区域。
  3. 使用函数boundaries以4连接顺时针坐标序列的形式获得步骤2中的区域的边界。
  4. 使用函数fchcode获得该4连接序列的Freeman链码。
  5. 从链码中获得凸顶点(黑点)与凹顶点(白顶点)。
  6. 使用黑点作为顶点构造一个初始多边形,在进一步的分析中删除位于该多边形之外的任何白顶点(在多边形边界上的白顶点将保留)。
  7. 用剩余的黑白点作为顶点构造一个多边形。
  8. 删除所有凹顶点的黑点。
  9. 重复步骤7与8,直到变化停止。此时,所有角度为180度的顶点均将删除。剩下的点就是该MPP的顶点。

这里写图片描述

MPP算法实现中用到的一些M函数
我们可使用函数qtdecomp作为获得包围边界的细胞联合体的第一步。通常,我们考虑区域B,它由1和背景0的组成。

代码实例:

b=bwperim(b,8);Q=qtdecomp(b,0,2);R=imfill(bf,'holes')&~bf;b=boundaries(b,4,'cw');b=b{1};

函数inpolygon用在函数minperpoly中,以便决定一个点是否在多边形的外部、边界上或者多边形的内部,其语法为

in=inpolygon(x,y,xv,yv)

其中,x和y是包含待测点的x和y坐标的向量,而xv和yv是包含按顺时针或逆时针顺序安排的多边形顶点的x和y坐标的向量。数组IN是一个向量,其长度等于待测点数。若点在多边形边界的内部或边界上,其值为1;若点在边界外部,则其值为0。
下面是计算MPP的M函数
我们使用函数minperpoly。语法为:

[x,y]=minperpoly(B,cellsize)

其中,B是一幅输入二值图像,它包含单个区域或边界,而cellsize是细胞联合体中用于形成边界的方形单元的大小。列向量x和y包含MPP顶点的x坐标和y坐标。

代码实例:

 b=boundaries(c,4,'cw');>> b=b{1};>> [M,N]=size(c);>> xmin=min(b(:,1));>> ymin=min(b(:,2));>> bim=bound2im(b,M,N,xmin,ymin);[x,y]=minperpoly(c,2);>> b2=connectpoly(x,y);>> B2=bound2im(b2,M,N,xmin,ymin);subplot(2,3,1),imshow(c);>> title('原图');>> subplot(2,3,2),imshow(bim);>> title('连接边界');

实例图像:

这里写图片描述

2.3 标记

标记是边界的一维函数的表示,它可以通过多种方法生成。其中最简单的方法就是作为角度的函数画出从一个内部点(如质心)到边界的距离。附录中有个函数signature可用于查找给定边界的标记,语法为:

[st,angle,x0,y0]=signature(b,x0,y0)

其中,b是一个大小为np*2的数组,它包含有一条按顺时针或逆时针排列边界的xy坐标。作为不断增加的angle函数的标记的幅值输出在st中。函数signature使用MATLAB函数cart2pol将笛卡尔坐标转换成极坐标,语法为

[theta,rho]=cart2pol(x,y)

其中,x和y是包含笛卡尔坐标点的坐标的向量。向量theta和rho包含对应极坐标下的长度和角度。若x和y是行向量,则theta和rho也是行向量;若x和y是列向量,则theta和rho也是列向量。

2.4 边界判断

将一条边界分解为片段通常是很有用的。分解降低了边界的复杂度,从而简化了描述过程。当边界包含一个或者多个携带形状信息的重要凹面时,这种方法尤其具有吸引力。在这种情况下,使用由边界包围的区域凸壳对边界的鲁棒分解是一种有力的工具。

这里写图片描述

2.5 骨骼

用于表示平面区域结构形状的一种重要方法是将其简化为一幅图形。这一简化可以通过一种细化(也成为骨骼化)算法获取区域骨骼来完成。
如第九章所述,IPT通过函数bwmorph来生成二值图像B中所有区域的骨骼:

代码实例:

f=imread('E:\matlab书中资源\素材图片\dipum_images_ch11\Fig1113(a)(chromo_original).tif');>> f=im2double(f);>> h=fspecial('gaussian',25,15);>> g=imfilter(f,h,'replicate');>> subplot(2,3,1),imshow(f);>> subplot(2,3,2),imshow(g);>> title('使用25*25高斯空间掩模平滑图像后的结果');>> g=im2bw(g,1.5*graythresh(g));>> subplot(2,3,3),imshow(g);>> title('经阈值处理后的图像');>> s=bwmorph(g,'skel',Inf);>> subplot(2,3,4),imshow(s);>> title('骨骼');>> s=bwmorph(g,'spur',8);>> subplot(2,3,5),imshow(s);>> s=bwmorph(g,'skel',Inf);>> s1=bwmorph(s,'spur',8);subplot(2,3,5),imshow(s1);>> title('应用8次去除毛刺的算法后的骨骼');>> s1=bwmorph(s1,'spur',15);subplot(2,3,6),imshow(s1);>> title('再应用7次去除刺算法后的骨骼');

效果如下:

这里写图片描述

原创粉丝点击