赞
踩
该代码包含人脸数据采集和人脸识别两部分。
import face_recognition import cv2 as cv import numpy as np import time import os class Rec_frg(object): #定义全局变量 def __init__(self): self.video_path = r"D:\pythonItems\opencv1\vodeo" self.image_data_path = r"D:\pythonItems\opencv1\reg_facedata" self.nums = 40 self.name = [] self.face_encodings = [] # 定义函数:用于计算视屏时长 def video_duration(self,filename): cap = cv.VideoCapture(filename) if cap.isOpened(): rate = cap.get(5) frame_num = cap.get(7) duration = frame_num // rate * 30 times = duration // 60 return times return -1 #定义方法:用于收集数据 def image_datacolloct(self): waitKey_count = 0 #显示该文件夹下的所有内容 video_path = os.listdir(self.video_path) #分别显示每一个视屏 for path_v in video_path: img_num = 1 # 找到每个视屏的绝对路径 p = r"{}".format(os.path.join(self.video_path,path_v)) #调用函数计算视屏时长 all_times = self.video_duration(p) #打开视屏 capture = cv.VideoCapture(p) while True: have_landmasks = True # 构造保存图片时图片的名称 name = path_v.split(".")[0] +"_"+ str(img_num) # 通过视屏名称,找出每个人的名字 label_name = path_v.split(".")[0] #显示时频每一帧 ret, frame = capture.read() #缩小视屏宽、高为原来的一般 frame = cv.resize(frame, (0, 0), fx=0.5, fy=0.5) #将每一帧的BGR格式转换为RGB格式 rgb_small_frame_data = frame[:, :, ::-1] if ret == False: break #找出每一帧中人脸的位置 face_location = face_recognition.face_locations(rgb_small_frame_data) #训练集面部特征编码 if waitKey_count == 0: face_encoding = face_recognition.face_encodings(rgb_small_frame_data,model= "large") if len(face_encoding) == 0: have_landmasks = False else: have_landmasks = True #将np.array()类型转换为list类型 fs = face_encoding[0].tolist() #将数据和标签添加到列表中 self.face_encodings.append(fs) self.name.append(label_name) #保存图片 cv.imwrite("D:/pythonItems/opencv1/reg_facedata/"+name+".jpg",frame) img_num += 1 #设置退出条件 if img_num > self.nums: break c = cv.waitKey(1) if c == 27: break #设置人脸数据获取条件 if len(face_location) > 0 and have_landmasks == True: waitKey_count += 1 print("wait",waitKey_count) if waitKey_count == all_times - 1: waitKey_count = 0 cv.imshow("face", frame) #释放资源 capture.release() #显示收集好的数据及标签 print("location", self.face_encodings) print("name", self.name) #将数据和标签存入文件中用于识别时使用 f_data = open("data.txt", "w") f_name = open("name.txt","w") f_data.write(str(self.face_encodings)) f_name.write(str(self.name)) #关闭文件 f_data.close() f_name.close() #关闭所有窗口 cv.destroyAllWindows() #定义方法:用于识别 def face_dances(self,video_name): success = 0 fail = 0 known_face_encodings = [] video_capture = cv.VideoCapture(video_name) #读取人脸编码数据和标签 data_file = open("data.txt", "r") label_file = open("name.txt","r") data = eval(data_file.read()) #将从文件中读取出的每一张人脸数据的类型转化为 np.array()类型 for i in data: list_to_array = np.array(i) known_face_encodings.append(list_to_array) known_face_names = eval(label_file.read()) #关闭文件 data_file.close() label_file.close() # 初始化变量 process_this_frame = True time1 = time.time() while True: face_names = [] name_str = "" # 读取视屏每一帧 ret, frame = video_capture.read() if ret == False: break # 将视屏款、高缩小一半 frame = cv.resize(frame, (0, 0), fx=0.5, fy=0.5) # 将BGR格式转化为RGB rgb_small_frame = frame[:, :, ::-1] # 只处理每隔一帧的视频以节省时间 if process_this_frame: # 定位所找到的人脸的位置 face_locations = face_recognition.face_locations(rgb_small_frame) # 对面部特征进行编码 face_encodings = face_recognition.face_encodings(rgb_small_frame, face_locations,model= "large") #循环每一个编码好的人脸 for face_encoding in face_encodings: # 由面部编码匹配人脸 matches = face_recognition.compare_faces(known_face_encodings, face_encoding,tolerance=0.5) #计算 "Ture" 的个数 true_count = matches.count(True) # print(matches) # print(true_count) #计算要识别的人脸和每个已知人脸之间的距离 face_distances = face_recognition.face_distance(known_face_encodings, face_encoding) #找出最小距离的索引 best_match_index = np.argmin(face_distances) #判断条件 if matches[best_match_index] == False or true_count < self.nums: name = "Unknown" #循环每一张人脸 for top, right, bottom, left in face_locations: #画出人脸框 cv.rectangle(frame, (left, top), (right, bottom), (0, 0, 255), 2) fail += 1 # 画出标签背景框 cv.rectangle(frame, (left, bottom - 35), (right, bottom), (0, 0, 255), cv.FILLED) font = cv.FONT_HERSHEY_DUPLEX #显示标签 cv.putText(frame, name, (left + 6, bottom - 6), font, 0.6, (255, 255, 255), 2) if fail == 10: print("识别失败!") fail = 0 #计算时间 time2 = time.time() spend = time2 - time1 print("花费时长:", spend) time1 = time.time() else: #找出距离最小人脸的名字 name = known_face_names[best_match_index] face_names.append(name) #将人脸和相应的标签合并,并循环每一张人脸 for (top, right, bottom, left),name in zip(face_locations,face_names): # 画出人脸框 cv.rectangle(frame, (left, top), (right, bottom), (0, 255, 0), 2) success += 1 # 画出标签背景框 cv.rectangle(frame, (left, bottom - 35), (right, bottom), (0, 255, 0), cv.FILLED) font = cv.FONT_HERSHEY_DUPLEX #显示标签 cv.putText(frame, name, (left + 6, bottom - 6), font, 0.6, (255, 255, 255), 2) if success == 10: for name_one in face_names: name_str += name_one+" " print(" 识别成功!") print(f"{name_str} 欢迎光临!") time2 = time.time() spend = time2 - time1 print("花费时长:", spend) time1 = time.time() success = 0 # 显示每一帧视屏 cv.imshow('Video', frame) #按ESC键退出 key = cv.waitKey(1) if key == 27: break # 释放视屏资源,并关闭所有窗口 video_capture.release() cv.destroyAllWindows() #程序入口 if __name__ == "__main__": answer = input("人脸采集请输入0,输入其他进行识别!") video1 = "test.mp4" video2 = "girl_test.mp4" #实例化类 Facerecognition = Rec_frg() #判断采集还是识别 if answer == "0": Facerecognition.image_datacolloct() Facerecognition.face_dances(video1) else: Facerecognition.face_dances(video1)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。