- 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>
187 lines
7.4 KiB
Python
187 lines
7.4 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Quick test script for YOLOv5 pipeline deployment using fixed configuration
|
|
"""
|
|
import sys
|
|
import os
|
|
|
|
# Add paths
|
|
sys.path.append(os.path.join(os.path.dirname(__file__), 'ui', 'dialogs'))
|
|
sys.path.append(os.path.join(os.path.dirname(__file__), 'core', 'functions'))
|
|
|
|
def test_mflow_loading():
|
|
"""Test loading and parsing the fixed .mflow file"""
|
|
import json
|
|
|
|
mflow_files = [
|
|
'multi_series_example.mflow',
|
|
'multi_series_yolov5_fixed.mflow',
|
|
'test.mflow'
|
|
]
|
|
|
|
print("=" * 60)
|
|
print("Testing .mflow Configuration Loading")
|
|
print("=" * 60)
|
|
|
|
for mflow_file in mflow_files:
|
|
if os.path.exists(mflow_file):
|
|
print(f"\n📄 Loading {mflow_file}:")
|
|
try:
|
|
with open(mflow_file, 'r') as f:
|
|
data = json.load(f)
|
|
|
|
# Check for postprocess nodes
|
|
postprocess_nodes = [
|
|
node for node in data.get('nodes', [])
|
|
if node.get('type') == 'ExactPostprocessNode'
|
|
]
|
|
|
|
if postprocess_nodes:
|
|
for node in postprocess_nodes:
|
|
props = node.get('properties', {})
|
|
postprocess_type = props.get('postprocess_type', 'NOT SET')
|
|
confidence_threshold = props.get('confidence_threshold', 'NOT SET')
|
|
class_names = props.get('class_names', 'NOT SET')
|
|
|
|
print(f" ✓ Found PostprocessNode: {node.get('name', 'Unnamed')}")
|
|
print(f" - Type: {postprocess_type}")
|
|
print(f" - Threshold: {confidence_threshold}")
|
|
print(f" - Classes: {len(class_names.split(',')) if isinstance(class_names, str) else 'N/A'} classes")
|
|
|
|
if postprocess_type == 'yolo_v5':
|
|
print(f" ✅ Correctly configured for YOLOv5")
|
|
else:
|
|
print(f" ❌ Still using: {postprocess_type}")
|
|
else:
|
|
print(f" ⚠ No ExactPostprocessNode found")
|
|
|
|
except Exception as e:
|
|
print(f" ❌ Error loading file: {e}")
|
|
else:
|
|
print(f"\n📄 {mflow_file}: File not found")
|
|
|
|
def test_deployment_direct():
|
|
"""Test deployment using the deployment dialog directly"""
|
|
try:
|
|
from deployment import DeploymentDialog
|
|
from PyQt5.QtWidgets import QApplication
|
|
|
|
print(f"\n" + "=" * 60)
|
|
print("Testing Direct Pipeline Deployment")
|
|
print("=" * 60)
|
|
|
|
# Load the fixed configuration
|
|
import json
|
|
config_file = 'multi_series_yolov5_fixed.mflow'
|
|
|
|
if not os.path.exists(config_file):
|
|
print(f"❌ Configuration file not found: {config_file}")
|
|
return
|
|
|
|
with open(config_file, 'r') as f:
|
|
pipeline_data = json.load(f)
|
|
|
|
print(f"✓ Loaded configuration: {pipeline_data.get('project_name', 'Unknown')}")
|
|
print(f"✓ Found {len(pipeline_data.get('nodes', []))} nodes")
|
|
|
|
# Create minimal Qt app for testing
|
|
app = QApplication.instance()
|
|
if app is None:
|
|
app = QApplication(sys.argv)
|
|
|
|
# Create deployment dialog
|
|
dialog = DeploymentDialog(pipeline_data)
|
|
print(f"✓ Created deployment dialog")
|
|
|
|
# Test analysis
|
|
print(f"🔍 Testing pipeline analysis...")
|
|
|
|
try:
|
|
from core.functions.mflow_converter import MFlowConverter
|
|
converter = MFlowConverter()
|
|
config = converter._convert_mflow_to_config(pipeline_data)
|
|
|
|
print(f"✓ Pipeline conversion successful")
|
|
print(f" - Pipeline name: {config.pipeline_name}")
|
|
print(f" - Total stages: {len(config.stage_configs)}")
|
|
|
|
# Check stage configurations
|
|
for i, stage_config in enumerate(config.stage_configs, 1):
|
|
print(f" Stage {i}: {stage_config.stage_id}")
|
|
if hasattr(stage_config, 'postprocessor_options') and stage_config.postprocessor_options:
|
|
print(f" - Postprocess type: {stage_config.postprocessor_options.postprocess_type.value}")
|
|
print(f" - Threshold: {stage_config.postprocessor_options.threshold}")
|
|
print(f" - Classes: {len(stage_config.postprocessor_options.class_names)}")
|
|
|
|
if stage_config.postprocessor_options.postprocess_type.value == 'yolo_v5':
|
|
print(f" ✅ YOLOv5 postprocessing configured correctly")
|
|
else:
|
|
print(f" ❌ Postprocessing type: {stage_config.postprocessor_options.postprocess_type.value}")
|
|
|
|
except Exception as e:
|
|
print(f"❌ Pipeline conversion failed: {e}")
|
|
import traceback
|
|
traceback.print_exc()
|
|
|
|
except ImportError as e:
|
|
print(f"❌ Cannot import deployment components: {e}")
|
|
print(f" This is expected if running outside the full application")
|
|
except Exception as e:
|
|
print(f"❌ Direct deployment test failed: {e}")
|
|
import traceback
|
|
traceback.print_exc()
|
|
|
|
def show_fix_summary():
|
|
"""Show summary of the fixes applied"""
|
|
print(f"\n" + "=" * 60)
|
|
print("FIX SUMMARY")
|
|
print("=" * 60)
|
|
|
|
print(f"\n🔧 Applied Fixes:")
|
|
print(f"1. ✅ Fixed dashboard.py postprocess property loading")
|
|
print(f" - Added missing 'postprocess_type' property")
|
|
print(f" - Added all missing postprocess properties")
|
|
print(f" - Location: ui/windows/dashboard.py:1203-1213")
|
|
|
|
print(f"\n2. ✅ Enhanced YOLOv5 postprocessing in Multidongle.py")
|
|
print(f" - Improved _process_yolo_generic method")
|
|
print(f" - Added proper NMS (Non-Maximum Suppression)")
|
|
print(f" - Enhanced live view display")
|
|
|
|
print(f"\n3. ✅ Updated .mflow configurations")
|
|
print(f" - multi_series_example.mflow: enable_postprocessing = true")
|
|
print(f" - multi_series_yolov5_fixed.mflow: Complete YOLOv5 setup")
|
|
print(f" - Added ExactPostprocessNode with yolo_v5 type")
|
|
|
|
print(f"\n🎯 Expected Results After Fix:")
|
|
print(f" - ❌ 'No Fire (Prob: -0.39)' → ✅ 'person detected (Conf: 0.85)'")
|
|
print(f" - ❌ Negative probabilities → ✅ Positive probabilities (0.0-1.0)")
|
|
print(f" - ❌ No bounding boxes → ✅ Colorful bounding boxes with labels")
|
|
print(f" - ❌ Fire detection classes → ✅ COCO 80 classes (person, car, etc.)")
|
|
|
|
print(f"\n💡 Usage Instructions:")
|
|
print(f" 1. Run: python main.py")
|
|
print(f" 2. Login to the dashboard")
|
|
print(f" 3. Load: multi_series_yolov5_fixed.mflow")
|
|
print(f" 4. Deploy the pipeline")
|
|
print(f" 5. Check Live View tab for enhanced bounding boxes")
|
|
|
|
def main():
|
|
print("Quick YOLOv5 Deployment Test")
|
|
print("=" * 60)
|
|
|
|
# Test configuration loading
|
|
test_mflow_loading()
|
|
|
|
# Test direct deployment (if possible)
|
|
test_deployment_direct()
|
|
|
|
# Show fix summary
|
|
show_fix_summary()
|
|
|
|
print(f"\n🎉 Quick test completed!")
|
|
print(f" Now try running: python main.py")
|
|
print(f" And load: multi_series_yolov5_fixed.mflow")
|
|
|
|
if __name__ == "__main__":
|
|
main() |