Spaces:
Sleeping
A newer version of the Gradio SDK is available: 6.13.0
title: Image Mosaic Generator
emoji: π§©
colorFrom: blue
colorTo: green
sdk: gradio
sdk_version: 5.49.1
app_file: app.py
pinned: false
Optimized Image Mosaic Generator
A high-performance image mosaic generator that reconstructs input images as mosaics composed of small tiles using optimized vectorized operations. This project demonstrates significant performance improvements over the baseline implementation through algorithmic optimizations and vectorized NumPy operations.
Features
- Optimized Performance: Uses fully vectorized NumPy operations for fast mosaic generation
- Two Algorithms: Vectorized (fully optimized) and loop-based (optimized hybrid) methods
- Color Matching: Uses CIELAB color space for perceptually accurate color matching
- Flexible Configuration: Adjustable grid size, tile size, and color quantization
- Quality Metrics: Computes MSE and SSIM to evaluate mosaic quality
- Performance Metrics: Real-time processing time display in the web interface
- Input Validation: Comprehensive parameter validation with informative error messages
- Graceful Error Handling: Handles missing tiles and invalid inputs gracefully
- Web Interface: Easy-to-use Gradio web interface with performance tracking
Installation
Prerequisites
- Python 3.8 or higher
- pip package manager
Step-by-Step Installation
Clone or navigate to the project directory:
cd optimized-codeCreate a virtual environment (recommended):
python -m venv venv # On Windows: venv\Scripts\activate # On macOS/Linux: source venv/bin/activateInstall dependencies:
pip install -r requirements.txtVerify installation:
python -c "import gradio, numpy, PIL, skimage; print('All dependencies installed successfully!')"
Dependencies
The project requires the following packages (see requirements.txt):
gradio==5.49.1: Web interface frameworknumpy==2.1.2: Numerical operations and array processingpillow==10.4.0: Image processing and manipulationscikit-image==0.24.0: Color space conversion and similarity metricsscipy>=1.11.0: Optional KD-tree support for fast nearest neighbor search
Usage
Web Interface (Recommended)
Start the application:
python app.pyAccess the interface:
- The application will display a local URL (typically
http://127.0.0.1:7860) - Open this URL in your web browser
- The application will display a local URL (typically
Generate a mosaic:
- Upload an image or select from the provided examples
- Adjust parameters:
- Grid cells: Number of cells per side (8-96, default: 32)
- Tile size: Size of each tile in pixels (8-64, default: 24)
- Quantize to K colors: Color quantization (0-64, 0 = disabled)
- Algorithm: Choose between "vectorized" (fast) or "loop" (optimized hybrid)
- Click "Build Mosaic"
- View the result and performance metrics
Performance Metrics Display: The interface displays:
- Quality metrics: MSE (Mean Squared Error) and SSIM (Structural Similarity Index)
- Performance metrics: Total processing time, mosaic generation time, preprocessing time
- Image information: Final size, grid dimensions, tile size
Command Line Usage
from mosaic_generator import (
load_and_preprocess_image,
build_tile_set,
mosaic_fully_vectorized,
mosaic_loop_optimized,
compute_metrics,
DEFAULT_TILE_PATHS,
DEFAULT_TILE_SIZE,
)
from PIL import Image
# Load and preprocess image
img = Image.open("input.jpg")
preprocessed = load_and_preprocess_image(
img,
grid_cells=32,
quantize_colors=None # Optional: set to integer for color quantization
)
# Build tile set
tiles = build_tile_set(
DEFAULT_TILE_PATHS,
tile_size=24,
crops_per_image=4
)
# Generate mosaic (choose one method)
mosaic = mosaic_fully_vectorized(preprocessed, tiles, grid_cells=32)
# OR
mosaic = mosaic_loop_optimized(preprocessed, tiles, grid_cells=32)
# Compute quality metrics
mse, ssim = compute_metrics(preprocessed, mosaic)
print(f"MSE: {mse:.5f}, SSIM: {ssim:.4f}")
# Save the result
mosaic.save("output_mosaic.png")
Advanced Usage Examples
Custom Tile Set
from mosaic_generator import build_tile_set
# Use your own tile images
custom_tile_paths = [
"path/to/tile1.jpg",
"path/to/tile2.jpg",
"path/to/tile3.jpg",
]
tiles = build_tile_set(
custom_tile_paths,
tile_size=32,
crops_per_image=4
)
Batch Processing
from mosaic_generator import load_and_preprocess_image, build_tile_set, mosaic_fully_vectorized
from PIL import Image
import os
# Build tile set once
tiles = build_tile_set(DEFAULT_TILE_PATHS, tile_size=24)
# Process multiple images
input_dir = "input_images/"
output_dir = "output_mosaics/"
for filename in os.listdir(input_dir):
if filename.endswith(('.jpg', '.png', '.jpeg')):
img = Image.open(os.path.join(input_dir, filename))
preprocessed = load_and_preprocess_image(img, grid_cells=32)
mosaic = mosaic_fully_vectorized(preprocessed, tiles, grid_cells=32)
mosaic.save(os.path.join(output_dir, f"mosaic_{filename}"))
Project Structure
optimized-code/
βββ mosaic_generator/
β βββ __init__.py # Package initialization and exports
β βββ image_processor.py # Image loading, preprocessing, grid division
β βββ tile_manager.py # Tile loading, caching, feature extraction
β βββ mosaic_builder.py # Main mosaic construction logic
β βββ metrics.py # Similarity metrics (MSE, SSIM)
β βββ config.py # Configuration constants
β βββ utils.py # Helper functions and validation utilities
βββ app.py # Gradio web interface
βββ requirements.txt # Python dependencies
βββ README.md # This file
Module Documentation
mosaic_generator.config
Configuration constants including default tile size, grid cells, asset paths, and other default parameters.
mosaic_generator.utils
Helper functions and validation utilities:
generate_assets(): Creates sample images and sprites_save_skimage_samples(): Saves sample images from skimage_make_mario_like_sprite(): Creates a Mario-like pixel sprite_multi_crops(): Extracts multiple crops from an imagevalidate_grid_cells(): Validates grid size parametersvalidate_tile_size(): Validates tile size parametersvalidate_image_size(): Validates image dimensionsvalidate_tile_paths(): Validates and handles missing tile files
mosaic_generator.image_processor
Image loading and preprocessing:
load_and_preprocess_image(): Loads and preprocesses images (resize, quantization, crop)image_to_cells_mean_lab(): Converts image to grid cells and computes mean LAB colors (optimized with single LAB conversion)
mosaic_generator.tile_manager
Tile management and matching:
TileSet: Data structure holding tiles and precomputed LAB colorsbuild_tile_set(): Builds a tile set from image paths with error handlingTileSet.find_nearest_tile_vectorized(): Vectorized tile matching using broadcastingTileManager: Class for managing tile sets with caching
mosaic_generator.mosaic_builder
Core mosaic generation algorithms:
mosaic_fully_vectorized(): Fully optimized vectorized implementation (no loops)mosaic_loop_optimized(): Optimized loop-based implementation with vectorized matchingMosaicBuilder: Class-based interface for mosaic generation
mosaic_generator.metrics
Similarity metrics:
compute_metrics(): Computes MSE and SSIM between original and mosaic
Performance Benchmarks
Comparison with Lab 1 Baseline
Comprehensive performance analysis was conducted comparing the optimized implementation against the Lab 1 baseline. The benchmarks were run on multiple image sizes (256Γ256, 512Γ512, 1024Γ1024) and grid configurations (16Γ16, 32Γ32, 64Γ64).
Overall Performance Summary
| Method | Average Speedup | Original Time | Optimized Time |
|---|---|---|---|
| Vectorized | 1.06x | 0.0174s | 0.0168s |
| Loop | 4.81x | 0.1477s | 0.0291s |
Detailed Results by Grid Size
Vectorized Method:
- 16Γ16 grid: 1.03x speedup
- 32Γ32 grid: 1.05x speedup
- 64Γ64 grid: 1.10x speedup
Loop Method:
- 16Γ16 grid: 2.62x speedup
- 32Γ32 grid: 4.67x speedup
- 64Γ64 grid: 7.15x speedup
Key Findings
Vectorized Method: Already highly optimized in Lab 1, showing modest but consistent improvements (~6% faster)
Loop Method: Dramatic improvements (~4.8x average speedup) due to:
- Single LAB conversion for entire image (instead of per-cell)
- Vectorized distance calculations (eliminating inner loops)
- Precomputed tile features
Scalability: Performance improvements increase with grid size, with the loop method showing up to 8.9x speedup for 64Γ64 grids
Correctness: All optimizations maintain identical output quality (MSE difference: 0.000000)
Performance Visualization
Detailed performance charts and visualizations are available in the profiling_analysis.ipynb notebook located in the parent directory. The notebook includes:
- Runtime comparison charts by method and grid size
- Speedup factor visualizations showing improvements across different configurations
- Performance breakdown by operation type (preprocessing, tile matching, mosaic assembly)
- Detailed timing analysis for each optimization technique
- Visual comparisons of original vs optimized implementations
To view the performance analysis:
Navigate to the project root directory:
cd ..Open the notebook using Jupyter:
jupyter notebook profiling_analysis.ipynbOr if using JupyterLab:
jupyter lab profiling_analysis.ipynbThe notebook contains embedded visualizations showing:
- Bar charts comparing speedup factors for vectorized and loop methods
- Performance time comparisons across different grid sizes
- Detailed analysis of optimization impact
Note: All performance benchmarks were conducted on the same hardware to ensure fair comparison. Results may vary based on system specifications.
Optimizations Implemented
The optimized code includes several key performance improvements:
1. Single LAB Conversion
Impact: Eliminates redundant color space conversions
- Before: Converted each grid cell to LAB color space individually
- After: Converts entire image to LAB once, then extracts cell means
- Benefit: Reduces color space conversions from NΒ² to 1 (where N = grid cells per side)
2. Vectorized Operations
Impact: Leverages NumPy's optimized C implementations
- Before: Nested loops for distance calculations
- After: Broadcasting operations compute all distances simultaneously
- Benefit: Utilizes SIMD instructions and parallel processing
3. Advanced Indexing
Impact: Eliminates loops in tile placement
- Before: Loops through each grid cell to place tiles
- After: Advanced NumPy indexing places all tiles at once
- Benefit: Reduces Python loop overhead
4. Precomputed Features
Impact: Caches expensive computations
- Before: Computed tile mean LAB colors during matching
- After: Precomputed and stored in TileSet
- Benefit: Eliminates redundant calculations
5. KD-Tree Support
Impact: Faster nearest neighbor search for large tile sets
- Implementation: Automatic KD-tree construction if scipy is available
- Benefit: O(log n) search instead of O(n) for large tile sets
Input Validation
The implementation includes comprehensive input validation:
- Grid cells: Validates range (4-128), type, and positive values
- Tile size: Validates range (4-256px), type, and positive values
- Image dimensions: Validates minimum (32px) and maximum (4096px) dimensions
- Image-grid compatibility: Ensures image can be divided into grid cells without excessive cropping
- Tile paths: Validates file existence and image file validity
- Missing tiles: Gracefully handles missing tile files, continuing with available tiles
All validation errors provide informative messages explaining:
- What parameter is invalid
- What the valid range is
- Why the validation failed
- How to fix the issue
Error Handling
The application handles errors gracefully:
- Missing tiles: Warns about missing tiles but continues with available ones
- Invalid images: Provides clear error messages for corrupted or invalid image files
- Parameter errors: Validates all inputs before processing
- Processing errors: Catches and reports errors with helpful messages
Troubleshooting
Common Issues
Import errors: Ensure all dependencies are installed
pip install -r requirements.txtMissing assets: Assets are auto-generated on first run. If issues occur:
python -c "from mosaic_generator.utils import generate_assets; generate_assets()"Memory errors: Reduce grid size or tile size for very large images
Slow performance: Use the vectorized method for best performance
Acknowledgments
- Sample images from scikit-image data module
- Gradio framework for the web interface