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