A modified version of the PyTorch implementation of FFDNet image denoising, created for the Signal, Image, and Video course of the master's degree program in Artificial Intelligence System and Computer Science at the University of Trento.
The original FFDNET implementation was provided by
- Author : Matias Tassano [email protected]
- Copyright : (C) 2018 IPOL Image Processing On Line http://www.ipol.im/
- Licence : GPL v3+
- Source code: http://www.ipol.im/pub/art/2019/231/
- Reference paper: https://doi.org/10.5201/ipol.2019.231
This source code provides a modified version of the "FFDNet image denoising, as in Zhang, Kai, Wangmeng Zuo, and Lei Zhang. FFDNet: Toward a fast and flexible solution for CNN based image denoising."
FFDNet paper.
This version, unlike the original, concentrates on detecting the cameras' PRNU.
It includes the option of training the network using the Wiener filter as a strategy to detect and extract noise from images, in addition to the original method provided in the paper.
Noise reduction is the process, which consists in removing noise from a signal. Images, taken with both digital cameras and conventional film cameras, will pick up noise from a variety of sources, which can be (partially) removed for practical purposes such as computer vision. Neural-PRNU-Extractor aims at predicting the noise from an image, provided a noise level \sigma \in \left[0, 75 \right].
In addition to noise extraction, Neural-PRNU-Extractor can compute and evaluate PRNU, given a dataset of flat images, and evaluate the natural images. PRNU, the acronym for photo response non-uniformity, is a form of fixed-pattern noise related to digital image sensors, as used in cameras and optical instruments, and is used with the purpose of identifying which device generated an image.
The code as-is runs in Python 3.9 with the following dependencies:
To facilitate the use of the application, a Makefile has been provided; to see its functions, simply call the appropriate help command with GNU/Make
make helpFor the development phase, the Makefile provides an automatic method to create a virtual environment.
If you want a virtual environment for the project, you can run the following commands:
pip install --upgrade pipVirtual environment creation in the venv folder
make envVirtual environment activation
source ./venv/ffdnet/bin/activateInstall the requirements listed in requirements.txt
make installNote: if you have Tesla K40c GPU, you can use dependency file for MMlab GPU [requirements.mmlabgpu.txt]
make install-mmlabThe documentation is built using Sphinx v4.3.0.
If you want to build the documentation, you need to enter the project folder first:
cd neural-prnu-extractorInstall the development dependencies [requirements.dev.txt]
make install-devBuild the Sphinx layout
make doc-layoutBuild the documentation
make docOpen the documentation
make open-docIn order to train the provided model, it is necessary to prepare the data first.
To this purpose, a set of commands has been created. It must be specified, however, that such commands work while considering the syntax of the VISION dataset.
This code does not include image datasets, however, you can retrieve one from: VISION Dataset
First of all, you will need to split the original dataset into training and validation.
You can learn more about how to perform this operation by executing
python -m ffdnet prepare_vision --helpGenerally, any dataset with a similar structure (no subfolders and images with experiment_name
<camera_model_number>_<I|V>_<resource_type>_<resource_number>.jpg) can be
split by executing the following command:
python -m ffdnet prepare_vision \
SOURCE_DIR \
DESTINATION_DIR \
--train_frac 0.7NOTES
- Use the
-moption to move files instead of copying them --train_fracis used to specify the proportion of elements in training/validation
At this point, you will need to prepare the dataset composed of patches by executing prepare_patches.py indicating the paths to the directories containing the training and validation datasets by specifying as arguments --trainset_dir and --valset_dir, respectively.
You can learn more about how to perform this operation by executing
python -m ffdnet prepare_patches --helpEXAMPLE
To prepare a dataset of patches 44x44 with stride 20, you can execute
python -m ffdnet prepare_patches \
SOURCE_DIR \
DESTINATION_DIR \
--patch_size 44 \
--stride 20NOTES
- To prepare a grayscale dataset:
python prepare_patches.py --gray - --max_number_patches can be used to set the maximum number of patches contained in the database
A model can be trained after having built the training and validation databases (i.e. train_rgb.h5 and val_rgb.h5 for color denoising, and train_gray.h5 and val_gray.h5 for grayscale denoising). Only training on GPU is supported.
python -m ffdnet train --helpEXAMPLE
python -m ffdnet train \
--batch_size 128 \
--val_batch_size 128 \
--epochs 80 \
--filter wiener \
--experiment_name en \
--grayNOTES
- The training process can be monitored with TensorBoard as logs get saved in the experiments/experiment_name folder
- By default, noise added at validation is set to 25 (--val_noiseL flag)
- A previous training can be resumed passing the --resume_training flag
- It is possible to specify a different dataset location for training (validation) with
--traindbf(--valdbf) - Resource can be limited by users (when using torch 1.10.0) with the option
--gpu_fraction - Training was performed by considering a file containing 50160 patches 100x100 with 50px of stride, while for the validation we considered a file containing 16080 patches.
You can learn more about the test function by calling the help of the test sub-parser
python -m ffdnet test --helpIf you want to denoise an image using one of the pre-trained models found under the models folder, you can execute
python -m ffdnet test \
INPUT_IMG1 INPUT_IMG2 ... INPUT_IMGK \
models/WEIGHTS \
DST_FOLDERTo run the algorithm on CPU instead of GPU:
python -m ffdnet test \
INPUT_IMG1 INPUT_IMG2 ... INPUT_IMGK \
models/WEIGHTS \
DST_FOLDER \
--device cpuOr just change the flags' values within the Makefile and run
make testOriginal image
Histogram equalized predicted noise
Denoised image
NOTES
- Models have been trained for values of noise in [0, 5]
- Models have been trained with the Wiener filter as a denoising method
In order to evaluate the model according to PRNU, it is necessary first to prepare the data.
To this purpose, a set of commands has been created. It must be specified, however, that such commands work while considering the syntax of the VISION dataset.
This code does not include image datasets, however, you can retrieve one from: VISION Dataset
For this purpose, you will need to split the original dataset into flat and nat images. In particular, it is required a dataset structure as follows:
.
├── flat
│ ├── D04_I_0001.jpg
.....
│ └── D06_I_0149.jpg
└── nat
├── D04_I_0001.jpg
...
└── D06_I_0132.jpgYou can learn more about how to perform this operation by executing
python -m ffdnet prepare_prnu --helpGenerally, any dataset with a similar structure (no subfolders and images with experiment_name
<camera_model_number>_<I|V>_<flat|nat>_<resource_number>.jpg) can be
split by executing the following
python -m ffdnet prepare_prnu \
SOURCE_DIRNOTES
- Use the
-moption to move files instead of copying them - Use the
--dstoption to specify a different destination folder
To evaluate a model according to the PRNU, a set of commands with various options was created. You can learn more about how to perform this operation by executing
python -m ffdnet prnu --helpThe evaluation uses a dataset, generated as described in the previous section, to evaluate a specific model.
python -m ffdnet prnu \
PREPARED_DATASET_DIR \
models/WEIGHTSEstimated PRNU
Statistics
{
'cc': {
'auc': 0.9163367807608622,
'eer': 0.19040247678018576,
'fpr': array([
...
]),
'th': array([
...
])
},
'pce': {
'auc': 0.8582477067737637,
'eer': 0.22678018575851394,
'fpr': array([
...
]),
'th': array([
...
]),
'tpr': array([
...
])
}
}Where:
ccis the cross-correlationpceis the peak to correlation energyaucis the area under the curveeeris the equal error ratefpris the false positive ratethare the thresholds
NOTES
- Use the
--sigmaoption to specify a set noise value for the dataset (if not specified, this is calculated for every image) - Use the
--grayoption if using a gray dataset - Use the
--cut_dimoption to specify the size of the cut of the images used for the estimation of the PRNU - For the fingerprints extraction, we considered a set of 3 camera models with 130 (flat) images per model
Copyright 2018 IPOL Image Processing On Line http://www.ipol.im/
Copying and distribution of this file, with or without modification, are permitted in any medium without royalty provided the copyright notice and this notice are preserved. This file is offered as-is, without any warranty.
Some of the code is based on code by Yiqi Yan [email protected]



