如何查找存储为numpy阵列的多个三维点的角点

2024-10-06 11:20:31 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在寻找一种从几个numpy数组中提取四个角点的有效方法。我读了this solution但无法解决我的问题。我的数组存储在字典中。这些数组和三列表示x、y和z坐标。每一行也是一个点,在某些情况下,我有数千个点。正如我的节目,我在这里有三套不同的颜色,并希望提取每个集的角落。应该注意的是,实际上我有几十个集合,每个集合有数千个点,但我仍然想提取每个集合的四个角点。在图c中,表示角,第一个数字是设置编号,第二个数字是角编号。 我复制了字典,其中包括两个数据集:

my_di={'sub_arr1': array([[50., 22.5, 28.53083253],
       [50., 7.5, 28.53022337],
       [41.23412371, 7.5, 10.],
       [41.22613668, 22.5, 10.],
       [50.69447517, 7.5, 30.],
       [50.6946373 , 22.5, 30.],
       [60.12217999, 7.5, 50.],
       [60.12265205, 22.5, 50.],
       [69.37286377, 7.5, 70.],
       [69.35833931, 22.5, 70.],
       [70., 22.5, 71.41123295],
       [70., 7.5, 71.37528419],
       [78.46719742, 7.5, 90.],
       [78.42491627, 22.5, 90.]]), 'sub_arr2': array([[60.79483509, 7.5, 30.],
       [51.35614872,  7.5, 10.],
       [60.7971096 , 22.5, 30.],
       [51.34645939, 22.5, 10.],
       [70., 22.5, 49.47742224],
       [70., 7.5, 49.50087547],
       [70.2344656 , 7.5, 50.],
       [70.24563313, 22.5, 50.],
       [79.53233719, 7.5, 70.],
       [79.53927994, 22.5, 70.],
       [88.7122488, 7.5, 90.],
       [88.69922638, 22.5, 90.]])}

从这两个集合中,我希望得到以下结果作为角点:

corners=[[[41.23412371, 7.5, 10.],
          [41.22613668, 22.5, 10.],
          [78.42491627, 22.5, 90.],
          [78.46719742, 7.5, 90.]],
          [51.35614872,  7.5, 10.],
          [51.34645939, 22.5, 10.],
          [88.69922638, 22.5, 90.],
          [88.7122488, 7.5, 90.]]]
      

我尝试了两种方法,但我的结果没有那么有用。首先,以下代码将4个最远的点与所有点的质心进行比较,但对于非对称重划分的情况,它不起作用:

from scipy.spatial import distance
four_c=np.array([])
for i in my_di.values():
    idx = np.argsort(distance.cdist([np.mean(i,axis=0)],i)).flatten()[-4:]
    f_c=i[idx,:]
    four_c=np.append (four_c, f_c)
four_c=four_c.reshape(int(len(four_c)/3),3)

当我打印four_c时,它会给出一些其他行,而不是每组的四个角。 然后,我尝试了更长的代码:

from scipy.spatial import distance
c1=np.array([])
c2=np.array([])
c3=np.array([])
c4=np.array([])
for i in dicti_ver_fault.values():
    corner1 = np.array(i.min (axis=0)) # this gives the row containing MIN values of x,y and z
    corner1 = corner1.reshape(1,3)
    c1=np.append(corner1, c1)
    corner2 = np.array([])
    corner3 = np.array([])
    corner4 = np.array(i.max (axis=0)) # this gives the row containing MAX values of x,y and z
    corner4 = corner4.reshape(1,3)
    c4=np.append(corner4, c4)
# the next block will find the corner in which x and y are minimum and z is maximum
    for j in i[:,0]:
        if j == max (i[:,0]):
            for h in i[:,1]: 
                if h == min (i[:,1]):
                    for k in i[:,2]:
                        if k == max (i[:,2]):
                            corner2 = np.append(corner2, np.array([j,h,k]))
                            corner2=corner2[0:3]
                            corner2 = corner2.reshape(1,3)
# the next block will find the corner in which x and z are minimum and y is maximum
    for m in i[:,0]:
        if m == min (i[:,0]):
            for n in i[:,1]: 
                if n == max (i[:,1]):
                    for o in i[:,2]:
                        if o == min (i[:,2]):
                            corner3 = np.append(corner3, np.array([m,n,o]))
                            corner3=corner3[0:3]
                            corner3 = corner3.reshape(1,3)
c1=c1.reshape(int(len(c1)/3),3)
c2=c2.reshape(int(len(c2)/3),3)
c3=c3.reshape(int(len(c3)/3),3)
c4=c4.reshape(int(len(c4)/3),3)

我也无法找到每列的绝对最大值和最小值并使用它们,因为在很多情况下,角点不是绝对最小值或最大值。我真的很感谢你的贡献

enter image description here


Tags: andtheinforifnparrayint
1条回答
网友
1楼 · 发布于 2024-10-06 11:20:31

通过计算从点到两边的向量,可以找到角点。然后,计算这两个向量的角度

import itertools
import numpy as np
arr = [[50., 22.5, 28.53083253],
       [50., 7.5, 28.53022337],
       [41.23412371, 7.5, 10.],
       [41.22613668, 22.5, 10.],
       [50.69447517, 7.5, 30.],
       [50.6946373 , 22.5, 30.],
       [60.12217999, 7.5, 50.],
       [60.12265205, 22.5, 50.],
       [69.37286377, 7.5, 70.],
       [69.35833931, 22.5, 70.],
       [70., 22.5, 71.41123295],
       [70., 7.5, 71.37528419],
       [78.46719742, 7.5, 90.],
       [78.42491627, 22.5, 90.]]

comb = list(itertools.combinations(arr, 3))

line = []

#find the combination which have almost 0 or almost 180 degree angle
for points_arr in comb:
    points = np.array(points_arr)
    ba = points[0] - points[1]
    bc = points[2] - points[1]

    cosine_angle = np.dot(ba, bc) / (np.linalg.norm(ba) * np.linalg.norm(bc))
    angle = np.arccos(cosine_angle)
    if(np.degrees(angle) < 1 or np.degrees(angle) > 179):
        print(np.degrees(angle))
        line.extend(points_arr)
        break


#remove points in line from arr          
for point1 in arr:
    for point2 in line:
        #print(sum(np.array(point1) - np.array(point2)), point1, point2)
        if sum(np.array(point1) - np.array(point2)) == 0:
            arr.remove(point1)

#add other points in line          
for point1 in arr:
    ba = np.array(line[0]) - np.array(line[1])
    bc = np.array(point1) - np.array(line[1])

    cosine_angle = np.dot(ba, bc) / (np.linalg.norm(ba) * np.linalg.norm(bc))
    angle = np.arccos(cosine_angle)
    if(np.degrees(angle) < 1 or np.degrees(angle) > 179):
        line.append(point1)

#remove points in line from arr          
for point1 in arr:
    for point2 in line:
        #print(sum(np.array(point1) - np.array(point2)), point1, point2)
        if sum(np.array(point1) - np.array(point2)) == 0:
            arr.remove(point1)

我知道代码不清楚,很多代码是重复的,可以修改为方法。这将把7个点从arr移动到line,您可以继续,直到arr不为空

相关问题 更多 >