Skip to content

MichailSemoglou/ColorCast

Repository files navigation

ColorCast

Python Version License Code Coverage Tests DOI PyPI Downloads

ColorCast is a Python toolkit for color and style transfer between images. It provides histogram matching, mean/std transfer, LUT-based curves (linear, S-curve, contrast), and selective regional color transfer across shadows, midtones, and highlights. Color-vision-deficiency simulation covers deuteranopia, protanopia, and tritanopia; the Daltonization pipeline re-encodes the chromatic information these deficiencies would otherwise hide, shifting it into a channel the affected observer can still perceive.

Features

Core Capabilities

  • 9 Transfer Methods - Choose from multiple algorithms for different effects
  • Intensity Control - Smooth slider (0-100%) to blend between original and styled images
  • Selective Regional Transfer - Target shadows, midtones, or highlights specifically
  • Modular Package - Use as Python API or run GUI/CLI
  • Performance Optimized - LRU caching and batch processing support
  • Tested - 43% test coverage with 162 passing tests
  • Documented - API documentation and examples
  • Plugin Architecture - Easy to add custom transfer methods

Transfer Methods

  1. Histogram Matching - Classic histogram equalization, preserves local contrast
  2. Mean/Std Transfer - Statistical color matching using mean and standard deviation
  3. Lab Color Transfer (Reinhard) - Industry-standard perceptually uniform color transfer in Lab* space
  4. LUT + Linear Curve - Histogram matching with linear tone mapping
  5. LUT + S-Curve - Adds smooth contrast enhancement to histogram matching
  6. LUT + Contrast - Increases overall contrast with power curve
  7. Selective: Shadows - Transfers colors only in dark regions (luminance < 0.3)
  8. Selective: Midtones - Transfers colors only in mid-tones (0.3 to 0.7)
  9. Selective: Highlights - Transfers colors only in bright regions (luminance > 0.7)

Interface

ColorCast Interface

ColorCast's intuitive interface showing content image, style image, and result panels

ColorCast Daltonize (P) mode

Daltonize (P) mode correcting an image for protanopia, with correction intensity control

Installation

From PyPI (Recommended)

Install ColorCast using pip:

pip install colorcast

For GPU support (requires CUDA):

pip install colorcast[gpu]

From Source

# Clone the repository
git clone https://github.com/MichailSemoglou/ColorCast.git
cd ColorCast

# Create a virtual environment (recommended)
python -m venv .venv
source .venv/bin/activate  # On Windows: .venv\Scripts\activate

# Install the package
pip install -e .

# For development with all dependencies
pip install -e ".[dev]"

# For GPU support (requires CUDA)
pip install -e ".[gpu]"

Requirements

  • Python 3.10+
  • NumPy >= 1.20.0
  • scikit-image >= 0.19.0
  • PyQt5 >= 5.15.0 (for GUI)
  • scipy >= 1.7.0

See pyproject.toml for complete dependency specifications.

Usage

1. GUI Application

Run the graphical interface:

colorcast-gui

Or use the package entry point:

python -m colorcast

The root colorcast.py script is kept as a deprecated compatibility shim and also launches the GUI. Use python -m colorcast or colorcast-gui for new work.

Step-by-step:

  1. Select Transfer Method: Choose from 9 different algorithms at the top
  2. Load Content Image: Click to select your base image
  3. Load Style Image: Click to select the image whose style you want to copy
  4. Apply Style Transfer: Click to process the images
  5. Adjust Intensity: Use the slider to control effect strength (0-100%)
  6. Save Result: Export your final image in your preferred format
  7. Clear Images: Reset and start over with new images

2. Command-Line Interface

Basic color transfer:

colorcast transfer content.jpg style.jpg -o output.jpg

With method and intensity:

colorcast transfer content.jpg style.jpg -o output.jpg -m meanstd -i 0.7

Batch process directory:

colorcast batch ./content_dir style.jpg -o ./output_dir

List available methods:

colorcast list-methods

Get package information:

colorcast info --version

CLI Options:

  • -m, --method: Transfer method (histogram, meanstd, lab_reinhard, lut_linear, lut_scurve, lut_contrast, selective_shadows, selective_midtones, selective_highlights)
  • -i, --intensity: Blend intensity 0.0-1.0
  • -w, --workers: Number of parallel workers (default: 4)
  • -p, --pattern: File pattern to match (default: *.jpg)

3. Python API

from colorcast import load_image, match_histograms_multichannel, save_image

# Load images
content = load_image("content.jpg")
style = load_image("style.jpg")

# Apply histogram matching
result = match_histograms_multichannel(content, style)

# Save result
save_image(result, "output.jpg")

Using Different Methods

from colorcast import (
    load_image,
    color_transfer_meanstd,
    color_transfer_lab,
    lut_transfer_with_curve,
    selective_color_transfer,
    blend_images,
    save_image,
)

content = load_image("content.jpg")
style = load_image("style.jpg")

# Mean/Std transfer
result1 = color_transfer_meanstd(content, style)

# Lab color transfer (Reinhard method)
result_lab = color_transfer_lab(content, style, alpha=0.8)

# LUT with S-curve
result2 = lut_transfer_with_curve(content, style, "s-curve")

# Selective shadows transfer
result3 = selective_color_transfer(content, style, mode="shadows")

# Blend with 70% intensity
final = blend_images(content, result2, intensity=0.7)
save_image(final, "output.jpg")

Using the Plugin Registry

from colorcast import load_image, registry

# List available methods
methods = registry.list_methods()
print(f"Available methods: {methods}")

# Get method and use it
content = load_image("content.jpg")
style = load_image("style.jpg")

method = registry.get_method("histogram")
result = method.transfer(content, style)

Batch Processing

from colorcast.processing.batch import BatchProcessor
from colorcast import match_histograms_multichannel

# Create batch processor
processor = BatchProcessor(
    transfer_method=match_histograms_multichannel,
    max_workers=4,
)

# Process directory
results = processor.process_directory(
    content_dir="./content_images",
    style_image="style.jpg",
    output_dir="./output",
    pattern="*.jpg",
)

# Check for failed files
if processor.failed_files:
    print(f"Failed to process {len(processor.failed_files)} files")

Using Caching

from colorcast.processing.cache import LRUCache

# Create cache
cache = LRUCache(max_size=100)

# Use cache for expensive operations
result = cache.get_or_compute(
    key="transfer_key",
    compute_func=lambda: match_histograms_multichannel(content, style),
)

# Get cache statistics
stats = cache.stats()
print(f"Cache hits: {stats['hits']}, misses: {stats['misses']}")

Tips for Best Results

Choosing the Right Method

  • Histogram Matching: Best for artistic effects and dramatic color shifts
  • Mean/Std Transfer: Better for subtle, natural-looking color grading
  • Lab Color Transfer (Reinhard): Industry-standard method for professional color grading with perceptually uniform results
  • LUT Curves: Experiment with different curves for varied contrast effects
    • Linear: Standard transfer
    • S-Curve: Enhanced midtones
    • Contrast: Punchier overall look
  • Selective Transfer: Target specific tonal ranges for precise control
    • Shadows: Affect only dark areas
    • Midtones: Affect only mid-tones (most natural for skin tones)
    • Highlights: Affect only bright areas

Intensity Blending

  • 0-30%: Very subtle color correction
  • 30-60%: Natural color grading
  • 60-80%: Noticeable style transfer
  • 80-100%: Full style application

Image Preparation

  • Use images with similar aspect ratios for best results
  • Higher resolution images produce better quality transfers
  • For selective transfer, ensure good dynamic range in both images

Testing

Run the test suite:

# Run all tests
pytest

# Run with coverage
pytest --cov=colorcast --cov-report=html

# Run specific test file
pytest tests/test_transfer_methods.py

# Run with verbose output
pytest -v

Test Coverage: 43% (162 passing tests, 1 skipped)

  • Core transfer methods: 99% coverage
  • Full test suite including integration, performance, and property-based tests
  • Property-based tests require the optional hypothesis dependency

Technical Details

Algorithms Implemented

1. Histogram Matching

matched = exposure.match_histograms(source, reference)
  • Per-channel histogram equalization
  • Preserves complete color distribution
  • Best for dramatic color transformations

2. Mean/Standard Deviation Transfer

result = ((source - μ_source) × (σ_ref / σ_source)) + μ_ref
  • Matches statistical properties per channel
  • Better color balance for photographic work

3. Lab Color Space Transfer (Reinhard)

result_lab = ((source_lab - μ_source) × (σ_ref / σ_source)) + μ_ref
  • Operates in perceptually uniform Lab* color space
  • Industry-standard in professional color grading
  • Preserves color relationships better than RGB methods
  • More natural-looking results

4. LUT with Curves

  • Linear: Standard histogram matching
  • S-Curve: 0.5 + 0.5 × sin(π(x - 0.5)) - smooth midtone enhancement
  • Contrast: x^0.8 - power curve for increased punch

5. Selective Color Transfer

luminance = 0.299R + 0.587G + 0.114B
mask = (luminance >= shadow_threshold) & (luminance <= highlight_threshold)
result = source × (1 - mask) + matched × mask
  • Region-based masking using luminance
  • Precise tonal range targeting

Performance Features

  • LRU Cache: 10-20x speedup for repeated operations
  • Batch Processing: Parallel processing with ThreadPoolExecutor
  • Memory Efficient: Processes images in-place where possible
  • Debounced Updates: 50ms delay prevents UI blocking
  • Automatic Format Conversion: Grayscale → RGB, RGBA → RGB

Use Cases

ColorCast is perfect for:

  • Film Color Grading - Matching scenes shot at different times
  • Photography - Applying vintage or cinematic looks
  • Art Creation - Transferring painting styles to photos
  • Social Media Content - Creating consistent color themes
  • Game Development - Style transfer for game assets
  • Research - Academic research in color transfer

Contributing

Contributions are welcome! Please feel free to:

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

For development:

# Install development dependencies
pip install -e ".[dev]"

# Run tests
pytest

# Run linting
black colorcast/
isort colorcast/
mypy colorcast/

# Run type checking
mypy colorcast/

License

Released under the MIT License.

Author

Michail Semoglou

Acknowledgments

Support

For issues, questions, or suggestions:

About

A Python and PyQt5 toolkit for color and style transfer between images, with color-vision-deficiency simulation and Daltonization for protanopia, deuteranopia, and tritanopia.

Topics

Resources

License

Stars

1 star

Watchers

0 watching

Forks

Packages

 
 
 

Contributors

Languages