Template matching เป็นเทคนิคที่ patch หรือ template สามารถจับคู่จากภาพจริงได้ นี่คือกลไก pattern matching พื้นฐาน
ใน Python มีโมดูล OpenCV ใช้ openCV จับคู่ได้ง่าย ดังนั้นในปัญหานี้ ใช้เทคนิค template matching ของ OpenCV
เพื่อใช้ฟังก์ชัน OpenCV ต้องดาวน์โหลดด้วย pip
sudo pip3 install opencv-python
สำหรับ template matching task มี accuracy factor เรียกว่า threshold ตัวอย่างเช่น เราสามารถสร้าง face recognizing scheme ได้ง่ายด้วย template matching ให้รูปภาพตา หรือส่วนใดของใบหน้า ใช้รูปเหล่านั้นเป็น template จะหา match ได้ง่าย แต่มี variation ต่างๆ ในตา ดังนั้นถ้าตั้ง accuracy level 50% จะ detect ได้ดีกว่า 80% โดยทั่วไป accuracy level คือ 80% ในกรณีต่างๆ
ขั้นตอนการจับคู่ Templates
นำภาพจริงมาแปลงเป็น grayscale image
นำ template มาเป็น grayscale image
Template slide เลื่อนผ่านภาพจริงและหาตำแหน่งที่ accuracy level ตรงกัน
เมื่อผลลัพธ์มากกว่าหรือเท่ากับ accuracy level จุดนั้นถูกทำเครื่องหมายว่า detected
สำหรับกรณีแรก Input image และ template คือ:
Main Image

The template

ตัวอย่างโค้ด
import cv2
import numpy as np
# เปิด main image และแปลงเป็น grayscale
main_image = cv2.imread('main_image.png')
gray_image = cv2.cvtColor(main_image, cv2.COLOR_BGR2GRAY)
# เปิด template เป็น grayscale
template = cv2.imread('template1.png', 0)
width, height = template.shape[::-1]
# จับคู่ template ด้วย cv2.matchTemplate
match = cv2.matchTemplate(gray_image, template, cv2.TM_CCOEFF_NORMED)
threshold = 0.8
position = np.where(match >= threshold)
# วาดสี่เหลี่ยมรอบ template ที่จับคู่ได้
for point in zip(*position[::-1]):
cv2.rectangle(main_image, point, (point[0] + width, point[1] + height), (0, 204, 153), 0)
cv2.imshow('Template Found', main_image)
cv2.waitKey(0)
ผลลัพธ์

โค้ดด้านบนไม่รองรับ multi-scaling ดังนั้นถ้าขนาด template ไม่เหมือนกัน จะไม่ detect ได้ ในส่วนต่อไปเราจะดูวิธีใช้ multi-scaling feature เพื่อ detect templates
ในแนวทางนี้ ภาพจริงถูกแปลงเป็นขนาดต่างๆ ทุกครั้งจับคู่ pattern และหา largest correlation coefficient เพื่อ locate matches
ที่นี่ main image เหมือนเดิม template อยู่ที่นี่:

ตัวอย่างโค้ด
import imutils
import cv2
import numpy as np
# เปิด template และได้ canny
template = cv2.imread('template3.jpg')
template = cv2.cvtColor(template, cv2.COLOR_BGR2GRAY)
template = cv2.Canny(template, 10, 25)
(height, width) = template.shape[:2]
# เปิด main image และแปลงเป็น grayscale
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 image และเก็บ ratio
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
# แปลงเป็น edged image สำหรับตรวจสอบ
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)
# ดึงข้อมูลจาก temp_found คำนวณ x,y coordinate
(_, 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)))
# วาดสี่เหลี่ยมรอบ template
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)
ผลลัพธ์
