代碼實現:
import cv2
import numpy as npimg_rgb = cv2.imread('mobanpipei.jpg')
img_gray = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2GRAY)
template = cv2.imread('jianto.jpg', flags=0)
h, w = template.shape[:2]# 讀取圖像# # 順時針旋轉 90 度(k=1)
# rotated_image1 = np.rot90(template, k=1)
# # 逆時針旋轉 90 度(k=-1)
# rotated_image2 = np.rot90(template, k=-1)
j=[0,1,-1]
# 模板匹配
for i in j:template1 = np.rot90(template,k=i)res = cv2.matchTemplate(img_gray, template1, cv2.TM_CCOEFF_NORMED)threshold = 0.9 # 匹配閾值loc = np.where(res >= threshold) # 獲取符合閾值的坐標(行,列)# 繪制所有匹配區域的矩形框for pt in zip(*loc[::-1]):cv2.rectangle(img_rgb, pt, (pt[0] + w, pt[1] + h), color=(0, 0, 255), thickness=6)cv2.imshow('Template Matching Result', img_rgb)
cv2.waitKey(0)
這段代碼是一個帶旋轉角度的模板匹配程序,核心功能是在目標圖像中查找與模板圖像(包含 0°、90° 順時針、90° 逆時針三種旋轉狀態)匹配度較高的區域,并標記出這些區域。下面分步驟解析:
一、基礎準備:導入庫與讀取圖像
import cv2 # 導入OpenCV庫,用于圖像處理
import numpy as np # 導入numpy庫,用于數組操作(如旋轉)# 讀取目標圖像(待檢測的大圖),默認讀取為BGR格式
img_rgb = cv2.imread('mobanpipei.jpg')
# 將目標圖像轉為灰度圖(模板匹配通常在單通道灰度圖上進行,減少計算量)
img_gray = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2GRAY)# 讀取模板圖像(要查找的小圖),flags=0表示以灰度圖格式讀取
template = cv2.imread('jianto.jpg', flags=0)
# 獲取模板圖像的高和寬(h:高度,w:寬度),后續繪制匹配區域時需要
h, w = template.shape[:2]
核心目的:加載目標圖像和模板圖像,并將目標圖像轉為灰度圖(模板匹配對顏色不敏感,灰度圖可簡化計算)。
注意:模板圖像直接以灰度圖讀取(flags=0
),避免后續重復轉換。
二、處理模板旋轉:考慮多方向匹配
# 定義旋轉角度參數:0(不旋轉)、1(順時針90°)、-1(逆時針90°)
j = [0, 1, -1]
為什么需要旋轉?實際場景中,模板可能在目標圖像中以不同角度存在(比如模板是 “箭頭”,可能朝上、朝左、朝右),通過旋轉模板可提高匹配覆蓋率。
np.rot90
函數說明:k=0
表示不旋轉;k=1
表示順時針旋轉 90°;k=-1
表示逆時針旋轉 90°。
三、核心邏輯:多角度模板匹配與結果標記
# 遍歷每個旋轉角度,分別進行模板匹配
for i in j:# 按當前角度旋轉模板(得到旋轉后的模板)template1 = np.rot90(template, k=i)# 模板匹配:在目標灰度圖中查找與旋轉后模板匹配的區域# 方法:cv2.TM_CCOEFF_NORMED(歸一化相關系數匹配,結果范圍[-1,1],越接近1匹配度越高)res = cv2.matchTemplate(img_gray, template1, cv2.TM_CCOEFF_NORMED)# 設置匹配閾值(只保留匹配度≥0.9的區域,閾值越高,匹配越嚴格)threshold = 0.9# 找到所有匹配值≥閾值的位置坐標(返回的loc是元組,格式:(行坐標列表, 列坐標列表))loc = np.where(res >= threshold)# 遍歷所有符合條件的坐標,繪制矩形框標記匹配區域# zip(*loc[::-1]):將坐標從(行,列)轉換為(列,行)(OpenCV中圖像坐標是(x,y)對應列和行)for pt in zip(*loc[::-1]):# 繪制矩形:左上角坐標pt=(x,y),右下角坐標=(x+w, y+h),紅色(BGR中(0,0,255)),線寬6cv2.rectangle(img_rgb, pt, (pt[0] + w, pt[1] + h), color=(0, 0, 255), thickness=6)
模板匹配原理:cv2.matchTemplate
會在目標圖像上滑動模板,計算每個位置的匹配度,生成一個 “匹配結果圖”(res
),其中每個像素值代表該位置的匹配程度。
坐標轉換細節:loc
返回的是(行,列)
,而 OpenCV 繪制矩形需要(x,y)
(對應列、行),因此用loc[::-1]
反轉順序,再用zip(*)
轉換為可迭代的坐標對。
閾值選擇:threshold=0.9
是經驗值,可根據實際匹配效果調整(值太高可能漏檢,太低可能誤檢)。
四、顯示結果
# 顯示標記了匹配區域的目標圖像
cv2.imshow('Template Matching Result', img_rgb)
# 等待按鍵輸入(0表示無限等待),按任意鍵后關閉窗口
cv2.waitKey(0)
最終在窗口中顯示目標圖像,所有匹配度≥0.9 的區域會被紅色矩形框標記。
實現效果:
代碼特點與注意事項
- 多角度匹配:通過旋轉模板(0°、90° 順 / 逆時針),解決了模板在目標圖像中旋轉導致的匹配失效問題。
- 潛在優化點:
- 旋轉后模板的尺寸會變化(如 90° 旋轉后,原高度 h 變為寬度,原寬度 w 變為高度),但代碼中仍用原
w
和h
繪制矩形,可能導致矩形框尺寸不準確(需根據旋轉后的模板尺寸動態調整)。 - 未處理模板縮放問題:如果目標圖像中模板的大小與原圖不同,可能匹配失敗(可結合圖像金字塔實現多尺度匹配)。
- 旋轉后模板的尺寸會變化(如 90° 旋轉后,原高度 h 變為寬度,原寬度 w 變為高度),但代碼中仍用原
- 適用場景:適用于檢測目標在圖像中可能存在 90° 旋轉的場景(如特定圖標、符號等)。
總結:這段代碼通過 “旋轉模板 + 多角度匹配” 的思路,提高了模板匹配的魯棒性,能有效標記出目標圖像中與不同角度模板匹配的區域,是模板匹配技術在實際場景中的典型應用。