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

树莓派4人脸识别代码多线程优化及改进建议咨询

树莓派4人脸识别代码多线程优化及性能提升方案

一、多线程改造后的完整代码

将帧采集与人脸识别拆分为独立线程,用队列传递数据,避免主线程因计算阻塞导致画面卡顿:

import face_recognition
import cv2
import numpy as np
import threading
from queue import Queue

# 帧队列:传递摄像头采集的画面(限制缓存避免内存占用过高)
frame_queue = Queue(maxsize=2)
# 结果队列:传递人脸识别的位置与名称(仅保留最新结果)
result_queue = Queue(maxsize=1)

# 预加载已知人脸编码(提前计算,避免重复耗时操作)
person_image = face_recognition.load_image_file("./faceRecognition/test.jpeg")
person_face_encoding = face_recognition.face_encodings(person_image)[0]
known_face_encodings = [person_face_encoding]
known_face_names = ["individual"]

def capture_frames():
    """摄像头帧采集线程"""
    video_capture = cv2.VideoCapture(0)
    # 手动降低采集分辨率,减少后续处理压力
    video_capture.set(cv2.CAP_PROP_FRAME_WIDTH, 640)
    video_capture.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)
    
    while True:
        ret, frame = video_capture.read()
        if not ret:
            break
        # 队列未满时存入帧,满则丢弃旧帧避免阻塞
        if not frame_queue.full():
            try:
                frame_queue.put_nowait(frame)
            except:
                pass
    video_capture.release()

def process_faces():
    """人脸识别处理线程"""
    process_this_frame = True
    while True:
        try:
            # 从队列获取待处理帧
            frame = frame_queue.get(timeout=1)
            if process_this_frame:
                # 缩小帧尺寸加速识别计算
                small_frame = cv2.resize(frame, (0, 0), fx=0.25, fy=0.25)
                rgb_small_frame = small_frame[:, :, ::-1]
                
                # 检测人脸位置与编码
                face_locations = face_recognition.face_locations(rgb_small_frame)
                face_encodings = face_recognition.face_encodings(rgb_small_frame, face_locations)
                
                face_names = []
                for face_encoding in face_encodings:
                    matches = face_recognition.compare_faces(known_face_encodings, face_encoding)
                    name = "Unknown"
                    face_distances = face_recognition.face_distance(known_face_encodings, face_encoding)
                    best_match_index = np.argmin(face_distances)
                    if matches[best_match_index]:
                        name = known_face_names[best_match_index]
                    face_names.append(name)
                
                # 更新识别结果,覆盖旧结果
                if not result_queue.full():
                    result_queue.put_nowait((face_locations, face_names))
                else:
                    result_queue.get()
                    result_queue.put((face_locations, face_names))
            process_this_frame = not process_this_frame
            frame_queue.task_done()
        except:
            continue

# 启动子线程
capture_thread = threading.Thread(target=capture_frames, daemon=True)
process_thread = threading.Thread(target=process_faces, daemon=True)
capture_thread.start()
process_thread.start()

# 主线程负责画面渲染与交互
while True:
    # 获取最新识别结果
    face_locations, face_names = [], []
    if not result_queue.empty():
        face_locations, face_names = result_queue.get()
    
    # 获取当前帧并绘制识别标记
    if not frame_queue.empty():
        frame = frame_queue.get()
        for (top, right, bottom, left), name in zip(face_locations, face_names):
            # 缩放人脸位置到原始帧尺寸
            top *= 4
            right *= 4
            bottom *= 4
            left *= 4
            # 绘制人脸框与名称标签
            cv2.rectangle(frame, (left, top), (right, bottom), (0, 0, 255), 2)
            cv2.rectangle(frame, (left, bottom - 35), (right, bottom), (0, 0, 255), cv2.FILLED)
            cv2.putText(frame, name, (left + 6, bottom - 6), cv2.FONT_HERSHEY_DUPLEX, 1.0, (255, 255, 255), 1)
        
        cv2.imshow('Video', frame)
    
    # 按q键退出程序
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

cv2.destroyAllWindows()

二、额外性能改进建议

  • 进一步降低处理分辨率:将帧缩放比例从0.25调整为0.2(1/5尺寸),在可接受的识别精度下大幅减少计算量
  • 调整检测间隔:将隔帧处理改为每3-4帧处理一次,进一步降低CPU负载
  • 切换轻量检测模型:用OpenCV的Haar级联检测器做前置人脸检测,再将检测到的人脸区域传给face_recognition做编码匹配,减少无效计算
  • 启用硬件加速:重新编译带MMAL/OpenCL支持的OpenCV版本,让树莓派的GPU参与帧处理
  • 预存人脸编码:将已知人脸编码保存为numpy文件(np.save("face_encoding.npy", person_face_encoding)),启动时直接加载(np.load()),避免重复计算编码
  • 简化绘制效果:降低人脸框线条粗细(从2改为1)、改用更轻量的字体,减少OpenCV渲染开销

内容的提问来源于stack exchange,提问作者DarkWolf DarkINFINITE

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 02:28:18