模板匹配是指在圖像A中尋找與圖像B最相似的部分,一般A稱為輸入圖像,B稱為模板圖像
模板匹配函數
result = cv2.matchTemplate(image , temp1 , method , [,mask])
result 函數每次計算模板和輸入圖像的重疊區域相似度之后將結果存入映射圖像result中,
result圖像中每個點都代表一次相似度的比較,類型是單通道32位浮點型
若輸入圖像的尺寸位W×H,模板圖像為w×h,則返回值為(W-w+1)×(H-h+1)
模板在原始圖像上遍歷,左上角的坐標從(0,0)開始到(W-w+1)×(H-h+1)
image為原始圖像,即輸入圖像,必須是8位或者32位浮點型圖像
temp1 位模板圖像,尺寸必須小於或等於輸入圖像,並且與其類型相同
method位匹配方法,
參數值 | 對應數值 | 說明 | 公式 |
cv2.TM_SQDIFE | 0 | 以方差位依據進行匹配。若完全匹配,則結果位零;若不匹配,則會得到一個很大的值 | ![]() |
cv2.TM_SQDIFE_NORMED | 1 | 標准(歸一化)平方差匹配 | ![]()
|
cv2.TM_ CCORR | 2 | 相關匹配,這類方法將模板圖像與輸入圖像相乘,如果乘積較大 ,表示匹配程度較高;如果乘積位0,表示匹配效果最差 | ![]()
|
cv2.TM_CCORR_NORMED | 3 | 標准(歸一化)相關匹配 | ![]()
|
cv2.TM_CCOEFF | 4 | 相關系數匹配,這類方法將模板圖像與其均值的相對值,和輸入圖像與其均值的相關值進行匹配,1表示完美匹配,-1表示糟糕的匹配,0表示沒有任何相關性 | ![]()
|
cv2.TM_ CCOEFF_NORMED | 5 | 標准(歸一化)相關系數匹配 | ![]()
|
(I表示輸入圖像,T表示模板圖像,R表示輸出的結果圖像,x,y表示位值信息
mask為模板圖像掩模,必須與模板圖像具有相同大小和類型,通常情況下使用默認值
從上表中可以看出method為,cv2.TM_SQDIFE和cv2.TM_SQDIFE時,result值為0表示匹配度最好,值越大,匹配度月差
method值為cv2.TM_CCORR , cv2.TM_CCORR_NORMED , cv2_TMCCOEFF 和 cv2.TM_CCOEFF_NORMED時,result的值
越小表示匹配度越差,值越大表示越好
查找方式的不同代表查找最佳匹配時也要先確定method值
然后使用函數查找最值與其為值
minVal , maxVal , minLoc , maxLoc = cv2.minMaxLoc( src , [,mask])
minVal 為返回的最小值,若沒有則可以是NULL
maxVal為為返回最大值,若沒有則可以是NULL
minLoc 為返回的最小值位置,若沒有則可以是NULL
maxLoc 為返回的最大值位置,若沒有則可以是NULL
返回值中的位置,時模板匹配位置的左上角坐標,結合模板圖像的寬度w和高度h可以得到右下角的坐標(x+w,y+h)
可以通過函數將該位置用白色標記出來
Img = cv2.rectangle( img , pt1 , pt2 , colot [,thickness])
img 表示要標記的目標圖像
pt1是矩形的頂點,
pt2是pt1的對角頂點
color是矩形的顏色
thickness是矩形邊線的寬度
1 import cv2 2 import numpy as np 3 from matplotlib import pyplot as plt 4 img = cv2.imread("/home/miao/dog.jpg" , 0) 5 template = cv2.imread("/home/miao/dog_ex.jpg" , 0) 6 w , h = template.shape[::-1] 7 rv = cv2.matchTemplate(img , template , cv2.TM_SQDIFF) 8 minVal , maxVal , minLoc , maxLoc = cv2.minMaxLoc(rv) 9 topLeft = minLoc 10 bottomRight = ( topLeft[0] + w , topLeft[1] + h) 11 cv2.rectangle(img , topLeft , bottomRight, 255, 2) 12 # 13 plt.subplot(221) 14 plt.imshow(img , cmap = 'gray') 15 plt.title("original") 16 plt.xticks([]) 17 plt.yticks([]) 18 # 19 plt.subplot(222) 20 plt.imshow(template , cmap = 'gray') 21 plt.title("template") 22 plt.xticks([]) 23 plt.yticks([]) 24 # 25 plt.subplot(223) 26 plt.imshow(rv , cmap = 'gray') 27 plt.title("rv") 28 plt.xticks([]) 29 plt.yticks([]) 30 # 31 plt.show()
這里的template應是60×40不知怎樣將其調整為原始圖像的大小
多模板匹配
獲取位置的集合
1 import numpy as np 2 a = np.array([[2,4,6,34,6] , [4,23,56,1,23] , [41,52,12,34,2]] ) 3 b = np.where(a >5) 4 print(b)
得到
(array([0, 0, 0, 1, 1, 1, 2, 2, 2, 2]), array([2, 3, 4, 1, 2, 4, 0, 1, 2, 3]))
若參數為一維數組則返回值為一維索引
若參數為二維數組則返回的是位置,因此會有兩組索引數組表示返回值的位置如上
通過函數np.where()得到兩組索引數組后
通過函數zip() 可以將t內對應的元素打包成一個元組,這些元組組成列表
1 x = [1,2,3] 2 y = [4,5,6] 3 z = [7,8,9] 4 t = (x,y,z) 5 print(t) 6 for i in zip(*t): 7 print(i)
([1, 2, 3], [4, 5, 6], [7, 8, 9]) (1, 4, 7) (2, 5, 8) (3, 6, 9)
使用函數where()后得到的參數形式為(行號,列號)的位置索引,
而函數cv2.rectangle()指定頂點的參數所使用的形式為(列號,行號),可通過切片來實現行列互換
1 import numpy as np 2 loc = ([3,4,5,2] , [34,45,67,56]) 3 print(loc) 4 print(loc[::-1])
([3, 4, 5, 2], [34, 45, 67, 56])
([34, 45, 67, 56], [3, 4, 5, 2])
多模板匹配
1 import cv2 2 import numpy as np 3 from matplotlib import pyplot as plt 4 img = cv2.imread("/home/miao/Figure.png" , 0) 5 template = cv2.imread("/home/miao/dog_ex.png" , 0) 6 w , h = template.shape[::-1] 7 res = cv2.matchTemplate(img , template , cv2.TM_CCOEFF_NORMED) 8 threshold = 0.45 9 loc = np.where( res >= threshold) 10 for pt in zip(*loc[::-1]): 11 cv2.rectangle(img , pt , (pt[0] + w , pt[1] + h) , 255 , 1) 12 plt.imshow(img , cmap = 'gray') 13 plt.axis('off') 14 plt.show()
由於該模板圖是手動截出來的,在處理過程中導致出現圖像中右側出現的矩形框,
出現的寬度遠遠大於一是因為存在多個指定閾值0.45的情況,所以都做了標記
------------恢復內容結束------------