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.
-
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
- Python 3.10+
Python packages:
numpy
scipy
opencv-python
scikit-image
pillow
Clone the repository:
git clone https://github.com/<your-username>/<repo-name>.git
cd <repo-name>Create a virtual environment:
python3 -m venv .venv
source .venv/bin/activatepython -m venv .venv
.venv\Scripts\activateInstall the dependencies:
python -m pip install --upgrade numpy scipy opencv-python scikit-image pillowBy 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.pyThe program will guide you through:
- Selecting a deblurring algorithm
- Selecting or defining the blur model / PSF
- Choosing a processing profile
- Configuring batch-processing options
- Reviewing the run settings
- Starting the processing job
Processed images are written to:
output-images/
python batch_deblur.pypython batch_deblur.py \
--input-dir ./my-input \
--output-dir ./my-outputOn Windows:
python batch_deblur.py --input-dir .\my-input --output-dir .\my-outputpython batch_deblur.py --no-color| 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.
The application searches for:
.jpg
.jpeg
.png
.bmp
.tif
.tiff
.webp
Images can optionally be discovered recursively inside subdirectories.
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
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
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
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
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
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.
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.
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.
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.
Models uniform averaging blur.
Parameter:
kernel size
Kernel dimensions must be odd.
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.
Instead of configuring every algorithm manually, the application provides three presets.
The recommended default.
Designed to provide a reasonable compromise between:
- Sharpness
- Noise
- Ringing artifacts
Uses more conservative restoration settings.
Useful when avoiding artifacts is more important than maximum sharpness.
Uses stronger restoration settings.
It may produce sharper results but has a greater chance of:
- Noise amplification
- Ringing
- Other deconvolution artifacts
Allows individual algorithm parameters to be entered manually.
Run:
python batch_deblur.pySelect 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.
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.
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.
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.
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.
Internally, image data is converted to a normalized floating-point representation before deconvolution.
After processing, the result is:
- Clipped to the valid normalized range
- Converted back to the source image's numeric range and data type
- Recombined with alpha data when present
- Encoded to the original image format
The application also reads EXIF orientation metadata and applies the appropriate orientation before processing.
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.
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.
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.
Install or upgrade the dependencies:
python -m pip install --upgrade numpy scipy opencv-python scikit-image pillowVerify 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.
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.pyPossible 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
The selected PSF is larger than the image being processed.
Use a smaller:
- Motion length
- Gaussian kernel
- Box kernel
- Custom PSF
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 |
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.
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.
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.
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.
Created as a Python utility for experimenting with and comparing classical image deblurring techniques.