树莓派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
相关产品推荐
相关产品推荐

