python - 在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]
解决方案
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)点顺序相反,因此可以根据需要随意交换。
推荐阅读
- javascript - 多个局部视图和 javascript
- angular - Ngrx 根据第一个动作数据调度另一个动作
- json - Struts 2 没有动作映射
- file - 从 Spring MultipartFile 中检索上传的文件属性
- c# - Sendgrid 在使用 urlPath 时找不到任何模板:“模板”
- scala - Scala 中的 DSE 5.0 自定义编解码器 - Intellij 无法编译
- javascript - 为什么 forEach 在 Edge 中不起作用?
- android - 使用本机应用程序 (Android) 保护 Oauth2 中的身份验证代码
- leaflet - 我可以将 Google 地图图块/图像与传单一起使用吗?
- android - Kotlin RxJava2 onError 未调用 Http 状态代码 400