A Python library for demonstrating lossy image compression using Singular Value Decomposition (SVD). This educational tool visualizes the trade-offs between compression ratio and image quality through low-rank matrix approximation.
This project implements image compression by decomposing grayscale images into their SVD components and reconstructing them using only the most significant singular values. It provides tools for analyzing compression efficiency, visualizing reconstruction quality, and understanding the mathematical principles behind SVD-based compression.
Singular Value Decomposition factorizes a matrix A (image) into three components:
A = U @ Σ @ V^T
Where:
- U: Left singular vectors (m × min(m,n))
- Σ: Diagonal matrix of singular values in descending order
- V^T: Right singular vectors transposed (min(m,n) × n)
By retaining only the top k singular values, we create a low-rank approximation:
A_k = U[:, :k] @ diag(σ[:k]) @ V^T[:k, :]
This compresses the image while preserving the most significant features.
- SVD Decomposition: Efficient image decomposition using NumPy
- Flexible Reconstruction: Reconstruct images at arbitrary compression levels (rank-k approximation)
- Compression Metrics: Calculate energy retention and compression ratios
- Visualization Tools:
- Singular value plots (linear and log-scale)
- Energy curves showing variance captured
- Energy vs. compression trade-off analysis
- Side-by-side image comparisons with error maps
- Educational Resources: Interactive Jupyter notebook with comprehensive examples
This project uses uv for package management. Requires Python 3.12+.
# Clone the repository
git clone https://github.com/yourusername/svd-image-compression.git
cd svd-image-compression
# Install dependencies using uv
uv sync
# Or using pip
pip install -e .from imgsvd import (
decompose_image,
reconstruct,
calculate_energy,
compression_ratio,
plot_energy_curve,
display_reconstructions,
config
)
# Decompose an image
image_path = config.SAMPLE_IMAGES_DIR / 'camera.png'
U, sigma, Vt = decompose_image(str(image_path))
# Reconstruct at different compression levels
k_values = [10, 50, 100]
reconstructions = {}
for k in k_values:
img = reconstruct(U, sigma, Vt, k)
energy = calculate_energy(sigma, k)
comp_ratio = compression_ratio((512, 512), k)
print(f"k={k}: {energy:.1%} energy, {comp_ratio:.2%} compression")
reconstructions[k] = img
# Visualize results
plot_energy_curve(sigma, max_k=200, save_path='energy_curve.png')
display_reconstructions(original, reconstructions, k_values, 'comparison.png')svd-image-compression/
├── src/imgsvd/ # Main package
│ ├── decompose.py # SVD decomposition implementation
│ ├── reconstruct.py # Image reconstruction from SVD
│ ├── utils.py # Image I/O utilities
│ ├── metrics.py # Energy and compression metrics
│ ├── visualize.py # Visualization functions
│ └── config.py # Path configuration
├── data/
│ ├── images/
│ │ ├── sample/ # Example images (camera.png, astronaut.png)
│ │ └── user/ # Your images (gitignored)
│ └── results/ # Generated outputs
│ ├── plots/ # Visualization outputs
│ └── reconstructions/ # Saved reconstructed images
├── svd-image-exercise/
│ ├── svd-exercise.ipynb # Interactive tutorial notebook
│ └── svd_image_exercise.pdf # Educational PDF guide
└── notebooks/ # Additional notebooks
Energy (Variance Captured):
Energy(k) = Σ(σᵢ²) for i=1..k / Σ(σᵢ²) for all i
Represents the proportion of image variance retained with k components.
Compression Ratio:
Ratio = k × (m + n + 1) / (m × n)
Where m × n is the original image size. Lower values indicate better compression.
| k | Energy | Compression | Visual Quality |
|---|---|---|---|
| 5 | ~50% | 2% | Very blurry |
| 10 | ~70% | 4% | Basic features visible |
| 50 | ~98% | 19% | High quality |
| 100 | ~99.5% | 39% | Near-perfect |
Explore the comprehensive Jupyter notebook for hands-on learning:
jupyter notebook svd-image-exercise/svd-exercise.ipynbThe notebook includes:
- Mathematical explanations with LaTeX formulas
- Step-by-step image decomposition
- Analysis of singular value decay
- Energy threshold calculations (90%, 95%, 99%)
- Reconstruction quality comparisons
- Error map visualizations
- numpy (≥2.3.4): SVD computation and numerical operations
- matplotlib (≥3.10.7): Visualization and plotting
- pillow (≥12.0.0): Image I/O operations
- scikit-image (≥0.25.2): Image processing utilities
- pandas (≥2.3.3): Data analysis and result tables
- jupyter (≥1.1.1): Interactive notebooks
decompose_image(image_path)
- Performs SVD on a grayscale image
- Returns:
(U, sigma, Vt)tuple
reconstruct(U, sigma, Vt, k)
- Reconstructs image using top-k singular values
- Returns: Reconstructed image as ndarray
reconstruct_multiple(U, sigma, Vt, k_values)
- Batch reconstruction at multiple k values
- Returns: Dictionary mapping k → reconstructed image
calculate_energy(sigma, k)
- Computes energy (variance) retained with k components
- Returns: Float between 0 and 1
compression_ratio(image_shape, k)
- Calculates compression ratio for rank-k approximation
- Returns: Float (< 1 indicates compression)
plot_singular_values(sigma, **kwargs)
- Plots singular values in linear and log scale
plot_energy_curve(sigma, max_k, **kwargs)
- Shows energy captured vs. number of components
plot_energy_vs_compression(sigma, image_shape, **kwargs)
- Analyzes energy-compression trade-offs
display_reconstructions(original, reconstructions, k_values, **kwargs)
- Shows side-by-side comparisons with error maps
from imgsvd import decompose_image, reconstruct, load_grayscale, config
# Place your image in data/images/user/
user_image = config.USER_IMAGES_DIR / 'myimage.png'
# Decompose and reconstruct
original = load_grayscale(str(user_image))
U, sigma, Vt = decompose_image(str(user_image))
# Find k for 95% energy retention
from imgsvd.metrics import find_k_for_energy
k_95 = find_k_for_energy(sigma, 0.95)
print(f"k={k_95} captures 95% energy")
# Reconstruct and save
reconstructed = reconstruct(U, sigma, Vt, k_95)
from imgsvd.utils import save_image
save_path = config.RECONSTRUCTIONS_DIR / f'myimage_k{k_95}.png'
save_image(reconstructed, str(save_path))- Linear Algebra: Visualizing SVD decomposition and low-rank approximation
- Data Compression: Understanding lossy compression trade-offs
- Numerical Methods: Exploring matrix factorization techniques
- Computer Vision: Introduction to dimensionality reduction in images
- Signal Processing: Analyzing energy distribution in frequency components
Contributions are welcome! This is an educational project designed to help students understand SVD applications in image processing.
[Add your license here]
Built with NumPy, Matplotlib, and scikit-image. Sample images from scikit-image's data module.