Python使用face_recognition库出现索引越界及重复存人脸问题求助
问题排查与修复方案
问题1:IndexError: list index out of range 报错修复
原因
face_recognition.face_encodings() 函数在输入图片中没有检测到人脸时,会返回空列表,直接取下标[0]就会触发索引越界报错。你初始加载的KArtIntel文件夹中可能存在不包含人脸的图片,或者图片损坏无法正常读取。
修复方法
- 读取初始图片后先判断是否读取成功,编码前先判断编码列表非空
- 路径拼接改用
os.path.join()避免操作系统路径格式问题
问题2:同一张人脸重复保存修复
现有代码逻辑错误点
- 每次循环都将计数变量
i重置为0,导致保存的文件名永远重复,旧文件会被覆盖 - 匹配逻辑错误:误将当前帧所有编码的列表
encodesCurFrame拿去和已知编码列表判断,应该判断当前单个人脸编码encodeFace和所有已知编码的最小距离是否超过阈值(通常取0.6) - 仅保存整帧图片,没有按人脸坐标截取单独的人脸区域
- 新增人脸后没有将对应编码加入已知编码列表
encodelistKnown,导致后续帧检测到同一张人脸仍会判定为新人脸 - 变量
i定义在循环内部,计数完全不生效
修正后完整代码
import face_recognition import cv2 import os import numpy as np # 配置路径 known_face_path = r"C:\Users\CHIJINDU\Desktop\KArtIntel" save_path = known_face_path # 新人脸保存路径 os.makedirs(save_path, exist_ok=True) # 加载已知人脸 images = [] class_names = [] myList = os.listdir(known_face_path) for cl in myList: # 跳过非图片文件,避免读取错误 if cl.lower().endswith(('.png', '.jpg', '.jpeg', '.bmp')): curImg_path = os.path.join(known_face_path, cl) curImg = cv2.imread(curImg_path) if curImg is None: continue images.append(curImg) class_names.append(os.path.splitext(cl)[0]) print("已加载已知人脸:", class_names) def find_encodings(images): encodelist = [] for idx, img in enumerate(images): img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) encodes = face_recognition.face_encodings(img) # 跳过没有检测到人脸的图片 if len(encodes) == 0: print(f"警告:第{idx}张图片未检测到人脸,已跳过") continue encodelist.append(encodes[0]) return encodelist encodelistKnown = find_encodings(images) print(f"已加载有效人脸编码数量:{len(encodelistKnown)}") # 初始化保存计数,避免覆盖已有文件 save_counter = len([f for f in os.listdir(save_path) if f.startswith("KUDOS-J14")]) # 匹配阈值,数值越低匹配要求越严格 MATCH_THRESHOLD = 0.6 cap = cv2.VideoCapture(r"C:\Users\CHIJINDU\Desktop\Elastic.mp4") while True: success, img = cap.read() # 视频读取结束就退出循环 if not success: break imgS = cv2.resize(img, (0,0), None, 0.25, 0.25) imgS = cv2.cvtColor(imgS, cv2.COLOR_BGR2RGB) faceCurFrame = face_recognition.face_locations(imgS) encodesCurFrame = face_recognition.face_encodings(imgS, faceCurFrame) for encodeFace, faceloc in zip(encodesCurFrame, faceCurFrame): # 计算和已知人脸的匹配度 if len(encodelistKnown) > 0: matches = face_recognition.compare_faces(encodelistKnown, encodeFace, tolerance=MATCH_THRESHOLD) faceDis = face_recognition.face_distance(encodelistKnown, encodeFace) min_dis = np.min(faceDis) is_known = min_dis < MATCH_THRESHOLD else: # 没有已知人脸的情况,直接判定为新人脸 is_known = False if not is_known: # 还原人脸坐标(因为之前缩放到了0.25倍) y1, x2, y2, x1 = [pos *4 for pos in faceloc] # 截取人脸区域 face_img = img[y1:y2, x1:x2] # 保存人脸截图 save_name = f"KUDOS-J14{save_counter}.jpg" cv2.imwrite(os.path.join(save_path, save_name), face_img) # 将新人脸编码加入已知列表,避免重复保存 encodelistKnown.append(encodeFace) save_counter += 1 print(f"已保存新人脸:{save_name}") # 显示结果 cv2.imshow('Video', img) if cv2.waitKey(1) & 0xFF == ord('q'): break cap.release() cv2.destroyAllWindows()
内容的提问来源于stack exchange,提问作者KUDOS
相关产品推荐
相关产品推荐

