2021SC@SDUSC
这部分我主要实现了对视频中指定人物出现次数逐帧(每6帧)进行检查。
利用前面生成的人脸库,对视频中的人物进行逐帧的检查,如果人物出现则计数加一。最终返回计数值更大的gif给用户。
目录
一.引言
二.相关代码
三.人物出现次数实时统计
人脸识别这里我使用的是dlib人脸识别的库,dlib进行人脸识别有很经典的思路:
1.计算已知图⽚中所有⼈脸对应的特征向量;
2.计算要识别的未知图⽚中所有⼈脸对应的特征向量;
3.计算⼈脸之间的欧式距离;
4.如果两张⼈脸之间的欧式距离⼩于设定的阈值,则认为是同⼀个⼈,否则认为不是同⼀个⼈
这些方法都已经是封装好的方法,所以我们使用起来直接调用很方便。
视频中人脸检测关键代码:
使用的库:
import dlib,os,glob,time
import cv2
import numpy as np
import pandas as pd
加载模型:
#人脸特征提取器
detector = dlib.get_frontal_face_detector()
#人脸关键点标记
predictor= dlib.shape_predictor(predictor_path)
#生成面部识别器
facerec = dlib.face_recognition_model_v1(model_path)
#定义视频创建器,用于输出视频
video_writer = cv2.VideoWriter(resources_vResult+"result1.avi",
cv2.VideoWriter_fourcc(*'XVID'), int(fps),
(int(video.get(cv2.CAP_PROP_FRAME_WIDTH)), int(video.get(cv2.CAP_PROP_FRAME_HEIGHT))))
识别过程核心代码:
#目标人物出现次数
count=0
#读取本地人脸库
head = []
for i in range(128):
fe = "feature_" + str(i + 1)
head.append(fe)
face_path=faceDB_path+"feature_all.csv"
face_feature=pd.read_csv(face_path,names=head)
#人脸库中人物的特征
face_feature_array=np.array(face_feature)
#待识别人物 这个序号和feature_all.csv的特征序号应该保持一致
num=len(face_feature_array)
face_list= []
for i in range(num):
face_list=face_list+[i]
#计算欧式距离
def compute_dst(feature_1,feature_2):
feature_1 = np.array(feature_1)
feature_2 = np.array(feature_2)
dist = np.linalg.norm(feature_1 - feature_2)
return dist
# 处理视频,按帧处理
ret,frame = video.read()
flag = True # 标记是否是第一次迭代
i = 0 # 记录当前迭代到的帧位置
while ret:
if i % 6== 0: # 每6帧截取一帧
# 转为灰度图像处理
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
dets = detector(gray, 1) # 检测帧图像中的人脸
# 处理这一帧检测到的每一张人脸
#检测到了人脸
if len(dets)>0:
for index,value in enumerate(dets):
#获取面部关键点
shape = predictor(gray,value)
#标记人脸
cv2.rectangle(frame, (value.left(), value.top()), (value.right(), value.bottom()), (0, 255, 0), 2)
#进行人脸识别并打上姓名标签
# 提取特征-图像中的68个关键点转换为128D面部描述符,其中同一人的图片被映射到彼此附近,并且不同人的图片被远离地映射。
face_descriptor = facerec.compute_face_descriptor(frame, shape)
#视频中这个人的特征向量
v = np.array(face_descriptor)
#l = len(descriptors)
Flen=len(face_list)
flag=0
for j in range(Flen):
# 人脸匹配,距离小于阈值,表示识别成功,打上标签
if(compute_dst(v,face_feature_array[j])<0.56):
flag=1
cv2.putText(frame,'Attention',(value.left(), value.top()),cv2.FONT_HERSHEY_COMPLEX,0.8, (0, 255, 255), 1, cv2.LINE_AA)
cv2.putText(frame, 'Attention', (value.left(), value.top()), cv2.FONT_HERSHEY_COMPLEX, 0.8, (0, 255, 255), 1, cv2.LINE_AA)
count=count+1
break
if(flag==0):
cv2.putText(frame,"Unknonw", (value.left(), value.top()), cv2.FONT_HERSHEY_COMPLEX, 0.8, (0, 255, 255), 1,
cv2.LINE_AA)
#标记关键点
for pti,pt in enumerate(shape.parts()):
pos=(pt.x,pt.y)
cv2.circle(frame, pos, 1, color=(0, 255, 0))
video_writer.write(frame)
ret,frame = video.read()
i += 1
输入的目标照片:
只需要一张即可
目标对象的特征向量:
对目标人物标注Attention,并且计数:
对非目标人物标注unknow,不理会:
可以观察到目标人物计数没有变:
再次检测到目标人物:
最终输出统计结果:
最后只需要对所有Gif执行操作,返回统计次数比较高的几个即可。
注:
这里视频形式演示只是在开发过程中方便检查,项目真正用到的数据就是出现次数这个量,作为比较的量。