Уменьшение пропусков при сопоставлении с шаблоном (с использованием прозрачного шаблона) - PullRequest
0 голосов
/ 07 августа 2020

Я пытаюсь определить положение части головоломки на изображении головоломки. У меня есть

  1. изображение части пазла (прозрачный png)
  2. изображение доски-головоломки с белым контуром вокруг правильного положения

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

Вот несколько примеров результатов, которые я получаю https://imgur.com/a/ZYyw7tU

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

Любые советы или мысли по оптимизации были бы очень признательны!

Это мой полный код:

full_image = cv2.imread('puzzle_1.jpg')    
piece = cv2.imread('piece_1.png', cv2.IMREAD_UNCHANGED)
partial_image = cv2.cvtColor(piece,cv2.COLOR_BGR2GRAY)

contours, hierarchy = cv2.findContours(partial_image.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
   
template = np.zeros((55, 55, 4), dtype=np.uint8)

cv2.drawContours(template, contours, -1, (255, 255, 255, 255),1)
hh, ww = template.shape[:2]

puzzleP = template[:,:,0:3]
alpha = template[:,:,3]
alpha = cv2.merge([alpha,alpha,alpha])

correlation = cv2.matchTemplate(full_image, puzzleP, cv2.TM_CCORR_NORMED, mask=alpha)

threshhold = 0.98
loc = np.where(correlation >= threshhold)

result = full_image.copy()
for pt in zip(*loc[::-1]):
    cv2.rectangle(result, pt, (pt[0]+ww, pt[1]+hh), (0,0,255), 1)
    print(pt)
    
cv2.imwrite('puzzle_piece.png', puzzleP)
cv2.imwrite('full_image_alpha.png', alpha)
cv2.imwrite('full_image_matches.jpg', result)

РЕДАКТИРОВАТЬ: Вот пример двух файлов (piece_1.png и puzzle_1.jpg) (в этом примере много несоответствий) https://imgur.com/a/nGSXcNg

1 Ответ

1 голос
/ 07 августа 2020

Кажется, это отлично работает для меня с вашим изображением в Python / OpenCV.

  • Прочтите большие и маленькие изображения
  • Преобразование маленького изображения в серый и пороговое в двоичное
  • Получить самый большой контур двоичного изображения
  • Нарисуйте этот контур как белый на черном фоне для использования в качестве маски
  • Извлеките каналы BGR прозрачного маленького изображения как template
  • Выполните сопоставление с шаблоном и получите наибольшее совпадение
  • Нарисуйте поле сопоставления на копии большого изображения
  • Сохраните результаты

Большое изображение:

enter image description here

Small image:

enter image description here

import cv2
import numpy as np

# read images
full_image = cv2.imread('puzzle_1.jpg')    
piece = cv2.imread('piece_1.png', cv2.IMREAD_UNCHANGED)

# convert piece to gray and threshold to binary
partial_image = cv2.cvtColor(piece,cv2.COLOR_BGR2GRAY)
partial_image = cv2.threshold(partial_image, 0, 255, cv2.THRESH_BINARY)[1]

# get largest contour from binary image
contours = cv2.findContours(partial_image.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours = contours[0] if len(contours) == 2 else contours[1]
big_contour = max(contours, key=cv2.contourArea)

# draw the contour of the piece outline as the mask
mask = np.zeros((55, 55, 3), dtype=np.uint8)
cv2.drawContours(mask, [big_contour], 0, (255,255,255), 1)
hh, ww = mask.shape[:2]

# extract the template from the BGR (no alpha) piece 
template = piece[:,:,0:3]

correlation = cv2.matchTemplate(full_image, template, cv2.TM_CCORR_NORMED, mask=mask)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(correlation)
max_val_ncc = '{:.3f}'.format(max_val)
print("normalize_cross_correlation: " + max_val_ncc)
xx = max_loc[0]
yy = max_loc[1]

print('xmatchloc =',xx,'ymatchloc =',yy)

# draw template bounds and corner intersection in red onto img
result = full_image.copy()
cv2.rectangle(result, (xx, yy), (xx+ww, yy+hh), (0, 0, 255), 1)

# save results
cv2.imwrite('puzzle_template.png', template)
cv2.imwrite('puzzle_mask.png', mask)
cv2.imwrite('full_image_matches.jpg', result)

# show results
cv2.imshow('full_image', full_image)
cv2.imshow('piece', piece)
cv2.imshow('partial_image', partial_image)
cv2.imshow('mask', mask)
cv2.imshow('template', template)
cv2.imshow('result', result)
cv2.waitKey(0)
cv2.destroyAllWindows()

(bgr) Template:

enter image description here

Mask:

enter image description here

Largest Match Location:

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

...