Skip to content

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 

Repository files navigation

Batch Image Deblurring

A Python command-line application for batch image deblurring using classical deconvolution algorithms.

The program processes images from an input directory, lets you interactively select a blur model and deblurring algorithm, and saves restored images into organized output folders. It also generates a detailed JSON report for every processing run.

Features

  • Batch-process multiple images

  • Process subdirectories recursively

  • Five deblurring algorithms:

    • Wiener–Hunt
    • Richardson–Lucy
    • Tikhonov / Laplacian regularization
    • Total Variation with ADMM
    • Unsupervised Wiener
  • Four Point Spread Function (PSF) options:

    • Motion blur
    • Gaussian blur
    • Box blur
    • Custom PSF
  • Built-in processing profiles:

    • Gentle
    • Balanced
    • Aggressive
    • Custom
  • Optional reflect padding to reduce edge artifacts

  • Automatic EXIF orientation handling

  • Support for grayscale and color images

  • Preserves alpha data separately from deblurring

  • Recursive folder processing

  • Existing-file protection with optional overwrite

  • Atomic image and report writes

  • Per-run JSON processing reports

  • Interactive terminal interface with optional ANSI colors

  • Custom input and output directories


Requirements

  • Python 3.10+

Python packages:

numpy
scipy
opencv-python
scikit-image
pillow

Installation

Clone the repository:

git clone https://github.com/<your-username>/<repo-name>.git
cd <repo-name>

Create a virtual environment:

Linux / macOS

python3 -m venv .venv
source .venv/bin/activate

Windows

python -m venv .venv
.venv\Scripts\activate

Install the dependencies:

python -m pip install --upgrade numpy scipy opencv-python scikit-image pillow

Quick Start

By default, the program looks for images in an input-images directory next to batch_deblur.py.

Example project layout:

project/
├── batch_deblur.py
└── input-images/
    ├── image1.jpg
    ├── image2.png
    └── examples/
        └── image3.tif

Run the application:

python batch_deblur.py

The program will guide you through:

  1. Selecting a deblurring algorithm
  2. Selecting or defining the blur model / PSF
  3. Choosing a processing profile
  4. Configuring batch-processing options
  5. Reviewing the run settings
  6. Starting the processing job

Processed images are written to:

output-images/

Command-Line Options

Default

python batch_deblur.py

Custom input and output directories

python batch_deblur.py \
    --input-dir ./my-input \
    --output-dir ./my-output

On Windows:

python batch_deblur.py --input-dir .\my-input --output-dir .\my-output

Disable terminal colors

python batch_deblur.py --no-color

Available arguments

Argument Description
--input-dir PATH Directory containing source images
--output-dir PATH Directory where processed images are written
--no-color Disable ANSI terminal colors

Default directories are:

input-images/
output-images/

relative to the location of the script.


Supported Image Formats

The application searches for:

.jpg
.jpeg
.png
.bmp
.tif
.tiff
.webp

Images can optionally be discovered recursively inside subdirectories.


Deblurring Algorithms

1. Wiener–Hunt

A fast and stable deconvolution method with configurable regularization.

It is a good general-purpose starting point, particularly when noise is present.

Main parameter:

balance

Higher values apply stronger regularization.

Speed: Fast


2. Richardson–Lucy

An iterative deconvolution algorithm capable of producing sharper results.

Main parameters:

iterations
filter_epsilon

Increasing the iteration count can improve sharpness but may also amplify noise and ringing artifacts.

Speed: Medium


3. Tikhonov / Laplacian

A frequency-domain deconvolution method using Laplacian regularization.

Main parameter:

regularization

The regularization coefficient controls the trade-off between restoration strength and stability.

Speed: Very fast


4. Total Variation with ADMM

An edge-preserving restoration method that solves a total-variation-regularized deconvolution problem using the Alternating Direction Method of Multipliers (ADMM).

Main parameters:

tv_weight
rho
iterations

It is designed to preserve image edges while controlling noise and restoration artifacts.

Speed: Slow


5. Unsupervised Wiener

An unsupervised Wiener restoration method that estimates regularization parameters using Gibbs sampling.

Main parameters:

threshold
burnin
min_iterations
max_iterations

Where supported by the installed scikit-image version, a deterministic random number generator seed is used to make batch results reproducible.

Speed: Slow


Run All Algorithms

The interactive menu also provides a:

Run all algorithms

option.

This processes every discovered image with all five algorithms and stores each algorithm's results in a separate directory.

This can be useful when comparing restoration methods for an unknown blur.


Blur Models / PSFs

Image deblurring requires an estimate of the Point Spread Function (PSF) — the kernel that describes how the original image was blurred.

The program provides four PSF modes.

Motion Blur

Models linear camera or subject movement.

Parameters:

length
angle

For example:

Length: 15 pixels
Angle: 0°

Angle conventions used by the application:

0°   = horizontal
90°  = vertical
positive angles = clockwise

The motion kernel is generated at higher resolution and area-downsampled to improve sub-pixel coverage.


Gaussian Blur

Approximates Gaussian or out-of-focus blur.

Parameters:

sigma
kernel size

The application suggests a kernel size based on the selected sigma while still allowing it to be changed manually.

Kernel dimensions must be odd.


Box Blur

Models uniform averaging blur.

Parameter:

kernel size

Kernel dimensions must be odd.


Custom PSF

A custom blur kernel can be supplied as either:

grayscale image

or:

.npy NumPy array

Example:

my_kernel.npy

Custom PSFs are validated before processing. The application checks that the kernel:

  • Is two-dimensional
  • Contains finite values
  • Contains no negative values
  • Has a positive sum

The kernel is then normalized so its values sum to 1.

Even-sized custom kernels are padded to odd dimensions to avoid half-pixel centering ambiguity.


Processing Profiles

Instead of configuring every algorithm manually, the application provides three presets.

Balanced

The recommended default.

Designed to provide a reasonable compromise between:

  • Sharpness
  • Noise
  • Ringing artifacts

Gentle

Uses more conservative restoration settings.

Useful when avoiding artifacts is more important than maximum sharpness.

Aggressive

Uses stronger restoration settings.

It may produce sharper results but has a greater chance of:

  • Noise amplification
  • Ringing
  • Other deconvolution artifacts

Custom

Allows individual algorithm parameters to be entered manually.


Example Workflow

Run:

python batch_deblur.py

Select an algorithm:

[1] Wiener–Hunt
[2] Richardson–Lucy
[3] Tikhonov / Laplacian
[4] Total Variation with ADMM
[5] Unsupervised Wiener
[6] Run all algorithms
[0] Exit

Then select the PSF:

[1] Motion blur
[2] Gaussian blur
[3] Box blur
[4] Custom PSF

Choose a processing profile:

[1] Balanced
[2] Gentle
[3] Aggressive
[4] Custom

Finally, configure options such as:

Process images in subfolders too?
Overwrite existing output files?
Use reflect padding to reduce edge artifacts?

The program displays a complete run summary before processing begins.


Output Structure

Results are grouped by algorithm.

For example:

output-images/
├── wiener/
├── richardson-lucy/
├── tikhonov/
├── tv-admm/
└── unsupervised-wiener/

If recursive processing is enabled, the source directory structure is retained beneath each algorithm directory.

For example:

input-images/
└── vacation/
    └── photo.jpg

may produce:

output-images/
└── wiener/
    └── vacation/
        └── photo__deblurred-wiener-motion-L15-A0-balanced.jpg

Output filenames contain information about:

  • Source filename
  • Algorithm
  • PSF configuration
  • Processing profile

This makes results from different experiments easier to identify and compare.


JSON Reports

Every processing run generates a report similar to:

output-images/deblur-report-YYYYMMDD-HHMMSS-ffffff.json

The report contains information including:

  • Application version
  • Start and finish timestamps
  • Python version
  • Operating system / platform
  • NumPy version
  • SciPy version
  • OpenCV version
  • scikit-image version
  • Input and output directories
  • Selected algorithms
  • Algorithm parameters
  • PSF configuration
  • Processing profile
  • Recursive-processing setting
  • Overwrite setting
  • Edge-padding setting
  • Individual image results
  • Processing durations
  • Failed jobs and error messages
  • Final success / skipped / failed counts

Reports are also preserved when batch processing is interrupted with Ctrl+C, allowing completed work to be inspected afterward.


Existing Output Files

By default, the program asks whether existing output files should be overwritten.

If overwrite is disabled, existing files with matching generated names are skipped.

This makes it possible to safely rerun a batch without automatically replacing previous output.


Edge Padding

Deconvolution can produce strong artifacts near image boundaries.

The application can apply reflect padding before deconvolution and crop the restored image back to its original dimensions afterward.

The option is enabled by default in the interactive workflow:

Use reflect padding to reduce edge artifacts? [Y/n]

For most images, keeping this enabled is recommended.


Image Handling

Internally, image data is converted to a normalized floating-point representation before deconvolution.

After processing, the result is:

  1. Clipped to the valid normalized range
  2. Converted back to the source image's numeric range and data type
  3. Recombined with alpha data when present
  4. Encoded to the original image format

The application also reads EXIF orientation metadata and applies the appropriate orientation before processing.


Atomic Output Writes

Images and JSON reports are first written to temporary files and then moved into their final locations.

This reduces the likelihood of leaving partially written output files if a write operation fails.


Recursive Processing

The application can search the input directory recursively.

For example:

input-images/
├── photo1.jpg
├── scans/
│   ├── scan1.png
│   └── scan2.png
└── archive/
    └── old-photo.tif

All supported images can be discovered and processed in a single run.

If the output directory is located inside the input directory, the program automatically excludes the output tree from recursive discovery to prevent processed images from being processed again.


Important: Choosing the Correct PSF

Deblurring is an inverse problem. Good restoration depends heavily on how accurately the selected PSF represents the blur that produced the input image.

For example, if an image contains approximately:

15-pixel horizontal motion blur

a motion PSF with approximately:

length = 15
angle = 0°

is a much more appropriate starting point than an unrelated Gaussian kernel.

If the PSF type, size, motion length, or angle does not match the actual blur, classical deconvolution cannot guarantee an accurate or artifact-free reconstruction.

Experimenting with several nearby PSF parameters and comparing results is often necessary.


Troubleshooting

One of the required libraries is not installed

Install or upgrade the dependencies:

python -m pip install --upgrade numpy scipy opencv-python scikit-image pillow

No images were found

Verify that your files use one of the supported extensions:

.jpg .jpeg .png .bmp .tif .tiff .webp

Also verify that the correct input directory was selected.


The program creates input-images and exits

If the default input folder does not exist, the program creates it automatically.

Add your images to:

input-images/

and run the program again:

python batch_deblur.py

Output contains ringing or excessive noise

Possible adjustments include:

  • Try the Gentle profile
  • Verify the PSF type
  • Adjust motion length or angle
  • Adjust Gaussian sigma or kernel size
  • Increase regularization for Wiener or Tikhonov processing
  • Reduce Richardson–Lucy iterations
  • Increase TV regularization
  • Keep edge padding enabled

Blur kernel is too large relative to the image

The selected PSF is larger than the image being processed.

Use a smaller:

  • Motion length
  • Gaussian kernel
  • Box kernel
  • Custom PSF

Exit Codes

The application uses standard process exit codes to distinguish common outcomes.

Code Meaning
0 Successful completion, cancellation before processing, or normal menu exit
1 Processing completed with one or more failed jobs
2 Input, directory, or filesystem-related problem
3 Missing Python dependency
130 Interrupted by the user with Ctrl+C

Performance Notes

Processing time depends on:

  • Image resolution
  • Number of images
  • Number of selected algorithms
  • Selected algorithm
  • Iteration count
  • PSF size
  • Number of image channels

In general:

Tikhonov        → Very fast
Wiener–Hunt     → Fast
Richardson–Lucy → Medium
TV-ADMM         → Slow
Unsupervised    → Slow

Selecting Run all algorithms multiplies the number of processing jobs by the number of discovered images.


Project Structure

A minimal repository can look like:

batch-image-deblurring/
├── batch_deblur.py
├── README.md
├── input-images/
└── output-images/

For a public repository, generated images and reports will usually be better excluded from version control with a .gitignore.

For example:

# Virtual environments
.venv/
venv/

# Python
__pycache__/
*.py[cod]

# Generated output
output-images/

# Local input images
input-images/*

# OS / editor files
.DS_Store
Thumbs.db
.vscode/
.idea/

If you want Git to keep an empty input-images directory, add an empty .gitkeep file:

input-images/.gitkeep

and adjust the ignore rules accordingly.


Technical Overview

The application implements a complete batch-processing pipeline:

Input image
    │
    ▼
Decode image
    │
    ▼
Apply EXIF orientation
    │
    ▼
Separate alpha data
    │
    ▼
Normalize image values
    │
    ▼
Optional reflect padding
    │
    ▼
Apply deconvolution per channel
    │
    ▼
Crop padding
    │
    ▼
Clip and restore original numeric range
    │
    ▼
Reattach alpha data
    │
    ▼
Atomic image write
    │
    ▼
JSON run report

The Tikhonov and TV-ADMM implementations use frequency-domain operations through SciPy's FFT functionality, while Wiener, Richardson–Lucy, and Unsupervised Wiener use restoration functionality provided by scikit-image.


Disclaimer

This project implements classical image deconvolution, not generative or AI-based image restoration.

Deblurring is inherently dependent on the assumed blur model. A poorly estimated PSF can lead to ringing, noise amplification, oversharpening, or other artifacts.

For meaningful results, choose a PSF that approximates the actual blur in the source image as closely as possible.


Author

Created as a Python utility for experimenting with and comparing classical image deblurring techniques.

About

Python CLI for batch image deblurring, image restoration, deconvolution, and classical computer vision. Includes Wiener, Richardson-Lucy, Tikhonov, TV-ADMM, and unsupervised Wiener methods; motion/Gaussian/box/custom PSFs; recursive OpenCV/scikit-image processing; color/grayscale support, edge padding, presets, and JSON reports.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages