一、理论分析
模式匹配简单来说就是我想在一副地图上找到一个我已知地名的位置,更通俗来叔也就是查地图。这其中需要查找时具有一定的变通性,比如我想在一个图里找到一只狗狗的位置,那么即使这只狗狗的动作和表情与待查找的不一致,也需要精准的匹配。而这些要求对于简单的模式匹配来说却很难实现,因为它仅仅会计算不同特征之间的相似度,很难变通。但是我们同样可以利用这一点来对图像通过模式识别来进行筛选与甄别。而对于狗狗的动作和表情与待查找不一致时,可以适当降低相似度要求。
背景减除(Background Subtraction)是许多基于计算机视觉的任务中的主要预处理步骤。就是我在做视频的目标识别时,主要是对动作的事物(比如行人和正在运行的汽车)进行识别,而不考虑保持不动的背影的因素,所以可以通过背景减除去掉背景在目标识别运算步骤,从而提高识别效率。
二、代码分析
2.1 模式匹配
from cv2 import cv2 as cv
img = cv.imread(r"./CV-Pictures/background.jpg")
templ = cv.imread(r"./CV-Pictures/template.png")
# templ = cv.flip(templ,1) #图像的翻转
# templ = cv.rotate(templ,cv.ROTATE_180) #图像的旋转
# templ = cv.resize(templ,None,fx=1.2,fy=1.4) #图像大小的变换
width,height = templ.shape[:2]
results = cv.matchTemplate(img,templ,cv.TM_SQDIFF_NORMED) # 按照标准平方差方式匹配
# print(results)
minVal,maxVal,minloc,maxloc = cv.minMaxLoc(results)
resultsPoints1 = minloc # 将最小值坐标当做最佳匹配区域的左上角点坐标
resultsPoints2 = (resultsPoints1[0]+width,resultsPoints1[1]+height) # 计算出最佳匹配区域的右下角点坐标
cv.rectangle(img,resultsPoints1,resultsPoints2,(0,0,255),2) # 在最佳匹配区域位置绘制红色方框,线宽为2像素
cv.imshow('img',img)
cv.imshow('templ',templ)
cv.waitKey(0)
cv.destroyAllWindows()
运行结果如下:
可以看到图像识别成功,读者可以自行尝试更改待查找图片的角度和大小,验证查找的结果。
这是模式匹配的另一个例子,用于检测相同的车辆识别
from cv2 import cv2
import os
import sys
PIC_PATH = r"./CV-Pictures/test/" # 照片文件夹地址
width, height = 100, 100 # 缩放比例
pic_file = os.listdir(PIC_PATH) # 所有照片文件列表
print("图片列表打印",pic_file)
same_pic_index = [] # 相同图像的索引列表
imgs = [] # 缩放后的图像对象列表
has_same = set() # 相同图像的集合
count = len(pic_file) # 照片数量
names = []
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) # 按文件顺序保存图像对象
names.append(pic_name)
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)
运行结果:
图片列表打印 [‘1.jpg’, ‘10.png’, ‘2.jpg’, ‘3.jpg’, ‘4.jpg’, ‘5.jpg’, ‘6.jpg’, ‘7.jpg’, ‘8.jpg’, ‘9.png’]
相同的照片:10.png, 4.jpg,
相同的照片:2.jpg, 5.jpg, 9.png,
2.2 背景减除
from cv2 import cv2 as cv
bgsubmog = cv.createBackgroundSubtractorMOG2() #创建背景减除方法
mask = bgsubmog.apply(img) #去除背景后的图像mask
该方法主要应用在视频中的模式识别中,这里不好举例。会在后期的综合案列中对应讲解。
三、代码文件
小程序员将代码文件和相关素材整理到了百度网盘里,因为文件大小基本不大,大家也不用担心限速问题。后期小程序员有能力的话,将在gitee或者github上上传相关素材。
链接:https://pan.baidu.com/s/1Ce14ZQYEYWJxhpNEP1ERhg?pwd=7mvf
提取码:7mvf