| |
| """ |
| Create side-by-side comparison of best circle packing solutions. |
| """ |
|
|
| from pathlib import Path |
| from PIL import Image, ImageDraw, ImageFont |
| import sys |
|
|
| def create_comparison(with_path, without_path, output_path): |
| """Create side-by-side comparison with labels.""" |
| |
| |
| img_with = Image.open(with_path) |
| img_without = Image.open(without_path) |
| |
| |
| target_height = 800 |
| aspect_with = img_with.width / img_with.height |
| aspect_without = img_without.width / img_without.height |
| |
| img_with = img_with.resize((int(target_height * aspect_with), target_height), Image.LANCZOS) |
| img_without = img_without.resize((int(target_height * aspect_without), target_height), Image.LANCZOS) |
| |
| |
| padding = 40 |
| label_height = 80 |
| total_width = img_with.width + img_without.width + padding * 3 |
| total_height = target_height + label_height + padding * 2 |
| |
| |
| combined = Image.new('RGB', (total_width, total_height), 'white') |
| |
| |
| combined.paste(img_with, (padding, label_height + padding)) |
| combined.paste(img_without, (img_with.width + padding * 2, label_height + padding)) |
| |
| |
| draw = ImageDraw.Draw(combined) |
| |
| |
| try: |
| font_title = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", 28) |
| font_score = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf", 20) |
| except: |
| font_title = ImageFont.load_default() |
| font_score = ImageFont.load_default() |
| |
| |
| label_with = "WITH Vision" |
| label_without = "WITHOUT Vision" |
| score_with = "Score: 2.5786 (Gen 95)" |
| score_without = "Score: 2.5507 (Gen 97)" |
| |
| |
| with_center_x = padding + img_with.width // 2 |
| without_center_x = img_with.width + padding * 2 + img_without.width // 2 |
| |
| |
| def draw_label(text, x, y, font, color): |
| bbox = draw.textbbox((x, y), text, font=font, anchor="mm") |
| draw.rectangle(bbox, fill='white') |
| draw.text((x, y), text, fill=color, font=font, anchor="mm") |
| |
| |
| title = "Best Circle Packing Solutions Comparison" |
| title_x = total_width // 2 |
| try: |
| font_main = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", 36) |
| except: |
| font_main = font_title |
| draw_label(title, title_x, padding // 2 + 5, font_main, 'black') |
| |
| |
| draw_label(label_with, with_center_x, label_height // 2 + 5, font_title, '#2E86AB') |
| draw_label(score_with, with_center_x, label_height - 15, font_score, '#555555') |
| |
| |
| draw_label(label_without, without_center_x, label_height // 2 + 5, font_title, '#A23B72') |
| draw_label(score_without, without_center_x, label_height - 15, font_score, '#555555') |
| |
| |
| diff_text = "Difference: +1.1% (WITH Vision)" |
| draw_label(diff_text, total_width // 2, total_height - padding // 2, font_score, '#008800') |
| |
| |
| combined.save(output_path, quality=95) |
| print(f"β
Created comparison: {output_path}") |
|
|
| def main(): |
| base_dir = Path(__file__).parent.parent / "examples" / "circle_packing" |
| |
| with_path = base_dir / "results_circle_packing_WITH_vision_20260114_065819" / \ |
| "best" / "results" / "packing_viz.png" |
| |
| without_path = base_dir / "results_circle_packing_WITHOUT_vision_20260114_070110" / \ |
| "best" / "results" / "packing_viz.png" |
| |
| output_dir = Path(__file__).parent / "plots" |
| output_dir.mkdir(exist_ok=True) |
| output_path = output_dir / "best_solutions_comparison.png" |
| |
| if not with_path.exists(): |
| print(f"β WITH vision image not found: {with_path}") |
| return |
| |
| if not without_path.exists(): |
| print(f"β WITHOUT vision image not found: {without_path}") |
| return |
| |
| print("π¨ Creating side-by-side comparison...") |
| create_comparison(with_path, without_path, output_path) |
| print(f"π Output: {output_path}") |
|
|
| if __name__ == "__main__": |
| main() |
|
|