PyQt5树莓派4平台实现每第N帧执行人脸检测其余帧仅显示
帧计数跳帧检测实现方案
这种方式完全可行,比延时逻辑稳定得多,计数直接对应摄像头实际读取到的有效帧数量,不会因为摄像头帧率波动、人脸检测耗时导致间隔不准。
原有代码的问题
- 计数步长错误:每成功读取1帧时,你给
process_this_frame加了2,而非加1,导致计数数值和实际物理帧数完全不匹配。比如原本想每20帧检测一次,按当前步长实际每10帧就会触发一次检测;如果改成%30的取模条件,实际要间隔60个物理帧才会检测一次,完全不符合预期。 - 没有可配置的间隔参数,后续调整检测频率需要改多处逻辑,不方便测试最优运行参数。
修正实现逻辑
- 定义独立的间隔常量
FRAME_INTERVAL,后续调整检测频率只需要修改这一个值即可 - 每成功读取1帧,计数器累加1,不跳步
- 当计数器对间隔值取模等于0时,才执行人脸检测、标注逻辑
- 若你要求非检测帧直接展示原始画面,直接发送原始采集帧即可;如果希望人脸标注不会在跳过帧上闪烁消失,可以加变量缓存上一次的检测结果,非检测帧复用缓存结果叠加标注。
参考实现代码
严格符合“非检测帧展示原始画面”的需求版本
def run(self): # 可配置参数:每隔N帧执行一次人脸检测,调整频率直接改这个值即可 FRAME_INTERVAL = 30 # 有效帧计数器 frame_count = 0 # 初始化摄像头 cap = cv2.VideoCapture(0) cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640) cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 300) while True: ret, cv_img = cap.read() if not ret: continue # 每成功读取1帧,计数器累加1 frame_count += 1 # 缩小帧用于检测,减少算力消耗(保留原有加速逻辑) img = cv2.resize(cv_img, (0, 0), fx=0.25, fy=0.25) # 仅在指定帧执行人脸检测 if frame_count % FRAME_INTERVAL == 0: predictions = predict(img, model_path="trained_knn_model.clf") cv_img = show_prediction_labels_on_image(cv_img, predictions) print(f"第{frame_count}帧完成人脸检测") # 不管是否检测,都发射信号刷新界面 self.change_pixmap_signal.emit(cv_img)
优化体验版(人脸标注不闪烁)
如果觉得非检测帧直接发原图会导致人脸框闪一下就消失,可以加缓存复用上次的检测结果:
def run(self): FRAME_INTERVAL = 30 frame_count = 0 # 缓存上一次的检测结果 last_predictions = [] cap = cv2.VideoCapture(0) cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640) cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 300) while True: ret, cv_img = cap.read() if not ret: continue frame_count += 1 img = cv2.resize(cv_img, (0, 0), fx=0.25, fy=0.25) if frame_count % FRAME_INTERVAL == 0: last_predictions = predict(img, model_path="trained_knn_model.clf") # 用缓存的结果叠加标注,不管是否是检测帧 if last_predictions: cv_img = show_prediction_labels_on_image(cv_img, last_predictions) self.change_pixmap_signal.emit(cv_img)
参数调整建议
- 树莓派4算力有限,初始可以把
FRAME_INTERVAL设为20~30,兼顾检测响应速度和画面流畅度 - 如果检测响应太慢可以把间隔调到10~15,如果画面卡顿就再调大间隔数值
内容的提问来源于stack exchange,提问作者julius
相关产品推荐
相关产品推荐

