Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f83472d011 | ||
|
|
e1b8832f1b | ||
|
|
6ff747174d | ||
|
|
c1669c4b0a | ||
|
|
18a9c386a8 | ||
|
|
b659608fb3 | ||
|
|
ee5f7b34cb | ||
|
|
3ce826cabe | ||
|
|
2c20a354b6 | ||
|
|
3e1f780f51 | ||
|
|
f5ccd64ce5 | ||
|
|
194c2c14b3 | ||
|
|
0fcb49a299 | ||
|
|
9976a34454 | ||
|
|
424a09457b | ||
|
|
52f77e74a8 |
9
.github/workflows/publish-pip.yml
vendored
9
.github/workflows/publish-pip.yml
vendored
@@ -18,12 +18,15 @@ jobs:
|
|||||||
- name: Install PyTorch (cpu)
|
- name: Install PyTorch (cpu)
|
||||||
run: pip install torch==1.7.0+cpu torchvision==0.8.1+cpu -f https://download.pytorch.org/whl/torch_stable.html
|
run: pip install torch==1.7.0+cpu torchvision==0.8.1+cpu -f https://download.pytorch.org/whl/torch_stable.html
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: pip install -r requirements.txt
|
run: |
|
||||||
|
pip install basicsr
|
||||||
|
pip install facexlib
|
||||||
|
pip install gfpgan
|
||||||
|
pip install -r requirements.txt
|
||||||
- name: Build and install
|
- name: Build and install
|
||||||
run: rm -rf .eggs && pip install -e .
|
run: rm -rf .eggs && pip install -e .
|
||||||
- name: Build for distribution
|
- name: Build for distribution
|
||||||
# remove bdist_wheel for pip installation with compiling cuda extensions
|
run: python setup.py sdist bdist_wheel
|
||||||
run: python setup.py sdist
|
|
||||||
- name: Publish distribution to PyPI
|
- name: Publish distribution to PyPI
|
||||||
uses: pypa/gh-action-pypi-publish@master
|
uses: pypa/gh-action-pypi-publish@master
|
||||||
with:
|
with:
|
||||||
|
|||||||
45
CONTRIBUTING.md
Normal file
45
CONTRIBUTING.md
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
# Contributing to Real-ESRGAN
|
||||||
|
|
||||||
|
We like open-source and want to develop practical algorithms for general image restoration. However, individual strength is limited. So, any kinds of contributions are welcome, such as:
|
||||||
|
|
||||||
|
- New features
|
||||||
|
- New models (your fine-tuned models)
|
||||||
|
- Bug fixes
|
||||||
|
- Typo fixes
|
||||||
|
- Suggestions
|
||||||
|
- Maintenance
|
||||||
|
- Documents
|
||||||
|
- *etc*
|
||||||
|
|
||||||
|
## Workflow
|
||||||
|
|
||||||
|
1. Fork and pull the latest Real-ESRGAN repository
|
||||||
|
1. Checkout a new branch (do not use master branch for PRs)
|
||||||
|
1. Commit your changes
|
||||||
|
1. Create a PR
|
||||||
|
|
||||||
|
**Note**:
|
||||||
|
1. Please check the code style and linting
|
||||||
|
1. The style configuration is specified in [setup.cfg](setup.cfg)
|
||||||
|
1. If you use VSCode, the settings are configured in [.vscode/settings.json](.vscode/settings.json)
|
||||||
|
1. Strongly recommend using `pre-commit hook`. It will check your code style and linting before your commit.
|
||||||
|
1. In the root path of project folder, run `pre-commit install`
|
||||||
|
1. The pre-commit configuration is listed in [.pre-commit-config.yaml](.pre-commit-config.yaml)
|
||||||
|
1. Better to [open a discussion](https://github.com/xinntao/Real-ESRGAN/discussions) before large changes.
|
||||||
|
1. Welcome to discuss :sunglasses:. I will try my best to join the discussion.
|
||||||
|
|
||||||
|
## TODO List
|
||||||
|
|
||||||
|
:zero: The most straightforward way of improving model performance is to fine-tune on some specific datasets.
|
||||||
|
|
||||||
|
Here are some TODOs:
|
||||||
|
|
||||||
|
- [ ] optimize for human faces
|
||||||
|
- [ ] optimize for texts
|
||||||
|
- [ ] support controllable restoration strength
|
||||||
|
|
||||||
|
:one: There are also [several issues](https://github.com/xinntao/Real-ESRGAN/issues) that require helpers to improve. If you can help, please let me know :smile:
|
||||||
|
|
||||||
|
## Contributors
|
||||||
|
|
||||||
|
- [AK391](https://github.com/AK391): Integrate RealESRGAN to [Huggingface Spaces](https://huggingface.co/spaces) with [Gradio](https://github.com/gradio-app/gradio). See [Gradio Web Demo](https://huggingface.co/spaces/akhaliq/Real-ESRGAN).
|
||||||
61
README.md
61
README.md
@@ -2,28 +2,39 @@
|
|||||||
|
|
||||||
[](https://github.com/xinntao/Real-ESRGAN/releases)
|
[](https://github.com/xinntao/Real-ESRGAN/releases)
|
||||||
[](https://pypi.org/project/realesrgan/)
|
[](https://pypi.org/project/realesrgan/)
|
||||||
[](https://github.com/xinntao/Real-ESRGAN/issues)
|
[](https://github.com/xinntao/Real-ESRGAN/issues)
|
||||||
|
[](https://github.com/xinntao/Real-ESRGAN/issues)
|
||||||
[](https://github.com/xinntao/Real-ESRGAN/blob/master/LICENSE)
|
[](https://github.com/xinntao/Real-ESRGAN/blob/master/LICENSE)
|
||||||
[](https://github.com/xinntao/Real-ESRGAN/blob/master/.github/workflows/pylint.yml)
|
[](https://github.com/xinntao/Real-ESRGAN/blob/master/.github/workflows/pylint.yml)
|
||||||
[](https://github.com/xinntao/Real-ESRGAN/blob/master/.github/workflows/publish-pip.yml)
|
[](https://github.com/xinntao/Real-ESRGAN/blob/master/.github/workflows/publish-pip.yml)
|
||||||
|
|
||||||
1. [Colab Demo](https://colab.research.google.com/drive/1k2Zod6kSHEvraybHl50Lys0LerhyTMCo?usp=sharing) for Real-ESRGAN <a href="https://colab.research.google.com/drive/1k2Zod6kSHEvraybHl50Lys0LerhyTMCo?usp=sharing"><img src="https://colab.research.google.com/assets/colab-badge.svg" alt="google colab logo"></a>.
|
1. [Colab Demo](https://colab.research.google.com/drive/1k2Zod6kSHEvraybHl50Lys0LerhyTMCo?usp=sharing) for Real-ESRGAN <a href="https://colab.research.google.com/drive/1k2Zod6kSHEvraybHl50Lys0LerhyTMCo?usp=sharing"><img src="https://colab.research.google.com/assets/colab-badge.svg" alt="google colab logo"></a>.
|
||||||
2. Portable [Windows](https://github.com/xinntao/Real-ESRGAN/releases/download/v0.1.2/realesrgan-ncnn-vulkan-20210801-windows.zip) / [Linux](https://github.com/xinntao/Real-ESRGAN/releases/download/v0.1.2/realesrgan-ncnn-vulkan-20210801-ubuntu.zip) / [MacOS](https://github.com/xinntao/Real-ESRGAN/releases/download/v0.1.2/realesrgan-ncnn-vulkan-20210801-macos.zip) **executable files for Intel/AMD/Nvidia GPU**. You can find more information [here](#Portable-executable-files).
|
2. Portable [Windows](https://github.com/xinntao/Real-ESRGAN/releases/download/v0.2.2.4/realesrgan-ncnn-vulkan-20210901-windows.zip) / [Linux](https://github.com/xinntao/Real-ESRGAN/releases/download/v0.2.2.4/realesrgan-ncnn-vulkan-20210901-ubuntu.zip) / [MacOS](https://github.com/xinntao/Real-ESRGAN/releases/download/v0.2.2.4/realesrgan-ncnn-vulkan-20210901-macos.zip) **executable files for Intel/AMD/Nvidia GPU**. You can find more information [here](#Portable-executable-files).
|
||||||
|
|
||||||
Real-ESRGAN aims at developing **Practical Algorithms for General Image Restoration**.<br>
|
Real-ESRGAN aims at developing **Practical Algorithms for General Image Restoration**.<br>
|
||||||
We extend the powerful ESRGAN to a practical restoration application (namely, Real-ESRGAN), which is trained with pure synthetic data.
|
We extend the powerful ESRGAN to a practical restoration application (namely, Real-ESRGAN), which is trained with pure synthetic data.
|
||||||
|
|
||||||
|
:art: Real-ESRGAN needs your contributions. Any contributions are welcome, such as new features/models/typo fixes/suggestions/maintenance, *etc*. See [CONTRIBUTING.md](CONTRIBUTING.md). All contributors are list [here](CONTRIBUTING.md#Contributors).
|
||||||
|
|
||||||
:question: Frequently Asked Questions can be found in [FAQ.md](FAQ.md).
|
:question: Frequently Asked Questions can be found in [FAQ.md](FAQ.md).
|
||||||
|
|
||||||
:triangular_flag_on_post: **Updates**
|
:triangular_flag_on_post: **Updates**
|
||||||
|
- :white_check_mark: Add [*RealESRGAN_x4plus_anime_6B.pth*](https://github.com/xinntao/Real-ESRGAN/releases/download/v0.2.2.4/RealESRGAN_x4plus_anime_6B.pth), which is optimized for **anime** images with much smaller model size. More details and comparisons with [waifu2x](https://github.com/nihui/waifu2x-ncnn-vulkan) are in [**anime_model.md**](docs/anime_model.md)
|
||||||
|
- :white_check_mark: Support finetuning on your own data or paired data (*i.e.*, finetuning ESRGAN). See [here](Training.md#Finetune-Real-ESRGAN-on-your-own-dataset)
|
||||||
- :white_check_mark: Integrate [GFPGAN](https://github.com/TencentARC/GFPGAN) to support **face enhancement**.
|
- :white_check_mark: Integrate [GFPGAN](https://github.com/TencentARC/GFPGAN) to support **face enhancement**.
|
||||||
- :white_check_mark: Integrated to [Huggingface Spaces](https://huggingface.co/spaces) with [Gradio](https://github.com/gradio-app/gradio). See [Gradio Web Demo](https://huggingface.co/spaces/akhaliq/Real-ESRGAN).
|
- :white_check_mark: Integrated to [Huggingface Spaces](https://huggingface.co/spaces) with [Gradio](https://github.com/gradio-app/gradio). See [Gradio Web Demo](https://huggingface.co/spaces/akhaliq/Real-ESRGAN). Thanks [@AK391](https://github.com/AK391)
|
||||||
- :white_check_mark: Support arbitrary scale with `--outscale` (It actually further resizes outputs with `LANCZOS4`). Add *RealESRGAN_x2plus.pth* model.
|
- :white_check_mark: Support arbitrary scale with `--outscale` (It actually further resizes outputs with `LANCZOS4`). Add *RealESRGAN_x2plus.pth* model.
|
||||||
- :white_check_mark: [The inference code](inference_realesrgan.py) supports: 1) **tile** options; 2) images with **alpha channel**; 3) **gray** images; 4) **16-bit** images.
|
- :white_check_mark: [The inference code](inference_realesrgan.py) supports: 1) **tile** options; 2) images with **alpha channel**; 3) **gray** images; 4) **16-bit** images.
|
||||||
- :white_check_mark: The training codes have been released. A detailed guide can be found in [Training.md](Training.md).
|
- :white_check_mark: The training codes have been released. A detailed guide can be found in [Training.md](Training.md).
|
||||||
|
|
||||||
If Real-ESRGAN is helpful in your photos/projects, please help to :star: this repo. Thanks:blush: <br>
|
---
|
||||||
Other recommended projects:   :arrow_forward: [GFPGAN](https://github.com/TencentARC/GFPGAN)   :arrow_forward: [BasicSR](https://github.com/xinntao/BasicSR)   :arrow_forward: [facexlib](https://github.com/xinntao/facexlib)
|
|
||||||
|
If Real-ESRGAN is helpful in your photos/projects, please help to :star: this repo or recommend it to your friends. Thanks:blush: <br>
|
||||||
|
Other recommended projects:<br>
|
||||||
|
:arrow_forward: [GFPGAN](https://github.com/TencentARC/GFPGAN): A practical algorithm for real-world face restoration <br>
|
||||||
|
:arrow_forward: [BasicSR](https://github.com/xinntao/BasicSR): An ppen-source image and video restoration toolbox<br>
|
||||||
|
:arrow_forward: [facexlib](https://github.com/xinntao/facexlib): A collection that provides useful face-relation functions.<br>
|
||||||
|
:arrow_forward: [HandyView](https://github.com/xinntao/HandyView): A PyQt5-based image viewer that is handy for view and comparison. <br>
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -52,7 +63,7 @@ Here is a TODO list in the near future:
|
|||||||
|
|
||||||
- [ ] optimize for human faces
|
- [ ] optimize for human faces
|
||||||
- [ ] optimize for texts
|
- [ ] optimize for texts
|
||||||
- [ ] optimize for anime images [in progress]
|
- [x] optimize for anime images
|
||||||
- [ ] support more scales
|
- [ ] support more scales
|
||||||
- [ ] support controllable restoration strength
|
- [ ] support controllable restoration strength
|
||||||
|
|
||||||
@@ -77,7 +88,7 @@ We have provided three models:
|
|||||||
|
|
||||||
1. realesrgan-x4plus (default)
|
1. realesrgan-x4plus (default)
|
||||||
2. realesrnet-x4plus
|
2. realesrnet-x4plus
|
||||||
3. esrgan-x4
|
3. realesrgan-x4plus-anime (optimized for anime images, small model size)
|
||||||
|
|
||||||
You can use the `-n` argument for other models, for example, `./realesrgan-ncnn-vulkan.exe -i input.jpg -o output.png -n realesrnet-x4plus`
|
You can use the `-n` argument for other models, for example, `./realesrgan-ncnn-vulkan.exe -i input.jpg -o output.png -n realesrnet-x4plus`
|
||||||
|
|
||||||
@@ -116,9 +127,9 @@ This executable file is based on the wonderful [Tencent/ncnn](https://github.com
|
|||||||
|
|
||||||
## :zap: Quick Inference
|
## :zap: Quick Inference
|
||||||
|
|
||||||
Download pre-trained models: [RealESRGAN_x4plus.pth](https://github.com/xinntao/Real-ESRGAN/releases/download/v0.1.0/RealESRGAN_x4plus.pth)
|
### Inference general images
|
||||||
|
|
||||||
Download pretrained models:
|
Download pre-trained models: [RealESRGAN_x4plus.pth](https://github.com/xinntao/Real-ESRGAN/releases/download/v0.1.0/RealESRGAN_x4plus.pth)
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
wget https://github.com/xinntao/Real-ESRGAN/releases/download/v0.1.0/RealESRGAN_x4plus.pth -P experiments/pretrained_models
|
wget https://github.com/xinntao/Real-ESRGAN/releases/download/v0.1.0/RealESRGAN_x4plus.pth -P experiments/pretrained_models
|
||||||
@@ -132,14 +143,36 @@ python inference_realesrgan.py --model_path experiments/pretrained_models/RealES
|
|||||||
|
|
||||||
Results are in the `results` folder
|
Results are in the `results` folder
|
||||||
|
|
||||||
|
### Inference anime images
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<img src="https://raw.githubusercontent.com/xinntao/public-figures/master/Real-ESRGAN/cmp_realesrgan_anime_1.png">
|
||||||
|
</p>
|
||||||
|
|
||||||
|
Pre-trained models: [RealESRGAN_x4plus_anime_6B](https://github.com/xinntao/Real-ESRGAN/releases/download/v0.2.2.4/RealESRGAN_x4plus_anime_6B.pth)<br>
|
||||||
|
More details and comparisons with [waifu2x](https://github.com/nihui/waifu2x-ncnn-vulkan) are in [**anime_model.md**](docs/anime_model.md)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# download model
|
||||||
|
wget https://github.com/xinntao/Real-ESRGAN/releases/download/v0.2.2.4/RealESRGAN_x4plus_anime_6B.pth -P experiments/pretrained_models
|
||||||
|
# inference
|
||||||
|
python inference_realesrgan.py --model_path experiments/pretrained_models/RealESRGAN_x4plus_anime_6B.pth --input inputs
|
||||||
|
```
|
||||||
|
|
||||||
|
Results are in the `results` folder
|
||||||
|
|
||||||
## :european_castle: Model Zoo
|
## :european_castle: Model Zoo
|
||||||
|
|
||||||
- [RealESRGAN-x4plus](https://github.com/xinntao/Real-ESRGAN/releases/download/v0.1.0/RealESRGAN_x4plus.pth)
|
- [RealESRGAN_x4plus](https://github.com/xinntao/Real-ESRGAN/releases/download/v0.1.0/RealESRGAN_x4plus.pth)
|
||||||
- [RealESRNet-x4plus](https://github.com/xinntao/Real-ESRGAN/releases/download/v0.1.1/RealESRNet_x4plus.pth)
|
- [RealESRGAN_x4plus_netD](https://github.com/xinntao/Real-ESRGAN/releases/download/v0.2.2.3/RealESRGAN_x4plus_netD.pth)
|
||||||
- [RealESRGAN-x2plus](https://github.com/xinntao/Real-ESRGAN/releases/download/v0.2.1/RealESRGAN_x2plus.pth)
|
- [RealESRGAN_x4plus_anime_6B](https://github.com/xinntao/Real-ESRGAN/releases/download/v0.2.2.4/RealESRGAN_x4plus_anime_6B.pth)
|
||||||
- [official ESRGAN-x4](https://github.com/xinntao/Real-ESRGAN/releases/download/v0.1.1/ESRGAN_SRx4_DF2KOST_official-ff704c30.pth)
|
- [RealESRGAN_x4plus_anime_6B_netD](https://github.com/xinntao/Real-ESRGAN/releases/download/v0.2.2.4/RealESRGAN_x4plus_anime_6B_netD.pth)
|
||||||
|
- [RealESRNet_x4plus](https://github.com/xinntao/Real-ESRGAN/releases/download/v0.1.1/RealESRNet_x4plus.pth)
|
||||||
|
- [RealESRGAN_x2plus](https://github.com/xinntao/Real-ESRGAN/releases/download/v0.2.1/RealESRGAN_x2plus.pth)
|
||||||
|
- [RealESRGAN_x2plus_netD](https://github.com/xinntao/Real-ESRGAN/releases/download/v0.2.2.3/RealESRGAN_x2plus_netD.pth)
|
||||||
|
- [official ESRGAN_x4](https://github.com/xinntao/Real-ESRGAN/releases/download/v0.1.1/ESRGAN_SRx4_DF2KOST_official-ff704c30.pth)
|
||||||
|
|
||||||
## :computer: Training
|
## :computer: Training and Finetuning on your own dataset
|
||||||
|
|
||||||
A detailed guide can be found in [Training.md](Training.md).
|
A detailed guide can be found in [Training.md](Training.md).
|
||||||
|
|
||||||
|
|||||||
157
Training.md
157
Training.md
@@ -1,16 +1,24 @@
|
|||||||
# :computer: How to Train Real-ESRGAN
|
# :computer: How to Train/Finetune Real-ESRGAN
|
||||||
|
|
||||||
The training codes have been released. <br>
|
- [Train Real-ESRGAN](#train-real-esrgan)
|
||||||
Note that the codes have a lot of refactoring. So there may be some bugs/performance drops. Welcome to report bugs/issues.
|
- [Overview](#overview)
|
||||||
|
- [Dataset Preparation](#dataset-preparation)
|
||||||
|
- [Train Real-ESRNet](#Train-Real-ESRNet)
|
||||||
|
- [Train Real-ESRGAN](#Train-Real-ESRGAN)
|
||||||
|
- [Finetune Real-ESRGAN on your own dataset](#Finetune-Real-ESRGAN-on-your-own-dataset)
|
||||||
|
- [Generate degraded images on the fly](#Generate-degraded-images-on-the-fly)
|
||||||
|
- [Use paired training data](#Use-paired-training-data)
|
||||||
|
|
||||||
## Overview
|
## Train Real-ESRGAN
|
||||||
|
|
||||||
|
### Overview
|
||||||
|
|
||||||
The training has been divided into two stages. These two stages have the same data synthesis process and training pipeline, except for the loss functions. Specifically,
|
The training has been divided into two stages. These two stages have the same data synthesis process and training pipeline, except for the loss functions. Specifically,
|
||||||
|
|
||||||
1. We first train Real-ESRNet with L1 loss from the pre-trained model ESRGAN.
|
1. We first train Real-ESRNet with L1 loss from the pre-trained model ESRGAN.
|
||||||
1. We then use the trained Real-ESRNet model as an initialization of the generator, and train the Real-ESRGAN with a combination of L1 loss, perceptual loss and GAN loss.
|
1. We then use the trained Real-ESRNet model as an initialization of the generator, and train the Real-ESRGAN with a combination of L1 loss, perceptual loss and GAN loss.
|
||||||
|
|
||||||
## Dataset Preparation
|
### Dataset Preparation
|
||||||
|
|
||||||
We use DF2K (DIV2K and Flickr2K) + OST datasets for our training. Only HR images are required. <br>
|
We use DF2K (DIV2K and Flickr2K) + OST datasets for our training. Only HR images are required. <br>
|
||||||
You can download from :
|
You can download from :
|
||||||
@@ -19,9 +27,30 @@ You can download from :
|
|||||||
2. Flickr2K: https://cv.snu.ac.kr/research/EDSR/Flickr2K.tar
|
2. Flickr2K: https://cv.snu.ac.kr/research/EDSR/Flickr2K.tar
|
||||||
3. OST: https://openmmlab.oss-cn-hangzhou.aliyuncs.com/datasets/OST_dataset.zip
|
3. OST: https://openmmlab.oss-cn-hangzhou.aliyuncs.com/datasets/OST_dataset.zip
|
||||||
|
|
||||||
For the DF2K dataset, we use a multi-scale strategy, *i.e.*, we downsample HR images to obtain several Ground-Truth images with different scales.
|
Here are steps for data preparation.
|
||||||
|
|
||||||
We then crop DF2K images into sub-images for faster IO and processing.
|
#### Step 1: [Optional] Generate multi-scale images
|
||||||
|
|
||||||
|
For the DF2K dataset, we use a multi-scale strategy, *i.e.*, we downsample HR images to obtain several Ground-Truth images with different scales. <br>
|
||||||
|
You can use the [scripts/generate_multiscale_DF2K.py](scripts/generate_multiscale_DF2K.py) script to geneate multi-scale images. <br>
|
||||||
|
Note that this step can be omitted if you just want to have a fast try.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python scripts/generate_multiscale_DF2K.py --input datasets/DF2K/DF2K_HR --output datasets/DF2K/DF2K_multiscale
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Step 2: [Optional] Crop to sub-images
|
||||||
|
|
||||||
|
We then crop DF2K images into sub-images for faster IO and processing.<br>
|
||||||
|
This step is optional if your IO is enough or your disk space is limited.
|
||||||
|
|
||||||
|
You can use the [scripts/extract_subimages.py](scripts/extract_subimages.py) script. Here is the example:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python scripts/extract_subimages.py --input datasets/DF2K/DF2K_multiscale --output datasets/DF2K/DF2K_multiscale_sub --crop_size 400 --step 200
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Step 3: Prepare a txt for meta information
|
||||||
|
|
||||||
You need to prepare a txt file containing the image paths. The following are some examples in `meta_info_DF2Kmultiscale+OST_sub.txt` (As different users may have different sub-images partitions, this file is not suitable for your purpose and you need to prepare your own txt file):
|
You need to prepare a txt file containing the image paths. The following are some examples in `meta_info_DF2Kmultiscale+OST_sub.txt` (As different users may have different sub-images partitions, this file is not suitable for your purpose and you need to prepare your own txt file):
|
||||||
|
|
||||||
@@ -32,7 +61,14 @@ DF2K_HR_sub/000001_s003.png
|
|||||||
...
|
...
|
||||||
```
|
```
|
||||||
|
|
||||||
## Train Real-ESRNet
|
You can use the [scripts/generate_meta_info.py](scripts/generate_meta_info.py) script to generate the txt file. <br>
|
||||||
|
You can merge several folders into one meta_info txt. Here is the example:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python scripts/generate_meta_info.py --input datasets/DF2K/DF2K_HR, datasets/DF2K/DF2K_multiscale --root datasets/DF2K, datasets/DF2K --meta_info datasets/DF2K/meta_info/meta_info_DF2Kmultiscale.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
### Train Real-ESRNet
|
||||||
|
|
||||||
1. Download pre-trained model [ESRGAN](https://github.com/xinntao/Real-ESRGAN/releases/download/v0.1.1/ESRGAN_SRx4_DF2KOST_official-ff704c30.pth) into `experiments/pretrained_models`.
|
1. Download pre-trained model [ESRGAN](https://github.com/xinntao/Real-ESRGAN/releases/download/v0.1.1/ESRGAN_SRx4_DF2KOST_official-ff704c30.pth) into `experiments/pretrained_models`.
|
||||||
```bash
|
```bash
|
||||||
@@ -84,7 +120,7 @@ DF2K_HR_sub/000001_s003.png
|
|||||||
python -m torch.distributed.launch --nproc_per_node=4 --master_port=4321 realesrgan/train.py -opt options/train_realesrnet_x4plus.yml --launcher pytorch --auto_resume
|
python -m torch.distributed.launch --nproc_per_node=4 --master_port=4321 realesrgan/train.py -opt options/train_realesrnet_x4plus.yml --launcher pytorch --auto_resume
|
||||||
```
|
```
|
||||||
|
|
||||||
## Train Real-ESRGAN
|
### Train Real-ESRGAN
|
||||||
|
|
||||||
1. After the training of Real-ESRNet, you now have the file `experiments/train_RealESRNetx4plus_1000k_B12G4_fromESRGAN/model/net_g_1000000.pth`. If you need to specify the pre-trained path to other files, modify the `pretrain_network_g` value in the option file `train_realesrgan_x4plus.yml`.
|
1. After the training of Real-ESRNet, you now have the file `experiments/train_RealESRNetx4plus_1000k_B12G4_fromESRGAN/model/net_g_1000000.pth`. If you need to specify the pre-trained path to other files, modify the `pretrain_network_g` value in the option file `train_realesrgan_x4plus.yml`.
|
||||||
1. Modify the option file `train_realesrgan_x4plus.yml` accordingly. Most modifications are similar to those listed above.
|
1. Modify the option file `train_realesrgan_x4plus.yml` accordingly. Most modifications are similar to those listed above.
|
||||||
@@ -98,3 +134,106 @@ DF2K_HR_sub/000001_s003.png
|
|||||||
CUDA_VISIBLE_DEVICES=0,1,2,3 \
|
CUDA_VISIBLE_DEVICES=0,1,2,3 \
|
||||||
python -m torch.distributed.launch --nproc_per_node=4 --master_port=4321 realesrgan/train.py -opt options/train_realesrgan_x4plus.yml --launcher pytorch --auto_resume
|
python -m torch.distributed.launch --nproc_per_node=4 --master_port=4321 realesrgan/train.py -opt options/train_realesrgan_x4plus.yml --launcher pytorch --auto_resume
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Finetune Real-ESRGAN on your own dataset
|
||||||
|
|
||||||
|
You can finetune Real-ESRGAN on your own dataset. Typically, the fine-tuning process can be divided into two cases:
|
||||||
|
|
||||||
|
1. [Generate degraded images on the fly](#Generate-degraded-images-on-the-fly)
|
||||||
|
1. [Use your own **paired** data](#Use-paired-training-data)
|
||||||
|
|
||||||
|
### Generate degraded images on the fly
|
||||||
|
|
||||||
|
Only high-resolution images are required. The low-quality images are generated with the degradation process described in Real-ESRGAN during trainig.
|
||||||
|
|
||||||
|
**1. Prepare dataset**
|
||||||
|
|
||||||
|
See [this section](#dataset-preparation) for more details.
|
||||||
|
|
||||||
|
**2. Download pre-trained models**
|
||||||
|
|
||||||
|
Download pre-trained models into `experiments/pretrained_models`.
|
||||||
|
|
||||||
|
- *RealESRGAN_x4plus.pth*:
|
||||||
|
```bash
|
||||||
|
wget https://github.com/xinntao/Real-ESRGAN/releases/download/v0.1.0/RealESRGAN_x4plus.pth -P experiments/pretrained_models
|
||||||
|
```
|
||||||
|
|
||||||
|
- *RealESRGAN_x4plus_netD.pth*:
|
||||||
|
```bash
|
||||||
|
wget https://github.com/xinntao/Real-ESRGAN/releases/download/v0.2.2.3/RealESRGAN_x4plus_netD.pth -P experiments/pretrained_models
|
||||||
|
```
|
||||||
|
|
||||||
|
**3. Finetune**
|
||||||
|
|
||||||
|
Modify [options/finetune_realesrgan_x4plus.yml](options/finetune_realesrgan_x4plus.yml) accordingly, especially the `datasets` part:
|
||||||
|
|
||||||
|
```yml
|
||||||
|
train:
|
||||||
|
name: DF2K+OST
|
||||||
|
type: RealESRGANDataset
|
||||||
|
dataroot_gt: datasets/DF2K # modify to the root path of your folder
|
||||||
|
meta_info: realesrgan/meta_info/meta_info_DF2Kmultiscale+OST_sub.txt # modify to your own generate meta info txt
|
||||||
|
io_backend:
|
||||||
|
type: disk
|
||||||
|
```
|
||||||
|
|
||||||
|
We use four GPUs for training. We use the `--auto_resume` argument to automatically resume the training if necessary.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
CUDA_VISIBLE_DEVICES=0,1,2,3 \
|
||||||
|
python -m torch.distributed.launch --nproc_per_node=4 --master_port=4321 realesrgan/train.py -opt options/finetune_realesrgan_x4plus.yml --launcher pytorch --auto_resume
|
||||||
|
```
|
||||||
|
|
||||||
|
### Use your own paired data
|
||||||
|
|
||||||
|
You can also finetune RealESRGAN with your own paired data. It is more similar to fine-tuning ESRGAN.
|
||||||
|
|
||||||
|
**1. Prepare dataset**
|
||||||
|
|
||||||
|
Assume that you already have two folders:
|
||||||
|
|
||||||
|
- **gt folder** (Ground-truth, high-resolution images): *datasets/DF2K/DIV2K_train_HR_sub*
|
||||||
|
- **lq folder** (Low quality, low-resolution images): *datasets/DF2K/DIV2K_train_LR_bicubic_X4_sub*
|
||||||
|
|
||||||
|
Then, you can prepare the meta_info txt file using the script [scripts/generate_meta_info_pairdata.py](scripts/generate_meta_info_pairdata.py):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python scripts/generate_meta_info_pairdata.py --input datasets/DF2K/DIV2K_train_HR_sub datasets/DF2K/DIV2K_train_LR_bicubic_X4_sub --meta_info datasets/DF2K/meta_info/meta_info_DIV2K_sub_pair.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
**2. Download pre-trained models**
|
||||||
|
|
||||||
|
Download pre-trained models into `experiments/pretrained_models`.
|
||||||
|
|
||||||
|
- *RealESRGAN_x4plus.pth*
|
||||||
|
```bash
|
||||||
|
wget https://github.com/xinntao/Real-ESRGAN/releases/download/v0.1.0/RealESRGAN_x4plus.pth -P experiments/pretrained_models
|
||||||
|
```
|
||||||
|
|
||||||
|
- *RealESRGAN_x4plus_netD.pth*
|
||||||
|
```bash
|
||||||
|
wget https://github.com/xinntao/Real-ESRGAN/releases/download/v0.2.2.3/RealESRGAN_x4plus_netD.pth -P experiments/pretrained_models
|
||||||
|
```
|
||||||
|
|
||||||
|
**3. Finetune**
|
||||||
|
|
||||||
|
Modify [options/finetune_realesrgan_x4plus_pairdata.yml](options/finetune_realesrgan_x4plus_pairdata.yml) accordingly, especially the `datasets` part:
|
||||||
|
|
||||||
|
```yml
|
||||||
|
train:
|
||||||
|
name: DIV2K
|
||||||
|
type: RealESRGANPairedDataset
|
||||||
|
dataroot_gt: datasets/DF2K # modify to the root path of your folder
|
||||||
|
dataroot_lq: datasets/DF2K # modify to the root path of your folder
|
||||||
|
meta_info: datasets/DF2K/meta_info/meta_info_DIV2K_sub_pair.txt # modify to the root path of your folder
|
||||||
|
io_backend:
|
||||||
|
type: disk
|
||||||
|
```
|
||||||
|
|
||||||
|
We use four GPUs for training. We use the `--auto_resume` argument to automatically resume the training if necessary.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
CUDA_VISIBLE_DEVICES=0,1,2,3 \
|
||||||
|
python -m torch.distributed.launch --nproc_per_node=4 --master_port=4321 realesrgan/train.py -opt options/finetune_realesrgan_x4plus_pairdata.yml --launcher pytorch --auto_resume
|
||||||
|
```
|
||||||
|
|||||||
68
docs/anime_model.md
Normal file
68
docs/anime_model.md
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
# Anime model
|
||||||
|
|
||||||
|
:white_check_mark: We add [*RealESRGAN_x4plus_anime_6B.pth*](https://github.com/xinntao/Real-ESRGAN/releases/download/v0.2.2.4/RealESRGAN_x4plus_anime_6B.pth), which is optimized for **anime** images with much smaller model size.
|
||||||
|
|
||||||
|
- [How to Use](#How-to-Use)
|
||||||
|
- [PyTorch Inference](#PyTorch-Inference)
|
||||||
|
- [ncnn Executable File](#ncnn-Executable-File)
|
||||||
|
- [Comparisons with waifu2x](#Comparisons-with-waifu2x)
|
||||||
|
- [Comparions with Sliding Bars](#Comparions-with-Sliding-Bars)
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<img src="https://raw.githubusercontent.com/xinntao/public-figures/master/Real-ESRGAN/cmp_realesrgan_anime_1.png">
|
||||||
|
</p>
|
||||||
|
|
||||||
|
The following is a video comparison with sliding bar. You may need to use the full-screen mode for better visual quality, as the original image is large; otherwise, you may encounter aliasing issue.
|
||||||
|
|
||||||
|
https://user-images.githubusercontent.com/17445847/131535127-613250d4-f754-4e20-9720-2f9608ad0675.mp4
|
||||||
|
|
||||||
|
## How to Use
|
||||||
|
|
||||||
|
### PyTorch Inference
|
||||||
|
|
||||||
|
Pre-trained models: [RealESRGAN_x4plus_anime_6B](https://github.com/xinntao/Real-ESRGAN/releases/download/v0.2.2.4/RealESRGAN_x4plus_anime_6B.pth)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# download model
|
||||||
|
wget https://github.com/xinntao/Real-ESRGAN/releases/download/v0.2.2.4/RealESRGAN_x4plus_anime_6B.pth -P experiments/pretrained_models
|
||||||
|
# inference
|
||||||
|
python inference_realesrgan.py --model_path experiments/pretrained_models/RealESRGAN_x4plus_anime_6B.pth --input inputs
|
||||||
|
```
|
||||||
|
|
||||||
|
### ncnn Executable File
|
||||||
|
|
||||||
|
Download the latest portable [Windows](https://github.com/xinntao/Real-ESRGAN/releases/download/v0.2.2.4/realesrgan-ncnn-vulkan-20210901-windows.zip) / [Linux](https://github.com/xinntao/Real-ESRGAN/releases/download/v0.2.2.4/realesrgan-ncnn-vulkan-20210901-ubuntu.zip) / [MacOS](https://github.com/xinntao/Real-ESRGAN/releases/download/v0.2.2.4/realesrgan-ncnn-vulkan-20210901-macos.zip) **executable files for Intel/AMD/Nvidia GPU**.
|
||||||
|
|
||||||
|
Taking the Windows as example, run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./realesrgan-ncnn-vulkan.exe -i input.jpg -o output.png -n realesrgan-x4plus-anime
|
||||||
|
```
|
||||||
|
|
||||||
|
## Comparisons with waifu2x
|
||||||
|
|
||||||
|
We compare Real-ESRGAN-anime with [waifu2x](https://github.com/nihui/waifu2x-ncnn-vulkan). We use the `-n 2 -s 4` for waifu2x.
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<img src="https://raw.githubusercontent.com/xinntao/public-figures/master/Real-ESRGAN/cmp_realesrgan_anime_1.png">
|
||||||
|
</p>
|
||||||
|
<p align="center">
|
||||||
|
<img src="https://raw.githubusercontent.com/xinntao/public-figures/master/Real-ESRGAN/cmp_realesrgan_anime_2.png">
|
||||||
|
</p>
|
||||||
|
<p align="center">
|
||||||
|
<img src="https://raw.githubusercontent.com/xinntao/public-figures/master/Real-ESRGAN/cmp_realesrgan_anime_3.png">
|
||||||
|
</p>
|
||||||
|
<p align="center">
|
||||||
|
<img src="https://raw.githubusercontent.com/xinntao/public-figures/master/Real-ESRGAN/cmp_realesrgan_anime_4.png">
|
||||||
|
</p>
|
||||||
|
<p align="center">
|
||||||
|
<img src="https://raw.githubusercontent.com/xinntao/public-figures/master/Real-ESRGAN/cmp_realesrgan_anime_5.png">
|
||||||
|
</p>
|
||||||
|
|
||||||
|
## Comparisons with Sliding Bars
|
||||||
|
|
||||||
|
The following are video comparisons with sliding bar. You may need to use the full-screen mode for better visual quality, as the original image is large; otherwise, you may encounter aliasing issue.
|
||||||
|
|
||||||
|
https://user-images.githubusercontent.com/17445847/131536647-a2fbf896-b495-4a9f-b1dd-ca7bbc90101a.mp4
|
||||||
|
|
||||||
|
https://user-images.githubusercontent.com/17445847/131536742-6d9d82b6-9765-4296-a15f-18f9aeaa5465.mp4
|
||||||
11
docs/ncnn_conversion.md
Normal file
11
docs/ncnn_conversion.md
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
# Instructions on converting to NCNN models
|
||||||
|
|
||||||
|
1. Convert to onnx model with `scripts/pytorch2onnx.py`. Remember to modify codes accordingly
|
||||||
|
1. Convert onnx model to ncnn model
|
||||||
|
1. `cd ncnn-master\ncnn\build\tools\onnx`
|
||||||
|
1. `onnx2ncnn.exe realesrgan-x4.onnx realesrgan-x4-raw.param realesrgan-x4-raw.bin`
|
||||||
|
1. Optimize ncnn model
|
||||||
|
1. fp16 mode
|
||||||
|
1. `cd ncnn-master\ncnn\build\tools`
|
||||||
|
1. `ncnnoptimize.exe realesrgan-x4-raw.param realesrgan-x4-raw.bin realesrgan-x4.param realesrgan-x4.bin 1`
|
||||||
|
1. Modify the blob name in `realesrgan-x4.param`: `data` and `output`
|
||||||
@@ -2,6 +2,7 @@ import argparse
|
|||||||
import cv2
|
import cv2
|
||||||
import glob
|
import glob
|
||||||
import os
|
import os
|
||||||
|
from basicsr.archs.rrdbnet_arch import RRDBNet
|
||||||
|
|
||||||
from realesrgan import RealESRGANer
|
from realesrgan import RealESRGANer
|
||||||
|
|
||||||
@@ -18,11 +19,12 @@ def main():
|
|||||||
parser.add_argument('--netscale', type=int, default=4, help='Upsample scale factor of the network')
|
parser.add_argument('--netscale', type=int, default=4, help='Upsample scale factor of the network')
|
||||||
parser.add_argument('--outscale', type=float, default=4, help='The final upsampling scale of the image')
|
parser.add_argument('--outscale', type=float, default=4, help='The final upsampling scale of the image')
|
||||||
parser.add_argument('--suffix', type=str, default='out', help='Suffix of the restored image')
|
parser.add_argument('--suffix', type=str, default='out', help='Suffix of the restored image')
|
||||||
parser.add_argument('--tile', type=int, default=800, help='Tile size, 0 for no tile during testing')
|
parser.add_argument('--tile', type=int, default=0, help='Tile size, 0 for no tile during testing')
|
||||||
parser.add_argument('--tile_pad', type=int, default=10, help='Tile padding')
|
parser.add_argument('--tile_pad', type=int, default=10, help='Tile padding')
|
||||||
parser.add_argument('--pre_pad', type=int, default=0, help='Pre padding size at each border')
|
parser.add_argument('--pre_pad', type=int, default=0, help='Pre padding size at each border')
|
||||||
parser.add_argument('--face_enhance', action='store_true', help='Use GFPGAN to enhance face')
|
parser.add_argument('--face_enhance', action='store_true', help='Use GFPGAN to enhance face')
|
||||||
parser.add_argument('--half', action='store_true', help='Use half precision during inference')
|
parser.add_argument('--half', action='store_true', help='Use half precision during inference')
|
||||||
|
parser.add_argument('--block', type=int, default=23, help='num_block in RRDB')
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'--alpha_upsampler',
|
'--alpha_upsampler',
|
||||||
type=str,
|
type=str,
|
||||||
@@ -35,9 +37,17 @@ def main():
|
|||||||
help='Image extension. Options: auto | jpg | png, auto means using the same extension as inputs')
|
help='Image extension. Options: auto | jpg | png, auto means using the same extension as inputs')
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
if 'RealESRGAN_x4plus_anime_6B.pth' in args.model_path:
|
||||||
|
args.block = 6
|
||||||
|
elif 'RealESRGAN_x2plus.pth' in args.model_path:
|
||||||
|
args.netscale = 2
|
||||||
|
|
||||||
|
model = RRDBNet(num_in_ch=3, num_out_ch=3, num_feat=64, num_block=args.block, num_grow_ch=32, scale=args.netscale)
|
||||||
|
|
||||||
upsampler = RealESRGANer(
|
upsampler = RealESRGANer(
|
||||||
scale=args.netscale,
|
scale=args.netscale,
|
||||||
model_path=args.model_path,
|
model_path=args.model_path,
|
||||||
|
model=model,
|
||||||
tile=args.tile,
|
tile=args.tile,
|
||||||
tile_pad=args.tile_pad,
|
tile_pad=args.tile_pad,
|
||||||
pre_pad=args.pre_pad,
|
pre_pad=args.pre_pad,
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
# general settings
|
# general settings
|
||||||
name: finetune_RealESRGANx4plus_400k_B12G4
|
name: finetune_RealESRGANx4plus_400k
|
||||||
model_type: RealESRGANModel
|
model_type: RealESRGANModel
|
||||||
scale: 4
|
scale: 4
|
||||||
num_gpu: 4
|
num_gpu: auto
|
||||||
manual_seed: 0
|
manual_seed: 0
|
||||||
|
|
||||||
# ----------------- options for synthesizing training data in RealESRGANModel ----------------- #
|
# ----------------- options for synthesizing training data in RealESRGANModel ----------------- #
|
||||||
|
|||||||
151
options/finetune_realesrgan_x4plus_pairdata.yml
Normal file
151
options/finetune_realesrgan_x4plus_pairdata.yml
Normal file
@@ -0,0 +1,151 @@
|
|||||||
|
# general settings
|
||||||
|
name: finetune_RealESRGANx4plus_400k_pairdata
|
||||||
|
model_type: RealESRGANModel
|
||||||
|
scale: 4
|
||||||
|
num_gpu: auto
|
||||||
|
manual_seed: 0
|
||||||
|
|
||||||
|
# USM the ground-truth
|
||||||
|
l1_gt_usm: True
|
||||||
|
percep_gt_usm: True
|
||||||
|
gan_gt_usm: False
|
||||||
|
|
||||||
|
high_order_degradation: False # do not use the high-order degradation generation process
|
||||||
|
|
||||||
|
# dataset and data loader settings
|
||||||
|
datasets:
|
||||||
|
train:
|
||||||
|
name: DIV2K
|
||||||
|
type: RealESRGANPairedDataset
|
||||||
|
dataroot_gt: datasets/DF2K
|
||||||
|
dataroot_lq: datasets/DF2K
|
||||||
|
meta_info: datasets/DF2K/meta_info/meta_info_DIV2K_sub_pair.txt
|
||||||
|
io_backend:
|
||||||
|
type: disk
|
||||||
|
|
||||||
|
gt_size: 256
|
||||||
|
use_hflip: True
|
||||||
|
use_rot: False
|
||||||
|
|
||||||
|
# data loader
|
||||||
|
use_shuffle: true
|
||||||
|
num_worker_per_gpu: 5
|
||||||
|
batch_size_per_gpu: 12
|
||||||
|
dataset_enlarge_ratio: 1
|
||||||
|
prefetch_mode: ~
|
||||||
|
|
||||||
|
# Uncomment these for validation
|
||||||
|
# val:
|
||||||
|
# name: validation
|
||||||
|
# type: PairedImageDataset
|
||||||
|
# dataroot_gt: path_to_gt
|
||||||
|
# dataroot_lq: path_to_lq
|
||||||
|
# io_backend:
|
||||||
|
# type: disk
|
||||||
|
|
||||||
|
# network structures
|
||||||
|
network_g:
|
||||||
|
type: RRDBNet
|
||||||
|
num_in_ch: 3
|
||||||
|
num_out_ch: 3
|
||||||
|
num_feat: 64
|
||||||
|
num_block: 23
|
||||||
|
num_grow_ch: 32
|
||||||
|
|
||||||
|
|
||||||
|
network_d:
|
||||||
|
type: UNetDiscriminatorSN
|
||||||
|
num_in_ch: 3
|
||||||
|
num_feat: 64
|
||||||
|
skip_connection: True
|
||||||
|
|
||||||
|
# path
|
||||||
|
path:
|
||||||
|
# use the pre-trained Real-ESRNet model
|
||||||
|
pretrain_network_g: experiments/pretrained_models/RealESRNet_x4plus.pth
|
||||||
|
param_key_g: params_ema
|
||||||
|
strict_load_g: true
|
||||||
|
pretrain_network_d: experiments/pretrained_models/RealESRGAN_x4plus_netD.pth
|
||||||
|
param_key_d: params
|
||||||
|
strict_load_d: true
|
||||||
|
resume_state: ~
|
||||||
|
|
||||||
|
# training settings
|
||||||
|
train:
|
||||||
|
ema_decay: 0.999
|
||||||
|
optim_g:
|
||||||
|
type: Adam
|
||||||
|
lr: !!float 1e-4
|
||||||
|
weight_decay: 0
|
||||||
|
betas: [0.9, 0.99]
|
||||||
|
optim_d:
|
||||||
|
type: Adam
|
||||||
|
lr: !!float 1e-4
|
||||||
|
weight_decay: 0
|
||||||
|
betas: [0.9, 0.99]
|
||||||
|
|
||||||
|
scheduler:
|
||||||
|
type: MultiStepLR
|
||||||
|
milestones: [400000]
|
||||||
|
gamma: 0.5
|
||||||
|
|
||||||
|
total_iter: 400000
|
||||||
|
warmup_iter: -1 # no warm up
|
||||||
|
|
||||||
|
# losses
|
||||||
|
pixel_opt:
|
||||||
|
type: L1Loss
|
||||||
|
loss_weight: 1.0
|
||||||
|
reduction: mean
|
||||||
|
# perceptual loss (content and style losses)
|
||||||
|
perceptual_opt:
|
||||||
|
type: PerceptualLoss
|
||||||
|
layer_weights:
|
||||||
|
# before relu
|
||||||
|
'conv1_2': 0.1
|
||||||
|
'conv2_2': 0.1
|
||||||
|
'conv3_4': 1
|
||||||
|
'conv4_4': 1
|
||||||
|
'conv5_4': 1
|
||||||
|
vgg_type: vgg19
|
||||||
|
use_input_norm: true
|
||||||
|
perceptual_weight: !!float 1.0
|
||||||
|
style_weight: 0
|
||||||
|
range_norm: false
|
||||||
|
criterion: l1
|
||||||
|
# gan loss
|
||||||
|
gan_opt:
|
||||||
|
type: GANLoss
|
||||||
|
gan_type: vanilla
|
||||||
|
real_label_val: 1.0
|
||||||
|
fake_label_val: 0.0
|
||||||
|
loss_weight: !!float 1e-1
|
||||||
|
|
||||||
|
net_d_iters: 1
|
||||||
|
net_d_init_iters: 0
|
||||||
|
|
||||||
|
# Uncomment these for validation
|
||||||
|
# validation settings
|
||||||
|
# val:
|
||||||
|
# val_freq: !!float 5e3
|
||||||
|
# save_img: True
|
||||||
|
|
||||||
|
# metrics:
|
||||||
|
# psnr: # metric name, can be arbitrary
|
||||||
|
# type: calculate_psnr
|
||||||
|
# crop_border: 4
|
||||||
|
# test_y_channel: false
|
||||||
|
|
||||||
|
# logging settings
|
||||||
|
logger:
|
||||||
|
print_freq: 100
|
||||||
|
save_checkpoint_freq: !!float 5e3
|
||||||
|
use_tb_logger: true
|
||||||
|
wandb:
|
||||||
|
project: ~
|
||||||
|
resume_id: ~
|
||||||
|
|
||||||
|
# dist training settings
|
||||||
|
dist_params:
|
||||||
|
backend: nccl
|
||||||
|
port: 29500
|
||||||
106
realesrgan/data/realesrgan_paired_dataset.py
Normal file
106
realesrgan/data/realesrgan_paired_dataset.py
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
import os
|
||||||
|
from basicsr.data.data_util import paired_paths_from_folder, paired_paths_from_lmdb
|
||||||
|
from basicsr.data.transforms import augment, paired_random_crop
|
||||||
|
from basicsr.utils import FileClient, imfrombytes, img2tensor
|
||||||
|
from basicsr.utils.registry import DATASET_REGISTRY
|
||||||
|
from torch.utils import data as data
|
||||||
|
from torchvision.transforms.functional import normalize
|
||||||
|
|
||||||
|
|
||||||
|
@DATASET_REGISTRY.register()
|
||||||
|
class RealESRGANPairedDataset(data.Dataset):
|
||||||
|
"""Paired image dataset for image restoration.
|
||||||
|
|
||||||
|
Read LQ (Low Quality, e.g. LR (Low Resolution), blurry, noisy, etc) and
|
||||||
|
GT image pairs.
|
||||||
|
|
||||||
|
There are three modes:
|
||||||
|
1. 'lmdb': Use lmdb files.
|
||||||
|
If opt['io_backend'] == lmdb.
|
||||||
|
2. 'meta_info': Use meta information file to generate paths.
|
||||||
|
If opt['io_backend'] != lmdb and opt['meta_info'] is not None.
|
||||||
|
3. 'folder': Scan folders to generate paths.
|
||||||
|
The rest.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
opt (dict): Config for train datasets. It contains the following keys:
|
||||||
|
dataroot_gt (str): Data root path for gt.
|
||||||
|
dataroot_lq (str): Data root path for lq.
|
||||||
|
meta_info (str): Path for meta information file.
|
||||||
|
io_backend (dict): IO backend type and other kwarg.
|
||||||
|
filename_tmpl (str): Template for each filename. Note that the
|
||||||
|
template excludes the file extension. Default: '{}'.
|
||||||
|
gt_size (int): Cropped patched size for gt patches.
|
||||||
|
use_hflip (bool): Use horizontal flips.
|
||||||
|
use_rot (bool): Use rotation (use vertical flip and transposing h
|
||||||
|
and w for implementation).
|
||||||
|
|
||||||
|
scale (bool): Scale, which will be added automatically.
|
||||||
|
phase (str): 'train' or 'val'.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, opt):
|
||||||
|
super(RealESRGANPairedDataset, self).__init__()
|
||||||
|
self.opt = opt
|
||||||
|
# file client (io backend)
|
||||||
|
self.file_client = None
|
||||||
|
self.io_backend_opt = opt['io_backend']
|
||||||
|
self.mean = opt['mean'] if 'mean' in opt else None
|
||||||
|
self.std = opt['std'] if 'std' in opt else None
|
||||||
|
|
||||||
|
self.gt_folder, self.lq_folder = opt['dataroot_gt'], opt['dataroot_lq']
|
||||||
|
if 'filename_tmpl' in opt:
|
||||||
|
self.filename_tmpl = opt['filename_tmpl']
|
||||||
|
else:
|
||||||
|
self.filename_tmpl = '{}'
|
||||||
|
|
||||||
|
if self.io_backend_opt['type'] == 'lmdb':
|
||||||
|
self.io_backend_opt['db_paths'] = [self.lq_folder, self.gt_folder]
|
||||||
|
self.io_backend_opt['client_keys'] = ['lq', 'gt']
|
||||||
|
self.paths = paired_paths_from_lmdb([self.lq_folder, self.gt_folder], ['lq', 'gt'])
|
||||||
|
elif 'meta_info' in self.opt and self.opt['meta_info'] is not None:
|
||||||
|
with open(self.opt['meta_info']) as fin:
|
||||||
|
paths = [line.strip() for line in fin]
|
||||||
|
self.paths = []
|
||||||
|
for path in paths:
|
||||||
|
gt_path, lq_path = path.split(', ')
|
||||||
|
gt_path = os.path.join(self.gt_folder, gt_path)
|
||||||
|
lq_path = os.path.join(self.lq_folder, lq_path)
|
||||||
|
self.paths.append(dict([('gt_path', gt_path), ('lq_path', lq_path)]))
|
||||||
|
else:
|
||||||
|
self.paths = paired_paths_from_folder([self.lq_folder, self.gt_folder], ['lq', 'gt'], self.filename_tmpl)
|
||||||
|
|
||||||
|
def __getitem__(self, index):
|
||||||
|
if self.file_client is None:
|
||||||
|
self.file_client = FileClient(self.io_backend_opt.pop('type'), **self.io_backend_opt)
|
||||||
|
|
||||||
|
scale = self.opt['scale']
|
||||||
|
|
||||||
|
# Load gt and lq images. Dimension order: HWC; channel order: BGR;
|
||||||
|
# image range: [0, 1], float32.
|
||||||
|
gt_path = self.paths[index]['gt_path']
|
||||||
|
img_bytes = self.file_client.get(gt_path, 'gt')
|
||||||
|
img_gt = imfrombytes(img_bytes, float32=True)
|
||||||
|
lq_path = self.paths[index]['lq_path']
|
||||||
|
img_bytes = self.file_client.get(lq_path, 'lq')
|
||||||
|
img_lq = imfrombytes(img_bytes, float32=True)
|
||||||
|
|
||||||
|
# augmentation for training
|
||||||
|
if self.opt['phase'] == 'train':
|
||||||
|
gt_size = self.opt['gt_size']
|
||||||
|
# random crop
|
||||||
|
img_gt, img_lq = paired_random_crop(img_gt, img_lq, gt_size, scale, gt_path)
|
||||||
|
# flip, rotation
|
||||||
|
img_gt, img_lq = augment([img_gt, img_lq], self.opt['use_hflip'], self.opt['use_rot'])
|
||||||
|
|
||||||
|
# BGR to RGB, HWC to CHW, numpy to tensor
|
||||||
|
img_gt, img_lq = img2tensor([img_gt, img_lq], bgr2rgb=True, float32=True)
|
||||||
|
# normalize
|
||||||
|
if self.mean is not None or self.std is not None:
|
||||||
|
normalize(img_lq, self.mean, self.std, inplace=True)
|
||||||
|
normalize(img_gt, self.mean, self.std, inplace=True)
|
||||||
|
|
||||||
|
return {'lq': img_lq, 'gt': img_gt, 'lq_path': lq_path, 'gt_path': gt_path}
|
||||||
|
|
||||||
|
def __len__(self):
|
||||||
|
return len(self.paths)
|
||||||
@@ -19,7 +19,7 @@ class RealESRGANModel(SRGANModel):
|
|||||||
super(RealESRGANModel, self).__init__(opt)
|
super(RealESRGANModel, self).__init__(opt)
|
||||||
self.jpeger = DiffJPEG(differentiable=False).cuda()
|
self.jpeger = DiffJPEG(differentiable=False).cuda()
|
||||||
self.usm_sharpener = USMSharp().cuda()
|
self.usm_sharpener = USMSharp().cuda()
|
||||||
self.queue_size = opt['queue_size']
|
self.queue_size = opt.get('queue_size', 180)
|
||||||
|
|
||||||
@torch.no_grad()
|
@torch.no_grad()
|
||||||
def _dequeue_and_enqueue(self):
|
def _dequeue_and_enqueue(self):
|
||||||
@@ -55,7 +55,7 @@ class RealESRGANModel(SRGANModel):
|
|||||||
|
|
||||||
@torch.no_grad()
|
@torch.no_grad()
|
||||||
def feed_data(self, data):
|
def feed_data(self, data):
|
||||||
if self.is_train:
|
if self.is_train and self.opt.get('high_order_degradation', True):
|
||||||
# training data synthesis
|
# training data synthesis
|
||||||
self.gt = data['gt'].to(self.device)
|
self.gt = data['gt'].to(self.device)
|
||||||
self.gt_usm = self.usm_sharpener(self.gt)
|
self.gt_usm = self.usm_sharpener(self.gt)
|
||||||
@@ -166,6 +166,7 @@ class RealESRGANModel(SRGANModel):
|
|||||||
self.lq = data['lq'].to(self.device)
|
self.lq = data['lq'].to(self.device)
|
||||||
if 'gt' in data:
|
if 'gt' in data:
|
||||||
self.gt = data['gt'].to(self.device)
|
self.gt = data['gt'].to(self.device)
|
||||||
|
self.gt_usm = self.usm_sharpener(self.gt)
|
||||||
|
|
||||||
def nondist_validation(self, dataloader, current_iter, tb_logger, save_img):
|
def nondist_validation(self, dataloader, current_iter, tb_logger, save_img):
|
||||||
# do not use the synthetic process during validation
|
# do not use the synthetic process during validation
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ class RealESRNetModel(SRModel):
|
|||||||
super(RealESRNetModel, self).__init__(opt)
|
super(RealESRNetModel, self).__init__(opt)
|
||||||
self.jpeger = DiffJPEG(differentiable=False).cuda()
|
self.jpeger = DiffJPEG(differentiable=False).cuda()
|
||||||
self.usm_sharpener = USMSharp().cuda()
|
self.usm_sharpener = USMSharp().cuda()
|
||||||
self.queue_size = opt['queue_size']
|
self.queue_size = opt.get('queue_size', 180)
|
||||||
|
|
||||||
@torch.no_grad()
|
@torch.no_grad()
|
||||||
def _dequeue_and_enqueue(self):
|
def _dequeue_and_enqueue(self):
|
||||||
@@ -54,7 +54,7 @@ class RealESRNetModel(SRModel):
|
|||||||
|
|
||||||
@torch.no_grad()
|
@torch.no_grad()
|
||||||
def feed_data(self, data):
|
def feed_data(self, data):
|
||||||
if self.is_train:
|
if self.is_train and self.opt.get('high_order_degradation', True):
|
||||||
# training data synthesis
|
# training data synthesis
|
||||||
self.gt = data['gt'].to(self.device)
|
self.gt = data['gt'].to(self.device)
|
||||||
# USM the GT images
|
# USM the GT images
|
||||||
@@ -164,6 +164,7 @@ class RealESRNetModel(SRModel):
|
|||||||
self.lq = data['lq'].to(self.device)
|
self.lq = data['lq'].to(self.device)
|
||||||
if 'gt' in data:
|
if 'gt' in data:
|
||||||
self.gt = data['gt'].to(self.device)
|
self.gt = data['gt'].to(self.device)
|
||||||
|
self.gt_usm = self.usm_sharpener(self.gt)
|
||||||
|
|
||||||
def nondist_validation(self, dataloader, current_iter, tb_logger, save_img):
|
def nondist_validation(self, dataloader, current_iter, tb_logger, save_img):
|
||||||
# do not use the synthetic process during validation
|
# do not use the synthetic process during validation
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
|||||||
|
|
||||||
class RealESRGANer():
|
class RealESRGANer():
|
||||||
|
|
||||||
def __init__(self, scale, model_path, tile=0, tile_pad=10, pre_pad=10, half=False):
|
def __init__(self, scale, model_path, model=None, tile=0, tile_pad=10, pre_pad=10, half=False):
|
||||||
self.scale = scale
|
self.scale = scale
|
||||||
self.tile_size = tile
|
self.tile_size = tile
|
||||||
self.tile_pad = tile_pad
|
self.tile_pad = tile_pad
|
||||||
@@ -23,7 +23,8 @@ class RealESRGANer():
|
|||||||
|
|
||||||
# initialize model
|
# initialize model
|
||||||
self.device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
|
self.device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
|
||||||
model = RRDBNet(num_in_ch=3, num_out_ch=3, num_feat=64, num_block=23, num_grow_ch=32, scale=scale)
|
if model is None:
|
||||||
|
model = RRDBNet(num_in_ch=3, num_out_ch=3, num_feat=64, num_block=23, num_grow_ch=32, scale=scale)
|
||||||
|
|
||||||
if model_path.startswith('https://'):
|
if model_path.startswith('https://'):
|
||||||
model_path = load_file_from_url(
|
model_path = load_file_from_url(
|
||||||
|
|||||||
@@ -5,3 +5,5 @@ numpy
|
|||||||
opencv-python
|
opencv-python
|
||||||
Pillow
|
Pillow
|
||||||
torch>=1.7
|
torch>=1.7
|
||||||
|
torchvision
|
||||||
|
tqdm
|
||||||
|
|||||||
151
scripts/extract_subimages.py
Normal file
151
scripts/extract_subimages.py
Normal file
@@ -0,0 +1,151 @@
|
|||||||
|
import argparse
|
||||||
|
import cv2
|
||||||
|
import numpy as np
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
from basicsr.utils import scandir
|
||||||
|
from multiprocessing import Pool
|
||||||
|
from os import path as osp
|
||||||
|
from tqdm import tqdm
|
||||||
|
|
||||||
|
|
||||||
|
def main(args):
|
||||||
|
"""A multi-thread tool to crop large images to sub-images for faster IO.
|
||||||
|
|
||||||
|
opt (dict): Configuration dict. It contains:
|
||||||
|
n_thread (int): Thread number.
|
||||||
|
compression_level (int): CV_IMWRITE_PNG_COMPRESSION from 0 to 9.
|
||||||
|
A higher value means a smaller size and longer compression time.
|
||||||
|
Use 0 for faster CPU decompression. Default: 3, same in cv2.
|
||||||
|
|
||||||
|
input_folder (str): Path to the input folder.
|
||||||
|
save_folder (str): Path to save folder.
|
||||||
|
crop_size (int): Crop size.
|
||||||
|
step (int): Step for overlapped sliding window.
|
||||||
|
thresh_size (int): Threshold size. Patches whose size is lower
|
||||||
|
than thresh_size will be dropped.
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
For each folder, run this script.
|
||||||
|
Typically, there are four folders to be processed for DIV2K dataset.
|
||||||
|
DIV2K_train_HR
|
||||||
|
DIV2K_train_LR_bicubic/X2
|
||||||
|
DIV2K_train_LR_bicubic/X3
|
||||||
|
DIV2K_train_LR_bicubic/X4
|
||||||
|
After process, each sub_folder should have the same number of
|
||||||
|
subimages.
|
||||||
|
Remember to modify opt configurations according to your settings.
|
||||||
|
"""
|
||||||
|
|
||||||
|
opt = {}
|
||||||
|
opt['n_thread'] = args.n_thread
|
||||||
|
opt['compression_level'] = args.compression_level
|
||||||
|
|
||||||
|
# HR images
|
||||||
|
opt['input_folder'] = args.input
|
||||||
|
opt['save_folder'] = args.output
|
||||||
|
opt['crop_size'] = args.crop_size
|
||||||
|
opt['step'] = args.step
|
||||||
|
opt['thresh_size'] = args.thresh_size
|
||||||
|
extract_subimages(opt)
|
||||||
|
|
||||||
|
|
||||||
|
def extract_subimages(opt):
|
||||||
|
"""Crop images to subimages.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
opt (dict): Configuration dict. It contains:
|
||||||
|
input_folder (str): Path to the input folder.
|
||||||
|
save_folder (str): Path to save folder.
|
||||||
|
n_thread (int): Thread number.
|
||||||
|
"""
|
||||||
|
input_folder = opt['input_folder']
|
||||||
|
save_folder = opt['save_folder']
|
||||||
|
if not osp.exists(save_folder):
|
||||||
|
os.makedirs(save_folder)
|
||||||
|
print(f'mkdir {save_folder} ...')
|
||||||
|
else:
|
||||||
|
print(f'Folder {save_folder} already exists. Exit.')
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
img_list = list(scandir(input_folder, full_path=True))
|
||||||
|
|
||||||
|
pbar = tqdm(total=len(img_list), unit='image', desc='Extract')
|
||||||
|
pool = Pool(opt['n_thread'])
|
||||||
|
for path in img_list:
|
||||||
|
pool.apply_async(worker, args=(path, opt), callback=lambda arg: pbar.update(1))
|
||||||
|
pool.close()
|
||||||
|
pool.join()
|
||||||
|
pbar.close()
|
||||||
|
print('All processes done.')
|
||||||
|
|
||||||
|
|
||||||
|
def worker(path, opt):
|
||||||
|
"""Worker for each process.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
path (str): Image path.
|
||||||
|
opt (dict): Configuration dict. It contains:
|
||||||
|
crop_size (int): Crop size.
|
||||||
|
step (int): Step for overlapped sliding window.
|
||||||
|
thresh_size (int): Threshold size. Patches whose size is lower
|
||||||
|
than thresh_size will be dropped.
|
||||||
|
save_folder (str): Path to save folder.
|
||||||
|
compression_level (int): for cv2.IMWRITE_PNG_COMPRESSION.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
process_info (str): Process information displayed in progress bar.
|
||||||
|
"""
|
||||||
|
crop_size = opt['crop_size']
|
||||||
|
step = opt['step']
|
||||||
|
thresh_size = opt['thresh_size']
|
||||||
|
img_name, extension = osp.splitext(osp.basename(path))
|
||||||
|
|
||||||
|
# remove the x2, x3, x4 and x8 in the filename for DIV2K
|
||||||
|
img_name = img_name.replace('x2', '').replace('x3', '').replace('x4', '').replace('x8', '')
|
||||||
|
|
||||||
|
img = cv2.imread(path, cv2.IMREAD_UNCHANGED)
|
||||||
|
|
||||||
|
if img.ndim == 2:
|
||||||
|
h, w = img.shape
|
||||||
|
elif img.ndim == 3:
|
||||||
|
h, w, c = img.shape
|
||||||
|
else:
|
||||||
|
raise ValueError(f'Image ndim should be 2 or 3, but got {img.ndim}')
|
||||||
|
|
||||||
|
h_space = np.arange(0, h - crop_size + 1, step)
|
||||||
|
if h - (h_space[-1] + crop_size) > thresh_size:
|
||||||
|
h_space = np.append(h_space, h - crop_size)
|
||||||
|
w_space = np.arange(0, w - crop_size + 1, step)
|
||||||
|
if w - (w_space[-1] + crop_size) > thresh_size:
|
||||||
|
w_space = np.append(w_space, w - crop_size)
|
||||||
|
|
||||||
|
index = 0
|
||||||
|
for x in h_space:
|
||||||
|
for y in w_space:
|
||||||
|
index += 1
|
||||||
|
cropped_img = img[x:x + crop_size, y:y + crop_size, ...]
|
||||||
|
cropped_img = np.ascontiguousarray(cropped_img)
|
||||||
|
cv2.imwrite(
|
||||||
|
osp.join(opt['save_folder'], f'{img_name}_s{index:03d}{extension}'), cropped_img,
|
||||||
|
[cv2.IMWRITE_PNG_COMPRESSION, opt['compression_level']])
|
||||||
|
process_info = f'Processing {img_name} ...'
|
||||||
|
return process_info
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument('--input', type=str, default='datasets/DF2K/DF2K_HR', help='Input folder')
|
||||||
|
parser.add_argument('--output', type=str, default='datasets/DF2K/DF2K_HR_sub', help='Output folder')
|
||||||
|
parser.add_argument('--crop_size', type=int, default=480, help='Crop size')
|
||||||
|
parser.add_argument('--step', type=int, default=240, help='Step for overlapped sliding window')
|
||||||
|
parser.add_argument(
|
||||||
|
'--thresh_size',
|
||||||
|
type=int,
|
||||||
|
default=0,
|
||||||
|
help='Threshold size. Patches whose size is lower than thresh_size will be dropped.')
|
||||||
|
parser.add_argument('--n_thread', type=int, default=20, help='Thread number.')
|
||||||
|
parser.add_argument('--compression_level', type=int, default=3, help='Compression level')
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
main(args)
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
import argparse
|
import argparse
|
||||||
|
import cv2
|
||||||
import glob
|
import glob
|
||||||
import os
|
import os
|
||||||
|
|
||||||
@@ -8,9 +9,20 @@ def main(args):
|
|||||||
for folder, root in zip(args.input, args.root):
|
for folder, root in zip(args.input, args.root):
|
||||||
img_paths = sorted(glob.glob(os.path.join(folder, '*')))
|
img_paths = sorted(glob.glob(os.path.join(folder, '*')))
|
||||||
for img_path in img_paths:
|
for img_path in img_paths:
|
||||||
img_name = os.path.relpath(img_path, root)
|
status = True
|
||||||
print(img_name)
|
if args.check:
|
||||||
txt_file.write(f'{img_name}\n')
|
try:
|
||||||
|
img = cv2.imread(img_path)
|
||||||
|
except Exception as error:
|
||||||
|
print(f'Read {img_path} error: {error}')
|
||||||
|
status = False
|
||||||
|
if img is None:
|
||||||
|
status = False
|
||||||
|
print(f'Img is None: {img_path}')
|
||||||
|
if status:
|
||||||
|
img_name = os.path.relpath(img_path, root)
|
||||||
|
print(img_name)
|
||||||
|
txt_file.write(f'{img_name}\n')
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
@@ -34,7 +46,11 @@ if __name__ == '__main__':
|
|||||||
type=str,
|
type=str,
|
||||||
default='datasets/DF2K/meta_info/meta_info_DF2Kmultiscale.txt',
|
default='datasets/DF2K/meta_info/meta_info_DF2Kmultiscale.txt',
|
||||||
help='txt path for meta info')
|
help='txt path for meta info')
|
||||||
|
parser.add_argument('--check', action='store_true', help='Read image to check whether it is ok')
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
assert len(args.input) == len(args.root), ('Input folder and folder root should have the same length, but got '
|
assert len(args.input) == len(args.root), ('Input folder and folder root should have the same length, but got '
|
||||||
f'{len(args.input)} and {len(args.root)}.')
|
f'{len(args.input)} and {len(args.root)}.')
|
||||||
|
os.makedirs(os.path.dirname(args.meta_info), exist_ok=True)
|
||||||
|
|
||||||
main(args)
|
main(args)
|
||||||
|
|||||||
47
scripts/generate_meta_info_pairdata.py
Normal file
47
scripts/generate_meta_info_pairdata.py
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
import argparse
|
||||||
|
import glob
|
||||||
|
import os
|
||||||
|
|
||||||
|
|
||||||
|
def main(args):
|
||||||
|
txt_file = open(args.meta_info, 'w')
|
||||||
|
img_paths_gt = sorted(glob.glob(os.path.join(args.input[0], '*')))
|
||||||
|
img_paths_lq = sorted(glob.glob(os.path.join(args.input[1], '*')))
|
||||||
|
|
||||||
|
assert len(img_paths_gt) == len(img_paths_lq), ('GT folder and LQ folder should have the same length, but got '
|
||||||
|
f'{len(img_paths_gt)} and {len(img_paths_lq)}.')
|
||||||
|
|
||||||
|
for img_path_gt, img_path_lq in zip(img_paths_gt, img_paths_lq):
|
||||||
|
img_name_gt = os.path.relpath(img_path_gt, args.root[0])
|
||||||
|
img_name_lq = os.path.relpath(img_path_lq, args.root[1])
|
||||||
|
print(f'{img_name_gt}, {img_name_lq}')
|
||||||
|
txt_file.write(f'{img_name_gt}, {img_name_lq}\n')
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
"""Generate meta info (txt file) for paired images.
|
||||||
|
"""
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument(
|
||||||
|
'--input',
|
||||||
|
nargs='+',
|
||||||
|
default=['datasets/DF2K/DIV2K_train_HR_sub', 'datasets/DF2K/DIV2K_train_LR_bicubic_X4_sub'],
|
||||||
|
help='Input folder, should be [gt_folder, lq_folder]')
|
||||||
|
parser.add_argument('--root', nargs='+', default=[None, None], help='Folder root, will use the ')
|
||||||
|
parser.add_argument(
|
||||||
|
'--meta_info',
|
||||||
|
type=str,
|
||||||
|
default='datasets/DF2K/meta_info/meta_info_DIV2K_sub_pair.txt',
|
||||||
|
help='txt path for meta info')
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
assert len(args.input) == 2, 'Input folder should have two elements: gt folder and lq folder'
|
||||||
|
assert len(args.root) == 2, 'Root path should have two elements: root for gt folder and lq folder'
|
||||||
|
os.makedirs(os.path.dirname(args.meta_info), exist_ok=True)
|
||||||
|
for i in range(2):
|
||||||
|
if args.input[i].endswith('/'):
|
||||||
|
args.input[i] = args.input[i][:-1]
|
||||||
|
if args.root[i] is None:
|
||||||
|
args.root[i] = os.path.dirname(args.input[i])
|
||||||
|
|
||||||
|
main(args)
|
||||||
@@ -3,7 +3,7 @@ import torch.onnx
|
|||||||
from basicsr.archs.rrdbnet_arch import RRDBNet
|
from basicsr.archs.rrdbnet_arch import RRDBNet
|
||||||
|
|
||||||
# An instance of your model
|
# An instance of your model
|
||||||
model = RRDBNet(num_in_ch=3, num_out_ch=3, num_feat=64, num_block=23, num_grow_ch=32)
|
model = RRDBNet(num_in_ch=3, num_out_ch=3, num_feat=64, num_block=23, num_grow_ch=32, scale=4)
|
||||||
model.load_state_dict(torch.load('experiments/pretrained_models/RealESRGAN_x4plus.pth')['params_ema'])
|
model.load_state_dict(torch.load('experiments/pretrained_models/RealESRGAN_x4plus.pth')['params_ema'])
|
||||||
# set the train mode to false since we will only run the forward pass.
|
# set the train mode to false since we will only run the forward pass.
|
||||||
model.train(False)
|
model.train(False)
|
||||||
|
|||||||
@@ -17,6 +17,6 @@ line_length = 120
|
|||||||
multi_line_output = 0
|
multi_line_output = 0
|
||||||
known_standard_library = pkg_resources,setuptools
|
known_standard_library = pkg_resources,setuptools
|
||||||
known_first_party = realesrgan
|
known_first_party = realesrgan
|
||||||
known_third_party = PIL,basicsr,cv2,numpy,torch
|
known_third_party = PIL,basicsr,cv2,numpy,torch,torchvision,tqdm
|
||||||
no_lines_before = STDLIB,LOCALFOLDER
|
no_lines_before = STDLIB,LOCALFOLDER
|
||||||
default_section = THIRDPARTY
|
default_section = THIRDPARTY
|
||||||
|
|||||||
2
setup.py
2
setup.py
@@ -45,7 +45,7 @@ def get_hash():
|
|||||||
sha = get_git_hash()[:7]
|
sha = get_git_hash()[:7]
|
||||||
elif os.path.exists(version_file):
|
elif os.path.exists(version_file):
|
||||||
try:
|
try:
|
||||||
from facexlib.version import __version__
|
from realesrgan.version import __version__
|
||||||
sha = __version__.split('+')[-1]
|
sha = __version__.split('+')[-1]
|
||||||
except ImportError:
|
except ImportError:
|
||||||
raise ImportError('Unable to get git version')
|
raise ImportError('Unable to get git version')
|
||||||
|
|||||||
Reference in New Issue
Block a user