Согласно ответу Нираджа Комуравалли на этот вопрос , matchTemplate
поддерживает аргумент mask
как способ исключения определенных пикселей в шаблоне из рассмотрения в соответствующих ( документах). ).
Чтобы сгенерировать маску на основе красных пикселей, простое решение состоит в том, чтобы использовать логическое выражение для выбора тех пикселей, которые 0
синим и зеленым, но 255
красным:
mask = (template[:,:,0]==0) & (template[:,:,1]==0) & (template[:,:,2]==255)
mask = ~mask
mask = mask.astype(np.uint8)
Обратите внимание, что преобразование в uint8
необходимо, поскольку маска должна иметь тот же тип данных, что и шаблон.
Редактировать: ~mask
инвертирует маску (0
становится 1
и наоборот), что необходимо, поскольку 0
указывает пиксели, которые должны быть маскированы, по крайней мере, при использовании метода cv2.TM_CCORR_NORMED
.
Хотя это в принципе решает ваш вопрос, в этом случае оно не даст рабочего решения.
Это из-за фильтра Канни Край, который применяется к изображениям. Поскольку при применении Canny невозможно замаскировать красные пиксели в шаблоне, границы областей красных пикселов будут влиять на результат обнаружения краев и, таким образом, изменять шаблон так, чтобы он выглядел совершенно иначе, чем оригинал.
В этом примере сопоставление завершается ошибкой, возвращая позицию, которая является полностью неправильной.
Удаление шагов Canny решает эту проблему ... но также делает подход менее надежным / точным. В этом случае сопоставление фактически заканчивается в нескольких пикселях от 100% правильного соответствия. К сожалению, я не могу придумать какие-либо способы улучшить это.
Вот полный код, который работает для меня (с вышеупомянутой оговоркой с точки зрения точности):
import cv2
import numpy as np
template = cv2.imread("masked_template.png")
mask = (template[:,:,0]==0) & (template[:,:,1]==0) & (template[:,:,2]==255)
mask = mask.astype(np.uint8)
template = cv2.cvtColor(template, cv2.COLOR_BGR2GRAY)
#template = cv2.Canny(template, 50, 200)
edged = cv2.imread("edged.png")
edged = cv2.cvtColor(edged, cv2.COLOR_BGR2GRAY)
#edged = cv2.Canny(edged, 50, 200)
result = cv2.matchTemplate(edged, template, cv2.TM_CCORR_NORMED, mask=mask)
(_, maxVal, _, maxLoc) = cv2.minMaxLoc(result)