柚子快報激活碼778899分享:OpenCV第十章——模板匹配
柚子快報激活碼778899分享:OpenCV第十章——模板匹配
1.模板匹配方法
模板是指被查找的目標(biāo)圖像,查找模板出現(xiàn)在原始圖像中哪個位置的過程就叫模板匹配。
OpenCV提供了matchTemplate()方法來實現(xiàn)目標(biāo)匹配,其語法結(jié)構(gòu)如下:
result = matchTemplate(iamge, temp1,method, mask)
參數(shù)說明:
iamge:原始圖像,必須是單通道,8位或32位浮點圖像。
temp1:模板圖像,其尺寸不得大于原始圖像
method:匹配的方法,詳情見下表
mask:可選參數(shù)。掩模,只有cv2.TM_SQDIFF和cv2.TM_CCORR_NORMED支持此參數(shù)
返回值說明:
函數(shù)返回的結(jié)果result是一個矩陣,其大小取決于源圖像和模板的相對大小。具體來說,如果源圖像的大小是(W, H),模板的大小是(w, h),則結(jié)果矩陣的大小將是(W-w+1, H-h+1)。結(jié)果矩陣中的每個元素都表示模板在原圖中對應(yīng)位置的匹配程度,具體取決于所選的比較方法。
1.平方差匹配(cv2.TM_SQDIFF)
? ? ? 此方法通過計算模板與圖像區(qū)域之間的平方差來進(jìn)行匹配。平方差越小,匹配程度越高。因此,最佳匹配是在結(jié)果矩陣中的最小值處找到的。(0)
2.歸一化平方差匹配(cv2.TM_SQDIFF_NORMED)
? ? ? 與平方差匹配類似,但結(jié)果會被歸一化到0(完全不匹配)到1(完美匹配)的范圍內(nèi)。這使得比較不同大小的圖像或模板時更為方便。最佳匹配同樣是在結(jié)果矩陣中的最小值處找到的。(1)
3.相關(guān)匹配(cv2.TM_CCORR)
? ? ? 此方法通過計算模板與圖像區(qū)域之間的互相關(guān)來進(jìn)行匹配?;ハ嚓P(guān)值越大,匹配程度越高。因此,最佳匹配是在結(jié)果矩陣中的最大值處找到的。(2)
4.歸一化相關(guān)匹配(cv2.TM_CCORR_NORMED)
? ? ? ?與相關(guān)匹配類似,但結(jié)果會被歸一化。歸一化后的值在-1(完全不相關(guān))到1(完全相關(guān))之間。這使得比較更加靈活,特別是當(dāng)模板和圖像之間的亮度差異很大時。最佳匹配是在結(jié)果矩陣中的最大值處找到的。(3)
5.系數(shù)匹配(cv2.TM_CCOEFF)
? ? ? ?此方法通過計算模板與圖像區(qū)域之間的相關(guān)系數(shù)來進(jìn)行匹配。相關(guān)系數(shù)是歸一化的協(xié)方差,其值在-1(負(fù)相關(guān))到1(正相關(guān))之間。值越接近1,匹配程度越高。因此,最佳匹配是在結(jié)果矩陣中的最大值處找到的。(4)
6.歸一化系數(shù)匹配(cv2.TM_CCOEFF_NORMED)
? ? ? 與系數(shù)匹配類似,但結(jié)果會被進(jìn)一步歸一化到0(完全不相關(guān))到1(完全相關(guān))的范圍內(nèi)。這種歸一化使得比較結(jié)果更加直觀和一致。最佳匹配同樣是在結(jié)果矩陣中的最大值處找到的。(5)
在模板匹配的過程中,模板會在原始圖像中移動,并與重疊區(qū)域內(nèi)的像素諸葛對比,最后將對比結(jié)果保存在模板左上角像素點索引位置對應(yīng)的數(shù)組位置中。?
2.單模板匹配
單模板匹配是指匹配過程中只用到一個模板場景,在原始圖像中可能只有一個和模板相似的圖像,也可能有多個,如果只獲取匹配程度最高的那一個,這種操作就叫單目標(biāo)匹配,如果同時獲取匹配程度較高的結(jié)果,這種操作就叫多目標(biāo)匹配。
2.1單目標(biāo)匹配
單目標(biāo)匹配只獲取一個結(jié)果,即匹配程度最高的那一個
matchTemplate()方法計算的結(jié)果是一個二維數(shù)組,OpenCV提供了minMaxLoc()方法用于解析這個二維數(shù)組中的最大值、最小值以及這兩個值對應(yīng)的坐標(biāo),其語法結(jié)構(gòu)如下:
minValue,MaxValue, minLoc,maxLoc = cv2.minMaxLoc(src, mask)
參數(shù)說明:
src:matchTemplate()方法計算的出的數(shù)組
mask:可選參數(shù),掩模
返回值說明:
minValue:數(shù)組的最小值
maxValue:數(shù)組的最大值
minLoc:最小值的坐標(biāo)
maxLoc:最大值的坐標(biāo)
2.1.1 標(biāo)識出匹配成功的區(qū)域
操作用圖像:原始圖像
模板圖片:
操作代碼示例
import cv2
img = cv2.imread(r"C:\Users\cgs\Desktop\pictures\10(1).jpg") # 讀取原始圖像
templ = cv2.imread(r"C:\Users\cgs\Desktop\pictures\10(2).png") # 讀取模板圖像
width, height, c = templ.shape # 獲取模板圖像的寬度、高度和通道數(shù)
results = cv2.matchTemplate(img, templ, cv2.TM_SQDIFF_NORMED) # 按照標(biāo)準(zhǔn)平方差方式匹配
# 獲取匹配結(jié)果中的最小值、最大值、最小值坐標(biāo)和最大值坐標(biāo)
minValue, maxValue, minLoc, maxLoc = cv2.minMaxLoc(results)
resultPoint1 = minLoc # 將最小值坐標(biāo)當(dāng)做最佳匹配區(qū)域的左上角點坐標(biāo)
# 計算出最佳匹配區(qū)域的右下角點坐標(biāo)
resultPoint2 = (resultPoint1[0] + width, resultPoint1[1] + height)
# 在最佳匹配區(qū)域位置繪制藍(lán)色方框,線寬為2像素
cv2.rectangle(img, resultPoint1, resultPoint2, 255, 0, 0)
cv2.imshow("img", img) # 顯示匹配的結(jié)果
cv2.waitKey()
cv2.destroyAllWindows()
操作效果圖像
?
2.1.2 選擇最佳的匹配結(jié)果
操作用圖像
模板圖像:
背景圖像1:
、
背景圖像2:
操作代碼示例:
import cv2
image = [] # 存儲原始圖像的列表
# 向image列表添加原始圖像221
image.append(cv2.imread(r"C:\Users\cgs\Desktop\pictures\10(3).png"))
# 向image列表添加原始圖像222
image.append(cv2.imread(r"C:\Users\cgs\Desktop\pictures\10(4).png"))
templ = cv2.imread(r"C:\Users\cgs\Desktop\pictures\10(5).png") # 讀取模板圖像
index = -1 # 初始化車位編號列表的索引為-1
min = 1
for i in range(0, len(image)): # 循環(huán)匹配image列表中的原始圖像
# 按照標(biāo)準(zhǔn)平方差方式匹配
results = cv2.matchTemplate(image[i], templ, cv2.TM_SQDIFF_NORMED)
# 獲得最佳匹配結(jié)果的索引
if min > any(results[0]):
index = i
cv2.imshow("result", image[index]) # 顯示最佳匹配結(jié)果
cv2.waitKey()
cv2.destroyAllWindows()
操作效果圖像:
2.1.3 查找重復(fù)圖像
操作代碼示例:
import cv2
import os
import sys
PIC_PATH = "C:\\Users\\cgs\\Desktop\\pictures" # 照片文件夾地址
width, height = 100, 100 # 縮放比例
pic_file = os.listdir(PIC_PATH) # 所有照片文件列表
same_pic_index = [] # 相同圖像的索引列表
imgs = [] # 縮放后的圖像對象列表
has_same = set() # 相同圖像的集合
count = len(pic_file) # 照片數(shù)量
if count == 0: # 如果照片數(shù)量為零
print("沒有圖像")
sys.exit(0) # 停止程序
for file_name in pic_file: # 遍歷照片文件
pic_name = os.path.join(PIC_PATH, file_name) # 拼接完整文件名
img = cv2.imread(pic_name) # 創(chuàng)建文件的圖像
if img is None:
print(f"Error: {pic_name} not found or unable to load.")
continue
img = cv2.resize(img, (width, height)) # 縮放成統(tǒng)一大小
imgs.append(img) # 按文件順序保存圖像對象
for i in range(count): # 遍歷所有圖像文件
if i in has_same: # 如果此圖像已經(jīng)找到相同的圖像
continue # 跳過
templ = imgs[i] # 取出模板圖像
same = [i] # 與templ內(nèi)容相同的圖像索引列表
for j in range(i + 1, count): # 從templ的下一個位置開始遍歷
if j in has_same: # 如果此圖像已經(jīng)找到相同的圖像
continue # 跳過
pic = imgs[j] # 取出對照圖像
results = cv2.matchTemplate(pic, templ, cv2.TM_CCOEFF_NORMED) # 比較兩圖像相似度
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(results)
if max_val > 0.9: # 如果相似度大于90%,認(rèn)為是同一張照片
same.append(j) # 記錄對照圖像的索引
has_same.add(i) # 模板圖像已找到相同圖像
has_same.add(j) # 對照圖像已找到相同圖像
if len(same) > 1: # 如果模板圖像找到了至少一張與自己相同的圖像
same_pic_index.append(same) # 記錄相同圖像的索引
for same_list in same_pic_index: # 遍歷所有相同圖像的索引
text = "相同的照片:"
for same in same_list:
text += str(pic_file[same]) + ", " # 拼接文件名
text = text.rstrip(", ") # 去掉最后的逗號和空格
print(text)
代碼的工作流如下:
1.讀取圖像:從指定文件夾讀取所有圖像文件,并將它們存儲在列表中。 2.圖像縮放:將每張圖像縮放到統(tǒng)一的尺寸,以便進(jìn)行比較。 3.模板匹配:逐一將每張圖像作為模板,與后續(xù)圖像進(jìn)行相似度比較。 4.記錄相似圖像:如果相似度超過90%,則記錄匹配的圖像索引。 5.輸出結(jié)果:最后,輸出所有找到的相同圖像的文件名列表。?
操作效果:
2.2多目標(biāo)匹配
多目標(biāo)匹配需要將原始圖像中所有與模板相似的圖像都找出來。
2.2.1 標(biāo)識出所有匹配成功的區(qū)域
?操作用圖像:
背景圖像:
?
模板圖像:
操作代碼示例:
import cv2
img = cv2.imread(r"C:\Users\cgs\Desktop\pictures\1(52).jpg") # 讀取原始圖像
templ = cv2.imread(r"C:\Users\cgs\Desktop\pictures\1 (2).png") # 讀取模板圖像
width, height, c = templ.shape # 獲取模板圖像的寬度、高度和通道數(shù)
results = cv2.matchTemplate(img, templ, cv2.TM_CCOEFF_NORMED) # 按照標(biāo)準(zhǔn)相關(guān)系數(shù)匹配
for y in range(len(results)): # 遍歷結(jié)果數(shù)組的行
for x in range(len(results[y])): # 遍歷結(jié)果數(shù)組的列
if results[y][x] > 0.99: # 如果相關(guān)系數(shù)大于0.99則認(rèn)為匹配成功
# 在最佳匹配結(jié)果位置繪制紅色方框
cv2.rectangle(img, (x, y), (x + width, y + height), (0, 0, 255), 2)
cv2.imshow("img", img) # 顯示匹配的結(jié)果
cv2.waitKey()
cv2.destroyAllWindows()
操作效果圖像:
?
2.2.2多目標(biāo)匹配實例(統(tǒng)計一條快軌線路的站臺總數(shù))
操作用圖像:
背景圖像:
模板圖像:
操作代碼示例:
import cv2
image = cv2.imread(r"C:\Users\cgs\Desktop\pictures\image.png") # 讀取原始圖像
templ = cv2.imread(r"C:\Users\cgs\Desktop\pictures\templ.png") # 讀取模板圖像
height, width, c = templ.shape # 獲取模板圖像的高度、寬度和通道數(shù)
results = cv2.matchTemplate(image, templ, cv2.TM_CCOEFF_NORMED) # 按照標(biāo)準(zhǔn)相關(guān)系數(shù)匹配
station_Num = 0 # 初始化快軌的站臺個數(shù)為0
for y in range(len(results)): # 遍歷結(jié)果數(shù)組的行
for x in range(len(results[y])): # 遍歷結(jié)果數(shù)組的列
if results[y][x] > 0.99: # 如果相關(guān)系數(shù)大于0.99則認(rèn)為匹配成功
# 在最佳匹配結(jié)果位置繪制矩形邊框
cv2.rectangle(image, (x, y), (x + width, y + height), (0, 0, 255), 2)
station_Num += 1 # 快軌的站臺個數(shù)加1
cv2.putText(image, "the numbers of stations: " + str(station_Num), (0, 30),
cv2.FONT_HERSHEY_COMPLEX_SMALL, 1, (255, 0, 0), 2) # 在原始圖像繪制快軌站臺的總數(shù)
cv2.imshow("result", image) # 顯示匹配的結(jié)果
cv2.waitKey()
cv2.destroyAllWindows()
操作效果圖像:
3.多模板匹配
對每一個模板都要做一次“單模板多目標(biāo)匹配”。
3.1 同時匹配多個模板
操作用圖像:
背景圖像:
模板圖像:
操作代碼示例:
import cv2
def myMatchTemplate(img, templ): # 自定義方法:獲取模板匹配成功后所有紅框位置的坐標(biāo)
width, height, c = templ.shape # 獲取模板圖像的寬度、高度和通道數(shù)
results = cv2.matchTemplate(img, templ, cv2.TM_CCOEFF_NORMED) # 按照標(biāo)準(zhǔn)相關(guān)系數(shù)匹配
loc = list() # 紅框的坐標(biāo)列表
for i in range(len(results)): # 遍歷結(jié)果數(shù)組的行
for j in range(len(results[i])): # 遍歷結(jié)果數(shù)組的列
if results[i][j] > 0.99: # 如果相關(guān)系數(shù)大于0.99則認(rèn)為匹配成功
# 在列表中添加匹配成功的紅框?qū)蔷€兩點坐標(biāo)
loc.append((j, i, j + width, i + height))
return loc
img = cv2.imread(r"C:\Users\cgs\Desktop\pictures\background2.jpg") # 讀取原始圖像
templs = list() # 模板列表
templs.append(cv2.imread(r"C:\Users\cgs\Desktop\pictures\template.png")) # 添加模板1
templs.append(cv2.imread(r"C:\Users\cgs\Desktop\pictures\template2.png")) # 添加模板2
templs.append(cv2.imread(r"C:\Users\cgs\Desktop\pictures\template3.png")) # 添加模板3
loc = list() # 所有模板匹配成功位置的紅框坐標(biāo)列表
for t in templs: # 遍歷所有模板
loc += myMatchTemplate(img, t) # 記錄該模板匹配得出的
for i in loc: # 遍歷所有紅框的坐標(biāo)
cv2.rectangle(img, (i[0], i[1]), (i[2], i[3]), (0, 0, 255), 2) # 在圖片中繪制紅框
cv2.imshow("img", img) # 顯示匹配的結(jié)果
cv2.waitKey()
cv2.destroyAllWindows()
操作效果圖像:
3.2 多模板匹配實例
操作用圖像
模板圖像:
背景圖像:
操作代碼示例:
import cv2
image = cv2.imread(r"C:\Users\cgs\Desktop\pictures\image.png") # 讀取原始圖像
templs = [] # 模板列表
templs.append(cv2.imread(r"C:\Users\cgs\Desktop\pictures\car1.png")) # 添加模板圖像1
templs.append(cv2.imread(r"C:\Users\cgs\Desktop\pictures\car2.png")) # 添加模板圖像2
templs.append(cv2.imread(r"C:\Users\cgs\Desktop\pictures\car3.png")) # 添加模板圖像3
templs.append(cv2.imread(r"C:\Users\cgs\Desktop\pictures\car4.png")) # 添加模板圖像3
for car in templs: # 遍歷所有模板圖像
# 按照標(biāo)準(zhǔn)相關(guān)系數(shù)匹配
results = cv2.matchTemplate(image, car, cv2.TM_CCOEFF_NORMED)
for i in range(len(results)): # 遍歷結(jié)果數(shù)組的行
for j in range(len(results[i])): # 遍歷結(jié)果數(shù)組的列
# print(results[i][j])
if results[i][j] > 0.99: # 如果相關(guān)系數(shù)大于0.99則認(rèn)為匹配成功
if 0 < j <= 140:
print("車位編號:", 1)
elif j <= 330:
print("車位編號:", 2)
elif j <= 500:
print("車位編號:", 3)
else:
print("車位編號:", 4)
break
操作效果圖像:
那么關(guān)于模板匹配的內(nèi)容就到這里了歡迎大家繼續(xù)關(guān)注?。?!
柚子快報激活碼778899分享:OpenCV第十章——模板匹配
好文推薦
本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點和立場。
轉(zhuǎn)載請注明,如有侵權(quán),聯(lián)系刪除。