第十一章 表示与描述(11.1-11.2)

第十一章 表示与描述(11.1-11.2)

背景

单元数组与结构

  • 单元数组

    单元数组提供了一种将各种类型的对象组合在一个变量名下的方法。单元数组包含的是变量的副本,而不是指向这些变量的指针。因此,若一个单元数组C的任何变量在C创建后改变,则改变不会反映在C中。具体示例见第一章。

    • 函数cellfun
      语法:D = cellfun(‘fname’, C)
      将函数fname应用与单元数组C的元素,返回结果为双精度数组D。数组D中的每个元素包含有由fname返回的与C中元素相对应的值。D与C的大小相同。
>> f = imread('D:\picture\MATLAB\1.jpg');
>> b = [1 2 3; 4 5 6; 7 8 9];
>> char_array = {'area', 'centroid'};
>> C = {f, b, char_array};
>> D = cellfun('length', C)

D =

   479     3     2
  • 结构
    结构类似于单元数组,但单元是通过数字来访问的,而结构元素是通过域名来访问的。与单元数组一样,在结构中产生的是副本。具体示例见第一章。

提取区域及其边界的函数

  • 函数bwlabel可计算一幅二值图像中的所有连接分量(区域)

    语法:[L, num] = bwlabel(f, conn)
    其中,f是输入图像,conn指定期望的连续性(4连接或8连接,后者为默认值),num是所找到的连接分量数,L是标记矩阵,它给每个连接分量分配区间[1, num]内的一个唯一整数。

    研究4连接和8连接

>> f = [ 0 1 1 1 0 1 1
         1 0 1 0 0 0 1
         0 1 0 1 0 1 1]
>> [L,M]=bwlabel(f, 4); %M = 5
>> L
L =
     0     2     2     2     0     5     5
     1     0     2     0     0     0     5
     0     3     0     4     0     5     5

>> [L,M]=bwlabel(f, 8); %M = 2
>> L

L =

     0     1     1     1     0     2     2
     1     0     1     0     0     0     2
     0     1     0     1     0     2     2

由以上实验可推得4连接相当于区域中心的上下左右四个方向区域,8连接相当于以区域中心为中心的3×3网格区域。于是:

>> f(2, 5) = 1;
>> [L,M]=bwlabel(f, 8);%M = 1
>> L
L =
     0     1     1     1     0     1     1
     1     0     1     0     1     0     1
     0     1     0     1     0     1     1
  • 函数bwperim
    语法: g = bwperim(f, conn)
    返回一个二值图像g,该图像仅包含f中所有区域的边界像素。conn指定背景的连续性:4连接(默认)或8连接。
>> f = imread('D:\picture\MATLAB\冈萨雷斯数字图像处理MATLAB版图片\dipum_images_ch11\chromo_binary.tif');
>> g = bwperim(f, 4);
>> subplot(121), imshow(f), title('原图')
>> subplot(122), imshow(g), title('边界')
![这里写图片描述](https://img-blog.csdn.net/20170707164350651?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXFfMzgzMTEwNDE=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
  • 函数bwboundaries提取二值图像f中所有区域的真实边界坐标

    语法1:B = bwboundaries(f, conn, options)
    其中,conn相对于边界本身,且具有值4或8(默认)。参数options的值为’holes’和’noholes’。使用第一个值时,提取区域和孔洞的边界;也可以提取包含嵌套区域的边界。使用第二个值时将仅提取区域及其子区域的边界。若该参数中仅包含f和conn中的一个值,则将’holes’作为options的默认值。B中先列出区域,然后列出孔洞。B是一个P×1单元数组,其中P是物体的数量。单元数组中的每个单元包含一个np×2矩阵,该矩阵的行是边界像素的行和列坐标,np是相应区域的边界像素数。每个边界的坐标都按顺时针方向排序,且边界的最后一点与第一点相同,这样就提供了一个闭合的边界。
    语法2:[B, L] = bwboundaries(…)
    此时,L是一个标记矩阵(大小与f相同),该矩阵用不同的整数来标记f的每个元素。背景像素标记0.区域和孔洞的数量由max(L(:))给出。
    语法3:[B, L, NR, A] = bwboundaries(…)
    返回所找到的区域数(NR)和一个逻辑稀疏矩阵A,该矩阵详细给出了父子孔洞的从属关系;B中的第一个NR项是区域,其余项是孔洞。孔洞数由numel(B) - NR给出。

  • 函数 flipud将边界B{k}的行进顺序从顺时针方向改为逆时针方向(反之亦然)

    语法:Breversed{k} = flipud(B{k})

  • 自定义函数bound2im生成一幅大小为M×N的二值图像

    语法:g = bound2im(b, M, N)
    其中,g在b中的坐标处其值为1,而在背景处其值为0。通常,M = size(f, 1)和N = size(f, 2),其中f是一幅图像,b是通过这幅图像得到的。若省略M和N,则g是包含边界且维持其原始坐标值的最小二值图像。

>> f = zeros(14, 14);
>> f(2:3, 2:13) = 1; f(12:13, 2:13) = 1; f(5:6, 5:10) = 1; f(9:10, 5:10) = 1;
>> f(4:11, 2:3) = 1; f(4:11, 12:13) = 1; f(7:8, 5:6) = 1; f(7:8, 9:10) = 1;
>> B = bwboundaries(f, 'noholes');
>> b = cat(1, B{:});
>> [M, N] = size(f);
>> image = bound2im(b, M, N);
>> [B, L, NR, A] = bwboundaries(f);
>> bR = cat(1, B{1:2}, B{4});
>> imageBoundaries = bound2im(bR, M, N);
>> imageNumberedBoundaries = imageBoundaries.*L
>> bR2 = cat(1, B{:});
>> imageBoundaries2 = bound2im(bR2, M, N);
>> imageNumberedBoundaries2 = imageBoundaries2.*L
>> subplot(221), imshow(f), title('原始数组')
>> subplot(222), imshow(image), title('bwboundaries提取边界')
>> subplot(223), imshow(imageNumberedBoundaries), title('区域和最内部孔洞的边界')
>> subplot(224), imshow(imageNumberedBoundaries2), title('已编号的边界')

这里写图片描述

本章其他工具箱函数

  • 函数imfill
    语法1: gB = imfill(fB, locations, conn)
    从locations指定的点开始,对输入二值图像fB的背景像素执行填充操作(即将背景像素值设为1)。若省略参数locations和conn,则函数会在屏幕上显示二值图像fB,并让用户使用鼠标来选择起始位置。
    语法2: g = imfill(f, conn, ‘holes’)
    可填充图像中的孔洞。当输入图像为二值图像时,孔洞是一个背景像素集合;若图像为灰度图像时,孔洞指较亮像素包围的暗像素区域。
>> f = imread('D:\picture\MATLAB\冈萨雷斯数字图像处理MATLAB版图片\dipum_images_ch09\recon-mask.tif');
>> gB = imfill(f);
>> subplot(121), imshow(f), title('原图')
>> subplot(122), imshow(gB), title('填充')
![这里写图片描述](https://img-blog.csdn.net/20170705192833852?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXFfMzgzMTEwNDE=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
  • 函数sortrows实现对数组的排序

    语法:z = sortrows(S)
    该函数对S中的行按升序排序。S必须是矩阵或向量。

  • 函数unique既对行进行排序又删除重复的行

    语法:[z, m, n] = unique(S, ‘rows’)
    其中,z是排序(升序)后没有重复行的数组。m和n满足z = S(m, :)和S = z(n, :)。

  • 函数circshift实现对数组的行进行上,下或左,右位移操作。

    语法:z = circshift(S, [ud lr])
    其中,ud是S上移或下移元素的数量。若ud为正,则位移操作向下;否则向上。同样,若lr为正,则数组右移lr个元素;否则向左。若只想上下移动,则省略另一个参数lr。

>> subplot(221), imshow(f), title('原图')
>> z = circshift(f, 50);
>> subplot(222), imshow(z), title('下移50')
>> z = circshift(f, [0 50]);
>> subplot(223), imshow(z), title('右移50')
>> z = circshift(f, [50 50]);
>> subplot(224), imshow(z), title('下移50并且右移50')

这里写图片描述

实用M函数

  • 函数boundaries

    语法:B = boundaries(f, conn, dir)
    跟踪f中的对象的外部边界。参数conn指明输出边界的期望连接方式(4或8)。参数dir指明边界被跟踪的方向,其值可以为’cw’(默认)或’cww’,分别表示顺时针或逆时针方向。输出B是一个单元数组,其元素是已找到的边界的坐标。

  • 函数bound2eight

    语法:b8 = bound2eight(b)
    从边界b中删除4连接的像素,而保留8连接的像素。要求b是闭合的,按顺时针方向或逆时针方向顺序排序的连接像素集合。

  • 函数bound2four

    语法:b4 = bound2four(b)
    对b的限制同bound2eight,只要存在对角连接的位置,该函数都插入新边界像素,从而产生4连接像素的输出边界。

  • 函数bsubsamp

    语法:[s, su] = bsubsamp(b, gridsep)
    在一个网格上对(单一的)边界b子取样,网格的行由gridsep个像素隔开。输出s是点数少于b的一个边界,点数由gridsep值确定。输出su是标定过的边界点的集合。

  • 函数connectpoly可使被bsubsamp子取样的边界上的点重新连接

    语法:z = connectpoly(s(:, 1), s(:, 2))
    其中,s(:, 1)和s(:, 2)分别是子取样后的边界的水平坐标和垂直坐标。要求s中的点是有序的(顺时针方向或逆时针方向)。z的行是连接边界的坐标,连接边界是通过连接s中的直线段来形成的。z中的坐标与s中的坐标的方向相同。

  • 函数intline连接两个点

    语法:[x y] = intline(x1, x2, y1, y2)
    其中,(x1, y1)和(x2, y2)分别是两个待连接点的整数坐标。输出x和y是列向量,这些列向量包含连接两点的一条直线的x和y坐标。

表示

链码

链码通过一个指定长度和方向的直线段的连接序列来表示一条边界。
每条线段的方向使用一种数字编号方案编码,如下图所示,以这种方向性数字序列表示的编码称为弗雷曼(Freeman)链码
这里写图片描述

  • 函数fchcode
    语法:函数计算一个储存在数组b中的有序边界点的np×2集合的弗雷曼链码。输出c是包含以下字段的一个结构,其中圆括号中的数字表示数组的大小:
    这里写图片描述
    (代-›链)
    参数conn仅当边界不包含对角转换时,值为4才是有效的。参数dir指定输出链码的方向:若为’same’,则链码方向与b中点的方向相同;使用’reverse’将导致链码方向相反。默认为’same’。
>> f = imread('D:\picture\MATLAB\冈萨雷斯数字图像处理MATLAB版图片\dipum_images_ch11\noisy_circular_stroke.tif');
>> subplot(231), imshow(f), title('原图')
>> h = fspecial('average', 9);
>> g = imfilter(f, h, 'replicate');
>> subplot(232), imshow(g), title('平滑处理')
>> gB = im2bw(g, 0.5);
>> subplot(233), imshow(gB), title('二值图像')
>> B = bwboundaries(gB, 'noholes');
>> d = cellfun('length', B);
>> [maxd, k] = max(d);
>> b = B{k};
>> [M N] = size(g);
>> g = bound2im(b, M, N);
>> subplot(234), imshow(g), title('边界图像')
>> [s, su] = bsubsamp(b, 50);
>> g2 = bound2im(s, M, N);
>> subplot(235), imshow(g2), title('子取样后的边界')
>> cn = connectpoly(s(:, 1), s(:, 2));
>> g3 = bound2im(cn, M, N);
>> subplot(236), imshow(g3), title('子取样后再连接的边界')
>> figure,imshow(g2)
>> figure,imshow(g3)
![这里写图片描述](https://img-blog.csdn.net/20170706111516182?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXFfMzgzMTEwNDE=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast) 后两张图放大才能看清: ![这里写图片描述](https://img-blog.csdn.net/20170706111525792?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXFfMzgzMTEwNDE=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast) ![这里写图片描述](https://img-blog.csdn.net/20170706111537991?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXFfMzgzMTEwNDE=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)

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

一条数字边界能用一个多边形以任意精度近似。在这些近似技术中,最强大的一种技术使用最小周长多边形(MPP)来表示边界。
  • 基础知识

    单元的大小决定多边形近似的精度。在极限的情况下,若每个(方形)单元的大小对应于边界上的一个像素,则MPP的每个顶点与原始边界中最靠近点间的最大误差为根号2倍像素间的最小可能距离。围成一个边界的的单元集合称为细胞组合体。
    这里写图片描述
    这里写图片描述
    只有内墙的凸顶点和外墙的凹顶点才能成为MPP的顶点。

  • 查找MPP的算法
    这里写图片描述
    这里写图片描述
    这里写图片描述
    这里写图片描述
  • 实现MPP算法的一些M函数
    • 函数qtdecomp
      语法:Q = qtdecomp(B, threshold, [mindim maxdim])
      这里写图片描述
    • 函数qtgetblk
      语法:[vals, r, c] = qtgetblk(B, Q, mindim)
      其中,vals是一个数组,该数组包含B的四叉树分解中的mindim×mindim个块的值,Q是由函数qtdecomp返回的一个稀疏矩阵。参数r和c是一个包含块的左上角的行和列坐标的向量。
  • 函数inpolygon确定一个点位于多边形边界的位置

    语法:IN = inpolygon(X, Y, xv, yv)
    其中,X和Y是包含待测点的x和y坐标的向量,xv和yv是包含按顺时针或逆时针顺序安排的多边形顶点的x和y坐标的向量。输出IN是一个向量,其长度等于待测点数。对于多边形内或边界上的点,其值为1;对边界外侧的点,其值为0。

  • 自定义函数im2minperpoly

    语法:[X, Y, R] = im2minperpoly(f, cellsize)
    其中,f是一幅包含单一区域或边界的输入二值图像,cellsize指定细胞组合体中用于包围边界的方形单元的大小。列向量X和Y包含MPP顶点的x和y坐标。输出R是一幅由细胞组合体包围的区域的二值图像。

  • 自定义函数minperpoly

    语法:[x, y] = minperpoly(B, cellsize)
    其中,B是一幅二值图像,它包含单个区域或边界,cellsize指定细胞组合体中用于包围边界的方形单元的大小。列向量X和Y包含MPP顶点的x和y坐标。

>> f = imread('D:\picture\MATLAB\冈萨雷斯数字图像处理MATLAB版图片\dipum_images_ch11\mapleleaf.tif');
>> subplot(321), imshow(f), title('原图')
>> b = boundaries(f, 4, 'cw');
>> b = b{1};
>> [M, N] = size(f);
>> xmin = min(b(:, 1));
>> ymin = min(b(:, 2));
>> bim = bound2im(b, M, N, xmin, ymin);
>> subplot(322), imshow(bim), title('4连接')
>> subplot(322), imshow(bim), title('4连接边界')
>> [x, y] = minperpoly(f, 2);
>> b2 = connectpoly(x, y);
>> B2 = bound2im(b2, M, N, xmin, ymin);
>> subplot(323), imshow(B2), title('大小为2的单元')
>> [x, y] = minperpoly(f, 3);
>> b3 = connectpoly(x, y);
>> B3 = bound2im(b3, M, N, xmin, ymin);
>> subplot(324), imshow(B3), title('大小为3的单元')
>> [x, y] = minperpoly(f, 4);
>> b4 = connectpoly(x, y);
>> B4 = bound2im(b4, M, N, xmin, ymin);
>> subplot(325), imshow(B4), title('大小为4的单元')
>> [x, y] = minperpoly(f, 8);
>> b8 = connectpoly(x, y);
>> B8 = bound2im(b8, M, N, xmin, ymin);
>> subplot(326), imshow(B8), title('大小为8的单元')

这里写图片描述

>> [x, y] = minperpoly(f, 10);
>> b10 = connectpoly(x, y);
>> B10 = bound2im(b10, M, N, xmin, ymin);
>> subplot(221), imshow(B10), title('大小为10的单元')
>> [x, y] = minperpoly(f, 16);
>> b16 = connectpoly(x, y);
>> B16 = bound2im(b16, M, N, xmin, ymin);
>> subplot(222), imshow(B16), title('大小为16的单元')
>> [x, y] = minperpoly(f, 20);
>> b20 = connectpoly(x, y);
>> B20 = bound2im(b20, M, N, xmin, ymin);
>> subplot(223), imshow(B20), title('大小为20的单元')
>> [x, y] = minperpoly(f, 32);
>> b32 = connectpoly(x, y);
>> B32 = bound2im(b32, M, N, xmin, ymin);
>> subplot(224), imshow(B32), title('大小为32的单元')

这里写图片描述

标记

标记是边界的一维函数表示,它可以使用各种方式来生成。将边界表示简化为一个一维函数,它描述起来比原始的二维函数更容易。

  • 函数signature可寻找边界的标记

    语法:[dist, angle] = signature(b, x0, y0)
    其中,b是一个np×2数组,它的行包含按顺时针或逆时针方向排列的边界点的x和y坐标。(x0, y0)是一个点的坐标,若省略,则函数默认使用该边界的质心坐标。

  • 函数cart2pol把笛卡尔坐标转换为极坐标

    语法:[THETA, RHO] = cart2pol(X, Y)
    其中,X和Y是包含笛卡尔坐标点的坐标和向量。向量THETA和RHO包含对应的极座标角度和长度。它们具有相同的维度。

  • 函数pol2cart将极坐标转换为笛卡尔坐标

    语法:[X, Y] = pol2cart(THETA, RHO)

>> f = imread('D:\picture\MATLAB\冈萨雷斯数字图像处理MATLAB版图片\dipum_images_ch11\boundary_sq.tif');
>> g = imread('D:\picture\MATLAB\冈萨雷斯数字图像处理MATLAB版图片\dipum_images_ch11\boundary_triangle.tif');
>> f1 = bwboundaries(f, 'noholes');
>> [distf, anglef] = signature(f1{1});
>> g1 = bwboundaries(g, 'noholes');
>> [distg, angleg] = signature(g1{1});
>> subplot(221), imshow(f), title('方形')
>> subplot(222), imshow(g), title('三角形')
>> subplot(223), plot(anglef, distf)
>> subplot(224), plot(angleg, distg)

这里写图片描述

边界线段(片段)

将边界分解为线段降低了边界的复杂性,从而简化了描述过程。
这里写图片描述

骨骼

表示一个平面区域的结构形状的一种重要方法就是将它简化为图形,这种简化可以通过一种细化(也称骨骼化)算法得到该区域的骨骼来实现。


  • 函数bwmorph产生图像中所有区域的骨骼

语法:skeletonImage = bwmorph(B, ‘skel’, Inf)
该函数删除物体边界上的像素但不允许物体断开。

>> f = imread('D:\picture\MATLAB\冈萨雷斯数字图像处理MATLAB版图片\dipum_images_ch11\Fig1116(a)(chromo_binary).tif');
>> subplot(221), imshow(f), title('原图')
>> s = bwmorph(f, 'skel', Inf);
>> subplot(222), imshow(s), title('骨骼')
>> s1 = bwmorph(s, 'spur', 8);
>> subplot(223), imshow(s1), title('刺状突起去除8次')
>> s2 = bwmorph(s1, 'spur', 7);
>> subplot(224), imshow(s2), title('刺状突起额外去除7次')

这里写图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值