项目语言:Python .
环境:win10 python3.8.6
大蟒
下面一起来看下效果先:
1.首先采集人脸:
# 进行人脸录入/Face注册表导入dlibimport numpy as npimport cv2导入OSI导入shutili导入时间# Dlib正向人脸检测器/使用Dlibdetector=dlib。get _ frontier _ Face _ detector()类face _ register : def _ _ init _ _(self): self。path _ photos _ from _ camera=' data/data _ faces _ from _ camera/' self。font=cv2 .ITIL赛尔夫。现有_面_碳纳米管=0 #已录入的人脸计数器/cnt用于计算保存的面的数量self.ss_cnt=0 #录入personX人脸时图片计数器/cnt用于屏幕截图自我。current _ frame _ faces _ CNT=0 #录入人脸计数器/cnt用于计算当前帧自己中的面,save_flag=1 #之后用来控制是否保存图像的标志/控制是否保存自己的标志。按下_n_flag=0 #之后用来检查是否先按不再按s /在s ' # FPS自我。frame _ time=0 self。frame _ start _ time=0 selfFPS=0 #之前检查是否按下不的标志新建保存人脸图像文件和数据战斗支援车文件夹/制作用于保存照片和战斗支援车文件的目录def pre_work_mkdir(self): #新建文件夹/如果操作系统。路径。isdir(自我。path _ photos _ from _ camera):通过else : OS。mkdir(self。path _ photos _ from _ camera)#,则创建文件夹以保存人脸图像和战斗支援车删除之前存的人脸数据文件夹/删除face def _ pre _ work _ del _ old _ face _ folders(self): #的旧数据删除之前存的人脸数据文件夹,删除/data _ faces _ from _ camera/person _ x/'.folders _ rd=OS。列表目录(自身。路径_照片_来自_相机)为我在范围内(len(folders _ rd)): shutil。rmtree(self。如果操作系统。路径。is file(' data/features _ all。CSV’): OS。移除('数据/特征_全部。CSV ')#如果有之前录入的人脸,在之前个人x的序号按照person_x 1开始录入/Start from person _ x 1 def check _ existing _ faces _ CNT(self): if OS。list dir(' data/data _ faces _ from _ camera/'): #获取已录入的最后一个人脸序号/获取最新人物的顺序person _ list=OS。list dir(' data/data _ faces _ from _ camera/')
person_num_list = [] for person in person_list: person_num_list.append(int(person.split('_')[-1])) self.existing_faces_cnt = max(person_num_list) # 如果第一次存储或者没有之前录入的人脸, 按照 person_1 开始录入 / Start from person_1 else: self.existing_faces_cnt = 0 # 获取处理之后 stream 的帧数 / Update FPS of video stream def update_fps(self): now = time.time() self.frame_time = now - self.frame_start_time self.fps = 1.0 / self.frame_time self.frame_start_time = now # 生成的 cv2 window 上面添加说明文字 / PutText on cv2 window def draw_note(self, img_rd): # 添加说明 / Add some notes cv2.putText(img_rd, "Face Register", (20, 40), self.font, 1, (255, 255, 255), 1, cv2.LINE_AA) cv2.putText(img_rd, "FPS: " + str(self.fps.__round__(2)), (20, 100), self.font, 0.8, (0, 255, 0), 1, cv2.LINE_AA) cv2.putText(img_rd, "Faces: " + str(self.current_frame_faces_cnt), (20, 140), self.font, 0.8, (0, 255, 0), 1, cv2.LINE_AA) cv2.putText(img_rd, "N: Create face folder", (20, 350), self.font, 0.8, (255, 255, 255), 1, cv2.LINE_AA) cv2.putText(img_rd, "S: Save current face", (20, 400), self.font, 0.8, (255, 255, 255), 1, cv2.LINE_AA) cv2.putText(img_rd, "Q: Quit", (20, 450), self.font, 0.8, (255, 255, 255), 1, cv2.LINE_AA) # 获取人脸 / Main process of face detection and saving def process(self, stream): # 1. 新建储存人脸图像文件目录 / Create folders to save photos self.pre_work_mkdir() # 2. 删除 "/data/data_faces_from_camera" 中已有人脸图像文件 / Uncomment if want to delete the saved faces and start from person_1 if os.path.isdir(self.path_photos_from_camera): self.pre_work_del_old_face_folders() # 3. 检查 "/data/data_faces_from_camera" 中已有人脸文件 self.check_existing_faces_cnt() while stream.isOpened(): flag, img_rd = stream.read() # Get camera video stream kk = cv2.waitKey(1) faces = detector(img_rd, 0) # Use Dlib face detector # 4. 按下 'n' 新建存储人脸的文件夹 / Press 'n' to create the folders for saving faces if kk == ord('n'): self.existing_faces_cnt += 1 current_face_dir = self.path_photos_from_camera + "person_" + str(self.existing_faces_cnt) os.makedirs(current_face_dir) print('\n') print("新建的人脸文件夹 / Create folders: ", current_face_dir) self.ss_cnt = 0 # 将人脸计数器清零 / Clear the cnt of screen shots self.press_n_flag = 1 # 已经按下 'n' / Pressed 'n' already # 5. 检测到人脸 / Face detected if len(faces) != 0: # 矩形框 / Show the ROI of faces for k, d in enumerate(faces): # 计算矩形框大小 / Compute the size of rectangle box height = (d.bottom() - d.top()) width = (d.right() - d.left()) hh = int(height/2) ww = int(width/2) # 6. 判断人脸矩形框是否超出 480x640 / If the size of ROI > 480x640 if (d.right()+ww) > 640 or (d.bottom()+hh > 480) or (d.left()-ww < 0) or (d.top()-hh < 0): cv2.putText(img_rd, "OUT OF RANGE", (20, 300), self.font, 0.8, (0, 0, 255), 1, cv2.LINE_AA) color_rectangle = (0, 0, 255) save_flag = 0 if kk == ord('s'): print("请调整位置 / Please adjust your position") else: color_rectangle = (255, 255, 255) save_flag = 1 cv2.rectangle(img_rd, tuple([d.left() - ww, d.top() - hh]), tuple([d.right() + ww, d.bottom() + hh]), color_rectangle, 2) # 7. 根据人脸大小生成空的图像 / Create blank image according to the size of face detected img_blank = np.zeros((int(height*2), width*2, 3), np.uint8) if save_flag: # 8. 按下 's' 保存摄像头中的人脸到本地 / Press 's' to save faces into local images if kk == ord('s'): # 检查有没有先按'n'新建文件夹 / Check if you have pressed 'n' if self.press_n_flag: self.ss_cnt += 1 for ii in range(height*2): for jj in range(width*2): img_blank[ii][jj] = img_rd[d.top()-hh + ii][d.left()-ww + jj] cv2.imwrite(current_face_dir + "/img_face_" + str(self.ss_cnt) + ".jpg", img_blank) print("写入本地 / Save into:", str(current_face_dir) + "/img_face_" + str(self.ss_cnt) + ".jpg") else: print("请先按 'N' 来建文件夹, 按 'S' / Please press 'N' and press 'S'") self.current_frame_faces_cnt = len(faces) # 9. 生成的窗口添加说明文字 / Add note on cv2 window self.draw_note(img_rd) # 10. 按下 'q' 键退出 / Press 'q' to exit if kk == ord('q'): break # 11. Update FPS self.update_fps() cv2.namedWindow("camera", 1) cv2.imshow("camera", img_rd) def run(self): cap = cv2.VideoCapture(0) self.process(cap) cap.release() cv2.destroyAllWindows()def main(): Face_Register_con = Face_Register() Face_Register_con.run()if __name__ == '__main__': main()2.采集到人脸信息:
3.人脸信息写入CSV做数据保存对比
# 从人脸图像文件中提取人脸特征存入 "features_all.csv" / Extract features from images and save into "features_all.csv"import osimport dlibfrom skimage import ioimport csvimport numpy as np# 要读取人脸图像文件的路径 / Path of cropped facespath_images_from_camera = "data/data_faces_from_camera/"# Dlib 正向人脸检测器 / Use frontal face detector of Dlibdetector = dlib.get_frontal_face_detector()# Dlib 人脸 landmark 特征点检测器 / Get face landmarkspredictor = dlib.shape_predictor('data/data_dlib/shape_predictor_68_face_landmarks.dat')# Dlib Resnet 人脸识别模型,提取 128D 的特征矢量 / Use Dlib resnet50 model to get 128D face descriptorface_reco_model = dlib.face_recognition_model_v1("data/data_dlib/dlib_face_recognition_resnet_model_v1.dat")# 返回单张图像的 128D 特征 / Return 128D features for single image# Input: path_img
4.做人脸识别:
# 利用 OT 对于单张人脸追踪, 实时人脸识别 / Real-time face detection and recognition via OT for single faceimport dlibimport numpy as npimport cv2import osimport pandas as pdimport time# Dlib 正向人脸检测器 / Use frontal face detector of Dlibdetector = dlib.get_frontal_face_detector()# Dlib 人脸 landmark 特征点检测器 / Get face landmarkspredictor = dlib.shape_predictor('data/data_dlib/shape_predictor_68_face_landmarks.dat')# Dlib Resnet 人脸识别模型,提取 128D 的特征矢量 / Use Dlib resnet50 model to get 128D face descriptorface_reco_model = dlib.face_recognition_model_v1("data/data_dlib/dlib_face_recognition_resnet_model_v1.dat")class Face_Recognizer: def __init__(self): self.font = cv2.FONT_ITALIC # For FPS self.frame_time = 0 self.frame_start_time = 0 self.fps = 0 # cnt for frame self.frame_cnt = 0 # 用来存储所有录入人脸特征的数组 / Save the features of faces in the database self.features_known_list = [] # 用来存储录入人脸名字 / Save the name of faces in the database self.name_known_list = [] # 用来存储上一帧和当前帧 ROI 的质心坐标 / List to save centroid positions of ROI in frame N-1 and N self.last_frame_centroid_list = [] self.current_frame_centroid_list = [] # 用来存储上一帧和当前帧检测出目标的名字 / List to save names of objects in frame N-1 and N self.last_frame_names_list = [] self.current_frame_face_names_list = [] # 上一帧和当前帧中人脸数的计数器 / cnt for faces in frame N-1 and N self.last_frame_faces_cnt = 0 self.current_frame_face_cnt = 0 # 用来存放进行识别时候对比的欧氏距离 / Save the e-distance for faceX when recognizing self.current_frame_face_X_e_distance_list = [] # 存储当前摄像头中捕获到的所有人脸的坐标名字 / Save the positions and names of current faces captured self.current_frame_face_position_list = [] # 存储当前摄像头中捕获到的人脸特征 / Save the features of people in current frame self.current_frame_face_features_list = [] # 从 "features_all.csv" 读取录入人脸特征 / Get known faces from "features_all.csv" def get_face_database(self): if os.path.exists("data/features_all.csv"): path_features_known_csv = "data/features_all.csv" csv_rd = pd.read_csv(path_features_known_csv, header=None) for i in range(csv_rd.shape[0]): features_someone_arr = [] for j in range(0, 128): if csv_rd.iloc[i][j] == '': features_someone_arr.append('0') else: features_someone_arr.append(csv_rd.iloc[i][j]) self.features_known_list.append(features_someone_arr) self.name_known_list.append("Person_" + str(i + 1)) print("Faces in Database:", len(self.features_known_list)) return 1 else: print('##### Warning #####', '\n') print("'features_all.csv' not found!") print( "Please run 'get_faces_from_camera.py' and 'features_extraction_to_csv.py' before 'face_reco_from_camera.py'", '\n') print('##### End Warning #####') return 0 # 计算两个128D向量间的欧式距离 / Compute the e-distance between two 128D features # 更新 FPS / Update FPS of Video stream def update_fps(self): now = time.time() self.frame_time = now - self.frame_start_time self.fps = 1.0 / self.frame_time self.frame_start_time = now # 计算两个128D向量间的欧式距离 / Compute the e-distance between two 128D features @staticmethod def return_euclidean_distance(feature_1, feature_2): feature_1 = np.array(feature_1) feature_2 = np.array(feature_2) dist = np.sqrt(np.sum(np.square(feature_1 - feature_2))) return dist # 生成的 cv2 window 上面添加说明文字 / putText on cv2 window def draw_note(self, img_rd): # 添加说明 / Add some statements cv2.putText(img_rd, "Face Recognizer with OT (one person)", (20, 40), self.font, 1, (255, 255, 255), 1, cv2.LINE_AA) cv2.putText(img_rd, "FPS: " + str(self.fps.__round__(2)), (20, 100), self.font, 0.8, (0, 255, 0), 1, cv2.LINE_AA) cv2.putText(img_rd, "Q: Quit", (20, 450), self.font, 0.8, (255, 255, 255), 1, cv2.LINE_AA) # 处理获取的视频流,进行人脸识别 / Face detection and recognition wit OT from input video stream def process(self, stream): # 1. 读取存放所有人脸特征的 csv / Get faces known from "features.all.csv" if self.get_face_database(): while stream.isOpened(): self.frame_cnt += 1 print(">>> Frame " + str(self.frame_cnt) + " starts") flag, img_rd = stream.read() kk = cv2.waitKey(1) # 2. 检测人脸 / Detect faces for frame X faces = detector(img_rd, 0) # Update cnt for faces in frames self.last_frame_faces_cnt = self.current_frame_face_cnt self.current_frame_face_cnt = len(faces) print(" >>> current_frame_face_cnt: ", self.current_frame_face_cnt) # 2.1 If cnt not changes, 1->1 or 0->0 if self.current_frame_face_cnt == self.last_frame_faces_cnt: print(" >>> scene 1: 当前帧和上一帧相比没有发生人脸数变化 / no faces cnt changes in this frame!!!") # One face in this frame if self.current_frame_face_cnt != 0: # 2.1.1 Get ROI positions for k, d in enumerate(faces): # 计算矩形框大小 / Compute the size of rectangle box height = (d.bottom() - d.top()) width = (d.right() - d.left()) hh = int(height / 2) ww = int(width / 2) cv2.rectangle(img_rd, tuple([d.left() - ww, d.top() - hh]), tuple([d.right() + ww, d.bottom() + hh]), (255, 255, 255), 2) self.current_frame_face_position_list[k] = tuple( [faces[k].left(), int(faces[k].bottom() + (faces[k].bottom() - faces[k].top()) / 4)]) print(" >>> self.current_frame_face_names_list[k]: ", self.current_frame_face_names_list[k]) print(" >>> self.current_frame_face_position_list[k]: ", self.current_frame_face_position_list[k]) # 2.1.2 写名字 / Write names under ROI cv2.putText(img_rd, self.current_frame_face_names_list[k], self.current_frame_face_position_list[k], self.font, 0.8, (0, 255, 255), 1, cv2.LINE_AA) # 2.2 if cnt of faces changes, 0->1 or 1->0 else: print(" >>> scene 2: 当前帧和上一帧相比人脸数发生变化 / Faces cnt changes in this frame") self.current_frame_face_position_list = [] self.current_frame_face_X_e_distance_list = [] # 2.2.1 face cnt: 1->0, no faces in this frame if self.current_frame_face_cnt == 0: print(" >>> scene 2.1 人脸消失, 当前帧中没有人脸 / no guy in this frame!!!") # clear list of names and self.current_frame_face_names_list = [] self.current_frame_face_features_list = [] # 2.2.2 face cnt: 0->1, get the new face elif self.current_frame_face_cnt == 1: print(" >>> scene 2.2 出现人脸,进行人脸识别 / Get person in this frame and do face recognition") self.current_frame_face_names_list = [] for i in range(len(faces)): shape = predictor(img_rd, faces[i]) self.current_frame_face_features_list.append( face_reco_model.compute_face_descriptor(img_rd, shape)) # 2.2.2.1 遍历捕获到的图像中所有的人脸 / Traversal all the faces in the database for k in range(len(faces)): self.current_frame_face_names_list.append("unknown") # 2.2.2.2 每个捕获人脸的名字坐标 / Positions of faces captured self.current_frame_face_position_list.append(tuple( [faces[k].left(), int(faces[k].bottom() + (faces[k].bottom() - faces[k].top()) / 4)])) # 2.2.2.3 对于某张人脸,遍历所有存储的人脸特征 # For every faces detected, compare the faces in the database for i in range(len(self.features_known_list)): # 如果 person_X 数据不为空 if str(self.features_known_list[i][0]) != '0.0': print(" >>> with person", str(i + 1), "the e distance: ", end='') e_distance_tmp = self.return_euclidean_distance( self.current_frame_face_features_list[k], self.features_known_list[i]) print(e_distance_tmp) self.current_frame_face_X_e_distance_list.append(e_distance_tmp) else: # 空数据 person_X self.current_frame_face_X_e_distance_list.append(999999999) # 2.2.2.4 寻找出最小的欧式距离匹配 / Find the one with minimum e distance similar_person_num = self.current_frame_face_X_e_distance_list.index(min(self.current_frame_face_X_e_distance_list)) if min(self.current_frame_face_X_e_distance_list) < 0.4: self.current_frame_face_names_list[k] = self.name_known_list[similar_person_num] print(" >>> recognition result for face " + str(k + 1) + ": " + self.name_known_list[similar_person_num]) else: print(" >>> recognition result for face " + str(k + 1) + ": " + "unknown") # 3. 生成的窗口添加说明文字 / Add note on cv2 window self.draw_note(img_rd) if kk == ord('q'): break self.update_fps() cv2.namedWindow("camera", 1) cv2.imshow("camera", img_rd) print(">>> Frame ends\n\n") def run(self): cap = cv2.VideoCapture(0) self.process(cap) cap.release() cv2.destroyAllWindows()def main(): Face_Recognizer_con = Face_Recognizer() Face_Recognizer_con.run()if __name__ == '__main__': main()
私信回复:人脸识别源码
获取项目源代码