關於Python機器視覺OpenCV圖片模板匹配


前言

本文的文字及圖片來源於網絡,僅供學習、交流使用,不具有任何商業用途,如有問題請及時聯系我們以作處理。

PS:如有需要Python學習資料的小伙伴可以點擊下方鏈接自行獲取

Python免費學習資料、代碼以及交流解答點擊即可加入


 

什么是模板匹配

簡單來說模板匹配就是通過現有的模板去與圖片進行比較找出圖中所匹配的圖像。

首先來看一下效果圖:

 

 

左圖是模板圖片,中圖是帶測試的圖片,右圖是匹配的結果

程序將在“中圖”中匹配“左圖”的模板圖片,如果中圖中含有模板圖片的話,則會在中圖畫出模板圖片的位置(用藍線圈出來)。

模板匹配原理:

模板匹配是一種用於在較大圖像中搜索和查找模板圖像位置的方法。為此,OpenCV帶有一個函數cv2.matchTemplate()。它只是將模板圖像滑動到輸入圖像上(就像在2D卷積中一樣),然后在模板圖像下比較模板和輸入圖像的補丁。OpenCV中實現了幾種比較方法。(您可以檢查文檔以了解更多詳細信息)。它返回一個灰度圖像,其中每個像素表示該像素的鄰域與模板匹配多少。

如果輸入圖像的大小(WxH)和模板圖像的大小(wxh),則輸出圖像的大小將為(W-w + 1,H-h + 1)。獲得結果后,可以使用cv2.minMaxLoc()函數查找最大/最小值在哪里。將其作為矩形的左上角,並以(w,h)作為矩形的寬度和高度。該矩形是您模板的區域。

目錄:

1.前提
2.兩種方法實現
3.后記

1.前提:

程序運行之前先安裝一下相關的庫


cv2
imutils

報錯1:


ModuleNotFoundError: No module named 'cv2' (安裝cv2) 

說明缺少opencv庫
在命令提示符窗口中,執行下面的命令:


pip install opencv-python

如果覺得下載過慢的可以執行下面的命令:(使用了豆瓣源下載,結果和上面是一樣的,只不過這個命令安裝快一些)


pip install -i https://pypi.doubanio.com/simple/ opencv-python 

兩種方法實現:

第一次方法:圖像模板匹配(最簡單)

模板匹配和卷積原理很像,模板在原圖像上從原點開始滑動,計算模板與(圖像被模板覆蓋的地方)的差別程度,這個差別程度的計算方法在OpenCV里有6種,然后將每次的結果放入一個矩陣里,作為結果輸出。假如原圖形是AXB大小,而模板是axb大小,則輸出結果的矩陣是(A-a+1)x(B-b+1)

代碼:

#模板匹配 import numpy as np import cv2 def cv_show(name,image): cv2.imshow(name,image) cv2.waitKey(0) cv2.destroyAllWindows() img = cv2.imread("source.jpg") template = cv2.imread("m.jpg") # 轉換為灰度圖片 gray1 = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) # 讀取測試圖片並將其轉化為灰度圖片 gray2 = cv2.cvtColor(template,cv2.COLOR_BGR2GRAY) h,w = template.shape[:2] #匹配 #TM_SQDIFF 匹配方法,歸一化的方法更好用 res = cv2.matchTemplate(gray1,gray2,cv2.TM_SQDIFF) #得到極值坐標 min_val,max_val,min_loc,max_loc = cv2.minMaxLoc(res) top_left = min_loc bottom_right = (top_left[0]+w,top_left[1]+h) #畫出標記點 cv2.rectangle(img,top_left,bottom_right,255,2) cv_show("img",img) 

運行結果:

 

第二種方法:多尺度模板匹配

多尺度模板匹配實現步驟

  • 步驟1-讀取模板圖片,並依次執行灰度化和邊緣檢測處理;
  • 步驟2-讀取測試圖片,遍歷整個尺度空間,進行圖片裁剪;
  • 步驟3-依次執行邊緣檢測和模板匹配,獲取到外接矩形;
  • 步驟4-根據結果對測試圖片中模板所在的位置進行更新;
  • 步驟5-首先進行位置轉換,然后繪制矩形框,最后顯示結果。

代碼實現:

# coding=utf-8 # 導入python包 import numpy as np import imutils import cv2 # 讀取模板圖片 template = cv2.imread("m.jpg") # 轉換為灰度圖片 template = cv2.cvtColor(template, cv2.COLOR_BGR2GRAY) # 讀取測試圖片並將其轉化為灰度圖片 image = cv2.imread('source.jpg') gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # 執行邊緣檢測 template = cv2.Canny(template, 50, 200) (tH, tW) = template.shape[:2] # 顯示模板 #cv2.imshow("Template", template) found = None # 循環遍歷不同的尺度 for scale in np.linspace(0.2, 1.0, 20)[::-1]: # 根據尺度大小對輸入圖片進行裁剪 resized = imutils.resize(gray, width = int(gray.shape[1] * scale)) r = gray.shape[1] / float(resized.shape[1]) # 如果裁剪之后的圖片小於模板的大小直接退出 if resized.shape[0] < tH or resized.shape[1] < tW: break # 首先進行邊緣檢測,然后執行模板檢測,接着獲取最小外接矩形 edged = cv2.Canny(resized, 50, 200) #匹配 #TM_SQDIFF 匹配方法,歸一化的方法更好用 result = cv2.matchTemplate(edged, template, cv2.TM_CCOEFF) (_, maxVal, _, maxLoc) = cv2.minMaxLoc(result) # 結果可視化 # 繪制矩形框並顯示結果 clone = np.dstack([edged, edged, edged]) cv2.rectangle(clone, (maxLoc[0], maxLoc[1]), (maxLoc[0] + tW, maxLoc[1] + tH), (0, 0, 255), 2) #cv2.imshow("Visualize", clone) #cv2.waitKey(0) # 如果發現一個新的關聯值則進行更新 if found is None or maxVal > found[0]: found = (maxVal, maxLoc, r) # 計算測試圖片中模板所在的具體位置,即左上角和右下角的坐標值,並乘上對應的裁剪因子 (_, maxLoc, r) = found (startX, startY) = (int(maxLoc[0] * r), int(maxLoc[1] * r)) (endX, endY) = (int((maxLoc[0] + tW) * r), int((maxLoc[1] + tH) * r)) # 繪制並顯示結果 cv2.rectangle(image, (startX, startY), (endX, endY), (0, 0, 255), 2) cv2.imshow("Image", image) cv2.waitKey(0) 

運行結果:

 

3.后記:

如果大家學會這種技術之后,再稍微改進一下,弄錯一個小腳本,這樣下次玩開心消消樂的那可以直接無敵了,再也不用擔心找不到匹配的小方塊了,哈哈哈哈。

在集體照的茫茫人海中,你還怕我找不到你???通過模板匹配,直接定位你的位置!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM