RuntimeError图像类型不兼容问题及人脸识别考勤代码优化求助
问题解决:人脸识别错误修复+代码优化
一、RuntimeError错误修复
这个错误是因为传入face_recognition的图像格式不符合要求,结合你的代码,主要问题及修复方案如下:
1. 摄像头帧读取异常
video.read()可能读取失败(比如摄像头初始化慢、设备故障),导致frame为空,后续处理必然报错。修复时先判断读取状态:
while True: check, frame = video.read() # 新增:跳过无效帧 if not check: continue small_frame = cv2.resize(frame, (0,0), fx=0.5, fy= 0.5) rgb_small_frame = small_frame[:,:,::-1]
2. 错误的图像通道重复操作
你的代码里rgb_small_frame.repeat(3,2)会把3通道RGB图像变成9通道,完全不符合face_recognition要求的8bit RGB格式,直接移除该操作:
# 原错误代码 # face_encodings = face_recognition.face_encodings(rgb_small_frame.repeat(3,2), face_locations) # 修改后: face_encodings = face_recognition.face_encodings(rgb_small_frame, face_locations)
3. 本地图片格式兼容问题
部分PNG图片是RGBA四通道格式,需要统一转成RGB:
for root,dirs,files in os.walk(image_dir): for file in files: if file.lower().endswith(('jpg', 'jpeg', 'png')): path = os.path.join(root, file) img = face_recognition.load_image_file(path) # 处理RGBA图片转RGB if img.shape[-1] == 4: img = img[...,:3] label = file[:len(file)-4] # 处理无人脸的图片,避免索引错误 try: img_encoding = face_recognition.face_encodings(img)[0] known_face_names.append(label) known_face_encodings.append(img_encoding) except IndexError: print(f"警告:图片{path}未检测到人脸,已跳过") continue
4. 路径末尾多余空格
image_dir拼接时末尾多了空格,可能导致找不到目录,改用os.path.join自动处理路径:
# 原代码 # image_dir = os.path.join(base_dir,"{}\{}\{}\{}\{}\{} ".format('static','images','Student_Images',details['branch'],details['year'],details['section'])) # 修改后: image_dir = os.path.join(base_dir, 'static', 'images', 'Student_Images', details['branch'], details['year'], details['section'])
二、指定代码段的执行效率优化
1. 数据库操作优化
原代码循环保存考勤记录,每次save()触发一次数据库请求,效率极低。改成批量创建,同时优化学生ID查询:
# 原代码 students = Student.objects.filter(branch=details['branch'], year=details['year'], section=details['section']) names = Recognizer(details) for student in students: attendence = Attendence(...) attendence.save() # 修改后: # 1. 直接获取学生ID集合,减少内存占用 student_ids = Student.objects.filter( branch=details['branch'], year=details['year'], section=details['section'] ).values_list('registration_id', flat=True) # 转成字符串集合,加快判断速度 names_set = set(names) # 2. 批量创建考勤记录 attendence_list = [] for student_id in student_ids: status = 'Present' if str(student_id) in names_set else '' attendence = Attendence( Faculty_Name=request.user.faculty, Student_ID=str(student_id), period=details['period'], branch=details['branch'], year=details['year'], section=details['section'], status=status ) attendence_list.append(attendence) # 批量插入,仅一次数据库请求 Attendence.objects.bulk_create(attendence_list)
2. 人脸识别函数优化
(1)缓存人脸编码
每次调用Recognizer都重新加载图片生成编码,重复计算浪费时间,用Django缓存缓存编码:
from django.core.cache import cache def Recognizer(details): cache_key = f"face_encodings_{details['branch']}_{details['year']}_{details['section']}" # 先从缓存取 cached_data = cache.get(cache_key) if cached_data: known_face_encodings, known_face_names = cached_data else: known_face_encodings = [] known_face_names = [] # ...(前面修复后的加载图片代码) # 缓存1小时(可按需调整) cache.set(cache_key, (known_face_encodings, known_face_names), 3600) # 后续摄像头识别逻辑...
(2)减少重复计算
原代码重复调用compare_faces和face_distance,直接去掉重复:
for face_encoding in face_encodings: try: face_distances = face_recognition.face_distance(known_face_encodings, face_encoding) best_match_index = np.argmin(face_distances) if face_distances[best_match_index] <= 0.6: name = known_face_names[best_match_index] face_names.append(name) if name not in names_set: names_set.add(name) except: pass
(3)优化集合判断
把names初始化为集合,避免每次查询的O(n)耗时:
# 原代码names = [] names_set = set() # 识别时: if name not in names_set: names_set.add(name) # 最后返回列表 return list(names_set)
内容的提问来源于stack exchange,提问作者Gupta Manish Deepak
相关产品推荐
相关产品推荐

