#python #numpy
#питон #numpy #python
Вопрос:
Я получил массив точек, объявленный следующим образом:
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]
Комментарии:
1.Что ты на самом деле пытаешься сделать?
np.where()
выполняет сортировку элементов по строке, затем по столбцу. Итак, я не уверен, какова здесь цель. Редактировать: ах, подождите, итак, вы хотите сделать заказ по шаблону, соответствующему значениям изображения. Это правильно? Мой первоначальный вопрос по-прежнему касается того, почему вы хотели бы это сделать, поскольку это кажется чрезвычайно медленным без всякой причины. Вам действительно нужен каждый пиксель? Или просто какое-то подмножество?2. Похоже, это работает медленно. Мне нужно подмножество найденных значений, превышающих пороговое значение. Затем отсортируйте их по значению. Затем повторите это. На самом деле я не самый лучший в Python 🙁
3. (a) Является
found
ли это 2d массивом bools? (b) Подfound[x][y]
вы на самом деле имеете в видуfound[x,y]
? (c) Что вы подразумеваете под «наименьшим или наибольшим значением вfound[x][y]
, особенно еслиfound
имеет только bools»?4.
found[x][y]
имеет значение, которое может быть bigint, изcv2.matchTemplate()
5. Ваше «РЕДАКТИРОВАТЬ, чтобы было понятно», кажется, делает это еще менее понятным. Он вводит
loc
, и в вашем заявлении о требовании вообще не упоминаетсяloc
Ответ №1:
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-индексов. Используя отрицательный результат для сортировки от max до min, как вы делали в 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), поэтому не стесняйтесь менять местами по мере необходимости.
Комментарии:
1. спасибо! это многое объяснило
Ответ №2:
Не уверен, что я вас правильно понял, но вы хотите что-то вроде:
found = np.random.randint(0, 10, (3, 4))
found2 = np.where(found)
found
# array([[5, 6, 8, 6],
# [0, 7, 7, 3],
# [7, 6, 0, 5]])
found2
# (array([0, 0, 0, 0, 1, 1, 1, 2, 2, 2]), array([0, 1, 2, 3, 1, 2, 3, 0, 1, 3]))
order = found[found2].argsort()
x, y = found2[1][order], found2[0][order]
found[y, x]
# array([3, 5, 5, 6, 6, 6, 7, 7, 7, 8])
Это сортирует 2d-индексы в found2
по значениям в точках в found
, на которые они ссылаются.
Комментарии:
1. Я отредактировал свой вопрос, чтобы указать, что такое
found
, мне все еще нужен код итерации, поскольку я выполняю итерациюfound2
, а неfound
, но, возможно, я понимаю это неправильно2. @FlashThunder
(y, x)
такой же, какfound2
, только переупорядоченный. Вы можете назначить его обратноfound2 = y, x
и использовать свой цикл без изменений.3. @FlashThunder Извините, я не понимаю вопроса. После того, как вы определили
found2
в своем коде, вы вставляете строку, начинающуюся сorder =
, и следующую строку, и строку, которую я написал в своем последнем комментарииfound2 = y, x
, и это должно быть все, что вам нужно сделать.
Ответ №3:
Решение:
sorted_pts = sorted(zip(*loc), key=lambda t:res[t])
print (sorted_pts)
Попробуйте это с образцами данных:
Давайте возьмем некоторые образцы данных в меньшем масштабе ( res
как просто массив формы (3,4)
и 4
как threshold
):
import numpy as np
res = np.arange(12).reshape(3,4)
print (res)
loc = np.where(res > 4) # Dummy threshold == 4
sorted_pts = sorted(zip(*loc), key=lambda t:res[t[0],t[1]])
print (sorted_pts)
Вывод:
[[ 0 1 2 3] # res
[ 4 5 6 7]
[ 8 9 10 11]]
# sorted_pts
[(1, 1), (2, 1), (3, 1), (0, 2), (1, 2), (2, 2), (3, 2)]
Примечание:
(Проверка того, что точки отсортированы в соответствии со значениями в res
)
[(1, 1), (2, 1), (3, 1), (0, 2), (1, 2), (2, 2), (3, 2)]
| | | | | | |
| | | | | | |
V V V V V V V
5 6 7 8 9 10 11
Комментарии:
1. извините, что не принимаю это, но я не могу принять два ответа, хотя это был хороший ответ! Спасибо!