如何在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坐标的二维数组进行排序?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Java 中对二维数组进行深拷贝?

如何在 C# 中对二维(矩形)数组进行排序?

如何在JavaScript中对二维数组进行排序?

存储为numpy的图像中的XY坐标?

C语言如何在子函数中对主函数中的二维数组值进行修改? 二维数组已经在主函数中用动态数组分配了空间。

深度学习对 xy 空间坐标的时间序列进行分类 - python