iT邦幫忙

2025 iThome 鐵人賽

DAY 28
0
佛心分享-IT 人自學之術

OpwnCV影像處理新手村系列 第 28

🚀 DAY 28:模板匹配(Template Matching)

  • 分享至 

  • xImage
  •  

在許多電腦視覺應用中,我們常常需要在一張大圖中尋找特定的小圖(模板)。
這種方法稱為 模板匹配(Template Matching),常用於 GUI 自動化測試、遊戲畫面偵測、零件定位等場景。


目錄

  1. 模板匹配原理
  2. 範例圖片準備
  3. 單目標模板匹配
  4. 多目標模板匹配
  5. 方法比較與補充說明

1. 模板匹配原理

模板匹配是透過滑動視窗的方式,將模板圖片逐像素套用到大圖中,計算相似度分數。
OpenCV 提供 cv2.matchTemplate 來完成此操作。

常見的比對方法:

  • cv2.TM_CCOEFF
  • cv2.TM_CCOEFF_NORMED
  • cv2.TM_CCORR
  • cv2.TM_CCORR_NORMED
  • cv2.TM_SQDIFF
  • cv2.TM_SQDIFF_NORMED

📖 一般推薦使用 NORMED 版本,結果會在 [-1,1][0,1] 範圍內,較好判斷。


2. 範例圖片準備

假設我們有一張大圖 lake.jpg,以及要尋找的模板小圖 boat.jpg

import cv2

# 讀取圖片
img = cv2.imread("lake.jpg")
template = cv2.imread("boat.jpg")

cv2.imshow("img", img)
cv2.imshow("template", template)

# 將以下程式碼放在所有顯示語句的最後面
cv2.waitKey()
cv2.destroyAllWindows()

原圖


3. 單目標模板匹配

只尋找一個最佳匹配位置,適合目標只出現一次的情境。

import numpy as np

# 轉灰階
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
template_gray = cv2.cvtColor(template, cv2.COLOR_BGR2GRAY)

w, h = template_gray.shape[::-1]

# 模板匹配
res = cv2.matchTemplate(img_gray, template_gray, cv2.TM_CCOEFF_NORMED)

# 取得最佳匹配位置
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)

# 取最大值的位置
top_left = max_loc
bottom_right = (top_left[0] + w, top_left[1] + h)

# 繪製矩形
cv2.rectangle(img, top_left, bottom_right, (0, 255, 0), 2)
cv2.imshow("Template Matching", img)

單目標模板匹配


4. 多目標模板匹配

若大圖中有多個相同模板,可設定相似度閾值,篩選所有大於該值的位置。

threshold = 0.5  # 相似度閾值,建議設在 0.7~0.9 之間,數值越高代表匹配要求越嚴格
loc = np.where(res >= threshold)  # 找出所有相似度大於閾值的位置

for pt in zip(*loc[::-1]):  # loc[::-1] 轉換為 (x, y) 座標
    cv2.rectangle(img, pt, (pt[0] + w, pt[1] + h), (0, 0, 255), 2)  # 在每個匹配位置畫紅色框

cv2.imshow("Multiple Matches", img)

程式與參數說明:

  • threshold:設定模板匹配的相似度門檻,數值越高只會顯示最接近的結果,太低可能會有誤判。我這裡故意將數值設定成較低的0.5,可以看到旁邊另個艘船就出現誤判而出現了。
  • np.where(res >= threshold):回傳所有符合條件的座標點。
  • cv2.rectangle():在每個找到的匹配位置畫出紅色矩形框,框的大小與模板一致。
  • 若模板在大圖中出現多次,這種方法能一次標示所有位置。

多目標模板匹配

這時會發現同個物件被重複框選,為了解決重複框選的問題,我們將程式調整一下。
OpenCV 有提供 groupRectangles,可以把多個重疊的框合併成一個。

# 假設 res 已經算好,w, h 是模板大小
threshold = 0.5
loc = np.where(res >= threshold)

rects = []  # 暫存所有偵測到的框
for pt in zip(*loc[::-1]):
    rects.append([pt[0], pt[1], w, h])  # (x, y, w, h)

# 用 groupRectangles 合併重疊的框
rects, weights = cv2.groupRectangles(rects, groupThreshold=1, eps=0.5)

# 畫框
for (x, y, w, h) in rects:
    cv2.rectangle(img, (x, y), (x + w, y + h), (0, 0, 255), 2)

cv2.imshow("Multiple Matches", img)

多目標模板匹配-去除重複


5. 方法比較與補充說明

方法 優點 缺點 適用場景
模板匹配 實作簡單、速度快 不支援縮放/旋轉 固定大小與方向目標
特徵點方法(ORB/SIFT) 支援縮放、旋轉、變形 實作較複雜、速度較慢 目標有變形或多樣性

補充說明:

  • 模板匹配適合目標大小、方向固定的情境,若目標有縮放或旋轉,效果會明顯下降。
  • 若需處理縮放、旋轉或多樣性問題,建議改用特徵點方法(如 ORB、SIFT)。

🎯 今日結語

模板匹配是一種簡單直接的方法,適合固定大小與方向的目標。
若目標在影像中有縮放或旋轉差異,建議使用特徵點方法以提升辨識效果。


上一篇
🚀 DAY 27:透視變換(Perspective Transform)與文件掃描
系列文
OpwnCV影像處理新手村28
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言