使用OpenCV+Python實現模板匹配

目標

在本章中,您將學習

  • 使用模板匹配在圖像中查找對象
  • 你將看到以下功能:cv.matchTemplate(),cv.minMaxLoc()

理論

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

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

注意
如果使用cv.TM_SQDIFF作為比較方法,則最小值提供最佳匹配。

OpenCV中的模板匹配

作為示例,我們將在梅西的照片中搜索他的臉。所以我創建了一個模板,如下所示:

使用OpenCV+Python實現模板匹配

我們將嘗試所有比較方法,以便我們可以看到它們的結果如何:

<code>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()/<code>

查看以下結果:

  • cv.TM_CCOEFF
使用OpenCV+Python實現模板匹配

  • cv.TMCCOEFFNORMED
  • cv.TM_CCORR
  • cv.TMCCORRNORMED
  • cv.TM_SQDIFF
  • cv.TMSQDIFFNORMED

您會看到,使用cv.TM_CCORR的結果並不理想。

多對象的模板匹配

在上一節中,我們在圖像中搜索了梅西的臉,該臉在圖像中僅出現一次。假設您正在搜索具有多次出現的對象,則cv.minMaxLoc()不會為您提供所有位置。在這種情況下,我們將使用閾值化。因此,在此示例中,我們將使用著名遊戲Mario的屏幕截圖,並在其中找到硬幣。

<code>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)/<code>

結果:

使用OpenCV+Python實現模板匹配


分享到:


相關文章: