【问题标题】:How to find corners of several 3d points stored as numpy arrays如何找到存储为 numpy 数组的几个 3d 点的角点
【发布时间】:2020-10-14 19:19:59
【问题描述】:

我正在寻找一种从几个 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)

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

【问题讨论】:

    标签: python arrays numpy


    【解决方案1】:

    您可以通过计算从点到两侧的向量来找到角点。之后,计算这两个向量的角度。

    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)
    

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

    【讨论】:

    • 亲爱的@Dalibor Cimr,感谢您的解决方案。但是,我怎样才能使用您的解决方案找到这四个角落?我尝试过这个。当我打印np.degrees(angle) 时,它给了我90.00210334413676。但是你能帮我理解一下我能找到角落吗?
    • 90度表示这3个点不在一条线上。如果另外 3 个点在一条线上,则算法的结果必须超过 180 度。我不知道你的点列表中的形状有多复杂(总是矩形或一些健壮的多边形),但如果你只有一个没有排序的点列表,你必须找到几组在一条线上的点(在矩形的情况有 4,在你的情况下,它是两条线,因为矩形的较短边没有更多的点)并且线的起点和终点是角
    • 你的意思是我应该为数组中存在的所有对运行代码以找到 180 度的结果?我的形状几乎都是平面矩形或正方形。他们总是有四个角。问题是我的观点可能都不成一条线,我该如何解决?感谢您的宝贵时间。
    • 啊哈,如果它们都没有 180 度会怎样?您能否将您的有用想法作为代码提供给我。我在 python 之类的东西上几乎是新手。非常感谢您的帮助和时间。
    • 只有两种情况没有 180 度:1) 你只有四个点 - 这些点是角 2) 你有一些健壮的多边形,而不是矩形或正方形
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-11-27
    • 1970-01-01
    • 2021-05-01
    • 2020-08-21
    • 1970-01-01
    • 2021-07-07
    • 1970-01-01
    相关资源
    最近更新 更多