今天Franpper给大家带来的是在一张图像上进行多种模板的匹配
首先展示一下原图、模板,与匹配结果
原图如下:
这里Franpper共设置了两种模板,分别是眼睛和手,如下:
匹配结果如下:
话不多说,上代码!(如果对大家有帮助的话求个关注!!!公众号是:Franpper的知识铺,谢谢大家!!!)
import cv2
import numpy as np
import os
from PIL import Image
"""
主要功能:多类模板匹配
实现原理:遍历模板文件夹,每次取出一张模板,进行旋转操作,分别以0°、90°、180°、270°在原图上进行匹配操作
"""
img_path = r'E:\pythonProject\PROJECT\matchTemplate\img' # 存放原图像的文件夹
save_path = r'E:\pythonProject\PROJECT\matchTemplate\save' # 匹配后图像储存路径
path = r'E:\pythonProject\PROJECT\matchTemplate\template' # 存放模板的文件夹
file_dir = [] # 模板列表
classname = [] # 模板类别名称列表
file_name = os.listdir(path)
# 添加模板列表、模板类别名称列表
for i in range(len(file_name)):
classname.append(file_name[i].split('.')[0])
file_dir.append(os.path.join(path, file_name[i]))
# 进行匹配
for file in os.listdir(img_path):
img_dir = os.path.join(img_path, file)
print('识别', img_dir)
img_ori = cv2.imread(img_dir, 0)
img_w, img_h = img_ori.shape[::-1]
for i in range(len(file_dir)):
class_name = classname[i]
print('图元' + class_name + '匹配中')
trans = [0, Image.ROTATE_90, Image.ROTATE_180, Image.ROTATE_270] # 创建用于旋转的角度列表
for operate in trans:
if operate == 0: # 为0时表示不进行任何操作,即以原图进行匹配
template = cv2.imread(file_dir[i], 0)
w, h = template.shape[::-1]
if w > img_w or h > img_h: # 进行一下过滤,防止模板比原始图片大而导致无法匹配
break
else:
res = cv2.matchTemplate(img_ori, template, cv2.TM_CCOEFF_NORMED) # 进行匹配
threshold = 0.95 # 阈值视匹配结果可调
loc = np.where(res >= threshold)
for pt in zip(*loc[::-1]):
cv2.rectangle(img_ori, pt, (pt[0] + w, pt[1] + h), 0, 1)
cv2.putText(img_ori, class_name, (pt[0], pt[1] - 5), cv2.FONT_HERSHEY_TRIPLEX,
(w - h) / 120, 0, 1, bottomLeftOrigin=False)
else:
template = cv2.imread(file_dir[i])
# 这里Franpper因为没找到其他办法,所以用了一个笨办法,旋转的时候用的是PIL格式的图像,大家有什么好办法可以留言讨论一下!!!
# 在PIL格式下进行transpose操作
# cv格式转为PIL格式
template_pil = Image.fromarray(cv2.cvtColor(template, cv2.COLOR_BGR2RGB))
template_trans = template_pil.transpose(operate)
# 旋转之后将PIL格式转为cv格式
template_cv = cv2.cvtColor(np.asarray(template_trans), cv2.COLOR_RGB2BGR)
template_cv_gray = cv2.cvtColor(np.asarray(template_cv), cv2.COLOR_BGR2GRAY)
w, h = template_cv_gray.shape[::-1]
if w > img_w or h > img_h:
break
else:
res = cv2.matchTemplate(img_ori, template_cv_gray, cv2.TM_CCOEFF_NORMED)
threshold = 0.85
loc = np.where(res >= threshold)
for pt in zip(*loc[::-1]):
cv2.rectangle(img_ori, pt, (pt[0] + w, pt[1] + h), 0, 1)
cv2.putText(img_ori, class_name, (pt[0], pt[1] - 5), cv2.FONT_HERSHEY_TRIPLEX,
(w - h) / 120, 0, 1, bottomLeftOrigin=False)
cv2.imwrite(os.path.join(save_path, file.split('.')[0] + '_temp.jpg'), img_ori)