Lohith Venkat Chamakura
update README
15d1392

A newer version of the Gradio SDK is available: 6.13.0

Upgrade
metadata
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

  1. Clone or navigate to the project directory:

    cd optimized-code
    
  2. Create a virtual environment (recommended):

    python -m venv venv
    
    # On Windows:
    venv\Scripts\activate
    
    # On macOS/Linux:
    source venv/bin/activate
    
  3. Install dependencies:

    pip install -r requirements.txt
    
  4. Verify 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 framework
  • numpy==2.1.2: Numerical operations and array processing
  • pillow==10.4.0: Image processing and manipulation
  • scikit-image==0.24.0: Color space conversion and similarity metrics
  • scipy>=1.11.0: Optional KD-tree support for fast nearest neighbor search

Usage

Web Interface (Recommended)

  1. Start the application:

    python app.py
    
  2. Access the interface:

    • The application will display a local URL (typically http://127.0.0.1:7860)
    • Open this URL in your web browser
  3. 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
  4. 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 image
  • validate_grid_cells(): Validates grid size parameters
  • validate_tile_size(): Validates tile size parameters
  • validate_image_size(): Validates image dimensions
  • validate_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 colors
  • build_tile_set(): Builds a tile set from image paths with error handling
  • TileSet.find_nearest_tile_vectorized(): Vectorized tile matching using broadcasting
  • TileManager: 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 matching
  • MosaicBuilder: 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

  1. Vectorized Method: Already highly optimized in Lab 1, showing modest but consistent improvements (~6% faster)

  2. 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
  3. Scalability: Performance improvements increase with grid size, with the loop method showing up to 8.9x speedup for 64Γ—64 grids

  4. 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:

  1. Navigate to the project root directory:

    cd ..
    
  2. Open the notebook using Jupyter:

    jupyter notebook profiling_analysis.ipynb
    

    Or if using JupyterLab:

    jupyter lab profiling_analysis.ipynb
    
  3. The 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

  1. Import errors: Ensure all dependencies are installed

    pip install -r requirements.txt
    
  2. Missing assets: Assets are auto-generated on first run. If issues occur:

    python -c "from mosaic_generator.utils import generate_assets; generate_assets()"
    
  3. Memory errors: Reduce grid size or tile size for very large images

  4. Slow performance: Use the vectorized method for best performance

Acknowledgments

  • Sample images from scikit-image data module
  • Gradio framework for the web interface