#!/usr/bin/env python3 """ Final test to verify all fixes are working correctly """ import sys import os import json # Add paths current_dir = os.path.dirname(os.path.abspath(__file__)) parent_dir = os.path.dirname(current_dir) sys.path.append(os.path.join(parent_dir, 'core', 'functions')) def test_converter_with_postprocessing(): """Test the mflow converter with postprocessing fixes""" print("=" * 60) print("Testing MFlow Converter with Postprocessing Fixes") print("=" * 60) try: from mflow_converter import MFlowConverter # Test with the fixed mflow file mflow_file = 'multi_series_yolov5_fixed.mflow' if not os.path.exists(mflow_file): print(f"āŒ Test file not found: {mflow_file}") return False print(f"āœ“ Loading {mflow_file}...") converter = MFlowConverter() config = converter.load_and_convert(mflow_file) print(f"āœ“ Conversion successful!") print(f" - Pipeline name: {config.pipeline_name}") print(f" - Total stages: {len(config.stage_configs)}") # Check each stage for postprocessor for i, stage_config in enumerate(config.stage_configs, 1): print(f"\n Stage {i}: {stage_config.stage_id}") if stage_config.stage_postprocessor: options = stage_config.stage_postprocessor.options print(f" āœ… Postprocessor found!") print(f" Type: {options.postprocess_type.value}") print(f" Threshold: {options.threshold}") print(f" Classes: {len(options.class_names)} ({options.class_names[:3]}...)") print(f" NMS Threshold: {options.nms_threshold}") if options.postprocess_type.value == 'yolo_v5': print(f" šŸŽ‰ YOLOv5 postprocessing correctly configured!") else: print(f" ⚠ Postprocessing type: {options.postprocess_type.value}") else: print(f" āŒ No postprocessor found") return True except Exception as e: print(f"āŒ Converter test failed: {e}") import traceback traceback.print_exc() return False def test_multidongle_postprocessing(): """Test MultiDongle postprocessing directly""" print(f"\n" + "=" * 60) print("Testing MultiDongle Postprocessing") print("=" * 60) try: from Multidongle import MultiDongle, PostProcessorOptions, PostProcessType # Create YOLOv5 postprocessor options options = PostProcessorOptions( postprocess_type=PostProcessType.YOLO_V5, threshold=0.3, class_names=["person", "bicycle", "car", "motorbike", "aeroplane"], nms_threshold=0.5, max_detections_per_class=50 ) print(f"āœ“ Created PostProcessorOptions:") print(f" - Type: {options.postprocess_type.value}") print(f" - Threshold: {options.threshold}") print(f" - Classes: {len(options.class_names)}") # Test with dummy MultiDongle multidongle = MultiDongle( port_id=[1], # Dummy port postprocess_options=options ) print(f"āœ“ Created MultiDongle with postprocessing") print(f" - Postprocess type: {multidongle.postprocess_options.postprocess_type.value}") # Test set_postprocess_options method new_options = PostProcessorOptions( postprocess_type=PostProcessType.YOLO_V5, threshold=0.25, class_names=["person", "car", "truck"], nms_threshold=0.4 ) multidongle.set_postprocess_options(new_options) print(f"āœ“ Updated postprocess options:") print(f" - New threshold: {multidongle.postprocess_options.threshold}") print(f" - New classes: {len(multidongle.postprocess_options.class_names)}") return True except Exception as e: print(f"āŒ MultiDongle test failed: {e}") import traceback traceback.print_exc() return False def show_fix_summary(): """Show comprehensive fix summary""" print(f"\n" + "=" * 60) print("COMPREHENSIVE FIX SUMMARY") print("=" * 60) print(f"\nšŸ”§ Applied Fixes:") print(f"1. āœ… Fixed ui/windows/dashboard.py:") print(f" - Added missing 'postprocess_type' in fallback logic") print(f" - Added all postprocessing properties") print(f" - Lines: 1203-1213") print(f"\n2. āœ… Enhanced core/functions/Multidongle.py:") print(f" - Improved YOLOv5 postprocessing implementation") print(f" - Added proper NMS (Non-Maximum Suppression)") print(f" - Enhanced live view display with corner markers") print(f" - Better result string generation") print(f"\n3. āœ… Fixed core/functions/mflow_converter.py:") print(f" - Added connection mapping for postprocessing nodes") print(f" - Extract postprocessing config from ExactPostprocessNode") print(f" - Create PostProcessor instances for each stage") print(f" - Attach stage_postprocessor to StageConfig") print(f"\n4. āœ… Enhanced core/functions/InferencePipeline.py:") print(f" - Apply stage_postprocessor during initialization") print(f" - Set postprocessor options to MultiDongle") print(f" - Debug logging for postprocessor application") print(f"\n5. āœ… Updated .mflow configurations:") print(f" - multi_series_example.mflow: enable_postprocessing = true") print(f" - multi_series_yolov5_fixed.mflow: Complete YOLOv5 setup") print(f" - Proper node connections: Input → Model → Postprocess → Output") print(f"\nšŸŽÆ Expected Results:") print(f" āŒ 'No Fire (Prob: -0.39)' → āœ… 'person detected (Conf: 0.85)'") print(f" āŒ Negative probabilities → āœ… Positive probabilities (0.0-1.0)") print(f" āŒ Fire detection output → āœ… COCO object detection") print(f" āŒ No bounding boxes → āœ… Enhanced bounding boxes in live view") print(f" āŒ Simple terminal output → āœ… Detailed object statistics") print(f"\nšŸš€ How the Fix Works:") print(f" 1. UI loads .mflow file with yolo_v5 postprocess_type") print(f" 2. dashboard.py now includes postprocess_type in properties") print(f" 3. mflow_converter.py extracts postprocessing config") print(f" 4. Creates PostProcessor with YOLOv5 options") print(f" 5. InferencePipeline applies postprocessor to MultiDongle") print(f" 6. MultiDongle processes with correct YOLOv5 settings") print(f" 7. Enhanced live view shows proper object detection") def main(): print("Final Fix Verification Test") print("=" * 60) # Run tests converter_ok = test_converter_with_postprocessing() multidongle_ok = test_multidongle_postprocessing() # Show summary show_fix_summary() if converter_ok and multidongle_ok: print(f"\nšŸŽ‰ ALL TESTS PASSED!") print(f" The YOLOv5 postprocessing fix should now work correctly.") print(f" Run: python main.py") print(f" Load: multi_series_yolov5_fixed.mflow") print(f" Deploy and check for positive probabilities!") else: print(f"\nāŒ Some tests failed. Please check the output above.") if __name__ == "__main__": main()