Code Monkey home page Code Monkey logo

blur-kernel-space-exploring's Introduction

Exploring Image Deblurring via Encoded Blur Kernel Space

About the project

We introduce a method to encode the blur operators of an arbitrary dataset of sharp-blur image pairs into a blur kernel space. Assuming the encoded kernel space is close enough to in-the-wild blur operators, we propose an alternating optimization algorithm for blind image deblurring. It approximates an unseen blur operator by a kernel in the encoded space and searches for the corresponding sharp image. Due to the method's design, the encoded kernel space is fully differentiable, thus can be easily adopted in deep neural network models.

Blur kernel space

Detail of the method and experimental results can be found in our following paper:

@inproceedings{m_Tran-etal-CVPR21, 
  author = {Phong Tran and Anh Tran and Quynh Phung and Minh Hoai}, 
  title = {Explore Image Deblurring via Encoded Blur Kernel Space}, 
  year = {2021}, 
  booktitle = {Proceedings of the {IEEE} Conference on Computer Vision and Pattern Recognition (CVPR)} 
}

Please CITE our paper whenever this repository is used to help produce published results or incorporated into other software.

Open In Colab

Table of Content

Getting started

Prerequisites

  • Python >= 3.7
  • Pytorch >= 1.4.0
  • CUDA >= 10.0

Installation

git clone https://github.com/VinAIResearch/blur-kernel-space-exploring.git
cd blur-kernel-space-exploring


conda create -n BlurKernelSpace -y python=3.7
conda activate BlurKernelSpace
conda install --file requirements.txt

Training and evaluation

Preparing datasets

You can download the datasets in the model zoo section.

To use your customized dataset, your dataset must be organized as follow:

root
├── blur_imgs
    ├── 000
    ├──── 00000000.png
    ├──── 00000001.png
    ├──── ...
    ├── 001
    ├──── 00000000.png
    ├──── 00000001.png
    ├──── ...
├── sharp_imgs
    ├── 000
    ├──── 00000000.png
    ├──── 00000001.png
    ├──── ...
    ├── 001
    ├──── 00000000.png
    ├──── 00000001.png
    ├──── ...

where root, blur_imgs, and sharp_imgs folders can have arbitrary names. For example, let root, blur_imgs, sharp_imgs be REDS, train_blur, train_sharp respectively (That is, you are using the REDS training set), then use the following scripts to create the lmdb dataset:

python create_lmdb.py --H 720 --W 1280 --C 3 --img_folder REDS/train_sharp --name train_sharp_wval --save_path ../datasets/REDS/train_sharp_wval.lmdb
python create_lmdb.py --H 720 --W 1280 --C 3 --img_folder REDS/train_blur --name train_blur_wval --save_path ../datasets/REDS/train_blur_wval.lmdb

where (H, C, W) is the shape of the images (note that all images in the dataset must have the same shape), img_folder is the folder that contains the images, name is the name of the dataset, and save_path is the save destination (save_path must end with .lmdb).

When the script is finished, two folders train_sharp_wval.lmdb and train_blur_wval.lmdb will be created in ./REDS.

Training

To do image deblurring, data augmentation, and blur generation, you first need to train the blur encoding network (The F function in the paper). This is the only network that you need to train. After creating the dataset, change the value of dataroot_HQ and dataroot_LQ in options/kernel_encoding/REDS/woVAE.yml to the paths of the sharp and blur lmdb datasets that were created before, then use the following script to train the model:

python train.py -opt options/kernel_encoding/REDS/woVAE.yml

where opt is the path to yaml file that contains training configurations. You can find some default configurations in the options folder. Checkpoints, training states, and logs will be saved in experiments/modelName. You can change the configurations (learning rate, hyper-parameters, network structure, etc) in the yaml file.

Testing

Data augmentation

To augment a given dataset, first, create an lmdb dataset using scripts/create_lmdb.py as before. Then use the following script:

python data_augmentation.py --target_H=720 --target_W=1280 \
			    --source_H=720 --source_W=1280\
			    --augmented_H=256 --augmented_W=256\
                            --source_LQ_root=datasets/REDS/train_blur_wval.lmdb \
                            --source_HQ_root=datasets/REDS/train_sharp_wval.lmdb \
			    --target_HQ_root=datasets/REDS/test_sharp_wval.lmdb \
                            --save_path=results/GOPRO_augmented \
                            --num_images=10 \
                            --yml_path=options/data_augmentation/default.yml

(target_H, target_W), (source_H, source_W), and (augmented_H, augmented_W) are the desired shapes of the target images, source images, and augmented images respectively. source_LQ_root, source_HQ_root, and target_HQ_root are the paths of the lmdb datasets for the reference blur-sharp pairs and the input sharp images that were created before. num_images is the size of the augmented dataset. model_path is the path of the trained model. yml_path is the path to the model configuration file. Results will be saved in save_path.

Data augmentation examples

Generate novel blur kernels

To generate a blur image given a sharp image, use the following command:

python generate_blur.py --yml_path=options/generate_blur/default.yml \
		        --image_path=imgs/sharp_imgs/mushishi.png \
			--num_samples=10
			--save_path=./res.png

where model_path is the path of the pre-trained model, yml_path is the path of the configuration file. image_path is the path of the sharp image. After running the script, a blur image corresponding to the sharp image will be saved in save_path. Here is some expected output: kernel generating examples Note: This only works with models that were trained with --VAE flag. The size of input images must be divisible by 128.

Generic Deblurring

To deblur a blurry image, use the following command:

python generic_deblur.py --image_path imgs/blur_imgs/blur1.png --yml_path options/generic_deblur/default.yml --save_path ./res.png

where image_path is the path of the blurry image. yml_path is the path of the configuration file. The deblurred image will be saved to save_path.

Image deblurring examples

Deblurring using sharp image prior

First, you need to download the pre-trained styleGAN or styleGAN2 networks. If you want to use styleGAN, download the mapping and synthesis networks, then rename and copy them to experiments/pretrained/stylegan_mapping.pt and experiments/pretrained/stylegan_synthesis.pt respectively. If you want to use styleGAN2 instead, download the pretrained model, then rename and copy it to experiments/pretrained/stylegan2.pt.

To deblur a blurry image using styleGAN latent space as the sharp image prior, you can use one of the following commands:

python domain_specific_deblur.py --input_dir imgs/blur_faces \
		    --output_dir experiments/domain_specific_deblur/results \
		    --yml_path options/domain_specific_deblur/stylegan.yml  # Use latent space of stylegan
python domain_specific_deblur.py --input_dir imgs/blur_faces \
		    --output_dir experiments/domain_specific_deblur/results \
		    --yml_path options/domain_specific_deblur/stylegan2.yml  # Use latent space of stylegan2

Results will be saved in experiments/domain_specific_deblur/results. Note: Generally, the code still works with images that have the size divisible by 128. However, since our blur kernels are not uniform, the size of the kernel increases as the size of the image increases.

PULSE-like Deblurring examples

Model Zoo

Pretrained models and corresponding datasets are provided in the below table. After downloading the datasets and models, follow the instructions in the testing section to do data augmentation, generating blur images, or image deblurring.

Model name dataset(s) status
REDS woVAE REDS ✔️
GOPRO woVAE GOPRO ✔️
GOPRO wVAE GOPRO ✔️
GOPRO + REDS woVAE GOPRO, REDS ✔️

Notes and references

The training code is borrowed from the EDVR project: https://github.com/xinntao/EDVR

The backbone code is borrowed from the DeblurGAN project: https://github.com/KupynOrest/DeblurGAN

The styleGAN code is borrowed from the PULSE project: https://github.com/adamian98/pulse

The stylegan2 code is borrowed from https://github.com/rosinality/stylegan2-pytorch

blur-kernel-space-exploring's People

Contributors

gshoai avatar p0lyfish avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

blur-kernel-space-exploring's Issues

How to create file "warmup_k_path"?

Thank you for this repo is really awesome. But I have a small question:
how is the "warmup_k_path" file created, what is it used for in the deblur process.

When I try to run generate_blur.py, I got this RuntimeError

The size of the image which I used is 640*640. It can be diviable by 128. Thanks for your help!

Sample #0/10
Traceback (most recent call last):
File ".\generate_blur.py", line 53, in
main()
File ".\generate_blur.py", line 45, in main
LQ_tensor = model.adaptKernel(HQ_tensor, kernel)
File "D:\Project\Pycharm\blur-kernel-space-exploring-main\models\kernel_encoding\kernel_wizard.py", line 157, in adaptKernel
out = self.adapter(x_sharp, kernel)
File "D:\ProgramData\Anaconda3\envs\py38\lib\site-packages\torch\nn\modules\module.py", line 889, in _call_impl
result = self.forward(*input, **kwargs)
File "D:\Project\Pycharm\blur-kernel-space-exploring-main\models\kernel_encoding\kernel_wizard.py", line 99, in forward
return self.model(x, k)
File "D:\ProgramData\Anaconda3\envs\py38\lib\site-packages\torch\nn\modules\module.py", line 889, in _call_impl
result = self.forward(*input, **kwargs)
File "D:\Project\Pycharm\blur-kernel-space-exploring-main\models\backbones\unet_parts.py", line 103, in forward
return self.up(self.submodule(self.down(x), noise))
File "D:\ProgramData\Anaconda3\envs\py38\lib\site-packages\torch\nn\modules\module.py", line 889, in _call_impl
result = self.forward(*input, **kwargs)
File "D:\Project\Pycharm\blur-kernel-space-exploring-main\models\backbones\unet_parts.py", line 109, in forward
return torch.cat((self.up(self.submodule(self.down(x), noise)), x), dim=1)
File "D:\ProgramData\Anaconda3\envs\py38\lib\site-packages\torch\nn\modules\module.py", line 889, in _call_impl
result = self.forward(*input, **kwargs)
File "D:\Project\Pycharm\blur-kernel-space-exploring-main\models\backbones\unet_parts.py", line 109, in forward
return torch.cat((self.up(self.submodule(self.down(x), noise)), x), dim=1)
File "D:\ProgramData\Anaconda3\envs\py38\lib\site-packages\torch\nn\modules\module.py", line 889, in _call_impl
result = self.forward(*input, **kwargs)
File "D:\Project\Pycharm\blur-kernel-space-exploring-main\models\backbones\unet_parts.py", line 109, in forward
return torch.cat((self.up(self.submodule(self.down(x), noise)), x), dim=1)
File "D:\ProgramData\Anaconda3\envs\py38\lib\site-packages\torch\nn\modules\module.py", line 889, in _call_impl
result = self.forward(*input, **kwargs)
File "D:\Project\Pycharm\blur-kernel-space-exploring-main\models\backbones\unet_parts.py", line 107, in forward
return torch.cat((self.up(torch.cat((self.down(x), noise), dim=1)), x), dim=1)
RuntimeError: Sizes of tensors must match except in dimension 2. Got 2 and 5 (The offending index is 0)

Generation of out-of-focus blurry image

Hello
How are you?
Thanks for contributing to this project.
I checked that the ONLY "GOPRO wVAE" model can be used to generate blurry image.
But I know that the GOPRO dataset contains ONLY motion blur.
Therefore, I think that your trained model "GOPRO wVAE" can generate ONLY motion blurry images.
I want to generate out-of-focus blurry image too.
Can your trained models be used to generate out-of-focus blurry image?
If not so, can we train such model by your method?
If we train such model, can we train on a mixed dataset consisting of both motion deblurring dataset and defocus deblurring dataset?

TypeError: cannot create 'generator' instances

I run in command line python domain_specific_deblur.py --input_dir imgs/blur_faces
--output_dir experiments/domain_specific_deblur/results
--yml_path options/domain_specific_deblur/stylegan.yml

and using 2 GPU, but I have error so How do I can fix this?
image

When running with 512x512, the code errors out

Hi, I'm trying to run domain_specific_deblur.py with styleGAN2 on 512x512 dimension with pretrained models. However, after I fixed the latent and noise dimentions in dsd_stylegan2.py, the code still errors out on unet_parts.py. Is 512x512 supported?

The stacktrace is as below:

Traceback (most recent call last):
  File "domain_specific_deblur.py", line 84, in <module>
    for j, (HR, LR) in enumerate(model(ref_im)):
  File "/deblur/blur-kernel-space-exploring/models/dsd/dsd.py", line 188, in forward
    self.optimize_x_step(epoch)
  File "/deblur/blur-kernel-space-exploring/models/dsd/dsd.py", line 150, in optimize_x_step
    loss, loss_dict = self.loss_builder(latent_in, self.gen_im, self.gen_ker, epoch)
  File "//anaconda3/envs/torch/lib/python3.8/site-packages/torch/nn/modules/module.py", line 727, in _call_impl
    result = self.forward(*input, **kwargs)
  File "/deblur/blur-kernel-space-exploring/models/losses/dsd_loss.py", line 108, in forward
    "gen_im_lr": self.D.adaptKernel(gen_im, kernel),
  File "/work/deblur/blur-kernel-space-exploring/models/kernel_encoding/kernel_wizard.py", line 157, in adaptKernel
    out = self.adapter(x_sharp, kernel)
  File "/anaconda3/envs/torch/lib/python3.8/site-packages/torch/nn/modules/module.py", line 727, in _call_impl
    result = self.forward(*input, **kwargs)
  File "//work/deblur/blur-kernel-space-exploring/models/kernel_encoding/kernel_wizard.py", line 99, in forward
    return self.model(x, k)
  File "/anaconda3/envs/torch/lib/python3.8/site-packages/torch/nn/modules/module.py", line 727, in _call_impl
    result = self.forward(*input, **kwargs)
  File "/work/deblur/blur-kernel-space-exploring/models/backbones/unet_parts.py", line 103, in forward
    return self.up(self.submodule(self.down(x), noise))
  File "/anaconda3/envs/torch/lib/python3.8/site-packages/torch/nn/modules/module.py", line 727, in _call_impl
    result = self.forward(*input, **kwargs)
  File "/work/deblur/blur-kernel-space-exploring/models/backbones/unet_parts.py", line 109, in forward
    return torch.cat((self.up(self.submodule(self.down(x), noise)), x), dim=1)
  File "/anaconda3/envs/torch/lib/python3.8/site-packages/torch/nn/modules/module.py", line 727, in _call_impl
    result = self.forward(*input, **kwargs)
  File "/work/deblur/blur-kernel-space-exploring/models/backbones/unet_parts.py", line 109, in forward
    return torch.cat((self.up(self.submodule(self.down(x), noise)), x), dim=1)
  File "/anaconda3/envs/torch/lib/python3.8/site-packages/torch/nn/modules/module.py", line 727, in _call_impl
    result = self.forward(*input, **kwargs)
  File "/work/deblur/blur-kernel-space-exploring/models/backbones/unet_parts.py", line 109, in forward
    return torch.cat((self.up(self.submodule(self.down(x), noise)), x), dim=1)
  File "/anaconda3/envs/torch/lib/python3.8/site-packages/torch/nn/modules/module.py", line 727, in _call_impl
    result = self.forward(*input, **kwargs)
  File "/deblur/blur-kernel-space-exploring/models/backbones/unet_parts.py", line 107, in forward
    return torch.cat((self.up(torch.cat((self.down(x), noise), dim=1)), x), dim=1)
RuntimeError: Sizes of tensors must match except in dimension 2. Got 2 and 4 (The offending index is 0)

Thank you for your help!

about kernel

first of all, impressive work!

  1. I am confused about the form of kernel. Ki is the kernel of uniform blur or can also be kernel of non-uniform blur?
  2. Why the regularization term on the L2 norm of the kernel k works?

Output of the PostProcessBlock added to the input sharp image.

Hi!
First of all congratulations for the work.

In the code, the output of the postprocessblock is added to the input sharp image in order to generate the blur image.
In the paper i do not find any place that says explicitly that the output is a residual to be added to the residual in order to create the blur image. is it a bug? should be added? Or F computes directly the blur image?

Thanks!

training time

Thank you for your excellent work!
How much time did your work take to complete the training process on the v100gpu

G function training for other blur kernel family

In Readme, the author said “To do image deblurring, data augmentation, and blur generation, you first need to train the blur encoding network (The F function in the paper). This is the only network that you need to train.“ However, after I retrained the F function using out-of-focus blur- sharp image pairs and used it in the image deblurring script "generic_deblur.py" to deblur out-of-focus images, the results are not yet satisfying.

I trained with a batch_size of 13 and iteration of 600,000. The final loss is around 1e03, and the training datasets volume is around 3000 image pairs.

I wonder if I need to retrain the G function as well, if I am using the network to deblur out-of-focus images. If needed, is it possible to provide a script that trains both G and F functions?

Thank you!

generate_blur

To transfer the motion blur between the image pair (x, y) to a new image xˆ, we can simply compute: yˆ := F(ˆx, G(x, y)). however, when i set the x^ same as the x, the output y^ is largely different from y. It seems that the extracted kernel is not that accurate。

Generic_deblur.py result image using pretrained weights is different from the paper.

Hi. I'm trying to deblur face01.png image of blur_faces. While I was running generic_deblur.py with default settings with pretrained weights of GOPRO_woVAE.pth and the results were unsatisfactory. I checked that the generate_blur.py made satisfactory results of blur generating process. For prerequisites, I'm using the versons below.

  • Python = 3.9.5
  • Pytorch = 1.9.0
  • CUDA = 10.1

I tried to use Pytorch version of 1.4.0 but version error occured, so I used 1.9.0.
I want to get results in the paper for face01.png image, and if there is anything I should tune or change, please let me know.
Thank you for your help.

run the generate_blur.py ocur and i got a error

generate_blur.py:30: YAMLLoadWarning: calling yaml.load() without Loader=... is deprecated, as the default Loader is unsafe. Please read https://msg.pyyaml.org/load for full details.
opt = yaml.load(f)["KernelWizard"]
Sample #0/10
Traceback (most recent call last):
File "generate_blur.py", line 53, in
main()
File "generate_blur.py", line 45, in main
LQ_tensor = model.adaptKernel(HQ_tensor, kernel)
File "C:\Users\Xun.Huang\blur-kernel-space-exploring\models\kernel_encoding\kernel_wizard.py", line 157, in adaptKernel
out = self.adapter(x_sharp, kernel)
File "C:\Users\Xun.Huang\Anaconda3\envs\pytorch-env\lib\site-packages\torch\nn\modules\module.py", line 1051, in _call_impl
return forward_call(*input, **kwargs)
File "C:\Users\Xun.Huang\blur-kernel-space-exploring\models\kernel_encoding\kernel_wizard.py", line 99, in forward
return self.model(x, k)
File "C:\Users\Xun.Huang\Anaconda3\envs\pytorch-env\lib\site-packages\torch\nn\modules\module.py", line 1051, in _call_impl
return forward_call(*input, **kwargs)
File "C:\Users\Xun.Huang\blur-kernel-space-exploring\models\backbones\unet_parts.py", line 103, in forward
return self.up(self.submodule(self.down(x), noise))
File "C:\Users\Xun.Huang\Anaconda3\envs\pytorch-env\lib\site-packages\torch\nn\modules\module.py", line 1051, in _call_impl
return forward_call(*input, **kwargs)
File "C:\Users\Xun.Huang\blur-kernel-space-exploring\models\backbones\unet_parts.py", line 109, in forward
return torch.cat((self.up(self.submodule(self.down(x), noise)), x), dim=1)
File "C:\Users\Xun.Huang\Anaconda3\envs\pytorch-env\lib\site-packages\torch\nn\modules\module.py", line 1051, in _call_impl
return forward_call(*input, **kwargs)
File "C:\Users\Xun.Huang\blur-kernel-space-exploring\models\backbones\unet_parts.py", line 109, in forward
return torch.cat((self.up(self.submodule(self.down(x), noise)), x), dim=1)
File "C:\Users\Xun.Huang\Anaconda3\envs\pytorch-env\lib\site-packages\torch\nn\modules\module.py", line 1051, in _call_impl
return forward_call(*input, **kwargs)
File "C:\Users\Xun.Huang\blur-kernel-space-exploring\models\backbones\unet_parts.py", line 109, in forward
return torch.cat((self.up(self.submodule(self.down(x), noise)), x), dim=1)
File "C:\Users\Xun.Huang\Anaconda3\envs\pytorch-env\lib\site-packages\torch\nn\modules\module.py", line 1051, in _call_impl
return forward_call(*input, **kwargs)
File "C:\Users\Xun.Huang\blur-kernel-space-exploring\models\backbones\unet_parts.py", line 107, in forward
return torch.cat((self.up(torch.cat((self.down(x), noise), dim=1)), x), dim=1)
RuntimeError: torch.cat(): Sizes of tensors must match except in dimension 1. Got 4 and 2 in dimension 2 (The offending index is 1)

the pre-trained model file is GOPRO_wVAE . anyone can help me? Should i change the dim=1 to dim=2?

model license?

Hello! Thank you so much for sharing the code and the model.

I would like to ask, what protocol is the pre-training model? Can I use it in a business project?

Your reply is very much needed.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.