如何并行化隔X帧调用的慢人脸识别函数避免拖慢视频处理主循环
实现方案
你可以用Python标准库multiprocessing的队列实现跨进程通信,单独启一个常驻工作进程处理人脸识别计算,主循环全程无阻塞。
核心逻辑
- 维护两个队列:
task_queue用来从主循环向工作进程传需要识别的帧,result_queue用来从工作进程向主循环返回识别结果 - 工作进程常驻后台,循环从任务队列取数据执行慢识别函数,算完就把结果丢到结果队列
- 主循环每隔10帧往任务队列塞帧(非阻塞,队列满就直接丢旧任务,优先保证主循环流畅),每轮循环都非阻塞检查结果队列,有新结果就更新人名,没有就沿用旧值
完整示例代码
import multiprocessing as mp import time # 你的慢识别函数,这里用sleep模拟0.4秒耗时 def slow_function(image): time.sleep(0.4) return "识别出的人名" # 工作进程逻辑,常驻运行 def worker_process(task_queue, result_queue): while True: # 阻塞等任务,不占CPU image = task_queue.get() # 收到退出信号就结束进程 if image is None: break result = slow_function(image) result_queue.put(result) if __name__ == "__main__": # 初始化队列,设最大长度避免内存堆积,旧任务没处理直接丢就行,我们只要最新的帧结果 task_queue = mp.Queue(maxsize=2) result_queue = mp.Queue(maxsize=2) # 启动工作进程 worker = mp.Process(target=worker_process, args=(task_queue, result_queue), daemon=True) worker.start() person_name = "unknown" frame_index = -1 try: while True: frame_index += 1 # 模拟获取新帧,这里可以替换成你的读视频逻辑 frame = f"frame_{frame_index}" time.sleep(1/30) # 模拟30FPS的帧间隔 # 每10帧提交一次识别任务,非阻塞提交,队列满就跳过,不卡主循环 if frame_index % 10 == 0: if not task_queue.full(): task_queue.put(frame, block=False) # 非阻塞取结果,有新结果就更新人名,没有就用旧的 if not result_queue.empty(): person_name = result_queue.get(block=False) # 渲染逻辑,这里替换成你的画框写字逻辑 print(f"帧{frame_index},显示人名:{person_name}") finally: # 退出时给工作进程发结束信号 task_queue.put(None, block=False) worker.join()
关键优化点
- 工作进程是常驻的,避免了每次调用识别函数都要重新启动进程的开销
- 所有队列操作都是非阻塞的,主循环不会等待任何计算结果,完全保证30FPS的帧率稳定性
- 队列设了最大长度,就算识别速度跟不上提交速度,也只会丢弃旧的待处理任务,优先处理最新的帧,不会出现内存堆积
- 适配多脸场景只需要修改队列传递的数据结构,把帧、人脸ID、人脸框一起打包传递,结果也带上对应ID即可更新多个人名
内容的提问来源于stack exchange,提问作者Jechos
相关产品推荐
相关产品推荐

