demo01.py
#模板匹配是识别方法,可在原始图像中寻找特定图像的位置。
import cv2
import numpy as np
import math
# ——————————————————————————模板匹配方法
# result = cv2.matchTemplate(image,templ,method,mask) #参数依次是:原始图像,模板图像(尺寸必须小于或等于原始图像),匹配的方法,掩模(可选参数)
# result:原始图像宽高W,H,模板图像宽高w,h,result即一个W-w+1列,H-h+1行的32位浮点型数组。每个浮点数都是原始图像中对应像素位置的匹配结果
# result为一个数组其大小为模板左上角像素点在图片上面的游走范围,保存对比的结果。详细:在模板匹配过程中,模板会在原始图像上移动。模板与重叠区域内的元素逐个对比,最后将对比的结果保存在模板左上角像素点索引位置对应创建的数组位置中。
# 匹配方法6种:
# ①:cv2.TM_SQDIFF :差值平方和匹配,匹配程度越高,计算结果越小
# ②:cv2.TM_SQDIFF_NORMED :标准差值平方和匹配
# ③:cv2.TM_CCORR :相关匹配,匹配程度越高,计算结果越大
# ④:cv2.TM_CCORR_NORMED :标准相关匹配
# ⑤:cv2.TM_CCOEFF :相关系数匹配,1表示完全匹配,0表示毫无关系,-1表示两张图片亮度相反
# ⑥:cv2.TM_CCOEFF_NORMED :标准相关系数匹配
# —————————————————————————————单模板匹配(只用到一个匹配场景即一个模板)。
# ————————————————单目标匹配(即只获取匹配程度最高的重叠区域位置,匹配程度最高的结果:若使用平方差匹配,为最小结果,若使用相关匹配或相关系数,为最大结果)
# minValue,maxValue,minloc,maxloc = cv2.minMaxLoc(src,mask) #参数依次是:数组中的最小值,数组中的最大值,数组中最小值的坐标(格式(x,y)),数组中最大值坐标(格式(x,y)),matchTemplate方法的出的数组,掩模(可选参数),
img = cv2.imread("background.jpg") # 读取原始图像
templ = cv2.imread("template.png") # 读取模板图像
results = cv2.matchTemplate(img, templ, cv2.TM_SQDIFF_NORMED) # 按照标准平方差方式匹配
minValue, maxValue, minLoc, maxLoc = cv2.minMaxLoc(results) # 获取匹配结果中的最小值、最大值、最小值坐标和最大值坐标
resultPoint1 = minLoc # 将最小值坐标当做最佳匹配区域的左上角点坐标
# test文件也是单目标匹配
# ————————————————多目标匹配
# 使用相关匹配或者相关系数匹配。若计算结果大于某个值(0.99)即认为图像相同,再将其标记(放入列表中,划线......)
# ——————————题①:
img = cv2.imread("background2.jpg") # 读取原始图像
templ = cv2.imread("template.png") # 读取模板图像
width, height, c = templ.shape # 获取模板图像的宽度、高度和通道数
results = cv2.matchTemplate(img, templ, cv2.TM_CCOEFF_NORMED) # 按照标准相关系数匹配
for y in range(len(results)): # 遍历结果数组的行
for x in range(len(results[y])): # 遍历结果数组的列
if results[y][x] > 0.99: # 如果相关系数大于0.99则认为匹配成功
cv2.rectangle(img, (x, y), (x + width, y + height), (0, 0, 255), 2) # 在最佳匹配结果位置绘制红色方框
cv2.imshow("img", img)
cv2.waitKey()
cv2.destroyAllWindows()
# ——————————题②:
image = cv2.imread("image.png") # 读取原始图像
templ = cv2.imread("templ.png") # 读取模板图像
height, width, c = templ.shape # 获取模板图像的高度、宽度和通道数
results = cv2.matchTemplate(image, templ, cv2.TM_CCOEFF_NORMED) # 按照标准相关系数匹配
point_X = [] # 用于存储最佳匹配结果左上角横坐标的列表
point_Y = [] # 用于存储最佳匹配结果左上角纵坐标的列表
for y in range(len(results)):
for x in range(len(results[y])):
if results[y][x] > 0.99:
cv2.rectangle(image, (x, y), (x + width, y + height), (255, 0, 0), 2) # 在最佳匹配结果位置绘制红色方框
point_X.extend([x]) # 把最佳匹配结果左上角的横坐标添加到列表中
point_Y.extend([y]) # 把最佳匹配结果左上角的纵坐标添加到列表中
start_X = 62 # 出发点的横、纵坐标
start_Y = 150
place_Square = np.array([point_X[0], point_Y[0]]) # 计算出发点到人民广场地铁站的距离
place_Start = np.array([start_X, start_Y])
minus_SS = place_Start - place_Square
start_Square = math.hypot(minus_SS[0], minus_SS[1])
place_Highroad = np.array([point_X[1], point_Y[1]]) # 计算出发点到解放大路地铁站的距离
minus_HS = place_Highroad - place_Start
start_Highroad = math.hypot(minus_HS[0], minus_HS[1])
if start_Square < start_Highroad: # 用绿色的线画出距离较短的路线
cv2.line(image, (start_X, start_Y), (point_X[0], point_Y[0]), (0, 255, 0), 2)
else:
cv2.line(image, (start_X, start_Y), (point_X[1], point_Y[1]), (0, 255, 0), 2)
cv2.imshow("result", image)
cv2.waitKey()
cv2.destroyAllWindows()
# —————————————————————————————多模板匹配(在一个图片中同时查找多个模板,实际上就是进行了”n次单模板匹配“)将单模板多目标匹配1封装成一个方法进行多次,实现多模板匹配
# ——————————题①
def myMatchTemplate(img, templ): # 自定义方法:获取模板匹配成功后所有红框位置的坐标
width, height, c = templ.shape # 获取模板图像的宽度、高度和通道数
results = cv2.matchTemplate(img, templ, cv2.TM_CCOEFF_NORMED) # 按照标准相关系数匹配
loc = list() # 红框的坐标列表
for i in range(len(results)): # 遍历结果数组的行
for j in range(len(results[i])): # 遍历结果数组的列
if results[i][j] > 0.99: # 如果相关系数大于0.99则认为匹配成功
loc.append((j, i, j + width, i + height)) # 在列表中添加匹配成功的红框对角线两点坐标
return loc
img = cv2.imread("background2.jpg") # 读取原始图像
templs = list() # 模板列表
templs.append(cv2.imread("template.png")) # 添加模板1
templs.append(cv2.imread("template2.png")) # 添加模板2
templs.append(cv2.imread("template3.png")) # 添加模板3
loc = list() # 所有模板匹配成功位置的红框坐标列表
for t in templs: # 遍历所有模板
loc += myMatchTemplate(img, t) # 记录该模板匹配得出的
for i in loc: # 遍历所有红框的坐标
cv2.rectangle(img, (i[0], i[1]), (i[2], i[3]), (0, 0, 255), 2) # 在图片中绘制红框
cv2.imshow("img", img)
cv2.waitKey()
cv2.destroyAllWindows()
# ——————————题②
image = cv2.imread("image1.png") # 读取原始图像
templs = [] # 模板列表
templs.append(cv2.imread("car1.png")) # 添加模板图像1
templs.append(cv2.imread("car2.png")) # 添加模板图像2
templs.append(cv2.imread("car3.png")) # 添加模板图像3
templs.append(cv2.imread("car4.png")) # 添加模板图像3
for car in templs: # 遍历所有模板图像
results = cv2.matchTemplate(image, car, cv2.TM_CCOEFF_NORMED) # 按照标准相关系数匹配
for i in range(len(results)):
for j in range(len(results[i])):
# print(results[i][j])
if results[i][j] > 0.99: # 如果相关系数大于0.99则认为匹配成功
if 0 < j <= 140:
print("车位编号:", 1)
elif j <= 330:
print("车位编号:", 2)
elif j <= 500:
print("车位编号:", 3)
else:
print("车位编号:", 4)
break
shiyan.py
import math
import cv2
import numpy as np
a = cv2.imread("sa.jpg")
b = cv2.imread("sb.png")
a = cv2.resize(a,(300,300))
b = cv2.resize(b,(70,70))
q1 = a
q2 = a+a
q3 = cv2.add(a,a)
w1 = cv2.blur(a,(5,5))
w2 = cv2.medianBlur(a,5)
w3 = cv2.GaussianBlur(a,(5,5),0,0)
e1 = cv2.bitwise_not(a)
e2 = a.copy()
e2[115:185,115:185,:] = b
e3 = cv2.bilateralFilter(a,15,120,100)
a1 = np.hstack((q1,q2,q3)) # 水平拼接两个图像
a2 = np.hstack((w1,w2,w3))
a3 = np.hstack((e1,e2,e3))
result = np.vstack((a1,a2,a3)) # 垂直拼接两个图像
cv2.imshow("20040420WQ",result)
cv2.imwrite("C:\\Users\\ASUS\\PycharmProjects\\pythonProject3\\Opencv\\10_template_matching\\20040420.jpg", result)
cv2.waitKey()
cv2.destroyAllWindows()
img = cv2.imread("20040420.jpg") # 读取原始图像
templ = b.copy() # 读取模板图像
width, height, c = templ.shape # 获取模板图像的宽度、高度和通道数
print(img.shape)
print(templ.shape)
results = cv2.matchTemplate(img, templ, cv2.TM_CCOEFF_NORMED) # 按照标准相关系数匹配
sum = 0
point_x = []
point_y =[]
for y in range(len(results)): # 遍历结果数组的行
for x in range(len(results[y])): # 遍历结果数组的列
if results[y][x] > 0.8: # 如果相关系数大于0.99则认为匹配成功
cv2.rectangle(img, (x, y), (x + width, y + height), (0, 0, 255), 2) # 在最佳匹配结果位置绘制黑色方框
sum = sum+1
point_x.extend([x+35])
point_y.extend([y+35])
x1 = 450
y1 = 450
sum1 = 0
for y in point_y:
for x in point_x:
now = np.array([x,y])-np.array([x1,y1]) #数组做差
now = math.hypot(now[0],now[1]) #两值的平方和然后开根
if(sum1>now):
x2 = x
y2 = y
sum1 = now
cv2.line(img, (x1, y1), (450, 450), (0, 0, 255), 10)
fontStyle = cv2.FONT_HERSHEY_TRIPLEX+cv2.FONT_ITALIC
cv2.putText(img, "cp = "+str(sum), (20, 90), fontStyle, 1, (0, 0, 0))
cv2.imshow("20040420WQ", img)
cv2.waitKey()
cv2.destroyAllWindows()
test.py
import cv2
import os
import sys
PIC_PATH = "C:\\Users\\ASUS\\PycharmProjects\\pythonProject3\\Opencv\\10_template_matching\\test\\" # 照片文件夹地址
width, height = 100, 100 # 缩放比例
pic_file = os.listdir(PIC_PATH) # 所有照片文件列表
same_pic_index = [] # 相同图像的索引列表
imgs = [] # 缩放后的图像对象列表
has_same = set() # 相同图像的集合
count = len(pic_file) # 照片数量
if count == 0: # 如果照片数量为零
print("没有图像")
sys.exit(0) # 停止程序
for file_name in pic_file: # 遍历照片文件
pic_name = PIC_PATH + file_name # 拼接完整文件名
img = cv2.imread(pic_name) # 创建文件的图像
img = cv2.resize(img, (width, height)) # 缩放成统一大小
imgs.append(img) # 按文件顺序保存图像对象
for i in range(0, count - 1): # 遍历所有图像文件,不遍历最后一个图像
if i in has_same: # 如果此图像已经找到相同的图像
continue # 跳过
templ = imgs[i] # 取出模板图像
same = [i] # 与templ内容相同的图像索引列表
for j in range(0 + i + 1, count): # 从templ的下一个位置开始遍历
if j in has_same: # 如果此图像已经找到相同的图像
continue # 跳过
pic = imgs[j] # 取出对照图像
results = cv2.matchTemplate(pic, templ, cv2.TM_CCOEFF_NORMED) # 比较两图像相速度
if results > 0.9: # 如果相似度大于90%,认为是同一张照片
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]) + ", " # 拼接文件名
print(text)
test/1.jpg
test/2.jpg
test/3.jpg
test/4.jpg
test/5.jpg
test/6.jpg
test/7.jpg
test/8.jpg
test/9.png
test/10.png
background.jpg
background2.jpg
car1.png
car2.png
car3.png
car4.png
image.png
image1.png
sa.jpg
sb.png
templ.png
template.png
template2.png
template3.png