You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 13:27:06