From 100edd848f9fa3ed28021a485c54f26aa4d411e7 Mon Sep 17 00:00:00 2001
From: LielinJiang <50691816+LielinJiang@users.noreply.github.com>
Date: Fri, 30 Oct 2020 10:09:45 +0800
Subject: [PATCH] Refine codes and docs (#61)
* refine codes docs
---
README.md | 25 +--
README_en.md | 30 +---
data/download_cyclegan_data.py | 30 ++++
data/download_pix2pix_data.py | 25 +++
docs/data_prepare.md | 63 ++++++-
docs/data_prepare_en.md | 67 ++++++-
docs/get_started.md | 55 +++++-
docs/get_started_en.md | 57 +++++-
docs/install.md | 36 ++++
docs/install_en.md | 35 ++++
docs/tutorials/video_restore.md | 12 +-
ppgan/apps/dain_predictor.py | 5 +-
ppgan/apps/deepremaster_predictor.py | 6 +-
ppgan/apps/deoldify_predictor.py | 5 +-
ppgan/apps/edvr_predictor.py | 5 +-
ppgan/apps/first_order_predictor.py | 5 +-
ppgan/apps/realsr_predictor.py | 5 +-
ppgan/utils/download.py | 254 +++++++++++++++++++++++++++
ppgan/utils/logger.py | 10 ++
script/pix2pix_download.sh | 9 -
20 files changed, 641 insertions(+), 98 deletions(-)
create mode 100644 data/download_cyclegan_data.py
create mode 100644 data/download_pix2pix_data.py
create mode 100644 docs/install.md
create mode 100644 docs/install_en.md
create mode 100644 ppgan/utils/download.py
delete mode 100644 script/pix2pix_download.sh
diff --git a/README.md b/README.md
index 9a69441..32574ee 100644
--- a/README.md
+++ b/README.md
@@ -32,31 +32,10 @@ PaddleGAN 是一个基于飞桨的生成对抗网络开发工具包.
## 安装
-### 1. 安装 paddlepaddle
-
-PaddleGAN 所需的版本:
-* PaddlePaddle >= 2.0.0-rc
-* Python >= 3.5+
-
-```
-pip install -U paddlepaddle-gpu
-```
-
-### 2. 安装ppgan
-```
-python -m pip install 'git+https://github.com/PaddlePaddle/PaddleGAN.git'
-```
-
-或者通过将项目克隆到本地
-```
-git clone https://github.com/PaddlePaddle/PaddleGAN
-cd PaddleGAN
-
-pip install -v -e . # or "python setup.py develop"
-```
+请参考[安装文档](./docs/install.md)来进行PaddlePaddle和ppgan的安装
## 数据准备
-请参考 [数据准备](./docs/data_prepare.md) 来准备对应的数据.
+请参考[数据准备](./docs/data_prepare.md) 来准备对应的数据.
## 快速开始
diff --git a/README_en.md b/README_en.md
index bc06bf1..888d0cb 100644
--- a/README_en.md
+++ b/README_en.md
@@ -1,4 +1,4 @@
-English | [简体中文](./README_cn.md)
+English | [简体中文](./README.md)
# PaddleGAN
@@ -35,35 +35,13 @@ changes.
## Install
-### 1. install paddlepaddle
-
-PaddleGAN work with:
-* PaddlePaddle >= 2.0.0-rc
-* Python >= 3.5+
-
-```
-pip install -U paddlepaddle-gpu
-```
-
-### 2. install ppgan
-
-```
-python -m pip install 'git+https://github.com/PaddlePaddle/PaddleGAN.git'
-```
-
-Or install it from a local clone
-```
-git clone https://github.com/PaddlePaddle/PaddleGAN
-cd PaddleGAN
-
-pip install -v -e . # or "python setup.py develop"
-```
+Please refer to [install](./docs/install_en.md).
## Data Prepare
-Please refer to [data prepare](./docs/data_prepare.md) for dataset preparation.
+Please refer to [data prepare](./docs/data_prepare_en.md) for dataset preparation.
## Get Start
-Please refer [get started](./docs/get_started.md) for the basic usage of PaddleGAN.
+Please refer [get started](./docs/get_started_en.md) for the basic usage of PaddleGAN.
## Model tutorial
* [Pixel2Pixel and CycleGAN](./docs/tutorials/pix2pix_cyclegan.md)
diff --git a/data/download_cyclegan_data.py b/data/download_cyclegan_data.py
new file mode 100644
index 0000000..3076328
--- /dev/null
+++ b/data/download_cyclegan_data.py
@@ -0,0 +1,30 @@
+import os
+import argparse
+
+from ppgan.utils.download import get_path_from_url
+
+CYCLEGAN_URL_ROOT = 'https://people.eecs.berkeley.edu/~taesung_park/CycleGAN/datasets/'
+
+parser = argparse.ArgumentParser(description='download datasets')
+parser.add_argument('--name',
+ type=str,
+ required=True,
+ help='dataset name, \
+ support dataset name: apple2orange, summer2winter_yosemite, \
+ horse2zebra, monet2photo, cezanne2photo, ukiyoe2photo, \
+ vangogh2photo, maps, cityscapes, facades, iphone2dslr_flower, \
+ ae_photos, cityscapes')
+
+if __name__ == "__main__":
+ args = parser.parse_args()
+
+ data_url = CYCLEGAN_URL_ROOT + args.name + '.zip'
+
+ if args.name == 'cityscapes':
+ data_url = 'https://paddlegan.bj.bcebos.com/datasets/cityscapes.zip'
+
+ path = get_path_from_url(data_url)
+
+ dst = os.path.join('data', args.name)
+ print('symlink {} to {}'.format(path, dst))
+ os.symlink(path, dst)
diff --git a/data/download_pix2pix_data.py b/data/download_pix2pix_data.py
new file mode 100644
index 0000000..ed250c7
--- /dev/null
+++ b/data/download_pix2pix_data.py
@@ -0,0 +1,25 @@
+import os
+import argparse
+
+from ppgan.utils.download import get_path_from_url
+
+PIX2PIX_URL_ROOT = 'http://efrosgans.eecs.berkeley.edu/pix2pix/datasets/'
+
+parser = argparse.ArgumentParser(description='download datasets')
+parser.add_argument('--name',
+ type=str,
+ required=True,
+ help='dataset name, \
+ support dataset name: cityscapes, night2day, edges2handbags, \
+ edges2shoes, facades, maps')
+
+if __name__ == "__main__":
+ args = parser.parse_args()
+
+ data_url = PIX2PIX_URL_ROOT + args.name + '.tar.gz'
+
+ path = get_path_from_url(data_url)
+
+ dst = os.path.join('data', args.name)
+ print('symlink {} to {}'.format(path, dst))
+ os.symlink(path, dst)
diff --git a/docs/data_prepare.md b/docs/data_prepare.md
index 546f09f..4f5e21b 100644
--- a/docs/data_prepare.md
+++ b/docs/data_prepare.md
@@ -1,6 +1,6 @@
## 数据准备
-推荐把数据集软链接到 `$PaddleGAN/data`. 软链接后的目录结构如下图所示:
+现有的配置默认数据集的路径是在`$PaddleGAN/data`下,目录结构如下图所示。如果你已经下载好数据集了,建议将数据集软链接到 `$PaddleGAN/data`。
```
PaddleGAN
@@ -28,8 +28,65 @@ PaddleGAN
```
-### cyclegan 相关的数据集下载
+如果将数据集放在其他位置,比如 ```your/data/path```,
+你可以修改配置文件中的 ```dataroot``` 参数:
+
+```
+dataset:
+ train:
+ name: PairedDataset
+ dataroot: your/data/path
+ num_workers: 4
+```
+
+### CycleGAN模型相关的数据集下载
+
+#### 已有的数据集下载
+
+##### 从网页下载
cyclgan模型相关的数据集可以在[这里](https://people.eecs.berkeley.edu/~taesung_park/CycleGAN/datasets/)下载
-### pix2pix 相关的数据集下载
+##### 使用脚本下载
+我们在 ```PaddleGAN/data``` 文件夹下提供了一个脚本 ```download_cyclegan_data.py``` 方便下载CycleGAN相关的
+数据集。执行如下命令可以下载相关的数据集,目前支持的数据集名称有:apple2orange, summer2winter_yosemite,horse2zebra, monet2photo, cezanne2photo, ukiyoe2photo, vangogh2photo, maps, cityscapes, facades, iphone2dslr_flower, ae_photos, cityscapes。
+
+执行如下命令,可以下载对应的数据集到 ```~/.cache/ppgan``` 并软连接到 ```PaddleGAN/data/``` 下。
+```
+python data/download_cyclegan_data.py --name horse2zebra
+```
+#### 使用自己的数据集
+如果你使用自己的数据集,需要构造成如下目录的格式。注意 ```xxxA```,```xxxB```文件数量,文件内容无需一一对应。
+```
+custom_datasets
+├── testA
+├── testB
+├── trainA
+└── trainB
+```
+
+### Pix2Pix相关的数据集下载
+
+#### 已有的数据集下载
+
+##### 从网页下载
pixel2pixel模型相关的数据集可以在[这里](hhttps://people.eecs.berkeley.edu/~tinghuiz/projects/pix2pix/datasets/)下载
+
+##### 使用脚本下载
+我们在 ```PaddleGAN/data``` 文件夹下提供了一个脚本 ```download_pix2pix_data.py``` 方便下载pix2pix模型相关的数据集。执行如下命令可以下载相关的数据集,目前支持的数据集名称有:apple2orange, summer2winter_yosemite,horse2zebra, monet2photo, cezanne2photo, ukiyoe2photo, vangogh2photo, maps, cityscapes, facades, iphone2dslr_flower, ae_photos, cityscapes。
+
+执行如下命令,可以下载对应的数据集到 ```~/.cache/ppgan``` 并软连接到 ```PaddleGAN/data/``` 下。
+```
+python data/download_pix2pix_data.py --name cityscapes
+```
+
+#### 使用自己的数据集
+如果你使用自己的数据集,需要构造成如下目录的格式。同时图片应该制作成下图的样式,即左边为一种风格,另一边为相应转换的风格。
+
+```
+facades
+├── test
+├── train
+└── val
+```
+
+![](./imgs/1.jpg)
diff --git a/docs/data_prepare_en.md b/docs/data_prepare_en.md
index 6c25aa2..c465284 100644
--- a/docs/data_prepare_en.md
+++ b/docs/data_prepare_en.md
@@ -1,6 +1,6 @@
## data prepare
-It is recommended to symlink the dataset root to `$PaddleGAN/data`.
+The config will suppose your data put in `$PaddleGAN/data`. You can symlink your datasets to `$PaddleGAN/data`.
```
PaddleGAN
@@ -28,8 +28,65 @@ PaddleGAN
```
-### cyclegan datasets
-more dataset for cyclegan you can download from [here](https://people.eecs.berkeley.edu/~taesung_park/CycleGAN/datasets/)
+if you put your datasets on other place,for example ```your/data/path```,
+you can also change ```dataroot``` in config file:
-### pix2pix datasets
-more dataset for pix2pix you can download from [here](hhttps://people.eecs.berkeley.edu/~tinghuiz/projects/pix2pix/datasets/)
+```
+dataset:
+ train:
+ name: PairedDataset
+ dataroot: your/data/path
+ num_workers: 4
+```
+
+### Datasets of CycleGAN
+
+#### download existed datasets
+
+##### download form website
+datasets for CycleGAN you can download from [here](https://people.eecs.berkeley.edu/~taesung_park/CycleGAN/datasets/)
+
+##### download by script
+You can use ```download_cyclegan_data.py``` in ```PaddleGAN/data``` to download datasets you wanted. Supported datasets are: apple2orange, summer2winter_yosemite,horse2zebra, monet2photo, cezanne2photo, ukiyoe2photo, vangogh2photo, maps, cityscapes, facades, iphone2dslr_flower, ae_photos, cityscapes。
+
+run following command. Dataset will be downloaded to ```~/.cache/ppgan``` and symlink to ```PaddleGAN/data/``` .
+```
+python data/download_cyclegan_data.py --name horse2zebra
+```
+
+#### custom dataset
+Data should be arranged in following way if you use custom dataset.
+```
+custom_datasets
+├── testA
+├── testB
+├── trainA
+└── trainB
+```
+
+### Datasets of Pix2Pix
+
+#### download existed datasets
+
+##### download from website
+dataset for pix2pix you can download from [here](hhttps://people.eecs.berkeley.edu/~tinghuiz/projects/pix2pix/datasets/)
+
+##### download by script
+You can use ```download_pix2pix_data.py``` in ```PaddleGAN/data``` to download datasets you wanted. Supported datasets are: apple2orange, summer2winter_yosemite,horse2zebra, monet2photo, cezanne2photo, ukiyoe2photo, vangogh2photo, maps, cityscapes, facades, iphone2dslr_flower, ae_photos, cityscapes.
+
+run following command. Dataset will be downloaded to ```~/.cache/ppgan``` and symlink to ```PaddleGAN/data/``` .
+```
+python data/download_pix2pix_data.py --name cityscapes
+```
+
+#### custom datasets
+Data should be arranged in following way if you use custom dataset. And image content shoubld be same with example image.
+
+```
+facades
+├── test
+├── train
+└── val
+```
+
+![](./imgs/1.jpg)
diff --git a/docs/get_started.md b/docs/get_started.md
index a584d9c..6692682 100644
--- a/docs/get_started.md
+++ b/docs/get_started.md
@@ -1,22 +1,71 @@
## 快速开始使用PaddleGAN
+注意:
+* 开始使用PaddleGAN前请确保已经阅读过[安装文档](./install.md),并根据[数据准备文档](./data_prepare.md)准备好数据集。
+* 以下教程以CycleGAN模型在Cityscapes数据集上的训练预测作为示例。
+
+
### 训练
+
+#### 单卡训练
```
python -u tools/main.py --config-file configs/cyclegan_cityscapes.yaml
```
+#### 参数
-continue train from last checkpoint
+- `--config-file (str)`: 配置文件的路径。
+
+ 输出的日志,权重,可视化结果会默认保存在```./output_dir```中,可以通过配置文件中的```output_dir```参数修改:
+ ```
+ output_dir: output_dir
+ ```
+
+ 保存的文件夹会根据模型名字和时间戳自动生成一个新目录,目录示例如下:
+```
+output_dir
+└── CycleGANModel-2020-10-29-09-21
+ ├── epoch_1_checkpoint.pkl
+ ├── log.txt
+ └── visual_train
+ ├── epoch001_fake_A.png
+ ├── epoch001_fake_B.png
+ ├── epoch001_idt_A.png
+ ├── epoch001_idt_B.png
+ ├── epoch001_real_A.png
+ ├── epoch001_real_B.png
+ ├── epoch001_rec_A.png
+ ├── epoch001_rec_B.png
+ ├── epoch002_fake_A.png
+ ├── epoch002_fake_B.png
+ ├── epoch002_idt_A.png
+ ├── epoch002_idt_B.png
+ ├── epoch002_real_A.png
+ ├── epoch002_real_B.png
+ ├── epoch002_rec_A.png
+ └── epoch002_rec_B.png
+```
+
+#### 恢复训练
+
+训练过程中默认会保存上一个epoch的checkpoint,方便恢复训练
```
python -u tools/main.py --config-file configs/cyclegan_cityscapes.yaml --resume your_checkpoint_path
```
+#### 参数
-multiple gpus train:
+- `--resume (str)`: 用来恢复训练的checkpoint路径。
+
+#### 多卡训练:
```
-CUDA_VISIBLE_DEVICES=0,1 python -m paddle.distributed.launch tools/main.py --config-file configs/pix2pix_cityscapes.yaml
+CUDA_VISIBLE_DEVICES=0,1 python -m paddle.distributed.launch tools/main.py --config-file configs/cyclegan_cityscapes.yaml
```
### 预测
```
python tools/main.py --config-file configs/cyclegan_cityscapes.yaml --evaluate-only --load your_weight_path
```
+
+#### 参数
+- `--evaluate-only`: 是否仅进行预测。
+- `--load (str)`: 训练好的权重路径。
diff --git a/docs/get_started_en.md b/docs/get_started_en.md
index 024e8de..474a8fd 100644
--- a/docs/get_started_en.md
+++ b/docs/get_started_en.md
@@ -1,22 +1,71 @@
## Getting started with PaddleGAN
+Note:
+* Before starting to use PaddleGAN, please make sure you have read the [install document](./install_en.md), and prepare the dataset according to the [data preparation document](./data_prepare_en.md)
+* The following tutorial uses the train and evaluate of the CycleGAN model on the Cityscapes dataset as an example
+
### Train
+
+#### Train with single gpu
```
python -u tools/main.py --config-file configs/cyclegan_cityscapes.yaml
```
+#### Args
+
+- `--config-file (str)`: path of config file。
+
+The output log, weight, and visualization result will be saved in ```./output_dir``` by default, which can be modified by the ```output_dir``` parameter in the config file:
+ ```
+ output_dir: output_dir
+ ```
+
+
-continue train from last checkpoint
+The saved folder will automatically generate a new directory based on the model name and timestamp. The directory example is as follows:
+```
+output_dir
+└── CycleGANModel-2020-10-29-09-21
+ ├── epoch_1_checkpoint.pkl
+ ├── log.txt
+ └── visual_train
+ ├── epoch001_fake_A.png
+ ├── epoch001_fake_B.png
+ ├── epoch001_idt_A.png
+ ├── epoch001_idt_B.png
+ ├── epoch001_real_A.png
+ ├── epoch001_real_B.png
+ ├── epoch001_rec_A.png
+ ├── epoch001_rec_B.png
+ ├── epoch002_fake_A.png
+ ├── epoch002_fake_B.png
+ ├── epoch002_idt_A.png
+ ├── epoch002_idt_B.png
+ ├── epoch002_real_A.png
+ ├── epoch002_real_B.png
+ ├── epoch002_rec_A.png
+ └── epoch002_rec_B.png
+```
+#### Recovery of training
+
+The checkpoint of the previous epoch will be saved by default during the training process to facilitate the recovery of training
```
python -u tools/main.py --config-file configs/cyclegan_cityscapes.yaml --resume your_checkpoint_path
```
+#### Args
-multiple gpus train:
+- `--resume (str)`: path of checkpoint。
+
+#### Train with multiple gpus:
```
-CUDA_VISIBLE_DEVICES=0,1 python -m paddle.distributed.launch tools/main.py --config-file configs/pix2pix_cityscapes.yaml
+CUDA_VISIBLE_DEVICES=0,1 python -m paddle.distributed.launch tools/main.py --config-file configs/cyclegan_cityscapes.yaml
```
-### Evaluate
+### evaluate
```
python tools/main.py --config-file configs/cyclegan_cityscapes.yaml --evaluate-only --load your_weight_path
```
+
+#### Args
+- `--evaluate-only`: whether to evaluate only。
+- `--load (str)`: path of weight。
diff --git a/docs/install.md b/docs/install.md
new file mode 100644
index 0000000..36a5672
--- /dev/null
+++ b/docs/install.md
@@ -0,0 +1,36 @@
+## 安装PaddleGAN
+
+### 要求
+
+* PaddlePaddle >= 2.0.0-rc
+* Python >= 3.5+
+* CUDA >= 9.0
+
+### 1. 安装PaddlePaddle
+```
+pip install -U paddlepaddle-gpu==2.0.0rc0
+```
+
+上面命令会默认安装cuda10.2的包,如果想安装其他cuda版本的包,可以参考下面的表格。
+
CUDA | python3.8 | python3.7 | python3.6 | 10.1 | install python -m pip install https://paddle-wheel.bj.bcebos.com/2.0.0-rc0-gpu-cuda10.1-cudnn7-mkl_gcc8.2%2Fpaddlepaddle_gpu-2.0.0rc0.post101-cp38-cp38-linux_x86_64.whl
+ | install python -m pip install https://paddle-wheel.bj.bcebos.com/2.0.0-rc0-gpu-cuda10.1-cudnn7-mkl_gcc8.2%2Fpaddlepaddle_gpu-2.0.0rc0.post101-cp37-cp37m-linux_x86_64.whl
+ | install python -m pip install https://paddle-wheel.bj.bcebos.com/2.0.0-rc0-gpu-cuda10.1-cudnn7-mkl_gcc8.2%2Fpaddlepaddle_gpu-2.0.0rc0.post101-cp36-cp36m-linux_x86_64.whl
+ | |
10.0 | install python -m pip install https://paddle-wheel.bj.bcebos.com/2.0.0-rc0-gpu-cuda10-cudnn7-mkl%2Fpaddlepaddle_gpu-2.0.0rc0.post100-cp38-cp38-linux_x86_64.whl
+ | install python -m pip install https://paddle-wheel.bj.bcebos.com/2.0.0-rc0-gpu-cuda10-cudnn7-mkl%2Fpaddlepaddle_gpu-2.0.0rc0.post100-cp37-cp37m-linux_x86_64.whl
+ | install python -m pip install https://paddle-wheel.bj.bcebos.com/2.0.0-rc0-gpu-cuda10-cudnn7-mkl%2Fpaddlepaddle_gpu-2.0.0rc0.post100-cp36-cp36m-linux_x86_64.whl
+ | |
9.0 | install python -m pip install https://paddle-wheel.bj.bcebos.com/2.0.0-rc0-gpu-cuda9-cudnn7-mkl%2Fpaddlepaddle_gpu-2.0.0rc0.post90-cp38-cp38-linux_x86_64.whl
+ | install python -m pip install https://paddle-wheel.bj.bcebos.com/2.0.0-rc0-gpu-cuda9-cudnn7-mkl%2Fpaddlepaddle_gpu-2.0.0rc0.post90-cp37-cp37m-linux_x86_64.whl
+ | install python -m pip install https://paddle-wheel.bj.bcebos.com/2.0.0-rc0-gpu-cuda9-cudnn7-mkl%2Fpaddlepaddle_gpu-2.0.0rc0.post90-cp36-cp36m-linux_x86_64.whl
+ |
+
+
+### 2. 安装ppgan
+
+```
+git clone https://github.com/PaddlePaddle/PaddleGAN
+cd PaddleGAN
+
+pip install -v -e . # or "python setup.py develop"
+```
+
+按照上述方法安装成功后,本地的修改也会自动同步到ppgan中
diff --git a/docs/install_en.md b/docs/install_en.md
new file mode 100644
index 0000000..07d3818
--- /dev/null
+++ b/docs/install_en.md
@@ -0,0 +1,35 @@
+## Install PaddleGAN
+
+### requirements
+
+* PaddlePaddle >= 2.0.0-rc
+* Python >= 3.5+
+* CUDA >= 9.0
+
+### 1. Install PaddlePaddle
+```
+pip install -U paddlepaddle-gpu==2.0.0rc0
+```
+
+Note: command above will install paddle with cuda10.2,if your installed cuda is different, you can choose an proper version to install from table below.
+
+ CUDA | python3.8 | python3.7 | python3.6 | 10.1 | install python -m pip install https://paddle-wheel.bj.bcebos.com/2.0.0-rc0-gpu-cuda10.1-cudnn7-mkl_gcc8.2%2Fpaddlepaddle_gpu-2.0.0rc0.post101-cp38-cp38-linux_x86_64.whl
+ | install python -m pip install https://paddle-wheel.bj.bcebos.com/2.0.0-rc0-gpu-cuda10.1-cudnn7-mkl_gcc8.2%2Fpaddlepaddle_gpu-2.0.0rc0.post101-cp37-cp37m-linux_x86_64.whl
+ | install python -m pip install https://paddle-wheel.bj.bcebos.com/2.0.0-rc0-gpu-cuda10.1-cudnn7-mkl_gcc8.2%2Fpaddlepaddle_gpu-2.0.0rc0.post101-cp36-cp36m-linux_x86_64.whl
+ | |
10.0 | install python -m pip install https://paddle-wheel.bj.bcebos.com/2.0.0-rc0-gpu-cuda10-cudnn7-mkl%2Fpaddlepaddle_gpu-2.0.0rc0.post100-cp38-cp38-linux_x86_64.whl
+ | install python -m pip install https://paddle-wheel.bj.bcebos.com/2.0.0-rc0-gpu-cuda10-cudnn7-mkl%2Fpaddlepaddle_gpu-2.0.0rc0.post100-cp37-cp37m-linux_x86_64.whl
+ | install python -m pip install https://paddle-wheel.bj.bcebos.com/2.0.0-rc0-gpu-cuda10-cudnn7-mkl%2Fpaddlepaddle_gpu-2.0.0rc0.post100-cp36-cp36m-linux_x86_64.whl
+ | |
9.0 | install python -m pip install https://paddle-wheel.bj.bcebos.com/2.0.0-rc0-gpu-cuda9-cudnn7-mkl%2Fpaddlepaddle_gpu-2.0.0rc0.post90-cp38-cp38-linux_x86_64.whl
+ | install python -m pip install https://paddle-wheel.bj.bcebos.com/2.0.0-rc0-gpu-cuda9-cudnn7-mkl%2Fpaddlepaddle_gpu-2.0.0rc0.post90-cp37-cp37m-linux_x86_64.whl
+ | install python -m pip install https://paddle-wheel.bj.bcebos.com/2.0.0-rc0-gpu-cuda9-cudnn7-mkl%2Fpaddlepaddle_gpu-2.0.0rc0.post90-cp36-cp36m-linux_x86_64.whl
+ |
+
+
+### 2. Install ppgan
+
+```
+git clone https://github.com/PaddlePaddle/PaddleGAN
+cd PaddleGAN
+
+pip install -v -e . # or "python setup.py develop"
+```
diff --git a/docs/tutorials/video_restore.md b/docs/tutorials/video_restore.md
index ec999e5..523e5cf 100644
--- a/docs/tutorials/video_restore.md
+++ b/docs/tutorials/video_restore.md
@@ -39,7 +39,7 @@ DAIN 模型通过探索深度的信息来显式检测遮挡。并且开发了一
```
ppgan.apps.DAINPredictor(
- output_path='output',
+ output='output',
weight_path=None,
time_step=None,
use_gpu=True,
@@ -47,7 +47,7 @@ ppgan.apps.DAINPredictor(
```
#### 参数
-- `output_path (str,可选的)`: 输出的文件夹路径,默认值:`output`.
+- `output (str,可选的)`: 输出的文件夹路径,默认值:`output`.
- `weight_path (None,可选的)`: 载入的权重路径,如果没有设置,则从云端下载默认的权重到本地。默认值:`None`。
- `time_step (int)`: 补帧的时间系数,如果设置为0.5,则原先为每秒30帧的视频,补帧后变为每秒60帧。
- `remove_duplicates (bool,可选的)`: 是否删除重复帧,默认值:`False`.
@@ -61,7 +61,7 @@ ppgan.apps.DeOldifyPredictor(output='output', weight_path=None, render_factor=32
```
#### 参数
-- `output_path (str,可选的)`: 输出的文件夹路径,默认值:`output`.
+- `output (str,可选的)`: 输出的文件夹路径,默认值:`output`.
- `weight_path (None,可选的)`: 载入的权重路径,如果没有设置,则从云端下载默认的权重到本地。默认值:`None`。
- `render_factor (int)`: 会将该参数乘以16后作为输入帧的resize的值,如果该值设置为32,
则输入帧会resize到(32 * 16, 32 * 16)的尺寸再输入到网络中。
@@ -80,7 +80,7 @@ ppgan.apps.DeepRemasterPredictor(
```
#### 参数
-- `output_path (str,可选的)`: 输出的文件夹路径,默认值:`output`.
+- `output (str,可选的)`: 输出的文件夹路径,默认值:`output`.
- `weight_path (None,可选的)`: 载入的权重路径,如果没有设置,则从云端下载默认的权重到本地。默认值:`None`。
- `colorization (bool)`: 是否对输入视频上色,如果选项设置为 `True` ,则参考帧的文件夹路径也必须要设置。默认值:`False`。
- `reference_dir (bool)`: 参考帧的文件夹路径。默认值:`None`。
@@ -96,7 +96,7 @@ ppgan.apps.RealSRPredictor(output='output', weight_path=None)
```
#### 参数
-- `output_path (str,可选的)`: 输出的文件夹路径,默认值:`output`.
+- `output (str,可选的)`: 输出的文件夹路径,默认值:`output`.
- `weight_path (None,可选的)`: 载入的权重路径,如果没有设置,则从云端下载默认的权重到本地。默认值:`None`。
-
### 超分辨率模型EDVRPredictor
@@ -111,5 +111,5 @@ ppgan.apps.EDVRPredictor(output='output', weight_path=None)
```
#### 参数
-- `output_path (str,可选的)`: 输出的文件夹路径,默认值:`output`.
+- `output (str,可选的)`: 输出的文件夹路径,默认值:`output`.
- `weight_path (None,可选的)`: 载入的权重路径,如果没有设置,则从云端下载默认的权重到本地。默认值:`None`。
diff --git a/ppgan/apps/dain_predictor.py b/ppgan/apps/dain_predictor.py
index e148b15..2e4b83d 100644
--- a/ppgan/apps/dain_predictor.py
+++ b/ppgan/apps/dain_predictor.py
@@ -22,7 +22,7 @@ from imageio import imread, imsave
import paddle
import paddle.fluid as fluid
-from paddle.utils.download import get_path_from_url
+from ppgan.utils.download import get_path_from_url
from ppgan.utils.video import video2frames, frames2video
from .base_predictor import BasePredictor
@@ -39,8 +39,7 @@ class DAINPredictor(BasePredictor):
remove_duplicates=False):
self.output_path = os.path.join(output, 'DAIN')
if weight_path is None:
- cur_path = os.path.abspath(os.path.dirname(__file__))
- weight_path = get_path_from_url(DAIN_WEIGHT_URL, cur_path)
+ weight_path = get_path_from_url(DAIN_WEIGHT_URL)
self.weight_path = weight_path
self.time_step = time_step
diff --git a/ppgan/apps/deepremaster_predictor.py b/ppgan/apps/deepremaster_predictor.py
index 2a8f555..5a57803 100644
--- a/ppgan/apps/deepremaster_predictor.py
+++ b/ppgan/apps/deepremaster_predictor.py
@@ -22,7 +22,7 @@ from skimage import color
import paddle
from ppgan.models.generators.remaster import NetworkR, NetworkC
-from paddle.utils.download import get_path_from_url
+from ppgan.utils.download import get_path_from_url
from .base_predictor import BasePredictor
DEEPREMASTER_WEIGHT_URL = 'https://paddlegan.bj.bcebos.com/applications/deep_remaster.pdparams'
@@ -77,9 +77,7 @@ class DeepRemasterPredictor(BasePredictor):
self.mindim = mindim
if weight_path is None:
- cur_path = os.path.abspath(os.path.dirname(__file__))
- weight_path = get_path_from_url(DEEPREMASTER_WEIGHT_URL, cur_path)
- print(weight_path)
+ weight_path = get_path_from_url(DEEPREMASTER_WEIGHT_URL)
self.weight_path = weight_path
diff --git a/ppgan/apps/deoldify_predictor.py b/ppgan/apps/deoldify_predictor.py
index b3ca461..c1bab40 100644
--- a/ppgan/apps/deoldify_predictor.py
+++ b/ppgan/apps/deoldify_predictor.py
@@ -20,7 +20,7 @@ from PIL import Image
from tqdm import tqdm
import paddle
-from paddle.utils.download import get_path_from_url
+from ppgan.utils.download import get_path_from_url
from ppgan.utils.video import frames2video, video2frames
from ppgan.models.generators.deoldify import build_model
@@ -36,8 +36,7 @@ class DeOldifyPredictor(BasePredictor):
self.render_factor = render_factor
self.model = build_model()
if weight_path is None:
- cur_path = os.path.abspath(os.path.dirname(__file__))
- weight_path = get_path_from_url(DEOLDIFY_WEIGHT_URL, cur_path)
+ weight_path = get_path_from_url(DEOLDIFY_WEIGHT_URL)
state_dict = paddle.load(weight_path)
self.model.load_dict(state_dict)
diff --git a/ppgan/apps/edvr_predictor.py b/ppgan/apps/edvr_predictor.py
index 0e9fe71..695ca41 100644
--- a/ppgan/apps/edvr_predictor.py
+++ b/ppgan/apps/edvr_predictor.py
@@ -19,7 +19,7 @@ import glob
import numpy as np
from tqdm import tqdm
-from paddle.utils.download import get_path_from_url
+from ppgan.utils.download import get_path_from_url
from ppgan.utils.video import frames2video, video2frames
from .base_predictor import BasePredictor
@@ -138,8 +138,7 @@ class EDVRPredictor(BasePredictor):
self.output = os.path.join(output, 'EDVR')
if weight_path is None:
- cur_path = os.path.abspath(os.path.dirname(__file__))
- weight_path = get_path_from_url(EDVR_WEIGHT_URL, cur_path)
+ weight_path = get_path_from_url(EDVR_WEIGHT_URL)
self.weight_path = weight_path
diff --git a/ppgan/apps/first_order_predictor.py b/ppgan/apps/first_order_predictor.py
index b83d456..c0f6dde 100644
--- a/ppgan/apps/first_order_predictor.py
+++ b/ppgan/apps/first_order_predictor.py
@@ -25,7 +25,7 @@ from skimage.transform import resize
from scipy.spatial import ConvexHull
import paddle
-from paddle.utils.download import get_path_from_url
+from ppgan.utils.download import get_path_from_url
from ppgan.utils.animate import normalize_kp
from ppgan.modules.keypoint_detector import KPDetector
from ppgan.models.generators.occlusion_aware import OcclusionAwareGenerator
@@ -78,8 +78,7 @@ class FirstOrderPredictor(BasePredictor):
}
if weight_path is None:
vox_cpk_weight_url = 'https://paddlegan.bj.bcebos.com/applications/first_order_model/vox-cpk.pdparams'
- cur_path = os.path.abspath(os.path.dirname(__file__))
- weight_path = get_path_from_url(vox_cpk_weight_url, cur_path)
+ weight_path = get_path_from_url(vox_cpk_weight_url)
self.weight_path = weight_path
self.output = output
diff --git a/ppgan/apps/realsr_predictor.py b/ppgan/apps/realsr_predictor.py
index e7bd32b..58f3b61 100644
--- a/ppgan/apps/realsr_predictor.py
+++ b/ppgan/apps/realsr_predictor.py
@@ -22,7 +22,7 @@ from tqdm import tqdm
import paddle
from ppgan.models.generators import RRDBNet
from ppgan.utils.video import frames2video, video2frames
-from paddle.utils.download import get_path_from_url
+from ppgan.utils.download import get_path_from_url
from .base_predictor import BasePredictor
REALSR_WEIGHT_URL = 'https://paddlegan.bj.bcebos.com/applications/DF2K_JPEG.pdparams'
@@ -34,8 +34,7 @@ class RealSRPredictor(BasePredictor):
self.output = os.path.join(output, 'RealSR')
self.model = RRDBNet(3, 3, 64, 23)
if weight_path is None:
- cur_path = os.path.abspath(os.path.dirname(__file__))
- weight_path = get_path_from_url(REALSR_WEIGHT_URL, cur_path)
+ weight_path = get_path_from_url(REALSR_WEIGHT_URL)
state_dict = paddle.load(weight_path)
self.model.load_dict(state_dict)
diff --git a/ppgan/utils/download.py b/ppgan/utils/download.py
new file mode 100644
index 0000000..49e1d06
--- /dev/null
+++ b/ppgan/utils/download.py
@@ -0,0 +1,254 @@
+# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from __future__ import absolute_import
+from __future__ import division
+from __future__ import print_function
+
+import os
+import sys
+import os.path as osp
+import shutil
+import requests
+import hashlib
+import tarfile
+import zipfile
+import time
+from tqdm import tqdm
+import logging
+
+from .logger import get_logger
+
+logger = get_logger('ppgan')
+
+PPGAN_HOME = os.path.expanduser("~/.cache/ppgan/")
+
+DOWNLOAD_RETRY_LIMIT = 3
+
+
+def is_url(path):
+ """
+ Whether path is URL.
+ Args:
+ path (string): URL string or not.
+ """
+ return path.startswith('http://') or path.startswith('https://')
+
+
+def _map_path(url, root_dir):
+ # parse path after download under root_dir
+ fname = osp.split(url)[-1]
+ fpath = fname
+ return osp.join(root_dir, fpath)
+
+
+def get_path_from_url(url, md5sum=None, check_exist=True):
+ """ Download from given url to root_dir.
+ if file or directory specified by url is exists under
+ root_dir, return the path directly, otherwise download
+ from url and decompress it, return the path.
+
+ Args:
+ url (str): download url
+ md5sum (str): md5 sum of download package
+
+ Returns:
+ str: a local path to save downloaded models & weights & datasets.
+ """
+
+ from paddle.fluid.dygraph.parallel import ParallelEnv
+
+ assert is_url(url), "downloading from {} not a url".format(url)
+ root_dir = PPGAN_HOME
+ # parse path after download to decompress under root_dir
+ fullpath = _map_path(url, root_dir)
+
+ if osp.exists(fullpath) and check_exist and _md5check(fullpath, md5sum):
+ logger.info("Found {}".format(fullpath))
+ else:
+ if ParallelEnv().local_rank == 0:
+ fullpath = _download(url, root_dir, md5sum)
+ else:
+ while not os.path.exists(fullpath):
+ time.sleep(1)
+
+ if ParallelEnv().local_rank == 0:
+ if tarfile.is_tarfile(fullpath) or zipfile.is_zipfile(fullpath):
+ fullpath = _decompress(fullpath)
+
+ return fullpath
+
+
+def _download(url, path, md5sum=None):
+ """
+ Download from url, save to path.
+
+ url (str): download url
+ path (str): download to given path
+ """
+ if not osp.exists(path):
+ os.makedirs(path)
+
+ fname = osp.split(url)[-1]
+ fullname = osp.join(path, fname)
+ retry_cnt = 0
+
+ while not (osp.exists(fullname) and _md5check(fullname, md5sum)):
+ if retry_cnt < DOWNLOAD_RETRY_LIMIT:
+ retry_cnt += 1
+ else:
+ raise RuntimeError("Download from {} failed. "
+ "Retry limit reached".format(url))
+
+ logger.info("Downloading {} from {}".format(fname, url))
+
+ req = requests.get(url, stream=True)
+ if req.status_code != 200:
+ raise RuntimeError("Downloading from {} failed with code "
+ "{}!".format(url, req.status_code))
+
+ # For protecting download interupted, download to
+ # tmp_fullname firstly, move tmp_fullname to fullname
+ # after download finished
+ tmp_fullname = fullname + "_tmp"
+ total_size = req.headers.get('content-length')
+ with open(tmp_fullname, 'wb') as f:
+ if total_size:
+ with tqdm(total=(int(total_size) + 1023) // 1024) as pbar:
+ for chunk in req.iter_content(chunk_size=1024):
+ f.write(chunk)
+ pbar.update(1)
+ else:
+ for chunk in req.iter_content(chunk_size=1024):
+ if chunk:
+ f.write(chunk)
+ shutil.move(tmp_fullname, fullname)
+ return fullname
+
+
+def _md5check(fullname, md5sum=None):
+ if md5sum is None:
+ return True
+
+ logger.info("File {} md5 checking...".format(fullname))
+ md5 = hashlib.md5()
+ with open(fullname, 'rb') as f:
+ for chunk in iter(lambda: f.read(4096), b""):
+ md5.update(chunk)
+ calc_md5sum = md5.hexdigest()
+
+ if calc_md5sum != md5sum:
+ logger.info("File {} md5 check failed, {}(calc) != "
+ "{}(base)".format(fullname, calc_md5sum, md5sum))
+ return False
+ return True
+
+
+def _decompress(fname):
+ """
+ Decompress for zip and tar file
+ """
+ logger.info("Decompressing {}...".format(fname))
+
+ # For protecting decompressing interupted,
+ # decompress to fpath_tmp directory firstly, if decompress
+ # successed, move decompress files to fpath and delete
+ # fpath_tmp and remove download compress file.
+
+ if tarfile.is_tarfile(fname):
+ uncompressed_path = _uncompress_file_tar(fname)
+ elif zipfile.is_zipfile(fname):
+ uncompressed_path = _uncompress_file_zip(fname)
+ else:
+ raise TypeError("Unsupport compress file type {}".format(fname))
+
+ return uncompressed_path
+
+
+def _uncompress_file_zip(filepath):
+ files = zipfile.ZipFile(filepath, 'r')
+ file_list = files.namelist()
+
+ file_dir = os.path.dirname(filepath)
+
+ if _is_a_single_file(file_list):
+ rootpath = file_list[0]
+ uncompressed_path = os.path.join(file_dir, rootpath)
+
+ for item in file_list:
+ files.extract(item, file_dir)
+
+ elif _is_a_single_dir(file_list):
+ rootpath = os.path.splitext(file_list[0])[0].strip(os.sep).split(
+ os.sep)[-1]
+ uncompressed_path = os.path.join(file_dir, rootpath)
+
+ for item in file_list:
+ files.extract(item, file_dir)
+
+ else:
+ rootpath = os.path.splitext(filepath)[0].split(os.sep)[-1]
+ uncompressed_path = os.path.join(file_dir, rootpath)
+ if not os.path.exists(uncompressed_path):
+ os.makedirs(uncompressed_path)
+ for item in file_list:
+ files.extract(item, os.path.join(file_dir, rootpath))
+
+ files.close()
+
+ return uncompressed_path
+
+
+def _uncompress_file_tar(filepath, mode="r:*"):
+ files = tarfile.open(filepath, mode)
+ file_list = files.getnames()
+
+ file_dir = os.path.dirname(filepath)
+
+ if _is_a_single_file(file_list):
+ rootpath = file_list[0]
+ uncompressed_path = os.path.join(file_dir, rootpath)
+ for item in file_list:
+ files.extract(item, file_dir)
+ elif _is_a_single_dir(file_list):
+ rootpath = os.path.splitext(file_list[0])[0].split(os.sep)[-1]
+ uncompressed_path = os.path.join(file_dir, rootpath)
+ for item in file_list:
+ files.extract(item, file_dir)
+ else:
+ rootpath = os.path.splitext(filepath)[0].split(os.sep)[-1]
+ uncompressed_path = os.path.join(file_dir, rootpath)
+ if not os.path.exists(uncompressed_path):
+ os.makedirs(uncompressed_path)
+
+ for item in file_list:
+ files.extract(item, os.path.join(file_dir, rootpath))
+
+ files.close()
+
+ return uncompressed_path
+
+
+def _is_a_single_file(file_list):
+ if len(file_list) == 1 and file_list[0].find(os.sep) < -1:
+ return True
+ return False
+
+
+def _is_a_single_dir(file_list):
+ file_name = file_list[0].split(os.sep)[0]
+ for i in range(1, len(file_list)):
+ if file_name != file_list[i].split(os.sep)[0]:
+ return False
+ return True
diff --git a/ppgan/utils/logger.py b/ppgan/utils/logger.py
index fed2acb..b758523 100644
--- a/ppgan/utils/logger.py
+++ b/ppgan/utils/logger.py
@@ -18,6 +18,8 @@ import sys
from paddle.distributed import ParallelEnv
+logger_initialized = {}
+
def setup_logger(output=None, name="ppgan"):
"""
@@ -67,3 +69,11 @@ def setup_logger(output=None, name="ppgan"):
logger.addHandler(fh)
return logger
+
+
+def get_logger(name, output=None):
+ logger = logging.getLogger(name)
+ if name in logger_initialized:
+ return logger
+
+ return setup_logger(name=name, output=name)
diff --git a/script/pix2pix_download.sh b/script/pix2pix_download.sh
deleted file mode 100644
index d3cc8ce..0000000
--- a/script/pix2pix_download.sh
+++ /dev/null
@@ -1,9 +0,0 @@
-FILE=$1
-URL=https://people.eecs.berkeley.edu/~tinghuiz/projects/pix2pix/datasets/$FILE.tar.gz
-TAR_FILE=./$FILE.tar.gz
-TARGET_DIR=./$FILE/
-wget -N $URL -O $TAR_FILE --no-check-certificate
-mkdir $TARGET_DIR
-tar -zxvf $TAR_FILE -C ../data/
-rm $TAR_FILE
-rm -rf $TARGET_DIR
--
GitLab