Hướng dẫn template matching python opencv - mẫu khớp với python opencv

Ở bài trước mình đã hướng dẩn các bạn về Canny Edge Detection và Gradients. Và ở bài viết tiếp theo này mình sẽ giới thiệu và hướng dẩn một phiên bản khá cơ bản về nhận dạng đối tượng.

I. Giới thiệu.

Ý tưởng ở đây là tìm các vùng giống nhau của hình ảnh khớp với mẫu tôi cung cấp, đưa ra một ngưỡng nhất định. So sánh chính xác đối tượng, chính xác ánh sáng / quy mô / góc, điều này có thể làm việc tuyệt vời.

Một ví dụ trong đó các điều kiện này thường được đáp ứng chỉ cần là có các điểm giống nhau, tương tưj nhau như các ánh đèn trên thiết bị điện tử. Có các nút và hình ảnh của chúng gần gần giống nhau, vì vậy bạn có thể sử dụng đối sánh mẫu. Để bắt đầu, bạn sẽ cần một hình ảnh chính và một mẫu. Bạn nên lấy mẫu của bạn từ việc cắt chúng ta từ ảnh gốc sao cho chính xác với ảnh bạn đang muốn tìm kiếm trong hình ảnh. Tôi sẽ cung cấp một hình ảnh làm ví dụ, nhưng vui lòng sử dụng hình ảnh của bạn yêu thích hoặc một cái gì đó tương tự.

II. Template Matching

1. Ví dụ.

Hình ảnh chính:

Hướng dẫn template matching python opencv - mẫu khớp với python opencv
Mẫu mà tôi sẽ tìm kiếm: (một nút trên thiết bị điện)

Hướng dẫn template matching python opencv - mẫu khớp với python opencv

Đây chỉ là một trong các nút, nhưng tôi tò mò muốn xem liệu tôi có thể tìm thấy kết hợp bất kỳ nút nào khác không. Tôi có tùy chọn ngưỡng, vì việc chọn ngường hoàn toàn không có vấn đề gì khi thực hiện việc so sánh nên tôi chọn là 80%, và tôi cho rằng đó là một ngưỡng tốt.

Tôi sẽ bắt đầu bằng cách tải và chuyển đổi hình ảnh ngay bây giờ.

2. Hướng dẫn.

import cv2
import numpy as np

img_rgb = cv2.imread('opencv-template-matching-python-tutorial.jpg')
img_gray = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2GRAY)

template = cv2.imread('opencv-template-for-matching.jpg',0)
w, h = template.shape[::-1]

Cho đến nay, tôi sẽ tải cả hai hình ảnh lên, chuyển đổi sang màu xám cho chúng. Tôi giữ nguyên hình ảnh RGB gốc và tạo phiên bản màu xám. Tôi đã đề cập điều này trước đây, nhưng lý do tại sao tôi làm điều này là bởi vì tôi thực hiện tất cả việc xử lý trong phiên bản màu xám, sau đó sử dụng cùng tọa độ cho nhãn và như vậy trên hình ảnh màu.

Với hình ảnh chính, tôi chỉ có phiên bản màu và phiên bản màu xám. Tôi tải mẫu và lưu ý kích thước.

res = cv2.matchTemplate(img_gray,template,cv2.TM_CCOEFF_NORMED)
threshold = 0.8
loc = np.where( res >= threshold)

Ở đây, ta gọi res matchTemplate giữa img_gray (hình ảnh chính của chúng ta), khuôn mẫu, và sau đó là phương thức kết hợp mà chúng ta sẽ sử dụng. Tôi chỉ định ngưỡng, ở đây 0,8 cho 80%.

Sau đó, tôi tìm các vị trí có câu lệnh logic, trong đó tỷ lệ này lớn hơn hoặc bằng 80%. Cuối cùng, tôi đánh dấu tất cả các kết quả phù hợp trên hình ảnh gốc, sử dụng tọa độ tôi tìm thấy trong hình ảnh màu xám:

for pt in zip(*loc[::-1]):
    cv2.rectangle(img_rgb, pt, (pt[0] + w, pt[1] + h), (0,255,255), 2)

cv2.imshow('Detected',img_rgb)

Hướng dẫn template matching python opencv - mẫu khớp với python opencv
Vì vậy, tôi đã có một vài nút tìm thấy trên hình. Có thể hạ thấp ngưỡng? Tôi sẽ thử ngưỡng = 0,7.

Hướng dẫn template matching python opencv - mẫu khớp với python opencv

3. Kết quả.

Có một số kết quả sai ở đây. Bạn có thể tiếp tục điều chỉnh ngưỡng cho đến khi bạn có 100%, nhưng bạn có thể không bao giờ đạt được điều đó mà không có kết quả dương tính giả. Một tùy chọn khác là chỉ cần chụp một mẫu hình ảnh khác. Đôi khi, có thể hữu ích khi có nhiều hình ảnh của cùng một đối tượng. Bằng cách này, bạn có thể giữ cho ngưỡng của bạn đủ cao để tương đối chắc chắn rằng kết quả của bạn sẽ chính xác. Trong hướng dẫn tiếp theo, chúng ta sẽ bao gồm khai thác tiền cảnh.

III. Tài liệu tham khảo.

http://docs.opencv.org/ https://techmaster.vn/ https://pythonprogramming.net/

Trong hướng dẫn tiếp theo, tôi sẽ giới thiệu về GrabCut Foreground Extraction trong openCV với Python nhé .

Introduction

Hello mọi người, trong bài viết này mình sẽ giới thiệu với các bạn một kỹ thuật object detection mà không sử dụng machine learning mang tên Template Matching.

Template matching cho phép chúng ta phát hiện vật thể trong ảnh đầu vào bằng cách sử dụng một ảnh tham chiếu (template) chứa vật thể cần phát hiện. Cách thuật toán hoạt động: cho phép chúng ta phát hiện vật thể trong ảnh đầu vào bằng cách sử dụng một ảnh tham chiếu (template) chứa vật thể cần phát hiện. Cách thuật toán hoạt động:

  • Trượt ảnh template trên ảnh đầu vào (giống tích chập 2D)
  • Ảnh template sẽ được so sánh với cửa sổ trượt tương ứng trên ảnh đầu vào bằng một công thức. Một số phương pháp so sánh được hỗ trợ trong opencv được cho ở hình dưới

Hướng dẫn template matching python opencv - mẫu khớp với python opencv

Trong bảng trên, TT là ảnh template, II là ảnh đầu vào. Khi ta trượt ảnh template trên ảnh đầu vào, một metric sẽ được tính toán tại mỗi pixel của ma trận đầu ra RR . Ma trận RR sẽ có kích thước nhỏ hơn ảnh đầu vào (giống với kết quả khi thực hiện tích chập). Giá trị mỗi pixel của RR biểu diễn mức độ trùng khớp của ảnh template với vị trí tương ứng trên ảnh đầu vào. Từ đó, ta có thể chọn ra pixel có giá trị cao nhất (nếu muốn detect 1 vật thể) hoặc lấy threshold RR (nếu detect nhiều vật thể).TT là ảnh template, II là ảnh đầu vào. Khi ta trượt ảnh template trên ảnh đầu vào, một metric sẽ được tính toán tại mỗi pixel của ma trận đầu ra RR . Ma trận RR sẽ có kích thước nhỏ hơn ảnh đầu vào (giống với kết quả khi thực hiện tích chập). Giá trị mỗi pixel của RR biểu diễn mức độ trùng khớp của ảnh template với vị trí tương ứng trên ảnh đầu vào. Từ đó, ta có thể chọn ra pixel có giá trị cao nhất (nếu muốn detect 1 vật thể) hoặc lấy threshold RR (nếu detect nhiều vật thể).

Ưu điểm:

  • Nhanh, đơn giản
  • Không tốn công làm data

Nhược điểm

  • 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.

Template matching trong opencv

Đầu tiên các bạn cài đặt opencv đã nhé

pip install opencv-contrib-python

Opencv cung cấp sẵn hàm cv2.matchTemplate() cho thuật toán template matching. Hàm này nhận vào 3 tham số chính

  • Ảnh đầu vào input chứa vật thể cần detect
  • Ảnh template
    res = cv2.matchTemplate(img_gray,template,cv2.TM_CCOEFF_NORMED)
    threshold = 0.8
    loc = np.where( res >= threshold)
    
    0
  • res = cv2.matchTemplate(img_gray,template,cv2.TM_CCOEFF_NORMED)
    threshold = 0.8
    loc = np.where( res >= threshold)
    
    1: cách tính ma trận output RRRR

Để minh họa chạy thuật toán, ta sẽ cần 1 ảnh đầu vào và 1 ảnh template. Ở đây mình sẽ dùng 2 ảnh này. Ảnh template đã được mình crop ra từ 1 vùng của ảnh đầu vào để cho kết quả tốt nhất

Hướng dẫn template matching python opencv - mẫu khớp với python opencv

Hướng dẫn template matching python opencv - mẫu khớp với python opencv

Đầu tiên ta import các thư viện và đọc ảnh vào

import cv2 import matplotlib.pyplot as plt def imshow(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]
imshow(img)

Tiếp theo, ta gọi hàm cv2.matchTemplate() với

res = cv2.matchTemplate(img_gray,template,cv2.TM_CCOEFF_NORMED)
threshold = 0.8
loc = np.where( res >= threshold)
3 và
res = cv2.matchTemplate(img_gray,template,cv2.TM_CCOEFF_NORMED)
threshold = 0.8
loc = np.where( res >= threshold)
4

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

Hướng dẫn template matching python opencv - mẫu khớp với python opencv

Ở trên mình visualize ma trận output RR. Những vị trí sáng hơn là những vị trí có độ tương đồng cao với ảnh template. Tiếp theo ta lấy threshold để lọc ra những vị trí nàyRR. Những vị trí sáng hơn là những vị trí có độ tương đồng cao với ảnh template. Tiếp theo ta lấy threshold để lọc ra những vị trí này

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

Và kết quả là:

Hướng dẫn template matching python opencv - mẫu khớp với python opencv

Trông rất tốt đúng không nào! Nếu các bạn muốn phát hiện thêm những hình quân bích ở dưới thì có thể hạ threshold xuống, và tất nhiên các trường hợp false positive cũng sẽ tăng theo.

THRESHOLD = 0.6
loc = np.where(res >= THRESHOLD) #Draw boudning box
for y, x in zip(loc[0], loc[1]): cv2.rectangle(img, (x, y), (x + w, y + h), (255,0,0), 1)
imshow(img)

Hướng dẫn template matching python opencv - mẫu khớp với python opencv

Lý do có nhiều các đường bao dày lên như vậy là do có nhiều bounding box bị vẽ đè lên nhau. Để loại bỏ bớt các bạn có thể sử dụng thuật toán như Non Maximum Suppression. Và thật may mắn khi có bài viết rất hay về chủ đề này tại đây của tác giả Lê Minh Chiến.

Kết luận

Trong bài viết này, mình đã giới thiệu tới các bạn thuật toán Template Matching sử dụng opencv. Đây là một kỹ thuật khá đơn giản, có thể áp dụng cho một số bài toán phát hiện vật thể trong các điều kiện nhất định. Nếu các bạn thấy có ích thì hãy like, share hoặc upvote nhé. Chào tạm biệt và hẹn các bạn ở bài viết sau

Hướng dẫn template matching python opencv - mẫu khớp với python opencv