OpenCV2 matchTemplate не работает на разных изображениях с одним и тем же шаблоном

#python #python-3.x #opencv #image-processing #opencv-python

Вопрос:

Я использую OpenCV2 для работы с функцией автоматической блокировки для игры, так просто: если красный индикатор, отображаемый в определенном регионе, имеет значение max_val выше порогового значения, нажмите указанную клавишу, чтобы заблокировать эту атаку.

Существует шаблон индикатора с прозрачным фоном, он работает на нескольких скриншотах, но не на большинстве других, однако.

Вот данные, которые я использую:

Шаблон:

Левый Блок

Снимок экрана, на котором он успешно обнаруживает: введите описание изображения здесь

Снимок экрана, на котором он не может обнаружить: введите описание изображения здесь

Код для обнаружения:

 import time
import cv2
import pyautogui
import numpy as np


def block_left():
    # while True:
        # screenshot = pyautogui.screenshot(region=(960, 455, 300, 260))
        # region = cv2.imread(np.array(screenshot), cv2.IMREAD_UNCHANGED)
    region = cv2.imread('Screenshots/Left S 1.png', cv2.IMREAD_UNCHANGED)
    block = cv2.imread(r'Block Images/Left Block.png', cv2.IMREAD_UNCHANGED)
    matched = cv2.matchTemplate(region, block, cv2.TM_CCOEFF_NORMED)

    min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(matched)
    print(max_val)

    w = block.shape[1]
    h = block.shape[0]

    cv2.rectangle(region, max_loc, (max_loc[0]   w, max_loc[1]   h), (255, 0, 0), 2)

    cv2.imshow('Region', region)
    cv2.waitKey()


block_left()
 

Итак, в заключение я перепробовал множество других методов, но все они показали менее успешные результаты. Есть ли какие-либо фильтры, какая-либо обработка, которую я могу добавить, чтобы исправить это?
Спасибо.

Загруженные изображения 8-разрядные, однако используемые изображения 32-разрядные, но не могут быть загружены из-за размера, используемые 32-разрядные изображения загружены здесь: https://ibb.co/r7B7G6B https://ibb.co/r0r9w5T https://ibb.co/KXP3wWc

Комментарии:

1. Вам нужно сделать маску красной области в вашем шаблоне, а затем использовать маску в matchTemplate(). См. Документацию по использованию изображения маски. Прочитайте изображение шаблона, чтобы оно сохранило ваш альфа-канал. Затем извлеките альфа-канал в виде маски и извлеките изображение BGR под альфа-каналом. Затем используйте изображение BGR в качестве шаблона и маски, как в matchTemplate().

2. Я просто попробовал и сделал маску шаблона, добавил ее в шаблон и использовал, но все равно получил те же результаты, или я мог ошибиться, так как я относительно новичок в OpenCV

3. Покажите свой новый код и то, как вы прочитали шаблон и извлекли маску, а также свой код соответствия.

4. Попробуйте TM_SQDIFF и min_loc

5. Имейте в виду, что соответствие шаблону не является ни масштабируемым, ни вращающимся инвариантом. Мне кажется, что угол красных фигур немного отличается на обоих изображениях.

Ответ №1:

Вот пример сопоставления замаскированных шаблонов в Python/OpenCV с использованием двух ваших изображений и шаблона с альфа-каналом.

Изображение 1:

введите описание изображения здесь

Изображение 2:

введите описание изображения здесь

Шаблон:

введите описание изображения здесь

 import cv2
import numpy as np

# read  image
img = cv2.imread('game2.jpg')

# read template with alpha channel
template_with_alpha = cv2.imread('game_template.png', cv2.IMREAD_UNCHANGED)
hh, ww = template_with_alpha.shape[:2]

# extract base template image and alpha channel and make alpha 3 channels
template = template_with_alpha[:,:,0:3]
alpha = template_with_alpha[:,:,3]
alpha = cv2.merge([alpha,alpha,alpha])

# do masked template matching and save correlation image
correlation = cv2.matchTemplate(img, template, cv2.TM_CCORR_NORMED, mask=alpha)

# get best match
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(correlation)
max_val_corr = '{:.6f}'.format(max_val)
print("correlation score: "   max_val_corr)
print("match location:", max_loc)

# draw match 
result = img.copy()
cv2.rectangle(result, (max_loc), ( max_loc[0] ww,  max_loc[1] hh), (0,0,255), 1)

# save results
cv2.imwrite('game2_matches.jpg', result)

cv2.imshow('template',template)
cv2.imshow('alpha',alpha)
cv2.imshow('result',result)
cv2.waitKey(0)
cv2.destroyAllWindows()
 

Совпадение с изображением 1:

 correlation score: 0.983882
match location: (783, 512)
 

введите описание изображения здесь

Совпадение с изображением 2:

 correlation score: 0.938928
match location: (867, 504)
 

введите описание изображения здесь

Комментарии:

1. Ты понял, что я сделал?

2. Обратите внимание, что ваш шаблон не такого размера, как красный на больших изображениях, но в этих случаях достаточно близок. Шаблон немного больше. Если у вас есть изменения большего масштаба, вам, возможно, придется выполнить сопоставление шаблонов с несколькими масштабами.

3. Вы понимаете, как я прочитал в шаблоне, чтобы в нем был альфа-канал, а затем разделил их? Затем есть опция для маски в matchTemplate(). В этом и заключается разница в сопоставлении замаскированных шаблонов.

4. В качестве небольшого пояснения, ваш шаблон не очень хорошо подходит, если не используется маскировка, так как изображение под прозрачной частью черное. Таким образом, шаблон пытается подобрать много черного и немного красного к вашему изображению. Как правило, этого не существует, так как изображение имеет текстуру вокруг красной области. Таким образом, добавление маски в matchTemplate позволяет ей игнорировать те области изображения, которые соответствуют черному цвету в маске, извлеченной из альфа-канала.

5. Это делается с помощью нарезки Numpy. Я читаю на изображении с прозрачностью. Затем я копирую только каналы BGR 0,1,2. Затем я копирую альфа-канал на изображение с канала 3.