MATLAB的"regionprops"函数如何计算周长? [英] How does MATLAB's `regionprops` function computes perimeter?

查看:1238
本文介绍了MATLAB的"regionprops"函数如何计算周长?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我发现该函数使用链代码来编码形状的边界,然后使用此公式以此方式 :

I have found that the function uses chain codes to encode the boundary of the shape, and then computes the perimeter this way using this formula:

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

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

What I do not know, however, is how this chain code is computed in some special cases.

考虑以下示例(对于该示例,MATLAB的周长为10.0150):

Consider the following example (for which MATLAB yields a perimeter of 10.0150):

 1     1     1     1     1
 1     1     0     0     1

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

How does MATLAB defines/computes the perimeter around the one pixel wide line attached to the 2x2 square on the left?

更准确地说:

如果我用字母表示非零边界像素(在此示例中,全1都是边界):

If I denote non-zero border pixels using letters (all 1s are borders in this example):

 a     d     e     f     g
 b     c                 h

链码可以从例如a开始.如果我们按顺时针方向进行计算,则它将继续在cef ...处进行,这意味着它无法返回到a,否则它将在同一字母处重复两次(甚至更多).如果有1像素宽的线条附加到其他1像素宽的线条等上,则为两倍.

A chain code could start at, say, a. If we compute it clockwise, it would then continue at c, e, f... Which means it cannot come back to a, otherwise it would have to go twice over the same letter (even more than twice if there are 1px wide lines attached to other 1px wide lines etc).

推荐答案

获取链码有两个步骤:跟踪边界并将坐标编码为链码.后面的步骤是微不足道的,我将不赘述.我认为这个问题是关于边界的.

There are two steps in obtaining chain codes: tracing the boundary and encoding the coordinates as chain codes. This latter step is trivial, I won't go into details. Tracing the boundary is what I think this question is about.

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

Typically what is traced are the object pixels that form the boundary (i.e. have at least one background neighbor). It is important that this happen in order, just listing these pixels is not enough. But do note that this description of the boundary is biased: the true object is larger than the polygon formed by joining the centers of the pixels at the object boundary. A perimeter computation needs to take this into account (as discussed in the blog post you linked).

此代码是根据此博客文章进行了稍微改编的. img是逻辑数组:

This code is adapted slightly from this blog post. img is a logical array:

% 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

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

As you can see here, the algorithm starts at a random pixel, and picks a direction to go around. Then it follows the boundary by finding the next neighbor in the given direction. The linked blog post has details explaining how this neighbor is found. In short, you look in the current direction, for the first neighboring object pixel that has a background neighbor. Given the current location and direction we came from, it is provable that the neighbor in a specific direction will be a background pixel. Going in clockwise (or anticlockwise, pick one) direction around the current point, starting with that background pixel, the first object pixel will guaranteed be a boundary pixel. We add that to out list and continue.

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

The algorithm terminates when we reach the start position and direction. The 1-pixel thick section of an object will thus be visited twice, to complete the boundary trace.

这篇关于MATLAB的"regionprops"函数如何计算周长?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆