cluster4npu/tests/test_postprocess_mode.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

212 lines
7.3 KiB
Python

#!/usr/bin/env python3
"""
Test script for postprocessing mode switching and visualization.
"""
import sys
import os
current_dir = os.path.dirname(os.path.abspath(__file__))
parent_dir = os.path.dirname(current_dir)
sys.path.append(parent_dir)
from core.nodes.exact_nodes import ExactPostprocessNode
def test_postprocess_node():
"""Test the ExactPostprocessNode for mode switching and configuration."""
print("=== Testing ExactPostprocessNode Mode Switching ===")
# Create node instance
try:
node = ExactPostprocessNode()
print("✓ ExactPostprocessNode created successfully")
# Check if NodeGraphQt is available
if not hasattr(node, 'set_property'):
print("⚠ NodeGraphQt not available - using mock properties")
return True # Skip tests that require NodeGraphQt
except Exception as e:
print(f"✗ Error creating node: {e}")
return False
# Test different postprocessing modes
test_modes = [
('fire_detection', 'No Fire,Fire'),
('yolo_v3', 'person,car,bicycle,motorbike,aeroplane'),
('yolo_v5', 'person,bicycle,car,motorbike,bus,truck'),
('classification', 'cat,dog,bird,fish'),
('raw_output', '')
]
print("\n--- Testing Mode Switching ---")
for mode, class_names in test_modes:
try:
# Set properties for this mode
node.set_property('postprocess_type', mode)
node.set_property('class_names', class_names)
node.set_property('confidence_threshold', 0.6)
node.set_property('nms_threshold', 0.4)
# Get configuration
config = node.get_postprocessing_config()
options = node.get_multidongle_postprocess_options()
print(f"✓ Mode: {mode}")
print(f" - Class names: {class_names}")
print(f" - Config: {config['postprocess_type']}")
if options:
print(f" - PostProcessor options created successfully")
else:
print(f" - Warning: PostProcessor options not available")
except Exception as e:
print(f"✗ Error testing mode {mode}: {e}")
return False
# Test validation
print("\n--- Testing Configuration Validation ---")
try:
# Valid configuration
node.set_property('postprocess_type', 'fire_detection')
node.set_property('confidence_threshold', 0.7)
node.set_property('nms_threshold', 0.3)
node.set_property('max_detections', 50)
is_valid, message = node.validate_configuration()
if is_valid:
print("✓ Valid configuration passed validation")
else:
print(f"✗ Valid configuration failed: {message}")
return False
# Invalid configuration
node.set_property('confidence_threshold', 1.5) # Invalid value
is_valid, message = node.validate_configuration()
if not is_valid:
print(f"✓ Invalid configuration caught: {message}")
else:
print("✗ Invalid configuration not caught")
return False
except Exception as e:
print(f"✗ Error testing validation: {e}")
return False
# Test display properties
print("\n--- Testing Display Properties ---")
try:
display_props = node.get_display_properties()
expected_props = ['postprocess_type', 'class_names', 'confidence_threshold']
for prop in expected_props:
if prop in display_props:
print(f"✓ Display property found: {prop}")
else:
print(f"✗ Missing display property: {prop}")
return False
except Exception as e:
print(f"✗ Error testing display properties: {e}")
return False
# Test business properties
print("\n--- Testing Business Properties ---")
try:
business_props = node.get_business_properties()
print(f"✓ Business properties retrieved: {len(business_props)} properties")
# Check key properties exist
key_props = ['postprocess_type', 'class_names', 'confidence_threshold', 'nms_threshold']
for prop in key_props:
if prop in business_props:
print(f"✓ Key property found: {prop} = {business_props[prop]}")
else:
print(f"✗ Missing key property: {prop}")
return False
except Exception as e:
print(f"✗ Error testing business properties: {e}")
return False
print("\n=== All Tests Passed! ===")
return True
def test_visualization_integration():
"""Test visualization integration with different modes."""
print("\n=== Testing Visualization Integration ===")
try:
node = ExactPostprocessNode()
# Test each mode for visualization compatibility
test_cases = [
{
'mode': 'fire_detection',
'classes': 'No Fire,Fire',
'expected_classes': 2,
'description': 'Binary fire detection'
},
{
'mode': 'yolo_v3',
'classes': 'person,car,bicycle,motorbike,bus',
'expected_classes': 5,
'description': 'Object detection'
},
{
'mode': 'classification',
'classes': 'cat,dog,bird,fish,rabbit',
'expected_classes': 5,
'description': 'Multi-class classification'
}
]
for case in test_cases:
print(f"\n--- {case['description']} ---")
# Configure node
node.set_property('postprocess_type', case['mode'])
node.set_property('class_names', case['classes'])
# Get configuration for visualization
config = node.get_postprocessing_config()
parsed_classes = config['class_names']
print(f"✓ Mode: {case['mode']}")
print(f"✓ Classes: {parsed_classes}")
print(f"✓ Expected {case['expected_classes']}, got {len(parsed_classes)}")
if len(parsed_classes) == case['expected_classes']:
print("✓ Class count matches expected")
else:
print(f"✗ Class count mismatch: expected {case['expected_classes']}, got {len(parsed_classes)}")
return False
print("\n✓ Visualization integration tests passed!")
return True
except Exception as e:
print(f"✗ Error in visualization integration test: {e}")
return False
if __name__ == "__main__":
print("Starting ExactPostprocessNode Tests...\n")
success = True
# Run main functionality tests
if not test_postprocess_node():
success = False
# Run visualization integration tests
if not test_visualization_integration():
success = False
if success:
print("\n🎉 All tests completed successfully!")
print("ExactPostprocessNode is ready for mode switching and visualization!")
else:
print("\n❌ Some tests failed. Please check the implementation.")
sys.exit(1)