OpenCV сопоставляет несколько кадров на изображении - PullRequest
1 голос
/ 10 апреля 2020

Я новичок в OpenCV, и я хотел бы найти решение, чтобы найти несколько изображений с текстом на одном изображении. В будущем мне понадобятся эти элементы для распознавания.

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

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

шаблон фрейма:

frame tempate

сцена:

scene

код:

import cv2
import numpy as np

method = cv2.TM_CCOEFF_NORMED
threshold = 0.90

img_main = cv2.imread('images/garden.jpg')
template = cv2.imread('images/frame_trans.png', cv2.IMREAD_GRAYSCALE)
template_gray = template

img_main_gray = cv2.cvtColor(img_main, cv2.COLOR_BGR2GRAY)
w, h = template.shape[::-1]

res = cv2.matchTemplate(img_main_gray, template_gray, method)

cv2.normalize(res, res, 0., 1., cv2.NORM_MINMAX)
cv2.threshold(res, threshold, 1, cv2.THRESH_TOZERO)

i = 0
while i < 100:
    min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)
    if method in [cv2.TM_SQDIFF, cv2.TM_SQDIFF_NORMED]:
        top_left = min_loc
    else:
        top_left = max_loc

    if max_val > threshold:
        print(top_left)
        bottom_right = (top_left[0] + w, top_left[1] + h)
        cv2.rectangle(img_main, top_left, bottom_right, (0, 0, 255), 2)
        cv2.floodFill(img_main_gray, None, top_left, 0, 0.1, 1.0)
    else:
        break
    i += 1

cv2.imwrite('sample6_output.png', img_main)
cv2.imshow('sample6', img_main)
cv2.waitKey()

Результат сценария здесь ...

PyDev console: starting.
Python 3.8.2 (tags/v3.8.2:7b3ab59, Feb 25 2020, 23:03:10) [MSC v.1916 64 bit (AMD64)] on win32
runfile('D:/MyProjects/PyHeroRecognition/sample6.py', wdir='D:/MyProjects/PyHeroRecognition')
(71, 45)
(71, 45)
(71, 45)
(71, 45)
(71, 45)
(71, 45)
(71, 45)
(71, 45)
(71, 45)
(71, 45)

Результат изображения:

result

Ответы [ 3 ]

0 голосов
/ 11 апреля 2020

Вот как выполнить сопоставление шаблона с прозрачным изображением шаблона в Python / OpenCV. Извините за использование изображений Imagemagick, но у меня уже был этот пример.

Ввод:

enter image description here

Прозрачный шаблон:

enter image description here

import cv2
import numpy as np

# read image
img = cv2.imread('logo.png')

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

# extract template mask as grayscale from alpha channel and make 3 channels
tmplt_mask = tmplt[:,:,3]
tmplt_mask = cv2.merge([tmplt_mask,tmplt_mask,tmplt_mask])

# extract templt2 without alpha channel from tmplt
tmplt2 = tmplt[:,:,0:3]

# do template matching
corrimg = cv2.matchTemplate(img,tmplt2,cv2.TM_CCORR_NORMED, mask=tmplt_mask)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(corrimg)
max_val_ncc = '{:.3f}'.format(max_val)
print("correlation match score: " + max_val_ncc)
xx = max_loc[0]
yy = max_loc[1]
print('xmatch =',xx,'ymatch =',yy)

# draw red bounding box to define match location
result = img.copy()
pt1 = (xx,yy)
pt2 = (xx+ww, yy+hh)
cv2.rectangle(result, pt1, pt2, (0,0,255), 1)

cv2.imshow('image', img)
cv2.imshow('template2', tmplt2)
cv2.imshow('template_mask', tmplt_mask)
cv2.imshow('result', result)
cv2.waitKey(0)
cv2.destroyAllWindows()

# save results
cv2.imwrite('logo_hat_match2.png', result)


Результат, показывающий ограничивающую рамку местоположения матча:

enter image description here

0 голосов
/ 12 апреля 2020

@ fmw42 Большое спасибо за идею! Я пересек ваш и мой код, но получил только один результат (см. Ниже). Мой следующий вопрос: как захватить несколько результатов?

import cv2
import numpy as np

method = cv2.TM_CCORR_NORMED
threshold = 0.90

# read scene image
main_img = cv2.imread('images/garden.jpg')

# read template with alpha
template = cv2.imread('images/frame_trans.png', cv2.IMREAD_UNCHANGED)
h, w = template.shape[:2]

# extract template mask as grayscale from alpha channel and make 3 channels
tmplt_mask = template[:, :, 3]
tmplt_mask = cv2.merge([tmplt_mask, tmplt_mask, tmplt_mask])

# extract templt2 without alpha channel from tmplt
tmplt2 = template[:, :, 0:3]

res = cv2.matchTemplate(main_img, tmplt2, method, mask=tmplt_mask)

output_img = main_img.copy()

i = 0
while i < 100:
    min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)
    if method in [cv2.TM_SQDIFF, cv2.TM_SQDIFF_NORMED]:
        top_left = min_loc
    else:
        top_left = max_loc

    if max_val > threshold:
        print("%s: %s" % (max_val, top_left))
        bottom_right = (top_left[0] + w, top_left[1] + h)
        cv2.rectangle(output_img, top_left, bottom_right, (0, 0, 255), 2)
        cv2.floodFill(res, None, top_left, 0, 0.1, 1.0)
    else:
        break
    i += 1

cv2.imwrite('sample8_output.png', output_img)
cv2.imshow('sample8', output_img)
cv2.waitKey()


Вывод на консоль:

PyDev console: starting.
Python 3.8.2 (tags/v3.8.2:7b3ab59, Feb 25 2020, 23:03:10) [MSC v.1916 64 bit (AMD64)] on win32
runfile('D:/MyProjects/PyHeroRecognition/sample8_alpha.py', wdir='D:/MyProjects/PyHeroRecognition')
0.9918215870857239: (71, 45)
>>>

Вывод изображения результата sample 8 ourput small

0 голосов
/ 10 апреля 2020

Для алгоритма сопоставления с шаблоном всякий раз, когда вы находите максимальное значение сходства, вы должны установить основанный пиксель равным нулю. Если вы этого не сделаете, то в каждой итерации вы найдете один и тот же пиксель с помощью функции cv2.minMaxLoc.

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

Я написал простой код для вашей проблемы, но в этом контексте он кажется, что соответствие шаблонов не очень хорошо

import cv2
import numpy as np

method = cv2.TM_CCORR_NORMED
threshold = 0.7


img_main = cv2.imread('images/garden.jpg')
template = cv2.imread('images/frame_trans.png', cv2.IMREAD_GRAYSCALE)
template_gray = template

img_main_gray = cv2.cvtColor(img_main, cv2.COLOR_BGR2GRAY)
w, h = template.shape[::-1]

res = cv2.matchTemplate(img_main_gray, template_gray, method)

cv2.normalize(res, res, 0., 1., cv2.NORM_MINMAX)
cv2.threshold(res, threshold, 1, cv2.THRESH_TOZERO)

i = 0

border=45  # I have added this line to control the area that must be zero
while i < 20:
    min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)
    print(max_val)
    if method in [cv2.TM_SQDIFF, cv2.TM_SQDIFF_NORMED]:
        top_left = min_loc
    else:
        top_left = max_loc

    if max_val > threshold:
#         print(top_left)
        bottom_right = (top_left[0] + w, top_left[1] + h)
#         cv2.circle(img_main,max_loc,5,(0,0,255),1)
        cv2.rectangle(img_main, top_left, bottom_right, (0, 0, 255), 5)
        cv2.floodFill(img_main_gray, None, top_left, 0, 0.1, 1.0)
    i += 1
    res[max_loc[1]-border:max_loc[1]+border,max_loc[0]-border:max_loc[0]+border]=0  # set zero the max loc

img_main=cv2.cvtColor(img_main,cv2.COLOR_BGR2RGB)
import matplotlib.pyplot as plt
plt.figure(figsize=(10,12))
plt.imshow(res)
plt.figure(figsize=(10,12))
plt.imshow(img_main)
...