如何在python中对存储xy坐标的二维数组进行排序?
Posted
技术标签:
【中文标题】如何在python中对存储xy坐标的二维数组进行排序?【英文标题】:How do I sort a 2d array that stores xy coordinates in clock wise in python? 【发布时间】:2021-11-04 17:35:17 【问题描述】:从一个包含 1 和 0 的数组中,我试图获取该数组的边界并绘制它。这是我用来获取边界的代码
import numpy as np
import math
import matplotlib.pyplot as plt
binI = np.array([[0,0,0,0,1,0,0,0,0,0,0],
[0,0,0,1,1,1,1,0,0,0,0],
[0,0,1,1,1,1,1,0,0,0,0],
[0,1,1,1,1,0,0,0,0,0,0],
[0,1,1,1,0,0,0,0,0,0,0],
[0,0,1,1,1,1,0,0,0,0,0],
[0,0,0,1,1,1,0,0,0,0,0],
[0,0,0,1,1,0,0,0,0,0,0]])
def boundary_Tracer(arr):
indices_list = []
for i in range (np.shape(arr)[0]):
for j in range (np.shape(arr)[1]):
if arr[i,j] == 1:
if i == 0 and j == 0:
if (arr[i+1,j] == 0) or (arr[i,j+1] == 0):
indices_list.append([i,j])
elif (i == 0) and (j == np.shape(arr)[1]-1):
if (arr[i,j-1] == 0) or (arr[i+1,j] == 0):
indices_list.append([i,j])
elif (i == (np.shape(arr)[0]-1)) and j == 0:
if (arr[i-1,j] == 0) or (arr[i,j+1] == 0):
indices_list.append([i,j])
elif (i == np.shape(arr)[0]-1) and (j == np.shape(arr)[1]-1):
if (arr[i-1,j] == 0) or (arr[i,j-1] == 0):
indices_list.append([i,j])
elif (i in range (1,np.shape(arr)[0]-1)) and (j == 0):
if (arr[i-1,j] == 0) or (arr[i,j+1] == 0) or (arr[i+1,j] == 0):
indices_list.append([i,j])
elif (i in range (1,np.shape(arr)[0]-1)) and (j == np.shape(arr)[1]-1):
if (arr[i-1,j] == 0) or (arr[i,j-1] == 0) or (arr[i+1,j] == 0):
indices_list.append([i,j])
elif (i == 0) and (j in range (1,np.shape(arr)[1]-1)):
if (arr[i,j-1] == 0) or (arr[i,j+1] == 0) or (arr[i+1,j] == 0):
indices_list.append([i,j])
elif (i == np.shape(arr)[0]-1) and (j in range (1,np.shape(arr)[1]-1)):
if (arr[i-1,j] == 0) or (arr[i,j-1] == 0) or (arr[i,j+1] == 0):
indices_list.append([i,j])
else:
if (arr[i-1,j] == 0) or (arr[i+1,j] == 0) or (arr[i,j-1] == 0) or (arr[i,j+1] == 0):
indices_list.append([i,j])
indicies_array = np.array(indices_list)
x_all = indicies_array[:,1]
x_init_bw = np.min(np.where(x_all == np.min(x_all)))
origin = np.reshape(indicies_array[x_init_bw,:],(1,2))[0]
indicies_array = np.vstack((indicies_array,origin))
return indicies_array, origin
bw = boundary_Tracer(binI)[0]
origin = boundary_Tracer(binI)[1]
plt.plot(bw[:,1],bw[:,0])
plt.gca().invert_yaxis()
我知道这很丑,我确信有更好的方法来做到这一点,但这是我最好的。无论如何,当我绘制这个时,情节在点之间曲折。我想让情节只是连接边界而不跨越标有 1 的区域的中间。
用边界的 xy 坐标(bw
)重新排列数组的最佳方法是什么?
【问题讨论】:
经过一番研究,我找到了一个解释,为什么这是not possible 有一组点,没有更多信息。我希望我的回答能在某种程度上有所帮助。 【参考方案1】:您可以将数据转换为原点,并使用复杂的角度对数据进行排序
bw = boundary_Tracer(binI)[0]
origin = boundary_Tracer(binI)[1]
xs = (bw - bw.mean(0))
x_sort = bw[np.angle((xs[:,0] + 1j*xs[:,1])).argsort()]
# Plot to test your trace
plt.imshow(binI, cmap='gray')
plt.plot(x_sort[:,1],x_sort[:,0])
plt.gca().invert_yaxis()
plt.axis('off');
输出
这个顺时针的解决方案不是想要的结果。不在凸包上的点被排错了位置。
一个可用的排序来证明问题不在您的数据中,例如
x_sort = bw[[18, 7, 4, 1, 0, 2, 3, 6, 5, 8, 10, 12, 13, 15, 17, 16, 14, 11, 9]]
plt.imshow(binI, cmap='gray')
plt.plot(x_sort[:,1],x_sort[:,0], 'ro--')
plt.gca().invert_yaxis()
plt.axis('off');
输出
有'star shaped' 非凸形状的算法,但no general unique solution 没有更多信息。
【讨论】:
我喜欢你使用 np.angle 进行排序的方式。我实际上尝试了这个,它似乎工作得相当好,但线仍然穿透内部,而不是仅仅绘制边界。例如,点 (5,1) 应该连接到 (0,4) 和 (6,1),但您的答案似乎将它连接到 (0,4) 和 (4,3)。你认为有没有办法安排点,让情节只画边界而不越过内部? 请注意,此方法仅适用于凸多边形。示例中的形状是凹形的,这会带来两个问题:1)质心不能保证在多边形的范围内; 2)沿周长的点的“角度值”可能不会单调增加,这意味着对它们进行排序会使它们“乱序”。以上是关于如何在python中对存储xy坐标的二维数组进行排序?的主要内容,如果未能解决你的问题,请参考以下文章