首页 > 解决方案 > MATLAB 的 `regionprops` 函数如何计算周长?

问题描述

我发现该函数使用链码来编码形状的边界,然后使用以下公式以这种方式计算周长:

perimeter = sum(isEven)*0.980 + sum(~isEven)*1.406 - sum(isCorner)*0.091;

但是,我不知道在某些特殊情况下如何计算此链码。

考虑以下示例(MATLAB 生成的周长为 10.0150):

 1     1     1     1     1
 1     1     0     0     1

MATLAB 如何定义/计算连接到左侧 2x2 正方形的一像素宽线周围的周长?

更确切地说:

如果我使用字母表示非零边框像素(在此示例中所有 1 都是边框):

 a     d     e     f     g
 b     c                 h

例如,链码可以从a. 如果我们顺时针计算它,它会在c, e, f...a宽线等)。

标签: matlabimage-processing

解决方案


获取链码有两个步骤:追踪边界和将坐标编码为链码。这后一步是微不足道的,我不会详细说明。我认为这个问题是关于追踪边界的。

通常,所跟踪的是形成边界的对象像素(即具有至少一个背景邻居)。重要的是按顺序进行,仅列出这些像素是不够的。但请注意,对边界的这种描述是有偏差的:真实对象大于通过在对象边界处连接像素中心形成的多边形。周长计算需要考虑到这一点(如您链接的博客文章中所述)。

这段代码稍微改编自这篇博文img是一个逻辑数组:

% Data for chain code encoding:
directions = [ 1, 0
               1,-1
               0,-1
              -1,-1
              -1, 0
              -1, 1
               0, 1
               1, 1];
% Get a start point, any pixel on the boundary is OK:
indx = find(img,1)-1;           % 0-based indexing is easier
% Image sizes
sz = [size(img,2),size(img,1)]; % x,y sizes, rather than y,x sizes
% Coordinates for start point
start = [floor(indx/sz(2)),0];
start(2) = indx-(start(1)*sz(2));
% Initialize algorithm
cc = [];                        % The chain code
coord = start;                  % Coordinates of the current pixel
dir = 1;                        % The starting direction
% Loop till full boundary is traced
while 1
   newcoord = coord + directions(dir+1,:);
   if all(newcoord>=0) && all(newcoord<sz) ...
         && img(newcoord(2)+1,newcoord(1)+1)
      cc = [cc,dir];
      coord = newcoord;
      dir = mod(dir+2,8);
   else
      dir = mod(dir-1,8);
   end
   if all(coord==start) && dir==1 % back to starting situation
      break;
   end
end

正如您在此处看到的,该算法从一个随机像素开始,并选择一个方向来绕行。然后它通过在给定方向上找到下一个邻居来遵循边界。链接的博客文章详细说明了如何找到此邻居。简而言之,您查看当前方向,寻找具有背景邻居的第一个相邻对象像素。给定我们来自的当前位置和方向,可以证明特定方向上的邻居将是背景像素。围绕当前点顺时针(或逆时针,选择一个)方向,从该背景像素开始,第一个对象像素将保证是边界像素。我们将其添加到列表中并继续。

当我们到达起始位置和方向时,算法终止。因此,对象的 1 像素厚部分将被访问两次,以完成边界跟踪。


推荐阅读