首页 > 解决方案 > 在numpy中对点数组进行排序

问题描述

我得到了一个这样声明的点数组:

found = np.empty(img_rgb.shape[:2])

它表示来自 OpenCV 模板匹配的值。因为我只保留了匹配中具有所需值的点,所以我在迭代之前重写了它:

found2 = np.where(found)

现在我像这样遍历它:

for pt in zip(*found2[::-1]):
    (x, y) = pt

但是我如何对其进行排序,以便它从found[x][y]数组中的最低值迭代到最高值?

我试过np.argsort()但似乎没有保持适当的 x,y 索引。事实上,我猜它根本不按值排序。

编辑:要清楚:

img_rgb = cv2.imread(os.path.join(DATA_DIR, 'some.png'))

(...)

res = cv2.matchTemplate(img_gray, tmpl, cv2.TM_CCOEFF)
loc = np.where(res > 230000)
for pt in zip(*loc[::-1]):
   (x, y) = pt
   found[y][x] = -res[y][x]

标签: pythonnumpy

解决方案


res = cv2.matchTemplate(img_gray, tmpl, cv2.TM_CCOEFF)
count = np.sum(res > 230000)
y, x = np.unravel_index((-res).argsort(None), res.shape)
for row, col in zip(y[:count], x[:count]):
    print(res[row, col], (row, col))

每行说明:

count = np.sum(res > 230000)

获取要迭代的值的总数。

y, x = np.unravel_index((-res).argsort(None), res.shape)

在这里,argsort(None)将线性索引返回到对其进行排序的数组中。我们想要(行,列)索引,而不是线性索引,所以我们np.unravel_index()用来获取 2d 索引。使用结果的负数从最大值到最小值排序,就像您在 OP 中所做的那样。

最后,我们可以遍历这些点:

for row, col in zip(y[:count], x[:count]):
    print(res[row, col], (row, col))

打印只是为了表明我们确实首先获得了最高值,并显示了这些对应值的(行、列)索引。


例子:

>>> import cv2
>>> import numpy as np
>>> img = np.uint8(255*np.random.rand(100, 100))
>>> tmp = np.uint8(255*np.random.rand(10, 10))
>>> res = cv2.matchTemplate(img, tmp, cv2.TM_CCOEFF)
>>> count = np.sum(res > 100000)
>>> y, x = np.unravel_index((-res).argsort(None), res.shape)
>>> for row, col in zip(y[:count], x[:count]):
>>>     print(res[row, col], (row, col))
206337.11 (19, 12)
177079.31 (76, 9)
173258.67 (63, 15)
...
100202.44 (56, 1)
100098.41 (0, 48)
100089.09 (68, 47)

请注意,这些最终值是(行,列)顺序,即与(x,y)点顺序相反,因此可以根据需要随意交换。


推荐阅读