Browse Source
- Move debug scripts to tools/debug_scripts/ directory with README - Create requirements.txt for Python debug environment setup - Remove excessive debug logging from ScreenCaptureService - Disable verbose detection logging in YOLOOnnxDetector - Update .gitignore to exclude debug artifacts - Preserve core BGR/RGB fix while cleaning up temporary code 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>feature/debug-shiny-pokeball-detection
9 changed files with 209 additions and 121 deletions
@ -0,0 +1,51 @@ |
|||
# Debug Scripts for YOLO ONNX Detection |
|||
|
|||
This directory contains debugging tools for troubleshooting YOLO object detection issues. |
|||
|
|||
## Setup |
|||
|
|||
1. Create a Python virtual environment: |
|||
```bash |
|||
python -m venv debug_env |
|||
source debug_env/bin/activate # On Windows: debug_env\Scripts\activate |
|||
``` |
|||
|
|||
2. Install dependencies: |
|||
```bash |
|||
pip install -r requirements.txt |
|||
``` |
|||
|
|||
## Scripts |
|||
|
|||
### `debug_model_comparison.py` |
|||
Compares .pt model predictions with ONNX model outputs on the same static test image. |
|||
- Tests both PyTorch and ONNX models side-by-side |
|||
- Provides detailed debug output including preprocessing steps |
|||
- Useful for identifying model export issues |
|||
|
|||
### `test_static_onnx.py` |
|||
Tests ONNX model against static images to isolate Android capture issues. |
|||
- Bypasses Android screen capture pipeline |
|||
- Tests multiple ONNX model variants |
|||
- Good for validating model functionality |
|||
|
|||
### `export_model_variants.py` |
|||
Exports YOLO model variants with different NMS settings. |
|||
- Creates models with different confidence/IoU thresholds |
|||
- Useful for debugging detection sensitivity issues |
|||
|
|||
### `inspect_onnx_model.py` |
|||
Inspects ONNX model structure and metadata. |
|||
- Verifies class mappings and model architecture |
|||
- Helpful for debugging model export problems |
|||
|
|||
## Usage |
|||
|
|||
Place test images in `../../test_images/` and ensure model files are in `../../raw_models/`. |
|||
|
|||
Example: |
|||
```bash |
|||
cd tools/debug_scripts |
|||
source debug_env/bin/activate |
|||
python debug_model_comparison.py |
|||
``` |
|||
@ -0,0 +1,78 @@ |
|||
#!/usr/bin/env python3 |
|||
""" |
|||
Export YOLO model variants with different NMS settings for shiny icon debugging |
|||
""" |
|||
|
|||
from ultralytics import YOLO |
|||
import os |
|||
|
|||
def export_model_variants(): |
|||
model_path = "./raw_models/best.pt" |
|||
output_dir = "./raw_models/exports" |
|||
|
|||
# Create output directory |
|||
os.makedirs(output_dir, exist_ok=True) |
|||
|
|||
print(f"Loading model from: {model_path}") |
|||
model = YOLO(model_path) |
|||
|
|||
# Export configurations to test |
|||
configs = [ |
|||
{ |
|||
"name": "no_nms", |
|||
"nms": False, |
|||
"simplify": True, |
|||
"description": "Raw model output without NMS - for debugging shiny detection" |
|||
}, |
|||
{ |
|||
"name": "nms_relaxed", |
|||
"nms": True, |
|||
"max_det": 500, # Increase from default 300 |
|||
"conf": 0.1, # Lower confidence threshold |
|||
"simplify": True, |
|||
"description": "NMS with more detections and lower confidence" |
|||
}, |
|||
{ |
|||
"name": "nms_very_relaxed", |
|||
"nms": True, |
|||
"max_det": 1000, # Even more detections |
|||
"conf": 0.05, # Very low confidence |
|||
"simplify": True, |
|||
"description": "NMS with maximum detections for rare classes" |
|||
} |
|||
] |
|||
|
|||
for config in configs: |
|||
try: |
|||
print(f"\n🚀 Exporting {config['name']}: {config['description']}") |
|||
|
|||
# Extract export parameters |
|||
export_params = {k: v for k, v in config.items() |
|||
if k not in ['name', 'description']} |
|||
|
|||
# Export model |
|||
exported_path = model.export( |
|||
format='onnx', |
|||
**export_params |
|||
) |
|||
|
|||
# Move to organized location |
|||
output_file = os.path.join(output_dir, f"best_{config['name']}.onnx") |
|||
if os.path.exists(exported_path): |
|||
os.rename(exported_path, output_file) |
|||
print(f"✅ Exported: {output_file}") |
|||
else: |
|||
print(f"❌ Export failed for {config['name']}") |
|||
|
|||
except Exception as e: |
|||
print(f"❌ Error exporting {config['name']}: {e}") |
|||
|
|||
print(f"\n📁 All exports saved to: {output_dir}") |
|||
print("\n📋 Summary:") |
|||
print("- best_no_nms.onnx: Raw 8400x99 output for debugging") |
|||
print("- best_nms_relaxed.onnx: NMS with 500 max detections") |
|||
print("- best_nms_very_relaxed.onnx: NMS with 1000 max detections") |
|||
print("\nNext: Copy desired model to app/src/main/assets/ as best.onnx") |
|||
|
|||
if __name__ == "__main__": |
|||
export_model_variants() |
|||
@ -0,0 +1,61 @@ |
|||
#!/usr/bin/env python3 |
|||
""" |
|||
Inspect ONNX model structure to verify class mappings |
|||
""" |
|||
|
|||
import onnx |
|||
import numpy as np |
|||
|
|||
def inspect_onnx_model(model_path): |
|||
print(f"Inspecting ONNX model: {model_path}") |
|||
|
|||
try: |
|||
# Load the model |
|||
model = onnx.load(model_path) |
|||
|
|||
print(f"\n📋 Model Info:") |
|||
print(f"IR Version: {model.ir_version}") |
|||
print(f"Producer: {model.producer_name} {model.producer_version}") |
|||
|
|||
# Check inputs |
|||
print(f"\n📥 Inputs:") |
|||
for input_info in model.graph.input: |
|||
print(f" {input_info.name}: {[d.dim_value for d in input_info.type.tensor_type.shape.dim]}") |
|||
|
|||
# Check outputs |
|||
print(f"\n📤 Outputs:") |
|||
for output_info in model.graph.output: |
|||
shape = [d.dim_value for d in output_info.type.tensor_type.shape.dim] |
|||
print(f" {output_info.name}: {shape}") |
|||
|
|||
# For NMS models, try to interpret the output format |
|||
if len(shape) == 3 and shape[2] == 6: |
|||
print(f" → NMS format: [batch, {shape[1]} detections, 6 values (x,y,w,h,conf,class)]") |
|||
elif len(shape) == 3 and shape[1] > 90: |
|||
print(f" → Raw format: [batch, {shape[1]} channels, {shape[2]} anchors]") |
|||
print(f" → Channels: 4 coords + {shape[1]-4} classes") |
|||
|
|||
# Check for any metadata about classes |
|||
print(f"\n🏷️ Metadata:") |
|||
for prop in model.metadata_props: |
|||
print(f" {prop.key}: {prop.value}") |
|||
|
|||
print(f"\n🔍 Model Summary: {len(model.graph.node)} nodes, {len(model.graph.initializer)} initializers") |
|||
|
|||
except Exception as e: |
|||
print(f"❌ Error inspecting model: {e}") |
|||
|
|||
if __name__ == "__main__": |
|||
models_to_check = [ |
|||
"app/src/main/assets/best.onnx", |
|||
"raw_models/exports/best_no_nms.onnx", |
|||
"raw_models/exports/best_nms_relaxed.onnx", |
|||
"raw_models/exports/best_nms_very_relaxed.onnx" |
|||
] |
|||
|
|||
for model_path in models_to_check: |
|||
try: |
|||
inspect_onnx_model(model_path) |
|||
print("\n" + "="*60 + "\n") |
|||
except FileNotFoundError: |
|||
print(f"⚠️ Model not found: {model_path}\n") |
|||
@ -0,0 +1,6 @@ |
|||
ultralytics>=8.0.0 |
|||
opencv-python>=4.5.0 |
|||
onnxruntime>=1.15.0 |
|||
onnx>=1.14.0 |
|||
numpy>=1.21.0 |
|||
Pillow>=8.0.0 |
|||
Loading…
Reference in new issue