【问题标题】:How to match closest arrays in two lists in Python?如何匹配Python中两个列表中最近的数组?
【发布时间】:2021-03-05 08:10:53
【问题描述】:

我在2400x3000 图像上检测到一些对象。每个图像的大小都相同。但每张图像都略有不同(可能有点旋转、倾斜等)。因此,我想使用第一张图像检测到的边界框坐标作为其他图像的参考。

所以我想找到检测到的边界框坐标数组之间的最佳匹配。这是一个例子:

[187.0, 489.0, 1501.0, 575.0]
[1810.0, 1967.0, 1917.0, 2052.0]
[1360.0, 2187.0, 1467.0, 2275.0]
[1256.0, 2188.0, 1361.0, 2276.0]
[506.0, 2197.0, 615.0, 2284.0]
[199.0, 2288.0, 306.0, 2372.0]

这是第一份坐标报告。另一个是:

[200.0, 490.0, 1491.0, 588.0]
[1813.0, 1966.0, 1919.0, 2053.0]
[1370.0, 2188.0, 1473.0, 2276.0]
[1265.0, 2189.0, 1365.0, 2275.0]
[520.0, 2200.0, 629.0, 2288.0]
[222.0, 2291.0, 327.0, 2376.0]

如您所知,这已经匹配。第一个报告中的每一行都对应于第二个。

但我想自动完成。我希望 Python 找到最近的数组并匹配它们。

我查看了数组比较、列表比较等算法,但我觉得我的情况有所不同,因为它们不是随机数而是坐标。

有人知道如何做到这一点吗?

例如:

[200.0, 490.0, 1491.0, 588.0]

应该匹配:

[187.0, 489.0, 1501.0, 575.0]

或 这个数组:

[1813.0, 1966.0, 1919.0, 2053.0]

应该匹配:

[1810.0, 1967.0, 1917.0, 2052.0]

提前致谢。

编辑:更具体地说,我需要根据匹配对两个列表进行排序。

TL;DR SOLUTION:请看詹姆斯的回答,它就像一个魅力!

【问题讨论】:

    标签: python arrays numpy coordinates bounding-box


    【解决方案1】:

    请更改以下函数中的变量closest_percentage 以定义接近度

    我在这里发送最接近的百分比默认为 10,这意味着元素应该接近 10% 的边距

    def最接近数组(lst1,lst2,closest_percentage=5.0):

    if(len(lst1)!=len(lst2)):
    
        return False;
    
    else:
    
        counter=1
    
        for i in range(len(lst1)):
    
            if (((abs(lst1[i])-abs(lst2[i]))/(abs(lst1[i]))*100) > closest_percentage):
    
                return False;
    
            
    return True;
    

    如果所有元素都小于或等于最接近的百分比(默认为 5%),则返回 True

    【讨论】:

      【解决方案2】:

      您可以使用设置为 1 的邻居数的 k 最近邻居。您的第一组边界框中的每个示例都将对应其自己的类。拟合模型后,您可以预测哪些边界框最接近第一组。

      from sklearn.neighbors import KNeighborsClassifier
      import numpy as np
      
      d1 = np.array(
        [[187.0, 489.0, 1501.0, 575.0],
        [1810.0, 1967.0, 1917.0, 2052.0],
        [1360.0, 2187.0, 1467.0, 2275.0],
        [1256.0, 2188.0, 1361.0, 2276.0],
        [506.0, 2197.0, 615.0, 2284.0],
        [199.0, 2288.0, 306.0, 2372.0]]
      )
      
      d2 = np.array(
        [[200.0, 490.0, 1491.0, 588.0],
        [1813.0, 1966.0, 1919.0, 2053.0],
        [1370.0, 2188.0, 1473.0, 2276.0],
        [1265.0, 2189.0, 1365.0, 2275.0],
        [520.0, 2200.0, 629.0, 2288.0],
        [222.0, 2291.0, 327.0, 2376.0]]
      )
      
      classes = np.arange(len(d1))
      
      knn = KNeighborsClassifier(n_neighbors=1)
      knn.fit(d1, y=classes)
      knn.predict(d1)
      # returns:
      array([0, 1, 2, 3, 4, 5])
      

      如您所述,这已经与第一组边界框的顺序相匹配。但是,如果我们查看一组更随机的数据:

      d3 = np.array([[ 524.0, 2182.0,  632.0, 2294.0],
        [1368.0, 2173.0, 1471.0, 2287.0],
        [ 182.0,  474.0, 1473.0,  605.0],
        [1797.0, 1975.0, 1930.0, 2055.0],
        [1281.0, 2202.0, 1356.0, 2263.0],
        [ 227.0, 2295.0,  339.0, 2394.0]]
      )
      
      matches = knn.predict(d3)
      matches
      # returns:
      array([4, 2, 0, 1, 3, 5])
      

      要实际使用最接近的匹配,我们可以使用 argsort 重新排序 d3 数组,使其与 d1 的类对齐。我们在预测的类matches 上使用 argsort 来获取对类进行排序的索引数组。然后使用索引数组正确排序d3 以匹配d1

      d3_sorted = d3[np.argsort(matches)]
      
      d3_sorted
      # returns:
      array([[ 182.,  474., 1473.,  605.],
             [1797., 1975., 1930., 2055.],
             [1368., 2173., 1471., 2287.],
             [1281., 2202., 1356., 2263.],
             [ 524., 2182.,  632., 2294.],
             [ 227., 2295.,  339., 2394.]])
      

      【讨论】:

      • 解决这个问题的好方法!技术很棒,我没想到我可以这么容易地使用 SciKit!我肯定会把它整合到我的项目中。真是太感谢你了。
      猜你喜欢
      • 2021-11-04
      • 2020-01-30
      • 2013-02-28
      • 2021-06-11
      • 2017-03-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多