我试图用二进制蒙版制作一个匀称的多边形,但是我总是以无效的多边形结尾。如何从任意的二进制蒙版制作有效的多边形?以下是使用圆形遮罩的示例。我怀疑这是因为我从蒙版轮廓获得的点是乱序的,这在我绘制点时很明显(见下图)。
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()
答案 0 :(得分:0)
事实上,我已经找到了一种对我有用的解决方案,但也许有人有更好的解决方案。问题的确是我的观点不合时宜。输入坐标顺序对于制作有效的多边形至关重要。因此,只需要按照正确的顺序排列分数即可。下面是使用带有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()