A Python tool to denoise images using FFmpeg's powerful denoising filters while preserving metadata and original quality settings.
- 6 denoising filters: nlmeans, bm3d, dctdnoiz, fftdnoiz, owdenoise, vaguedenoiser
- Metadata preservation: Maintains EXIF, TIFF tags, and other metadata using exiftool
- Quality preservation: Detects and maintains original quality settings for lossy formats
- Format support: Works with all image formats supported by FFmpeg (JPEG, PNG, TIFF, WEBP, etc.)
- Batch processing: Process entire directories of images
- Customizable parameters: Fine-tune each filter's behavior
- Error handling: Robust validation and clear error messages
-
FFmpeg with denoising filters:
# macOS (Homebrew) brew install ffmpeg # Ubuntu/Debian sudo apt update && sudo apt install ffmpeg # Windows (Chocolatey) choco install ffmpeg
-
exiftool for metadata preservation:
# macOS (Homebrew) brew install exiftool # Ubuntu/Debian sudo apt install libimage-exiftool-perl # Windows: Download from https://exiftool.org/
# From source
git clone <repository-url>
cd ffmpeg-denoise-images
pip install .
# Or install in development mode
pip install -e .# Denoise all images in a directory using nlmeans (default)
ffmpeg-denoise-images input_dir output_dir
# Denoise a single image file
ffmpeg-denoise-images input.jpg output.jpg
# Use a specific filter
ffmpeg-denoise-images input_dir output_dir --filter bm3d
ffmpeg-denoise-images input.png output.png --filter bm3dEach filter has customizable parameters for fine-tuning:
# nlmeans with custom strength
ffmpeg-denoise-images input_dir output_dir --filter nlmeans --nlmeans-strength 2.0
# bm3d with custom sigma
ffmpeg-denoise-images input_dir output_dir --filter bm3d --bm3d-sigma 3.0
# dctdnoiz with custom noise sigma
ffmpeg-denoise-images input_dir output_dir --filter dctdnoiz --dctdnoiz-sigma 5.0
# fftdnoiz with custom strength
ffmpeg-denoise-images input_dir output_dir --filter fftdnoiz --fftdnoiz-sigma 2.0
# owdenoise with custom luma strength
ffmpeg-denoise-images input_dir output_dir --filter owdenoise --owdenoise-strength 1.5
# vaguedenoiser with custom threshold
ffmpeg-denoise-images input_dir output_dir --filter vaguedenoiser --vaguedenoiser-threshold 3.0For complete control over filter parameters:
# Custom filter string (overrides filter selection and parameters)
ffmpeg-denoise-images input_dir output_dir --custom-filter "nlmeans=s=2.0:p=7:r=15"
# Complex filter chains
ffmpeg-denoise-images input_dir output_dir --custom-filter "nlmeans=s=1.0,unsharp=5:5:0.8:3:3:0.4"| Filter | Description | Best For | Speed |
|---|---|---|---|
| nlmeans | Non-local means denoiser | General noise reduction | Medium |
| bm3d | Block-Matching 3D (2D mode) | High-quality denoising | Slow |
| dctdnoiz | 2D DCT-based denoiser | JPEG artifacts, fast processing | Fast |
| fftdnoiz | 3D FFT (spatial-only mode) | Frequency domain noise | Medium |
| owdenoise | Wavelet denoiser | Natural images | Fast |
| vaguedenoiser | Wavelet denoiser | Soft noise reduction | Fast |
- atadenoise: Adaptive Temporal Averaging (needs multiple frames)
- hqdn3d: High Quality 3D Denoiser (has temporal component)
--nlmeans-strength(default: 1.0): Denoising strength (1-30)
--bm3d-sigma(default: 1.0): Denoising strength (0-99999.9)- Automatically uses 2D mode (group=1) for per-frame processing
--dctdnoiz-sigma(default: 0.0): Noise sigma (0 for auto-detection)
--fftdnoiz-sigma(default: 1.0): Denoising strength (0-100)- Automatically uses spatial-only mode (prev=0, next=0)
--owdenoise-strength(default: 1.0): Luma strength (0-1000)
--vaguedenoiser-threshold(default: 2.0): Filtering strength (0-DBL_MAX)
The tool automatically detects and preserves image quality settings:
- JPEG: Attempts to detect original quality from metadata, falls back to high quality (q:v=2)
- PNG/TIFF: Lossless formats processed without quality loss
- WEBP: High quality default (q:v=95)
- Other formats: High quality fallback (q:v=2)
All metadata is preserved using exiftool:
- EXIF data (camera settings, GPS, etc.)
- TIFF tags
- XMP data
- Format-specific metadata
If metadata cannot be preserved for a file, the tool will continue processing but warn you at the end.
The tool includes comprehensive error handling:
- Validates input directory (must contain only files, no subdirectories)
- Checks FFmpeg format support for each image
- Stops immediately if unsupported formats are encountered
- Reports metadata preservation failures
- Provides clear error messages
# Process a directory of noisy photos
ffmpeg-denoise-images ./noisy_photos ./clean_photos
# Process a single noisy image
ffmpeg-denoise-images noisy_photo.jpg clean_photo.jpg# Use bm3d for best quality (slower) - directory
ffmpeg-denoise-images ./input ./output --filter bm3d --bm3d-sigma 2.5
# Use bm3d for single file
ffmpeg-denoise-images noisy.jpg clean.jpg --filter bm3d --bm3d-sigma 2.5# Use dctdnoiz for speed
ffmpeg-denoise-images ./input ./output --filter dctdnoiz --dctdnoiz-sigma 3.0# Fine-tune nlmeans parameters
ffmpeg-denoise-images ./input ./output --custom-filter "nlmeans=s=1.5:p=5:r=10"The project includes a comprehensive test suite using pytest:
# Install test dependencies
pip install -e ".[test]"
# Run tests
pytest test_ffmpeg_denoise_images.py
# Run tests with verbose output
pytest test_ffmpeg_denoise_images.py -vThe test suite covers:
- Directory validation and error handling
- FFmpeg format support detection
- Image quality settings detection for all formats
- Metadata copying functionality
- Filter parameter generation for all 6 filters
- Image denoising with mocked FFmpeg calls
- Main function integration testing
- Command-line argument parsing
- Python 3.10+
- FFmpeg (with denoising filters)
- exiftool
- ffmpeg-python
- PyExifTool
MIT License - see LICENSE file for details.
Contributions are welcome! Please feel free to submit a Pull Request.