日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

第15章:模板匹配

發布時間:2023/12/9 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 第15章:模板匹配 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

第15章:模板匹配

    • 一、模板匹配基礎:
      • 1. cv2.matchTemplate()函數:
      • 2. 匹配原理:
      • 3. 查找最值:
    • 二、多模版匹配:
      • 1. 獲取匹配位置集合:
      • 2. 循環:
      • 3.調整坐標
      • 4.標記匹配圖像的位置

? 模板匹配是指在當前圖像A內匹配與圖像B最相似的部分,一般將圖像A稱為輸入圖像,將圖像B稱為模板圖像。 模板匹配的方法是將模板圖像B在圖像A上滑動,逐個遍歷所有像素以完成匹配。

? 例如,下圖中,大圖像“lena”是輸入圖像,“眼睛”圖像是模板圖像。查找的方式是,將模板圖像在輸入圖像內從左上角開始滑動,逐個像素遍歷整幅輸入圖像,以查找與其最匹配的部分。

一、模板匹配基礎:

1. cv2.matchTemplate()函數:

在OpenCV內,通過函數cv2.matchTemplate()實現模板匹配。語法格式為:

  • result=cv2.matchTemplate(image,templ,method[,mask])

    • image:為原始圖像,必須是8位或者32位的浮點型圖像。

    • templ:為模板圖像。它的尺寸必須小于或等于原始圖像,并且與原始圖像具有同樣的類型。

    • method:為匹配方法。該參數通過TemplateMatchModes實現,有6種可能的值,如表所示。

      其具體對應的計算公式:

    • mask: 為模板圖像掩模。它必須和模板圖像 templ 具有相同的類型和大小。通常情況下該值使用默認值即可。當前,該參數僅支持TM_SQDIFF和TM_CCORR_NORMED兩個值。

函數cv2.matchTemplate()的返回值result 是一個結果集。類型是單通道32位浮點型。是由每個位置的比較結果所構成的。

2. 匹配原理:

? 如果輸入圖像(原始圖像)尺寸是W * H,模板的尺寸是w * h,則返回值的大小為(W-w+1)*(H-h+1)。

在進行模板匹配時,模板在原始圖像內遍歷。在水平方向上:

  • 遍歷的起始坐標是原始圖像左數第1個像素值(序號從1開始)。
  • 最后一次比較是當模板圖像位于原始圖像的最右側時,此時其左上角像素點所在的位置是W-w+1。

因此,返回值result在水平方向上的大小是W-w+1(水平方向上的比較次數)。

在垂直方向上:

  • 遍歷的起始坐標從原始圖像頂端的第1個像素開始。
  • 最后一次比較是當模板圖像位于原始圖像的最下端時,此時其左上角像素點所在位置是H-h+1。

所以,返回值result在垂直方向上的大小是H-h+1(垂直方向上的比較次數)。

如果原始圖像尺寸是 W * H,模板的尺寸是w * h,則返回值的大小為(W-w+1)* (H-h+1)。也就是說,模板圖像要在輸入圖像內比較(W-w+1)*(H-h+1)次。

例如,在上圖中,左上方的2×2小方塊是模板圖像,右下方的10×10圖像是輸入圖像(原始圖像)。在進行模板匹配時:

  • 首先將模板圖像置于輸入圖像的左上角。
  • 模板圖像在向右移動時,最遠只能位于輸入圖像的最右側邊界處,此時模板圖像左上角的像素對應著輸入圖像的第9列(輸入圖像寬度-模板圖像寬度+1=10-2+1=9)。
  • 模板圖像在向下移動時,最遠只能位于輸入圖像最下端的邊界處。此時模板圖像左上角的像素對應著輸入圖像的第9行(輸入圖像高度-模板圖像高度+1=10-2+1=9)。

根據上述分析可知,比較結果result的大小滿足(W-w+1)*(H-h+1),在上例中就是(10-2+1)×(10-2+1),即9×9。也就是說,模板圖像要在輸入圖像內總計比較9×9=81次,這些比較結果將構成一個9×9大小的二維數組。

需要注意的是,函數cv2.matchTemplate()通過參數method來決定使用不同的查找方法。對于不同的查找方法,返回值result具有不同的含義。例如:

  • method的值為cv2.TM_SQDIFF和cv2.TM_SQDIFF_NORMED時,result值為0表示匹配度最好,值越大,表示匹配度越差。
  • method 的值為 cv2.TM_CCORR、cv2.TM_CCORR_NORMED、cv2.TM_CCOEFF 和cv2.TM_CCOEFF_NORMED時,result的值越小表示匹配度越差,值越大表示匹配度越好。

查找方法不同,結果的判定方式也不同。在查找最佳匹配時,首先要確定使用的是何種method,然后再確定到底是查找最大值,還是查找最小值。

3. 查找最值:

查找最值(極值)與最值所在的位置,可以使用 cv2.minMaxLoc()函數實現。語法格式如下:

  • minVal,maxVal,minLoc,maxLoc=cv2.minMaxLoc(src[,mask])
    • src:為單通道數組。
    • minVal:為返回的最小值,如果沒有最小值,則可以是NULL(空值)。
    • maxVal:為返回的最大值,如果沒有最小值,則可以是NULL。
    • minLoc:為最大值的位置,如果沒有最大值,則可以是NULL。
    • maxLoc:為最大值的位置,如果沒有最大值,則可以是NULL。
    • mask:為用來選取掩模的子集,可選項

函數 cv2.minMaxLoc()能夠查找整個數組內的最值及它們的位置,并且可以根據當前的掩模集來選取特定子集的極值。有關該函數的更多說明及實例,請參考第12章。

綜上所述,函數cv2.matchTemplate()返回值中的最值位置就是模板匹配的位置。

例如,當method的值為cv2.TM_SQDIFF和cv2.TM_SQDIFF_NORMED時,0表示最佳匹配,值越大,則表示匹配效果越差。當使用這兩種方法時,要尋找最小值所在的位置作為最佳匹配。如下語句能夠找到cv2.matchTemplate()函數返回值中最小值的位置:

  • minVal,maxVal,minLoc,maxLoc=cv2.minMaxLoc(matchTemplate函數的返回值)

    topLeft=minLoc # 查找最小值所在的位置

以topLeft點為模板匹配位置的左上角坐標,結合模板圖像的寬度w和高度h可以確定匹配位置的右下角坐標,代碼如下所示:

  • bottomRight=(topLeft[0]+w,topLeft[1]+h)  #w和h是模板圖像的寬度和高度

當 method 的值為 cv2.TM_CCORR、cv2.TM_CCORR_NORMED、cv2.TM_CCOEFF 和cv2.TM_CCOEFF_NORMED時,cv2.matchTemplate()函數的返回值越小,表示匹配度越差,而返回值越大則表示匹配度越好。此時,要尋找最大值所在的位置作為最佳匹配。

通過上述方式,我們確定了模板匹配的矩形對角坐標位置,接下來可以借助函數cv2.rectangle()將該位置用白色標記出來。

函數cv2.rectangle的語法格式為:

  • Img=cv.rectangle(img,pt1,pt2,color[,thickness])
    • img:表示要標記的目標圖像。
    • pt1:是矩形的頂點。
    • pt2:是pt1的對角頂點。
    • color:是要繪制矩形的顏色或灰度級(灰度圖像)。
    • thickness:是矩形邊線的寬度。

因此,使用的標記語句為:cv2.rectangle(img,topLeft,bottomRight,255,2)

import cv2 import numpy as np import matplotlib.pyplot as pltimg = cv2.imread('../lena.bmp') template = cv2.imread('../template.bmp')th, tw = template.shape[:2] rv = cv2.matchTemplate(img, template, cv2.TM_SQDIFF) min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(rv)top_left = min_loc bottom_right = (top_left[0] + tw, top_left[1] + th) new_img = img.copy() cv2.rectangle(new_img, top_left, bottom_right, 255, 2)plt.subplot(131) plt.imshow(template, cmap='gray') plt.title('template') plt.axis('off')plt.subplot(132) plt.imshow(rv, cmap='gray') plt.title('matcing result') plt.axis('off')plt.subplot(133) plt.imshow(new_img, cmap='gray') plt.title('result') plt.axis('off')plt.show()

二、多模版匹配:

前面的例子中,我們在輸入圖像lena中搜索其眼部子圖,該子圖在整個輸入圖像內僅出現了一次。但是,有些情況下,要搜索的模板圖像很可能在輸入圖像內出現了多次,這時就需要找出多個匹配結果。而函數 cv2.minMaxLoc()僅僅能夠找出最值,無法給出所有匹配區域的位置信息。所以,要想匹配多個結果,使用函數 cv2.minMaxLoc()是無法實現的,需要利用閾值進行處理,來獲取所有匹配的集合。

1. 獲取匹配位置集合:

numpy模塊中的函數where()能夠獲取模板匹配位置的集合。對于不同的輸入,其返回的值是不同的。

  • 當輸入(參數)是一維數組時,返回值是一維索引,只有一組索引數組。
  • 當輸入是二維數組時,返回的是匹配值的位置索引,因此會有兩組索引數組表示返回值的位置。

例如:

# 當輸入數組是一維時 import numpy as npa=np.array([3,6,8,1,2,88]) b=np.where(a>5) print(b)# 輸出結果 (array([1,2,5],dtype=int64),) # 當輸入數組是二維時 import numpy as npam=np.array([[3,6,8,77,66],[1,2,88,3,98],[11,2,67,5,2]]) b=np.where(am>5) print(b)# 輸出結果 (array([0,0,0,0,1,1,2,2],dtype=int64), array([1,2,3,4,2,4,0,2],dtype=int64))

綜上所述,函數 np.where()可以找出在函數 cv2.matchTemplate()的返回值中,哪些位置上的值是大于閾值threshold的。

具體實現時,可以采用的語句為:

  • loc=np.where(res >=threshold)
    • res:是函數cv2.matchTemplate()進行模板匹配后的返回值。
    • threshold:是預設的閾值
    • loc:是滿足“res >=threshold”的像素點的索引集合。

2. 循環:

處理多個值,通常需要用到循環。因此,在獲取匹配值的索引集合后,可以采用如下語句遍歷所有匹配的位置,對這些位置做標記:

for i in 匹配位置集合:

? 標記匹配位置。

在循環處理匹配位置的時候,可以在循環中使用函數zip():

函數zip()用可迭代的對象作為參數,將對象中對應的元素打包成一個個元組,然后返回由這些元組組成的列表。
例如:

import numpy as npam = np.random.randint(0, 50, size=(3, 5)) print(am) b = np.where(am > 20) print(b) for i in zip(*b):print(i)# 輸出結果 [[37 39 43 48 49][16 48 37 23 25][44 40 0 44 38]] (array([0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2], dtype=int64), array([0, 1, 2, 3, 4, 1, 2, 3, 4, 0, 1, 3, 4], dtype=int64)) (0, 0) (0, 1) (0, 2) (0, 3) (0, 4) (1, 1) (1, 2) (1, 3) (1, 4) (2, 0) (2, 1) (2, 3) (2, 4)

因此,如果希望循環遍歷由np.where()返回的模板匹配索引集合,可以采用的語句為:

for i in zip(*模板匹配索引集合):

? 標記處理

3.調整坐標

函數 numpy.where()可以獲取滿足條件的模板匹配位置集合,然后可以使用函數cv2.rectangle()在上述匹配位置繪制矩形來標注匹配位置。

使用函數numpy.where()在函數cv2.matchTemplate()的輸出值中查找指定值,得到的形式為“(行號,列號)”的位置索引。但是,**函數cv2.rectangle()中用于指定頂點的參數所使用的是形式為“(列號,行號)”的位置索引。**所以,在使用函數cv2.rectangle()繪制矩形前,要先將函數numpy.where()得到的位置索引做“行列互換”??梢允褂萌缦抡Z句實現loc內行列位置的互換:

  • loc[::-1]

4.標記匹配圖像的位置

函數cv2.rectangle()可以標記匹配圖像的具體位置,分別指定要標記的原始圖像、對角頂點、顏色、矩形邊線寬度即可。

關于矩形的對角頂點:

  • 其中的一個對角頂點A可以通過for循環語句從確定的滿足條件的“匹配位置集合”內獲取。

  • 另外一個對角頂點,可以通過頂點A的位置與模板的寬(w)和高(h)進行運算得到。
    因此,標記各個匹配位置的語句為:

    • for i in 匹配位置集合:

      ? cv2.rectangle(輸入圖像,i, (i[0] + w, i[1] + h ), 255, 2)

import cv2 import numpy as np import matplotlib.pyplot as pltimg = cv2.imread('../four_lena.bmp') template = cv2.imread('../template.bmp')h, w = template.shape[:2] rst = cv2.matchTemplate(img, template, cv2.TM_CCORR_NORMED) print(rst) threshold = 0.99 loc = np.where(rst >= threshold) new_img = img.copy() for pt in zip(*loc):cv2.rectangle(new_img, pt, (pt[0] + w, pt[1] + h), 255, 1)plt.subplot(121) plt.imshow(template, cmap='gray') plt.title('template') plt.axis('off')plt.subplot(122) plt.imshow(new_img, cmap='gray') plt.title('rst') plt.axis('off')plt.show()

創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

總結

以上是生活随笔為你收集整理的第15章:模板匹配的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。