master_adapt_detect/optimize_split_parameters.py
2025-10-01 14:32:55 -05:00

240 lines
No EOL
8.4 KiB
Python

#!/usr/bin/env python3
"""
Parameter Optimization Script for Advanced Panel Splitting
This script iteratively tests different percentile and min_gap parameters
to find the optimal settings that result in exactly 8 panels for layout 6791346.jpg.
"""
import os
import sys
import cv2
import numpy as np
from pathlib import Path
from PIL import Image
from advanced_splitter import AdvancedPanelSplitter
import itertools
def test_parameters(image_path: str, percentile: float, min_gap: int, target_panels: int = 8, verbose: bool = False) -> dict:
"""
Test a specific combination of parameters and return results
Args:
image_path: Path to the layout image
percentile: Percentile threshold for gutter detection
min_gap: Minimum gap size for gutter detection
target_panels: Target number of panels (default: 8)
verbose: Print detailed information
Returns:
Dict with test results
"""
try:
# Create splitter with test parameters
splitter = AdvancedPanelSplitter(percentile=percentile, min_gap=min_gap, debug=False)
# Load image
img = Image.open(image_path).convert("RGB")
img_gray = cv2.cvtColor(np.array(img), cv2.COLOR_RGB2GRAY)
# Find boundaries
boundaries = splitter.find_boundaries_auto(img_gray)
panel_count = len(boundaries) - 1 # Number of panels is boundaries - 1
if verbose:
print(f" Percentile: {percentile:5.1f}, Min Gap: {min_gap:2d}{panel_count:2d} panels (boundaries: {boundaries})")
return {
'percentile': percentile,
'min_gap': min_gap,
'panel_count': panel_count,
'boundaries': boundaries,
'exact_match': panel_count == target_panels,
'error': abs(panel_count - target_panels)
}
except Exception as e:
if verbose:
print(f" ERROR with percentile={percentile}, min_gap={min_gap}: {e}")
return {
'percentile': percentile,
'min_gap': min_gap,
'panel_count': 0,
'boundaries': [],
'exact_match': False,
'error': float('inf'),
'exception': str(e)
}
def optimize_parameters(image_path: str, target_panels: int = 8) -> dict:
"""
Optimize parameters to achieve the target number of panels
Args:
image_path: Path to the layout image
target_panels: Target number of panels
Returns:
Dict with optimization results
"""
if not os.path.exists(image_path):
raise FileNotFoundError(f"Image not found: {image_path}")
print(f"Optimizing parameters for {os.path.basename(image_path)}")
print(f"Target panel count: {target_panels}")
print("-" * 60)
# Define parameter ranges to test
percentile_range = list(range(1, 51)) # 1% to 50%
min_gap_range = list(range(1, 21)) # 1 to 20 pixels
# Store all results
all_results = []
exact_matches = []
print("Testing parameter combinations...")
total_combinations = len(percentile_range) * len(min_gap_range)
tested = 0
# Test all combinations
for percentile in percentile_range:
for min_gap in min_gap_range:
tested += 1
if tested % 50 == 0:
print(f" Progress: {tested}/{total_combinations} ({tested/total_combinations*100:.1f}%)")
result = test_parameters(image_path, percentile, min_gap, target_panels)
all_results.append(result)
if result['exact_match']:
exact_matches.append(result)
print(f"\nCompleted testing {total_combinations} parameter combinations")
print(f"Found {len(exact_matches)} exact matches for {target_panels} panels")
# Analysis
if exact_matches:
print("\n" + "="*60)
print("EXACT MATCHES FOUND!")
print("="*60)
print(f"\nAll parameter combinations that produce exactly {target_panels} panels:")
print("Percentile | Min Gap | Boundaries")
print("-" * 40)
for match in exact_matches:
boundaries_str = str(match['boundaries'])
if len(boundaries_str) > 40:
boundaries_str = boundaries_str[:37] + "..."
print(f"{match['percentile']:9.1f} | {match['min_gap']:7d} | {boundaries_str}")
# Find the "best" match (middle percentile value for stability)
exact_matches.sort(key=lambda x: x['percentile'])
middle_idx = len(exact_matches) // 2
best_match = exact_matches[middle_idx]
print(f"\nRECOMMENDED PARAMETERS:")
print(f" Percentile: {best_match['percentile']}")
print(f" Min Gap: {best_match['min_gap']}")
print(f" Result: {best_match['panel_count']} panels")
print(f" Boundaries: {best_match['boundaries']}")
return best_match
else:
print("\n" + "="*60)
print("NO EXACT MATCHES FOUND")
print("="*60)
# Find closest matches
all_results.sort(key=lambda x: x['error'])
closest_matches = [r for r in all_results[:10] if r['error'] == all_results[0]['error']]
print(f"\nClosest matches (error = {all_results[0]['error']}):")
print("Percentile | Min Gap | Panels | Error | Boundaries")
print("-" * 60)
for match in closest_matches:
boundaries_str = str(match['boundaries'])
if len(boundaries_str) > 30:
boundaries_str = boundaries_str[:27] + "..."
print(f"{match['percentile']:9.1f} | {match['min_gap']:7d} | {match['panel_count']:6d} | {match['error']:5.1f} | {boundaries_str}")
best_match = closest_matches[0]
print(f"\nBEST AVAILABLE PARAMETERS:")
print(f" Percentile: {best_match['percentile']}")
print(f" Min Gap: {best_match['min_gap']}")
print(f" Result: {best_match['panel_count']} panels (target: {target_panels})")
print(f" Boundaries: {best_match['boundaries']}")
return best_match
def test_optimized_parameters(image_path: str, percentile: float, min_gap: int):
"""
Test the optimized parameters and show detailed results
"""
print("\n" + "="*60)
print("TESTING OPTIMIZED PARAMETERS")
print("="*60)
# Create splitter with optimized parameters
splitter = AdvancedPanelSplitter(percentile=percentile, min_gap=min_gap, debug=True)
# Test the parameters
result = test_parameters(image_path, percentile, min_gap, target_panels=8, verbose=True)
# Also create the actual splits to verify
print(f"\nCreating actual splits with optimized parameters...")
splits = splitter.split_panels(image_path, target_panel_count=8)
print(f"Successfully created {len(splits)} splits:")
for i, split in enumerate(splits):
bounds = split['bounds']
print(f" Panel {i+1}: bounds=({bounds[0]}, {bounds[1]}, {bounds[2]}, {bounds[3]}), "
f"confidence={split['confidence']:.3f}, method={split['method']}")
return result
def main():
"""Main execution function"""
# Check if layout image exists
layout_path = "layouts/6791346.jpg"
if not os.path.exists(layout_path):
print(f"Error: Layout image not found at {layout_path}")
print("Please ensure the image exists in the layouts directory")
return 1
try:
# Run optimization
best_result = optimize_parameters(layout_path, target_panels=8)
# Test the optimized parameters
test_result = test_optimized_parameters(
layout_path,
best_result['percentile'],
best_result['min_gap']
)
print("\n" + "="*60)
print("FINAL RECOMMENDATION")
print("="*60)
print(f"For layout 6791346.jpg to achieve 8 panels:")
print(f" --percentile {best_result['percentile']}")
print(f" --min-gap {best_result['min_gap']}")
print(f"\nCommand line usage:")
print(f" python cli.py --test --hybrid --split-advanced --percentile {best_result['percentile']} --min-gap {best_result['min_gap']}")
return 0
except Exception as e:
print(f"Error during optimization: {e}")
return 1
if __name__ == "__main__":
exit(main())