Files
momentry_core/scripts/yolo_count_comparison.py
Warren e75c4d6f07 cleanup: remove dead code and duplicate docs
- Remove session-ses_2f27.md (161KB raw session log)
- Remove 49 ROOT_* duplicate files across REFERENCE/
- Remove 14 duplicate files between REFERENCE/ root and history/
- Remove asr_legacy.rs (dead code, replaced by asr.rs)
- Remove src/core/worker/ (duplicate JobWorker)
- Remove src/core/layers/ (empty directory)
- Remove 4 .bak files in src/
- Remove 7 dead private methods in worker/processor.rs
- Remove backup directory from git tracking
2026-05-04 01:31:21 +08:00

210 lines
6.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/opt/homebrew/bin/python3.11
"""
YOLO Detection Count Comparison
对比 YOLO processor 的检测物体数量和类别
"""
import json
from pathlib import Path
from collections import defaultdict
def load_yolo_results(filepath):
"""加载 YOLO 检测结果"""
if not filepath.exists():
print(f"❌ 文件不存在: {filepath}")
return None
with open(filepath) as f:
data = json.load(f)
results = {
'total_frames': 0,
'total_objects': 0,
'classes': defaultdict(int),
'confidence_avg': 0.0,
'frames_with_objects': 0,
'frames_empty': 0,
}
frames_data = data.get('frames', [])
if isinstance(frames_data, dict):
frames_list = list(frames_data.values())
elif isinstance(frames_data, list):
frames_list = frames_data
else:
return results
results['total_frames'] = len(frames_list)
total_confidence = 0.0
total_objects = 0
for frame in frames_list:
if isinstance(frame, dict):
detections = frame.get('detections', frame.get('objects', []))
if detections and len(detections) > 0:
results['frames_with_objects'] += 1
for det in detections:
if isinstance(det, dict):
total_objects += 1
class_name = det.get('class_name', det.get('name', det.get('class', 'unknown')))
results['classes'][class_name] += 1
confidence = det.get('confidence', det.get('score', 1.0))
if isinstance(confidence, (int, float)):
total_confidence += confidence
else:
results['frames_empty'] += 1
results['total_objects'] = total_objects
if total_objects > 0:
results['confidence_avg'] = total_confidence / total_objects
return results
def compare_classes(results_a, results_b, results_c):
"""对比检测类别"""
all_classes = set()
if results_a:
all_classes.update(results_a['classes'].keys())
if results_b:
all_classes.update(results_b['classes'].keys())
if results_c:
all_classes.update(results_c['classes'].keys())
comparison = []
for class_name in sorted(all_classes):
count_a = results_a['classes'].get(class_name, 0) if results_a else 0
count_b = results_b['classes'].get(class_name, 0) if results_b else 0
count_c = results_c['classes'].get(class_name, 0) if results_c else 0
if count_a != count_b or count_a != count_c or count_b != count_c:
comparison.append({
'class_name': class_name,
'cpu': count_a,
'mps': count_b,
'contract': count_c,
'max': max(count_a, count_b, count_c),
'min': min(count_a, count_b, count_c),
})
return comparison
def main():
benchmark_dir = Path('/Users/accusys/momentry_core_0.1/output/benchmark/yolo_processor')
print("=" * 80)
print("YOLO Detection Count Comparison")
print("=" * 80)
print()
# 加载三个版本的结果
results_a = load_yolo_results(benchmark_dir / 'scheme_A_yolo_processor.json')
results_b = load_yolo_results(benchmark_dir / 'scheme_B_yolo_processor_mps.json')
results_c = load_yolo_results(benchmark_dir / 'scheme_C_yolo_processor_contract_v1.json')
if not results_a and not results_b and not results_c:
print("❌ 没有可用的检测结果文件")
return
# 统计概览
print("【检测统计】")
print()
print("| 版本 | 总帧数 | 检测物体数 | 有物体帧 | 空帧 | 平均置信度 |")
print("|------|--------|-----------|---------|------|------------|")
for name, results in [('CPU', results_a), ('MPS', results_b), ('Contract', results_c)]:
if results:
print(f"| {name} | {results['total_frames']} | {results['total_objects']} | {results['frames_with_objects']} | {results['frames_empty']} | {results['confidence_avg']:.2f} |")
else:
print(f"| {name} | - | - | - | - | - |")
print()
# 类别统计
print("【检测类别统计】")
print()
if results_a and results_a['classes']:
print("CPU版本检测类别:")
print("| 类别 | 数量 |")
print("|------|------|")
for class_name, count in sorted(results_a['classes'].items(), key=lambda x: -x[1]):
print(f"| {class_name} | {count} |")
print(f"| **总计** | {sum(results_a['classes'].values())} |")
print()
# 类别对比
print("【类别数量对比】")
print()
comparison = compare_classes(results_a, results_b, results_c)
if comparison:
print(f"共有 {len(comparison)} 个类别检测数量不同")
print()
print("| 类别 | CPU | MPS | Contract | 最大差异 |")
print("|------|-----|-----|----------|---------|")
for item in comparison[:20]:
diff = item['max'] - item['min']
print(f"| {item['class_name']} | {item['cpu']} | {item['mps']} | {item['contract']} | {diff} |")
if len(comparison) > 20:
print("| ... | ... | ... | ... | ... |")
else:
print("所有类别检测数量一致")
print()
# 检测率分析
print("【检测率分析】")
print()
if results_a and results_a['total_objects'] > 0:
baseline = results_a['total_objects']
print(f"以CPU版本为基准{baseline}个物体):")
print()
print("| 版本 | 检测数 | 检测率 | 漏检数 |")
print("|------|--------|--------|--------|")
for name, results in [('CPU', results_a), ('MPS', results_b), ('Contract', results_c)]:
if results:
rate = results['total_objects'] / baseline * 100
missed = baseline - results['total_objects']
print(f"| {name} | {results['total_objects']} | {rate:.1f}% | {missed} |")
else:
print(f"| {name} | - | - | - |")
print()
print("=" * 80)
print("对比完成")
print("=" * 80)
# 保存结果
output = {
'cpu': results_a,
'mps': results_b,
'contract': results_c,
'comparison': comparison,
}
output_path = benchmark_dir / 'YOLO_COUNT_COMPARISON.json'
with open(output_path, 'w') as f:
json.dump(output, f, indent=2, ensure_ascii=False)
print(f"\n对比结果已保存: {output_path}")
if __name__ == '__main__':
main()