如何从多边形的离散化细胞表示产生有序多边形顶点序列

时间:2017-06-07 18:39:03

标签: python algorithm matlab image-processing computational-geometry

以下是多边形的细胞表示: -

enter image description here

这是显示的提取多边形。

enter image description here

我们将输入作为矩阵polM给出,其中粉红色单元格存储1,黄色单元格存储2个。从黄色单元格我们想要创建一个多边形。这也是使用从here派生的以下代码完成的。

clear;
close all;
A=ones(25,25);
indices=[64,65,88,89,90,91,111,112,113,114,115,116,117,135,136,137,138,139,140,141,142,143,158,159,160,161,162,163,164,165,166,167,168,169,182,183,184,185,186,187,188,189,190,191,192,193,194,195,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,282,283,284,285,286,287,288,289,290,291,292,293,294,295,307,308,309,310,311,314,315,316,317,318,319,320,341,342,343,344,345,367,368,369,393,394];
A(indices)=2;

figure
hold on
axis equal
axis ij
xx=10:20:500;
yy=10:20:500;
imagesc(xx,yy,A);
colormap([1.0000         0    0.7931;
    1.0000    0.8276         0]);
rt=[0,500];
gcs=0:20:500;
gds=ones(size(rt,2),size(gcs,2));
gds = bsxfun(@times,gds,gcs);
plot(rt,gds,'Color','k','LineStyle','-');
plot(gds,rt,'Color','k','LineStyle','-');
axis([0 350 100 450])

A=A-1;
% we identify patterns with edges over 2x2 patches, describing with
% the first 4 binary values what pixels are set, and with the next 2
% the edge with 2 indices over the 2x2 patch
patterns = [
    0,1,0,1,  3,4 % vertical edge at rhe right
    1,0,1,0,  1,2 % vertical edge at the left
    0,0,1,1,  2,4 % horizontal edge at the bottom
    1,1,0,0,  1,3 % horizontal edge at the top
    1,0,0,1,  1,4 % diagonal edge
    0,1,1,0,  2,3 % diagonal edge
    1,0,1,1,  1,4 % diagonal edge, extra pixel set
    1,1,0,1,  1,4 % diagonal edge, extra pixel set
    1,1,1,0,  2,3 % diagonal edge, extra pixel set
    0,1,1,1,  2,3 % diagonal edge, extra pixel set
    ];

% 2x2 patches (matrix form)
P00 = A(1:end-1,1:end-1);
P10 = A(2:end,1:end-1);
P01 = A(1:end-1,2:end);
P11 = A(2:end,2:end);

% edge unique identifier using powers of 2
id = @(p00,p01,p10,p11) 1*p00 + 2*p10 + 4*p01 + 8*p11;
P = id(P00,P01,P10,P11); % vectorized pattern identification

% edges
e0 = []; % from (i,j)
e1 = []; % to (i,j)
for i = 1:size(patterns, 1) % small loop over the 10 patterns
    p = patterns(i, :);
    E = (P == id(p(1),p(2),p(3),p(4))); % pattern search, vectorized
    [c,r] = ind2sub(size(E), find(E));
    [c0,r0] = ind2sub([2,2], p(5));
    [c1,r1] = ind2sub([2,2], p(6));
    e0 = [e0; c+c0, r+r0];
    e1 = [e1; c+c1, r+r1];
end

X = [e0(:,2) e1(:,2)]';
Y = size(A,1) - [e0(:,1) e1(:,1)]';

figure
hold on
axis equal
axis ij
X=X*20;
Y=Y*20; Y=500-Y;
plot(X, Y, '.-')
axis([0 350 100 450])

但是代表多边形的代码输出由数组XY给出。我想以nx2矩阵形式表示输出,其中所有行表示顶点,如果最终多边形和顶点是从第一个顶点开始的顺时针或逆时针顺序。有方法here可以将混乱的顶点序列后处理到有序序列,但我想要一个算法来确定有序序列中输入矩阵polM的多边形顶点。 SO输入为polM,输出为多边形顶点的nx2矩阵,仅以cw或ccw顺序排列。

有人可以建议对算法进行有效更改吗?

修改

如果你添加这段代码假设有序结果已经到来你会得到错误: -

newp=[X(1,:)',Y(1,:)'];
figure
hold on
axis([0 350 100 450])
axis equal
axis ij
line(newp(:,1), newp(:,2));

基本上我想解决这个错误。

1 个答案:

答案 0 :(得分:0)

XY都是指定2xn无序顶点的n矩阵,即应在[X(1, i) Y(1, i)][X(2, i) Y(2, i)]之间绘制一条线,每i=1:n。由于所有顶点都是连通的,因此每个点应在这些XY矩阵中出现两次。因此,可以从多边形上的任意点开始并迭代地搜索下一个点。这可以按如下方式完成:

% XY_from: a `nx2` matrix containing all starting points 
% with a third column indicating if this vertex is already used
XY_from = [X(1, :)' Y(1, :)' zeros(size(X, 2), 1)]; 
XY_to = [X(2, :)' Y(2, :)' zeros(size(X, 2), 1)]; % similar matrix for destination points
new_poly = zeros(size(X, 2)+1, 2); % allocate output space
new_poly(1, :) = XY_from(1, 1:2); % select an arbitrary starting point
for i=2:size(new_poly, 1)
  index = find(all([new_poly(i-1, :) 0] == XY_from, 2), 1); % search the previous (unused) point in the starting points
  if isempty(index) 
    index = find(all([new_poly(i-1, :) 0] == XY_to, 2), 1); % if no point was found, search it in the destination points
    new_poly(i, :) = XY_from(index, 1:2); % add the new point (corresponding with the found destination point)
  else
    new_poly(i, :) = XY_to(index, 1:2); % add the new point (corresponding with the found start point)
  end
  XY_from(index, 3) = 1; % indicate that this start point is used
  XY_to(index, 3) = 1; % indicate that this destination point is used
end

hold on
plot(new_poly(:, 1), new_poly(:, 2), '--k', 'LineWidth', 2); % plot on top of the polygon

enter image description here