240 lines
No EOL
8.4 KiB
Python
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()) |