Поиск шаблона на скриншоте
Недавно я начал писать бота для игры World of Warcraft(3.3.5) и для этого мне пришлось постигнуть cv2 но я его так и не постиг, ниже код:
import cv2
import numpy as np
import os
screenshot = cv2.imread('scren.png')
template_folder = 'tem_1'
templates = [cv2.imread(os.path.join(template_folder, f))
for f in os.listdir(template_folder) if f.endswith('.png')]
threshold = 0.8
coordinates = []
def are_points_close(pt1, pt2, threshold_distance=40):
return np.linalg.norm(np.array(pt1) - np.array(pt2)) < threshold_distance
for template in templates:
result = cv2.matchTemplate(
screenshot, template, cv2.TM_CCOEFF_NORMED)
loc = np.where(result >= threshold)
# Отметьте найденные шаблоны
for pt in zip(*loc[::-1]): # Переворот координат
cv2.rectangle(
screenshot, pt, (pt[0] + template.shape[1], pt[1] + template.shape[0]), (0, 255, 255), 2)
coordinates.append((pt))
print(coordinates)
cv2.imwrite('output.png', screenshot)
cv2.imshow('Detected Templates', screenshot)
cv2.waitKey(0)
cv2.destroyAllWindows()
Который обводит шаблон на скрине, и выявляет его координаты для дальнейшей итерации, но код возвращает мне:
np.int64(575)), (np.int64(1427), np.int64(575)), (np.int64(1428), np.int64(575)), (np.int64(1427), np.int64(576)), (np.int64(1654), np.int64(689)), (np.int64(1655), np.int64(689)), (np.int64(1656), np.int64(689)), (np.int64(1655), np.int64(690)), (np.int64(1655), np.int64(404....
Вроде всё норм, но суть в том что на скрине вещи всего 4, а кординат много, и они отличаются 1-3 значениями, бот находит вещи, и выделяет, но как то слишком много у него этого получается.
Первые три это шаблоны, потом скрин, и что находит бот.
Ответы (1 шт):
Дело в том, что loc у вас содержит не максимум функции корреляции, а некоторую область около него (чем меньше порог, тем больше эта область).
Вариант первый: как-то объединять координаты близких точек в кластеры.
Вариант второй: просто найти центроиды связных областей:
import cv2
import numpy as np
import os
screenshot = cv2.imread('screen.png')
template_folder = 'tem_1'
templates = [cv2.imread(os.path.join(template_folder, f))
for f in os.listdir(template_folder) if f.endswith('.png')]
threshold = 0.65
coordinates = []
for template in templates:
result = cv2.matchTemplate(
screenshot, template, cv2.TM_CCOEFF_NORMED)
max_bw=np.where(result>=threshold, 255, 0, ).astype('uint8')
_,_,_,centroids=cv2.connectedComponentsWithStats(max_bw)
centroids=np.int64(centroids)
# Отметьте найденные шаблоны
for pt in centroids[1:,:]:
cv2.rectangle(
screenshot, pt, (pt[0] + template.shape[1], pt[1] + template.shape[0]), (0, 255, 255), 2)
coordinates.append((pt))
print(coordinates)
cv2.imwrite('output.png', screenshot)
cv2.imshow('Detected Templates', screenshot)
cv2.waitKey(0)
cv2.destroyAllWindows()
Результат:
[array([1290, 519], dtype=int64), array([1497, 623], dtype=int64), array([1497, 365], dtype=int64)]