File size: 7,831 Bytes
f647a80 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 | """
main.py - OPTIMIZED
Complete mosaic generator with Numba + parallel optimizations.
"""
import numpy as np
import cv2
from pathlib import Path
from typing import Tuple, Dict, Optional
import time
import matplotlib.pyplot as plt
from ImagePreprocessor import ImagePreprocessor
from contextual_Mosaic_Builder import ContextualMosaicGenerator, ImageContext
from Performance_metrics import PerformanceEvaluator
def create_advanced_mosaic(image_path: str,
tile_folder: str = "extracted_images",
grid_size: Tuple[int, int] = (64, 64),
tile_size: Tuple[int, int] = (32, 32),
diversity_factor: float = 0.15,
enable_rotation: bool = True,
enable_face_detection: bool = False,
colour_bins: int = 8,
apply_quantization: bool = False,
n_colors: int = 12,
use_numba: bool = True,
use_parallel: bool = True,
evaluate_quality: bool = False,
show_visualizations: bool = False,
verbose: bool = False) -> Tuple[np.ndarray, Optional[Dict], Optional[ImageContext]]:
"""
Create advanced mosaic - FULLY OPTIMIZED.
Args:
image_path: Path to input image
tile_folder: Path to tile images folder
grid_size: Grid dimensions (rows, cols)
tile_size: Individual tile size (width, height)
diversity_factor: Tile diversity factor (0.0-0.5)
enable_rotation: Whether to enable 4-way tile rotation
enable_face_detection: Whether to enable face detection
colour_bins: Number of color bins for subgrouping
apply_quantization: Whether to apply color quantization
n_colors: Number of colors for quantization
use_numba: Use Numba JIT compilation (recommended)
use_parallel: Use parallel processing (recommended)
evaluate_quality: Whether to calculate quality metrics
show_visualizations: Whether to display analysis
verbose: Enable detailed logging
Returns:
Tuple of (mosaic_image, quality_metrics, context_analysis)
"""
if verbose:
print(f"Advanced Mosaic Generator (Numba={'ON' if use_numba else 'OFF'}, Parallel={'ON' if use_parallel else 'OFF'})")
print(f"Image: {image_path}")
print(f"Grid: {grid_size[0]}x{grid_size[1]} = {np.prod(grid_size):,} tiles")
print(f"Tile size: {tile_size[0]}x{tile_size[1]}")
total_start = time.time()
# Initialize generator
cache_filename = f"cache_{tile_size[0]}x{tile_size[1]}_bins{colour_bins}{'_rot' if enable_rotation else ''}.pkl"
generator = ContextualMosaicGenerator(
cache_file=cache_filename,
tile_folder=tile_folder,
tile_size=tile_size,
colour_bins=colour_bins,
enable_rotation=enable_rotation,
enable_face_detection=enable_face_detection,
verbose=verbose,
use_numba=use_numba
)
# Preprocess image
target_width = grid_size[1] * tile_size[0]
target_height = grid_size[0] * tile_size[1]
preprocessor = ImagePreprocessor(
target_resolution=(target_width, target_height),
grid_size=grid_size,
verbose=verbose
)
processed_image = preprocessor.load_and_preprocess_image(
image_path,
apply_quantization=apply_quantization,
n_colors=n_colors
)
if processed_image is None:
raise ValueError("Failed to preprocess image")
# Analyze context (optional)
context = None
if enable_face_detection or show_visualizations:
context = generator.analyze_image_context(processed_image)
# Generate mosaic
mosaic, context = generator.create_contextual_mosaic(
processed_image,
grid_size,
diversity_factor,
context=context,
use_parallel=use_parallel
)
# Visualizations (optional)
if show_visualizations and context is not None:
generator.visualize_context_analysis(processed_image, context)
# Quality evaluation (optional)
metrics = None
if evaluate_quality:
evaluator = PerformanceEvaluator()
metrics = evaluator.evaluate_mosaic_quality(processed_image, mosaic, image_path)
if show_visualizations:
evaluator.visualize_quality_comparison(processed_image, mosaic, metrics)
total_time = time.time() - total_start
if verbose:
print(f"\n✅ Total time: {total_time:.2f}s")
if metrics:
print(f"Quality score: {metrics['overall_quality']:.1f}/100")
return mosaic, metrics, context
def create_mosaic_for_gradio(image_array: np.ndarray,
tile_folder: str = "extracted_images",
grid_size: int = 64,
tile_size: int = 32,
diversity_factor: float = 0.15,
enable_rotation: bool = True) -> Tuple[np.ndarray, str]:
"""Gradio-optimized mosaic creation."""
try:
grid_tuple = (grid_size, grid_size)
tile_tuple = (tile_size, tile_size)
temp_path = "temp_gradio_input.jpg"
cv2.imwrite(temp_path, cv2.cvtColor(image_array, cv2.COLOR_RGB2BGR))
mosaic, metrics, context = create_advanced_mosaic(
image_path=temp_path,
tile_folder=tile_folder,
grid_size=grid_tuple,
tile_size=tile_tuple,
diversity_factor=diversity_factor,
enable_rotation=enable_rotation,
enable_face_detection=False,
use_numba=True,
use_parallel=True,
evaluate_quality=True,
show_visualizations=False,
verbose=False
)
Path(temp_path).unlink(missing_ok=True)
status = f"""Mosaic Generated Successfully!
Configuration:
• Grid: {grid_size}×{grid_size} = {grid_size**2:,} tiles
• Tile size: {tile_size}×{tile_size} pixels
• Optimizations: Numba JIT + Parallel
• Quality score: {metrics['overall_quality']:.1f}/100"""
return mosaic, status
except Exception as e:
return None, f"Error: {str(e)}"
if __name__ == "__main__":
IMAGE_PATH = "Images/EmmaPotrait.jpg"
TILE_FOLDER = "extracted_images"
if not Path(TILE_FOLDER).exists():
print(f"Tile folder not found: {TILE_FOLDER}")
exit(1)
if not Path(IMAGE_PATH).exists():
print(f"Image not found: {IMAGE_PATH}")
exit(1)
print("Creating optimized mosaic (Numba + Parallel)...")
mosaic, metrics, context = create_advanced_mosaic(
image_path=IMAGE_PATH,
tile_folder=TILE_FOLDER,
grid_size=(64, 64),
tile_size=(64, 64),
diversity_factor=0.15,
enable_rotation=True,
enable_face_detection=False,
apply_quantization=False,
use_numba=True,
use_parallel=True,
evaluate_quality=True,
show_visualizations=False,
verbose=True
)
if mosaic is not None:
print("✅ Mosaic generation completed!")
if metrics:
print(f"Quality score: {metrics['overall_quality']:.1f}/100")
cv2.imwrite("output_mosaic.jpg", cv2.cvtColor(mosaic, cv2.COLOR_RGB2BGR))
print("Saved: output_mosaic.jpg") |