在本章中,您將學習
模板匹配是一種用於在較大圖像中搜索和查找模板圖像位置的方法。為此,OpenCV帶有一個函數cv.matchTemplate()。它只是將模板圖像滑動到輸入圖像上(就像在2D卷積中一樣),然後在模板圖像下比較模板和輸入圖像的拼圖。OpenCV中實現了幾種比較方法。(您可以檢查文檔以了解更多詳細信息)。它返回一個灰度圖像,其中每個像素表示該像素的鄰域與模板匹配的程度。
如果輸入圖像的大小為(WxH),而模板圖像的大小為(wxh),則輸出圖像的大小將為(W-w + 1,H-h + 1)。得到結果後,可以使用cv.minMaxLoc()函數查找最大/最小值在哪。將其作為矩形的左上角,並以(w,h)作為矩形的寬度和高度。該矩形是您模板的區域。
注意
如果使用cv.TM_SQDIFF作為比較方法,則最小值提供最佳匹配。
作為示例,我們將在梅西的照片中搜索他的臉。所以我創建了一個模板,如下所示:
我們將嘗試所有比較方法,以便我們可以看到它們的結果如何:
import cv2 as cvimport numpy as npfrom matplotlib import pyplot as pltimg = cv.imread('messi5.jpg',0)img2 = img.copy()template = cv.imread('template.jpg',0)w, h = template.shape[::-1]# 列表中所有的6種比較方法methods = ['cv.TM_CCOEFF', 'cv.TM_CCOEFF_NORMED', 'cv.TM_CCORR', 'cv.TM_CCORR_NORMED', 'cv.TM_SQDIFF', 'cv.TM_SQDIFF_NORMED']for meth in methods: img = img2.copy() method = eval(meth) # 應用模板匹配 res = cv.matchTemplate(img,template,method) min_val, max_val, min_loc, max_loc = cv.minMaxLoc(res) # 如果方法是TM_SQDIFF或TM_SQDIFF_NORMED,則取最小值 if method in [cv.TM_SQDIFF, cv.TM_SQDIFF_NORMED]: top_left = min_loc else: top_left = max_loc bottom_right = (top_left[0] + w, top_left[1] + h) cv.rectangle(img,top_left, bottom_right, 255, 2) plt.subplot(121),plt.imshow(res,cmap = 'gray') plt.title('Matching Result'), plt.xticks([]), plt.yticks([]) plt.subplot(122),plt.imshow(img,cmap = 'gray') plt.title('Detected Point'), plt.xticks([]), plt.yticks([]) plt.suptitle(meth) plt.show()
查看以下結果:
您會看到,使用cv.TM_CCORR的結果並不理想。
在上一節中,我們在圖像中搜索了梅西的臉,該臉在圖像中僅出現一次。假設您正在搜索具有多次出現的對象,則cv.minMaxLoc()不會為您提供所有位置。在這種情況下,我們將使用閾值化。因此,在此示例中,我們將使用著名遊戲Mario的螢幕截圖,並在其中找到硬幣。
import cv2 as cvimport numpy as npfrom matplotlib import pyplot as pltimg_rgb = cv.imread('mario.png')img_gray = cv.cvtColor(img_rgb, cv.COLOR_BGR2GRAY)template = cv.imread('mario_coin.png',0)w, h = template.shape[::-1]res = cv.matchTemplate(img_gray,template,cv.TM_CCOEFF_NORMED)threshold = 0.8loc = np.where( res >= threshold)for pt in zip(*loc[::-1]): cv.rectangle(img_rgb, pt, (pt[0] + w, pt[1] + h), (0,0,255), 2)cv.imwrite('res.png',img_rgb)
結果: