TensorFlow实时人体检测性能优化咨询(家庭多摄像头监控场景)
针对家庭监控多摄像头人体检测的性能优化方案
首先,先指出你代码里一个明显的操作不当:每次循环都重复调用get_tensor_by_name。这些张量在计算图中是固定存在的,完全不需要每次迭代都重新获取,把它们移到while循环外面,能省下不少不必要的CPU开销。
接下来,我从模型选型、硬件利用、代码细节、多线程实现这几个维度,给你具体的优化方案:
一、模型选型优化(最立竿见影)
你当前大概率选用了计算量偏大的模型(比如Faster RCNN系列),这类模型在CPU上运行效率极低。建议立刻替换为轻量级的SSD-MobileNet系列模型:
- SSD MobileNet v2 320x320:在保证人体检测精度的前提下,推理速度远快于重型模型
- SSD MobileNet V2 Lite:专为边缘设备优化,CPU/GPU环境下都有更出色的帧率表现
这些模型在TensorFlow Detection Model Zoo里都能找到对应的冻结推理图,直接替换即可。
二、充分利用GPU硬件加速
你有GTX960Ti,但从CPU高占用率来看,TensorFlow可能没用到GPU。请按以下步骤排查:
- 确认安装的是GPU版本的TensorFlow(不是仅支持CPU的版本)
- 在代码开头添加GPU检测代码,验证是否成功识别显卡:
import tensorflow as tf print(tf.config.list_physical_devices('GPU'))
如果输出为空,需要检查CUDA和cuDNN的版本是否与你的TensorFlow版本匹配(比如TF2.x通常对应CUDA11.x系列)。
另外,OpenCV读取IP摄像头时,启用硬件解码能大幅降低CPU占用:
# 替换原有的摄像头初始化代码 cap = cv2.VideoCapture("你的IP摄像头URL", cv2.CAP_FFMPEG) # 强制使用硬件解码器(适配NVIDIA显卡的nvdec) cap.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter_fourcc('H', '2', '6', '4'))
三、代码基础优化
除了把张量获取移到循环外,还有这些细节能提升性能:
- 缩小输入图像尺寸:将原始帧resize到模型要求的输入尺寸(比如320x320)再传入模型,能大幅降低计算量:
# 循环外提前定义目标尺寸 input_size = (320, 320) # 循环内预处理 frame_resized = cv2.resize(frame, input_size) frame_expanded = np.expand_dims(frame_resized, axis=0)
- 优化可视化环节:
vis_util.visualize_boxes_and_labels_on_image_array是CPU密集型操作,可做如下优化:- 只在检测到人体(class=1)且置信度超过阈值时才绘制框
- 降低字体大小、框的粗细等参数,减少渲染开销
- 减少循环阻塞:把
cv2.waitKey(25)改成cv2.waitKey(1),降低循环等待时间,提升帧率。
四、多线程实现方案(支持多摄像头)
多线程的核心是把摄像头帧抓取和模型推理解耦,避免单线程中等待帧读取或推理阻塞整个流程。这里给你一个基于threading和queue的实现框架:
1. 摄像头读取线程
每个摄像头启动独立线程,持续抓取帧并放入队列:
import threading import queue def camera_worker(cap, frame_queue, input_size): while True: ret, frame = cap.read() if not ret: break # 预处理后放入队列(原始帧用于显示,resize后用于推理) frame_resized = cv2.resize(frame, input_size) frame_queue.put((frame, frame_resized)) cv2.waitKey(1) # 控制抓取频率,避免队列积压
2. 推理线程
单独线程从队列取帧,执行模型推理和可视化:
def inference_worker(frame_queue, sess, input_tensor, output_tensors, category_index): boxes_tensor, scores_tensor, classes_tensor, num_detections_tensor = output_tensors while True: if not frame_queue.empty(): original_frame, resized_frame = frame_queue.get() frame_expanded = np.expand_dims(resized_frame, axis=0) # 执行推理 boxes, scores, classes, num_detections = sess.run( [boxes_tensor, scores_tensor, classes_tensor, num_detections_tensor], feed_dict={input_tensor: frame_expanded} ) # 只绘制人体检测结果(class=1) vis_util.visualize_boxes_and_labels_on_image_array( original_frame, np.squeeze(boxes), np.squeeze(classes).astype(np.int32), np.squeeze(scores), category_index, use_normalized_coordinates=True, line_thickness=2, min_score_thresh=0.5, category_filter={1} # 过滤非人体类别 ) cv2.imshow("Multi-Camera Feed", original_frame) if cv2.waitKey(1) & 0xFF == ord("q"): break frame_queue.task_done()
3. 主函数整合
if __name__ == "__main__": # 初始化模型和会话 with detection_graph.as_default(): with tf.Session(graph=detection_graph) as sess: # 提前获取所有张量(关键优化!) input_tensor = detection_graph.get_tensor_by_name("image_tensor:0") output_tensors = ( detection_graph.get_tensor_by_name("detection_boxes:0"), detection_graph.get_tensor_by_name("detection_scores:0"), detection_graph.get_tensor_by_name("detection_classes:0"), detection_graph.get_tensor_by_name("num_detections:0") ) input_size = (320, 320) category_index = {1: {'id': 1, 'name': 'person'}} # 仅关注人体 # 初始化摄像头和队列 cap1 = cv2.VideoCapture("摄像头1URL", cv2.CAP_FFMPEG) cap2 = cv2.VideoCapture("摄像头2URL", cv2.CAP_FFMPEG) frame_queue = queue.Queue(maxsize=10) # 限制队列大小,避免内存溢出 # 启动线程 cam_thread1 = threading.Thread(target=camera_worker, args=(cap1, frame_queue, input_size)) cam_thread2 = threading.Thread(target=camera_worker, args=(cap2, frame_queue, input_size)) inf_thread = threading.Thread(target=inference_worker, args=(frame_queue, sess, input_tensor, output_tensors, category_index)) # 设置为守护线程,主进程退出时自动结束 cam_thread1.daemon = True cam_thread2.daemon = True inf_thread.daemon = True cam_thread1.start() cam_thread2.start() inf_thread.start() # 等待线程结束 cam_thread1.join() cam_thread2.join() inf_thread.join() # 清理资源 cap1.release() cap2.release() cv2.destroyAllWindows()
额外建议
- 如果使用TensorFlow 2.x,建议迁移到SavedModel格式,用
tf.saved_model.load加载模型,并结合tf.function加速推理,性能会比TF1.x的Session模式更好。 - 可以尝试用TensorRT对模型进行优化,针对你的GTX960Ti生成专用推理引擎,进一步提升GPU推理速度。
内容的提问来源于stack exchange,提问作者simonEE




