Почему мой стройный многоугольник создан из маски неверно? - PullRequest
0 голосов
/ 21 ноября 2018

Я пытаюсь создать красивый многоугольник из бинарной маски, но всегда получаю неправильный многоугольник.Как я могу сделать правильный полигон из произвольной двоичной маски?Ниже приведен пример использования круговой маски.Я подозреваю, что это потому, что точки, которые я получаю от контура маски, не в порядке, что очевидно, когда я строю точки (см. Изображения ниже).

import matplotlib.pyplot as plt
import numpy as np
from shapely.geometry import Point, Polygon
from scipy.ndimage.morphology import binary_erosion
from skimage import draw

def get_circular_se(radius=2):

    N = (radius * 2) + 1
    se = np.zeros(shape=[N,N])
    for i in range(N):
        for j in range(N):
                se[i,j] = (i - N / 2)**2 + (j - N / 2)**2 <= radius**2
    se = np.array(se, dtype="uint8")
    return se

    return new_regions, np.asarray(new_vertices)

#generates a circular mask
side_len = 512
rad = 100
mask = np.zeros(shape=(side_len, side_len))
rr, cc = draw.circle(side_len/2, side_len/2, radius=rad, shape=mask.shape)
mask[rr, cc] = 1

#makes a polygon from the mask perimeter
se = get_circular_se(radius=1)
contour = mask - binary_erosion(mask, structure=se)
pixels_mask = np.array(np.where(contour==1)[::-1]).T
polygon = Polygon(pixels_mask)
print polygon.is_valid

>>False

#plots the results
fig, ax = plt.subplots()
ax.imshow(mask,cmap='Greys_r')
ax.plot(pixels_mask[:,0],pixels_mask[:,1],'b-',lw=0.5)
plt.tight_layout()
plt.show()

enter image description here enter image description here

1 Ответ

0 голосов
/ 21 ноября 2018

На самом деле я уже нашел решение, которое сработало для меня, но, возможно, у кого-то есть лучшее.Проблема была в том, что мои пункты были не в порядке.Порядок ввода координат имеет решающее значение для создания допустимых полигонов.Таким образом, нужно просто поставить точки в правильном порядке в первую очередь.Ниже приведен пример решения с использованием подхода ближайшего соседа с KDTree, которое я уже опубликовал в другом месте для связанных проблем.

from sklearn.neighbors import KDTree

def polygonize_by_nearest_neighbor(pp):
    """Takes a set of xy coordinates pp Numpy array(n,2) and reorders the array to make
    a polygon using a nearest neighbor approach.

    """

    # start with first index
    pp_new = np.zeros_like(pp)
    pp_new[0] = pp[0]
    p_current_idx = 0

    tree = KDTree(pp)

    for i in range(len(pp) - 1):

        nearest_dist, nearest_idx = tree.query([pp[p_current_idx]], k=4)  # k1 = identity
        nearest_idx = nearest_idx[0]

        # finds next nearest point along the contour and adds it
        for min_idx in nearest_idx[1:]:  # skip the first point (will be zero for same pixel)
            if not pp[min_idx].tolist() in pp_new.tolist():  # make sure it's not already in the list
                pp_new[i + 1] = pp[min_idx]
                p_current_idx = min_idx
                break

    pp_new[-1] = pp[0]
    return pp_new

pixels_mask_ordered = polygonize_by_nearest_neighbor(pixels_mask)
polygon = Polygon(pixels_mask_ordered)
print polygon.is_valid

>>True

#plots the results
fig, ax = plt.subplots()
ax.imshow(mask,cmap='Greys_r')
ax.plot(pixels_mask_ordered[:,0],pixels_mask_ordered[:,1],'b-',lw=2)
plt.tight_layout()
plt.show()

enter image description here enter image description here

...