cluster4npu/tests/quick_fix_detection_issues.py
HuangMason320 ccd7cdd6b9 feat: Reorganize test scripts and improve YOLOv5 postprocessing
- Move test scripts to tests/ directory for better organization
- Add improved YOLOv5 postprocessing with reference implementation
- Update gitignore to exclude *.mflow files and include main.spec
- Add debug capabilities and coordinate scaling improvements
- Enhance multi-series support with proper validation
- Add AGENTS.md documentation and example utilities

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-11 19:23:59 +08:00

150 lines
4.8 KiB
Python

#!/usr/bin/env python3
"""
Quick fixes for detection result issues.
快速修復偵測結果問題的補丁程式。
"""
import sys
import os
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
def apply_quick_fixes():
"""應用快速修復到檢測結果"""
print("=== 快速修復偵測結果問題 ===")
print()
# 修復建議
fixes = [
{
"issue": "過多的偵測結果 (100+ 物件)",
"cause": "可能的原因:模型輸出格式不匹配、閾值太低、測試模式",
"solutions": [
"1. 提高信心閾值到 0.5-0.7",
"2. 添加檢測數量限制",
"3. 檢查是否在測試/調試模式",
"4. 驗證模型輸出格式"
]
},
{
"issue": "座標異常 (0,0 或負值)",
"cause": "可能的原因:座標轉換錯誤、輸出格式不匹配",
"solutions": [
"1. 檢查座標轉換邏輯",
"2. 驗證輸入圖片尺寸",
"3. 確認模型輸出格式",
"4. 添加座標有效性檢查"
]
},
{
"issue": "LiveView 卡頓",
"cause": "可能的原因:處理過多檢測結果導致渲染瓶頸",
"solutions": [
"1. 限制顯示的檢測數量",
"2. 降低 FPS 或跳幀顯示",
"3. 異步處理檢測結果",
"4. 優化渲染代碼"
]
}
]
for fix in fixes:
print(f"問題: {fix['issue']}")
print(f"原因: {fix['cause']}")
print("解決方案:")
for solution in fix['solutions']:
print(f" {solution}")
print()
# 立即可用的代碼修復
print("=== 立即可用的代碼修復 ===")
print()
print("1. 在 Multidongle.py 的 _process_yolo_generic 函數開頭添加:")
print("""
# 緊急修復:限制檢測數量
MAX_DETECTIONS = 50
if len(boxes) > MAX_DETECTIONS:
print(f"WARNING: Too many detections ({len(boxes)}), limiting to {MAX_DETECTIONS}")
boxes = sorted(boxes, key=lambda x: x.score, reverse=True)[:MAX_DETECTIONS]
""")
print("\n2. 在創建 BoundingBox 之前添加驗證:")
print("""
# 座標有效性檢查
if x1 < 0 or y1 < 0 or x1 >= x2 or y1 >= y2:
continue # 跳過無效的邊界框
if (x2 - x1) * (y2 - y1) < 4: # 最小面積
continue # 跳過太小的框
if best_score > 2.0: # 檢查異常分數
continue # 跳過異常分數
""")
print("\n3. 在 PostProcessorOptions 中設置更嚴格的參數:")
print("""
postprocess_options = PostProcessorOptions(
postprocess_type=PostProcessType.YOLO_V5,
threshold=0.6, # 提高閾值
class_names=["person", "bicycle", "car", "motorbike", "aeroplane"],
nms_threshold=0.4,
max_detections_per_class=10 # 限制每類檢測數量
)
""")
print("\n4. 添加檢測結果統計和警告:")
print("""
# 在函數結尾添加
class_counts = {}
for box in boxes:
class_counts[box.class_name] = class_counts.get(box.class_name, 0) + 1
for class_name, count in class_counts.items():
if count > 20:
print(f"WARNING: Abnormally high count for {class_name}: {count}")
""")
def create_emergency_filter():
"""創建緊急過濾函數"""
filter_code = '''
def emergency_filter_detections(boxes, max_total=50, max_per_class=10):
"""緊急過濾檢測結果"""
if len(boxes) <= max_total:
return boxes
# 按類別分組
from collections import defaultdict
class_groups = defaultdict(list)
for box in boxes:
class_groups[box.class_name].append(box)
# 每類保留最高分數的檢測
filtered = []
for class_name, class_boxes in class_groups.items():
class_boxes.sort(key=lambda x: x.score, reverse=True)
keep_count = min(len(class_boxes), max_per_class)
filtered.extend(class_boxes[:keep_count])
# 總數限制
if len(filtered) > max_total:
filtered.sort(key=lambda x: x.score, reverse=True)
filtered = filtered[:max_total]
return filtered
'''
with open("emergency_filter.py", "w", encoding="utf-8") as f:
f.write(filter_code)
print("緊急過濾函數已保存到 emergency_filter.py")
if __name__ == "__main__":
apply_quick_fixes()
create_emergency_filter()
print("\n=== 下一步建議 ===")
print("1. 檢查當前的後處理配置")
print("2. 調整信心閾值和檢測限制")
print("3. 使用 debug_detection_issues.py 分析結果")
print("4. 考慮使用 improved_yolo_postprocessing.py 中的改進版本")
print("5. 如果問題持續,請檢查模型文件和配置")