""" 解析验证结果并生成对比报告 """ import re import json from pathlib import Path from datetime import datetime import numpy as np class ResultsParser: def __init__(self): self.results_dir = Path("vehicle_person_benchmark") self.results_dir.mkdir(exist_ok=True) def parse_file(self, filepath): """解析验证结果文件""" with open(filepath, 'r', encoding='utf-8', errors='replace') as f: content = f.read() results = {} # 提取速度信息 speed_match = re.search(r'(\d+\.\d+)ms preprocess.*?(\d+\.\d+)ms inference.*?(\d+\.\d+)ms postprocess', content) if speed_match: results['preprocess_ms'] = float(speed_match.group(1)) results['inference_ms'] = float(speed_match.group(2)) results['postprocess_ms'] = float(speed_match.group(3)) # 提取整体AP ap5095_match = re.search(r'Average Precision.*?IoU=0\.50:0\.95.*?=\s*([\d.]+)', content) if ap5095_match: results['mAP50_95'] = float(ap5095_match.group(1)) ap50_match = re.search(r'Average Precision.*?IoU=0\.50\s.*?=\s*([\d.]+)', content) if ap50_match: results['mAP50'] = float(ap50_match.group(1)) # 提取Person和Vehicle类别 results['person'] = self._parse_category(content, 'person') results['car'] = self._parse_category(content, 'car') results['bicycle'] = self._parse_category(content, 'bicycle') results['motorcycle'] = self._parse_category(content, 'motorcycle') results['bus'] = self._parse_category(content, 'bus') results['truck'] = self._parse_category(content, 'truck') # 计算所有车辆的平均值 vehicle_keys = ['bicycle', 'car', 'motorcycle', 'bus', 'truck'] results['all_vehicles'] = { 'ap50_95': np.mean([results[k].get('ap50_95', 0) for k in vehicle_keys]), 'ap50': np.mean([results[k].get('ap50', 0) for k in vehicle_keys]), 'P': np.mean([results[k].get('P', 0) for k in vehicle_keys]), 'R': np.mean([results[k].get('R', 0) for k in vehicle_keys]) } return results def _parse_category(self, content, category): """解析特定类别的指标""" lines = content.split('\n') metrics = {} for i, line in enumerate(lines): if category in line.lower() and 'Class' not in line and '----' not in line: parts = line.split() if len(parts) >= 6: try: metrics['P'] = float(parts[2]) if parts[2] != '0' else 0.0 metrics['R'] = float(parts[3]) if parts[3] != '0' else 0.0 metrics['ap50'] = float(parts[4]) if parts[4] != '0' else 0.0 metrics['ap50_95'] = float(parts[5]) if parts[5] != '0' else 0.0 except: pass break return metrics def generate_report(self): """生成完整报告""" all_results = { 'FP32_PyTorch': self.parse_file('fp32_results.txt'), 'INT8_640p': self.parse_file('int8_640_results.txt'), 'FP16_640p': self.parse_file('fp16_640_results.txt'), 'FP16_480p': self.parse_file('fp16_480_results.txt') } report = [] report.append("="*70) report.append("YOLO11n 人和车辆检测性能对比分析报告") report.append("="*70) report.append(f"生成时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}") report.append("") # 1. 整体性能对比 report.append("-"*70) report.append("一、整体性能对比") report.append("-"*70) report.append(f"{'配置':<15} {'mAP50-95':<12} {'mAP50':<12} {'推理(ms)':<12} {'FPS':<10}") report.append("-"*70) for name, data in all_results.items(): map50_95 = data.get('mAP50_95', 0) map50 = data.get('mAP50', 0) inf_ms = data.get('inference_ms', 0) fps = round(1000/inf_ms, 1) if inf_ms > 0 else 0 report.append(f"{name:<15} {map50_95:<12.4f} {map50:<12.4f} {inf_ms:<12.1f} {fps:<10.1f}") report.append("") # 2. Person类别 report.append("-"*70) report.append("二、Person (人) 类别检测性能") report.append("-"*70) report.append(f"{'配置':<15} {'P':<10} {'R':<10} {'AP50':<12} {'AP50-95':<12}") report.append("-"*70) for name, data in all_results.items(): person = data.get('person', {}) p = person.get('P', 0) r = person.get('R', 0) ap50 = person.get('ap50', 0) ap50_95 = person.get('ap50_95', 0) report.append(f"{name:<15} {p:<10.3f} {r:<10.3f} {ap50:<12.4f} {ap50_95:<12.4f}") report.append("") # 3. Vehicle类别 report.append("-"*70) report.append("三、Vehicles (车辆) 类别检测性能") report.append("-"*70) report.append(f"{'配置':<15} {'P':<10} {'R':<10} {'AP50':<12} {'AP50-95':<12}") report.append("-"*70) for name, data in all_results.items(): vehicles = data.get('all_vehicles', {}) p = vehicles.get('P', 0) r = vehicles.get('R', 0) ap50 = vehicles.get('ap50', 0) ap50_95 = vehicles.get('ap50_95', 0) report.append(f"{name:<15} {p:<10.3f} {r:<10.3f} {ap50:<12.4f} {ap50_95:<12.4f}") report.append("") # 4. 速度对比 report.append("-"*70) report.append("四、推理速度对比") report.append("-"*70) speeds = [(name, data.get('inference_ms', 0)) for name, data in all_results.items() if data.get('inference_ms', 0) > 0] speeds.sort(key=lambda x: x[1]) for i, (name, ms) in enumerate(speeds, 1): fps = 1000/ms if ms > 0 else 0 report.append(f" {i}. {name}: {ms:.2f}ms ({fps:.1f} FPS)") report.append("") # 5. 计算掉点 report.append("-"*70) report.append("五、精度掉点分析 (相对于FP32)") report.append("-"*70) fp32_map = all_results.get('FP32_PyTorch', {}).get('mAP50_95', 0) for name, data in all_results.items(): if name == 'FP32_PyTorch' or data.get('mAP50_95', 0) == 0: continue if fp32_map > 0: drop = (fp32_map - data['mAP50_95']) / fp32_map * 100 report.append(f" {name}: mAP50-95 掉点 {drop:.2f}%") report.append("") # 6. 结论 report.append("="*70) report.append("六、结论与建议") report.append("="*70) report.append("") report.append("1. 精度最优: 选择 FP16_640p 或 INT8_640p") report.append("2. 速度最快: 选择 FP16_480p") report.append("3. 性价比: 推荐 FP16_640p (平衡精度和速度)") report.append("4. INT8量化在人和车辆检测上表现良好") report.append("") # 保存报告 report_text = '\n'.join(report) report_file = self.results_dir / "final_report.txt" with open(report_file, 'w', encoding='utf-8') as f: f.write(report_text) print(report_text) print(f"\n报告已保存: {report_file}") # 保存JSON数据 with open(self.results_dir / "all_results.json", 'w', encoding='utf-8') as f: json.dump(all_results, f, indent=2, ensure_ascii=False) if __name__ == "__main__": parser = ResultsParser() parser.generate_report()