如何匹配 Python 中两个列表中最接近的数组?

How to match closest arrays in two lists in Python?

我正在 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 解决方案:请看 James 的回答,它很有魅力!

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

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 的 class 对齐。我们对预测的 classes matches 使用 argsort 来获得一个索引数组,该索引数组将对 classes 进行排序。然后使用索引数组正确排序 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.]])

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

默认情况下,我发送的最接近百分比是 10,这意味着元素应该接近 10% 的边距

def closest_arrays(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;

如果所有元素都小于或等于 closest_percentage(默认为 5%)则 return True