Multiscale template matching

Introduction Hello mọi người, trong bài viết trước, mình đã giới thiệu tới mọi người kỹ thuật template matching dùng để phát hiện đối tượng trong ảnh. Tuy nhiên, phương pháp này có nhược điểm là ảnh template phải rất giống với vật thể trong ảnh cả về kích thước độ nghiêng, … Nếu khác

Introduction

Hello mọi người, trong bài viết trước, mình đã giới thiệu tới mọi người kỹ thuật template matching dùng để phát hiện đối tượng trong ảnh. Tuy nhiên, phương pháp này có nhược điểm là ảnh template phải rất giống với vật thể trong ảnh cả về kích thước độ nghiêng, … Nếu khác biệt quá lớn sẽ không phát hiện được
Trong bài viết này, mình sẽ sử dụng một mẹo nhỏ giúp ta sử dụng template matching với object có kích thước lớn hơn

Multiscale template matching

Ở bài viết trước, ta đã dừng lại ở đây

import cv2 
import matplotlib.pyplot as plt

defimshow(img, figsize=(6,6)):
    fig, ax = plt.subplots(1,1, figsize=(figsize))
    ax.axis('off')
    ax.imshow(img)
    
img = cv2.imread('spade.png')#Convert to grayscale
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
template = cv2.imread('template.png',0)
w, h = template.shape[1], template.shape[0]

res = cv2.matchTemplate(img_gray,template, cv2.TM_CCOEFF_NORMED)

THRESHOLD =0.95
loc = np.where(res >= THRESHOLD)#Draw boudning boxfor y, x inzip(loc[0], loc[1]):
    cv2.rectangle(img,(x, y),(x + w, y + h),(255,0,0),1)
imshow(img)

Khi ta thử đoạn code trên với object lớn hơn

img = cv2.imread('spade.png')#Convert to grayscale
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
template = cv2.imread('template.png',0)
w, h = template.shape[1], template.shape[0]

res = cv2.matchTemplate(img_gray,template, cv2.TM_CCOEFF_NORMED)

THRESHOLD =0.95
loc = np.where(res >= THRESHOLD)print(loc)#Output: (array([], dtype=int64), array([], dtype=int64))

Có thể thấy, khi vật thể lớn hơn hoặc bé hơn so với template thì thuật toán không phát hiện được. Ta có thể áp dụng mẹo sau để có phát hiện vật thể lớn hơn (hoặc làm ngược lại với vật thể nhỏ)

  • Downscale ảnh đầu vào xuống nhiều kích cỡ khác nhau (hoặc upscale lên)
  • Áp dụng thuật toán lên ảnh ở nhiều kích cỡ khác nhau
  • Lấy threshold và scale lại tọa độ tìm được

Code

Đầu tiên vẫn là tiết mục đọc ảnh quen thuộc

THRESHOLD = 0.9
img = cv2.imread('sun_work/ace.png')
#Convert to grayscale
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
template = cv2.imread('template.png', 0)
template_width, template_height = template.shape[1], template.shape[0]
imshow(img)

Định nghĩa các mức scale ảnh khác nhau bằng hàm np.linspace

for scale in np.linspace(0.1,1.0,20)[::-1]:
     resized = imutils.resize(img_gray, width=int(img_gray.shape[1]* scale))
     ratio = img_gray.shape[1]/float(resized.shape[1])#Bé hơn template thì dừngif resized.shape[0]< template_height or resized.shape[1]< template_width:break

Áp dụng template matching

res = cv2.matchTemplate(resized, template, cv2.TM_CCOEFF_NORMED)
loc = np.where(res >= THRESHOLD)#Draw boudning boxfor y, x inzip(loc[0], loc[1]):
    cv2.rectangle(img,(x, y),(x + w, y + h),(255,0,0),1)

Kết quả

Kết luận

Có thể thấy thuật toán chỉ phát hiện được một phần của vật thể. Tuy đã giải quyết được một phần vấn đề với vật thể nhiều kích thược khác nhau, nhưng cách cải tiến đơn giản này vẫn hoạt động không tốt trong các điểu kiện khác như ảnh bị nghiêng.. Một số cách tiếp cận khác để xử lý vẫn đề này có thể kể đến như keypoint matching sử dụng SIFT hoặc SURF

Nguồn: viblo.asia

Bài viết liên quan

WebP là gì? Hướng dẫn cách để chuyển hình ảnh jpg, png qua webp

WebP là gì? WebP là một định dạng ảnh hiện đại, được phát triển bởi Google

Điểm khác biệt giữa IPv4 và IPv6 là gì?

IPv4 và IPv6 là hai phiên bản của hệ thống địa chỉ Giao thức Internet (IP). IP l

Check nameservers của tên miền xem website trỏ đúng chưa

Tìm hiểu cách check nameservers của tên miền để xác định tên miền đó đang dùn

Mình đang dùng Google Domains để check tên miền hàng ngày

Từ khi thông báo dịch vụ Google Domains bỏ mác Beta, mình mới để ý và bắt đầ