Khớp mẫu (Template matching) là một kỹ thuật, theo đó một bản vá hoặc mẫu có thể được khớp từ một ảnh thực tế. Đây cơ bản là một cơ chế khớp mẫu (pattern matching).
Trong Python có module OpenCV. Sử dụng OpenCV, chúng ta có thể dễ dàng tìm thấy sự khớp. Vì vậy trong bài toán này, các kỹ thuật khớp mẫu OpenCV được sử dụng.
Để sử dụng chức năng OpenCV, chúng ta cần tải chúng xuống sử dụng pip.
sudo pip3 install opencv-python
Đối với nhiệm vụ khớp mẫu, có một yếu tố độ chính xác, yếu tố này được gọi là ngưỡng (threshold). Ví dụ, chúng ta có thể dễ dàng tạo sơ đồ nhận diện khuôn mặt sử dụng giải pháp khớp mẫu này. Chúng ta có thể cung cấp một số hình ảnh của mắt hoặc bất kỳ bộ phận nào của khuôn mặt, sau đó sử dụng những hình ảnh đó làm mẫu, nó có thể dễ dàng tìm thấy sự khớp, nhưng có nhiều biến thể khác nhau trong mắt. Vì vậy nếu chúng ta đặt mức độ chính xác ở 50%, nó sẽ phát hiện tốt hơn mức độ chính xác 100%. Thông thường, mức độ chính xác là 80% trong các trường hợp khác nhau.
Các bước khớp Mẫu
Lấy ảnh thực tế và chuyển đổi nó thành ảnh thang độ xám (gray scale).
Lấy mẫu làm ảnh thang độ xám.
Mẫu trượt qua ảnh thực tế và tìm vị trí nơi mức độ chính xác khớp.
Khi kết quả lớn hơn mức độ chính xác, đánh dấu vị trí đó là đã phát hiện.
Đối với trường hợp đầu tiên ảnh đầu vào và mẫu là:
Ảnh chính

Mẫu

Mã ví dụ
import cv2
import numpy as np
# mở ảnh chính và chuyển đổi thành ảnh thang độ xám
main_image = cv2.imread('main_image.png')
gray_image = cv2.cvtColor(main_image, cv2.COLOR_BGR2GRAY)
# mở mẫu như ảnh thang độ xám
template = cv2.imread('template1.png', 0)
width, height = template.shape[::-1] # lấy chiều rộng và chiều cao
# khớp mẫu sử dụng cv2.matchTemplate
match = cv2.matchTemplate(gray_image, template, cv2.TM_CCOEFF_NORMED)
threshold = 0.8
position = np.where(match >= threshold) # lấy vị trí của mẫu trong ảnh
for point in zip(*position[::-1]):
# vẽ hình chữ nhật quanh mẫu khớp
cv2.rectangle(main_image, point, (point[0] + width, point[1] + height), (0, 204, 153), 0)
cv2.imshow('Template Found', main_image)
cv2.waitKey(0)
Đầu ra

Mã trên không hỗ trợ multi-scaling (đa tỷ lệ). Vì vậy nếu kích thước của mẫu không giống nhau, nó sẽ không phát hiện. Vì vậy trong phần tiếp theo, chúng ta sẽ xem cách chúng ta có thể sử dụng tính năng multi-scaling để phát hiện mẫu.
Trong cách tiếp cận này, ảnh thực tế được chuyển đổi thành các kích thước khác nhau, mỗi lần nó khớp mẫu, và tìm hệ số tương quan lớn nhất để định vị các khớp.
Ở đây ảnh thực tế giống nhau, mẫu ở đây là:

Mã ví dụ
import imutils
import cv2
import numpy as np
# Mở mẫu và lấy canny
template = cv2.imread('template3.jpg')
template = cv2.cvtColor(template, cv2.COLOR_BGR2GRAY)
template = cv2.Canny(template, 10, 25)
(height, width) = template.shape[:2]
# mở ảnh chính và chuyển đổi thành ảnh thang độ xám
main_image = cv2.imread('main_image.png')
gray_image = cv2.cvtColor(main_image, cv2.COLOR_BGR2GRAY)
temp_found = None
for scale in np.linspace(0.2, 1.0, 20)[::-1]:
# resize ảnh và lưu tỷ lệ
resized_img = imutils.resize(gray_image, width=int(gray_image.shape[1] * scale))
ratio = gray_image.shape[1] / float(resized_img.shape[1])
if resized_img.shape[0] < height or resized_img.shape[1] < width:
break
# Chuyển thành ảnh cạnh để kiểm tra
e = cv2.Canny(resized_img, 10, 25)
match = cv2.matchTemplate(e, template, cv2.TM_CCOEFF)
(_, val_max, _, loc_max) = cv2.minMaxLoc(match)
if temp_found is None or val_max > temp_found[0]:
temp_found = (val_max, loc_max, ratio)
# Lấy thông tin từ temp_found để tính toán tọa độ x,y
(_, loc_max, r) = temp_found
(x_start, y_start) = (int(loc_max[0]), int(loc_max[1]))
(x_end, y_end) = (int((loc_max[0] + width)), int((loc_max[1] + height)))
# Vẽ hình chữ nhật quanh mẫu
cv2.rectangle(main_image, (x_start, y_start), (x_end, y_end), (153, 22, 0), 5)
cv2.imshow('Template Found', main_image)
cv2.waitKey(0)
Đầu ra
