import cv2 import numpy as np import yaml import torch from ultralytics import YOLO import time import datetime import json import os def test_real_world_performance(model_path, config_path, framework_name, test_duration=30, max_cameras=5): """测试真实场景性能""" print(f"\n{'='*60}") print(f"测试框架: {framework_name}") print(f"{'='*60}") # 加载配置 with open(config_path, 'r', encoding='utf-8') as f: cfg = yaml.safe_load(f) # 加载模型 device = 'cuda' if torch.cuda.is_available() else 'cpu' print(f"🚀 加载模型: {model_path}") print(f" 设备: {device}") model = YOLO(model_path, task='detect') # TensorRT引擎不需要.to(),直接使用即可 model_cfg = cfg['model'] imgsz = model_cfg['imgsz'] conf_thresh = model_cfg['conf_threshold'] # 选择前N个摄像头 cameras = cfg['cameras'][:max_cameras] print(f"✅ 测试 {len(cameras)} 个摄像头") # 打开视频流 caps = [] cam_ids = [] for cam_cfg in cameras: cam_id = cam_cfg['id'] rtsp_url = cam_cfg['rtsp_url'] print(f"📹 连接摄像头 {cam_id}...") cap = cv2.VideoCapture(rtsp_url, cv2.CAP_FFMPEG) if cap.isOpened(): cap.set(cv2.CAP_PROP_BUFFERSIZE, 1) caps.append(cap) cam_ids.append(cam_id) print(f" ✅ {cam_id} 连接成功") else: print(f" ⚠️ {cam_id} 连接失败") if not caps: print("❌ 没有可用的摄像头") return None print(f"\n✅ 成功连接 {len(caps)} 个摄像头") print(f"⏳ 开始测试,时长: {test_duration}秒\n") # 性能统计 frame_count = 0 inference_times = [] start_time = time.time() last_print_time = start_time try: while (time.time() - start_time) < test_duration: for i, cap in enumerate(caps): ret, frame = cap.read() if not ret: continue # 推理 infer_start = time.time() results = model.predict( frame, imgsz=imgsz, conf=conf_thresh, verbose=False, device=0 if device == 'cuda' else 'cpu', half=(device == 'cuda'), classes=[0] ) infer_end = time.time() inference_times.append((infer_end - infer_start) * 1000) frame_count += 1 # 每5秒打印一次进度 current_time = time.time() if current_time - last_print_time >= 5.0: elapsed = current_time - start_time avg_fps = frame_count / elapsed avg_latency = np.mean(inference_times) if inference_times else 0 print(f"⏱️ {elapsed:.0f}s | 帧数: {frame_count} | FPS: {avg_fps:.1f} | 延迟: {avg_latency:.1f}ms") last_print_time = current_time except KeyboardInterrupt: print("\n⏹️ 测试被用户中断") finally: # 释放资源 for cap in caps: cap.release() # 计算统计 elapsed = time.time() - start_time avg_fps = frame_count / elapsed if elapsed > 0 else 0 stats = { 'framework': framework_name, 'total_frames': frame_count, 'elapsed_time': elapsed, 'avg_fps': avg_fps, 'avg_inference_time_ms': np.mean(inference_times) if inference_times else 0, 'p50_inference_time_ms': np.percentile(inference_times, 50) if inference_times else 0, 'p95_inference_time_ms': np.percentile(inference_times, 95) if inference_times else 0, 'p99_inference_time_ms': np.percentile(inference_times, 99) if inference_times else 0, 'num_cameras': len(caps) } print(f"\n{'='*60}") print(f"{framework_name} 测试完成") print(f"{'='*60}") print(f"总帧数: {stats['total_frames']}") print(f"测试时长: {stats['elapsed_time']:.1f}秒") print(f"平均FPS: {stats['avg_fps']:.1f}") print(f"平均推理延迟: {stats['avg_inference_time_ms']:.1f}ms") print(f"P95推理延迟: {stats['p95_inference_time_ms']:.1f}ms") print(f"P99推理延迟: {stats['p99_inference_time_ms']:.1f}ms") print(f"{'='*60}\n") return stats def main(): """主函数""" print("真实场景快速性能测试") print("=" * 60) config_path = "config.yaml" pytorch_model = "C:/Users/16337/PycharmProjects/Security/yolo11n.pt" tensorrt_model = "C:/Users/16337/PycharmProjects/Security/yolo11n.engine" # 检查文件 if not os.path.exists(config_path): print(f"❌ 配置文件不存在: {config_path}") return if not os.path.exists(pytorch_model): print(f"❌ PyTorch 模型不存在: {pytorch_model}") return if not os.path.exists(tensorrt_model): print(f"❌ TensorRT 引擎不存在: {tensorrt_model}") return # 检查 CUDA if not torch.cuda.is_available(): print("❌ CUDA 不可用") return print(f"✅ CUDA 可用,设备: {torch.cuda.get_device_name(0)}") # 测试配置 test_duration = 30 # 每个框架测试30秒 max_cameras = 5 # 只测试前5个摄像头 results = {} # 测试 PyTorch print(f"\n{'='*60}") print("测试 1/2: PyTorch 框架") print(f"{'='*60}") try: pytorch_stats = test_real_world_performance( pytorch_model, config_path, "PyTorch", test_duration=test_duration, max_cameras=max_cameras ) results['pytorch'] = pytorch_stats except Exception as e: print(f"❌ PyTorch 测试失败: {e}") import traceback traceback.print_exc() results['pytorch'] = None # 等待系统稳定 print("\n⏳ 等待系统稳定...") time.sleep(3) # 测试 TensorRT print(f"\n{'='*60}") print("测试 2/2: TensorRT 框架") print(f"{'='*60}") try: tensorrt_stats = test_real_world_performance( tensorrt_model, config_path, "TensorRT", test_duration=test_duration, max_cameras=max_cameras ) results['tensorrt'] = tensorrt_stats except Exception as e: print(f"❌ TensorRT 测试失败: {e}") import traceback traceback.print_exc() results['tensorrt'] = None # 生成对比报告 print(f"\n{'='*60}") print("性能对比报告") print(f"{'='*60}\n") if results['pytorch'] and results['tensorrt']: pt_stats = results['pytorch'] trt_stats = results['tensorrt'] print(f"指标 | PyTorch | TensorRT | 提升") print(f"{'-'*60}") print(f"平均FPS | {pt_stats['avg_fps']:12.1f} | {trt_stats['avg_fps']:12.1f} | {(trt_stats['avg_fps']/pt_stats['avg_fps']-1)*100:+.1f}%") print(f"平均推理延迟(ms) | {pt_stats['avg_inference_time_ms']:12.1f} | {trt_stats['avg_inference_time_ms']:12.1f} | {(1-trt_stats['avg_inference_time_ms']/pt_stats['avg_inference_time_ms'])*100:+.1f}%") print(f"P95推理延迟(ms) | {pt_stats['p95_inference_time_ms']:12.1f} | {trt_stats['p95_inference_time_ms']:12.1f} | {(1-trt_stats['p95_inference_time_ms']/pt_stats['p95_inference_time_ms'])*100:+.1f}%") print(f"P99推理延迟(ms) | {pt_stats['p99_inference_time_ms']:12.1f} | {trt_stats['p99_inference_time_ms']:12.1f} | {(1-trt_stats['p99_inference_time_ms']/pt_stats['p99_inference_time_ms'])*100:+.1f}%") print(f"总帧数 | {pt_stats['total_frames']:12d} | {trt_stats['total_frames']:12d} | {(trt_stats['total_frames']/pt_stats['total_frames']-1)*100:+.1f}%") print(f"摄像头数量 | {pt_stats['num_cameras']:12d} | {trt_stats['num_cameras']:12d} |") # 保存结果 output_dir = "real_world_results" os.makedirs(output_dir, exist_ok=True) results_data = { 'pytorch': pt_stats, 'tensorrt': trt_stats, 'timestamp': datetime.datetime.now().isoformat(), 'test_duration': test_duration, 'max_cameras': max_cameras } json_file = os.path.join(output_dir, f"real_world_quick_test_{datetime.datetime.now().strftime('%Y%m%d_%H%M%S')}.json") with open(json_file, 'w', encoding='utf-8') as f: json.dump(results_data, f, indent=2, ensure_ascii=False) print(f"\n✅ 结果已保存: {json_file}") # 生成文本报告 report = f""" 真实场景性能测试报告 {'='*60} 测试时间: {datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')} 测试时长: {test_duration}秒 摄像头数量: {max_cameras}个 详细对比数据: {'='*60} 指标 | PyTorch | TensorRT | 提升 {'-'*60} 平均FPS | {pt_stats['avg_fps']:12.1f} | {trt_stats['avg_fps']:12.1f} | {(trt_stats['avg_fps']/pt_stats['avg_fps']-1)*100:+.1f}% 平均推理延迟(ms) | {pt_stats['avg_inference_time_ms']:12.1f} | {trt_stats['avg_inference_time_ms']:12.1f} | {(1-trt_stats['avg_inference_time_ms']/pt_stats['avg_inference_time_ms'])*100:+.1f}% P50推理延迟(ms) | {pt_stats['p50_inference_time_ms']:12.1f} | {trt_stats['p50_inference_time_ms']:12.1f} | {(1-trt_stats['p50_inference_time_ms']/pt_stats['p50_inference_time_ms'])*100:+.1f}% P95推理延迟(ms) | {pt_stats['p95_inference_time_ms']:12.1f} | {trt_stats['p95_inference_time_ms']:12.1f} | {(1-trt_stats['p95_inference_time_ms']/pt_stats['p95_inference_time_ms'])*100:+.1f}% P99推理延迟(ms) | {pt_stats['p99_inference_time_ms']:12.1f} | {trt_stats['p99_inference_time_ms']:12.1f} | {(1-trt_stats['p99_inference_time_ms']/pt_stats['p99_inference_time_ms'])*100:+.1f}% 总帧数 | {pt_stats['total_frames']:12d} | {trt_stats['total_frames']:12d} | {(trt_stats['total_frames']/pt_stats['total_frames']-1)*100:+.1f}% 关键发现: {'='*60} ✅ TensorRT 在真实场景下平均FPS提升: {(trt_stats['avg_fps']/pt_stats['avg_fps']-1)*100:+.1f}% ✅ TensorRT 推理延迟降低: {(1-trt_stats['avg_inference_time_ms']/pt_stats['avg_inference_time_ms'])*100:+.1f}% ✅ TensorRT 在相同时间内处理更多帧: {(trt_stats['total_frames']/pt_stats['total_frames']-1)*100:+.1f}% 说明: {'='*60} 本测试接入真实RTSP视频流,包含完整的业务逻辑: - 视频流解码 - YOLO目标检测(person类) - ROI区域判断 - 离岗检测算法 - 周界入侵检测算法 测试结果反映了实际生产环境的性能表现。 """ report_file = os.path.join(output_dir, f"real_world_report_{datetime.datetime.now().strftime('%Y%m%d_%H%M%S')}.txt") with open(report_file, 'w', encoding='utf-8') as f: f.write(report) print(f"✅ 报告已保存: {report_file}") else: print("❌ 测试未完成,无法生成对比报告") print(f"\n🎉 测试完成!") if __name__ == "__main__": try: main() except KeyboardInterrupt: print("\n\n⏹️ 测试被用户中断") except Exception as e: print(f"\n❌ 测试过程中发生错误: {e}") import traceback traceback.print_exc()