diff --git a/PaddleCV/PaddleGAN/README.md b/PaddleCV/PaddleGAN/README.md
index 04bb8b5a4167b668f2fe861dd01b5d040c8cbc2c..05630422b791bf7b05a7c0a5379373be3d2621ed 100644
--- a/PaddleCV/PaddleGAN/README.md
+++ b/PaddleCV/PaddleGAN/README.md
@@ -16,7 +16,7 @@
## 模型简介
-本图像生成模型库包含CGAN\[[3](#参考文献)\], DCGAN\[[4](#参考文献)\], Pix2Pix\[[5](#参考文献)\], CycleGAN\[[6](#参考文献)\], StarGAN\[[7](#参考文献)\], AttGAN\[[8](#参考文献)\], STGAN\[[9](#参考文献)\]。
+本图像生成模型库包含CGAN\[[3](#参考文献)\], DCGAN\[[4](#参考文献)\], Pix2Pix\[[5](#参考文献)\], CycleGAN\[[6](#参考文献)\], StarGAN\[[7](#参考文献)\], AttGAN\[[8](#参考文献)\], STGAN\[[9](#参考文献)\], SPADE\[[13](#参考文献)\]。
注意:
1. StarGAN,AttGAN和STGAN由于梯度惩罚所需的操作目前只支持GPU,需使用GPU训练。
@@ -86,6 +86,7 @@ StarGAN,AttGAN和STGAN采用celeba\[[11](#参考文献)\]数据集进行属性
通过指定dataset参数来下载相应的数据集。
StarGAN, AttGAN和STGAN所需要的[Celeba](http://mmlab.ie.cuhk.edu.hk/projects/CelebA.html)数据集可以自行下载。
+SPADE使用的[cityscapes](https://www.cityscapes-dataset.com)数据集可以自行下载。下载完成后新建一个目录data/cityscapes/,并在目录下准备3个子目录,分别是真实图片、分割图、实例图。准备一个train_list和test_list,每一行的顺序是分割图\t真实图\t实例图。
**自定义数据集:**
如果您要使用自定义的数据集,只要设置成对应的生成模型所需要的数据格式,并放在data文件夹下,然后把`--dataset`参数设置成您自定义数据集的名称,data_reader.py文件就会自动去data文件夹中寻找数据。
@@ -113,6 +114,7 @@ StarGAN, AttGAN和STGAN所需要的[Celeba](http://mmlab.ie.cuhk.edu.hk/projects
- 每个GAN都给出了一份运行示例,放在scripts文件夹内,用户可以直接运行训练脚本快速开始训练。
- 用户可以通过设置`--model_net`参数来选择想要训练的模型,通过设置`--dataset`参数来选择训练所需要的数据集。
+- SPADE模型的训练需要在主目录下新建一个VGG19_pretrained目录,从[该链接](https://paddle-imagenet-models-name.bj.bcebos.com/VGG19_pretrained.tar)下载在ImageNet上预训练好的VGG19模型,解压之后把VGG19模型的参数名改成`vgg19_`开头的参数名。
### 模型测试
模型测试是利用训练完成的生成模型进行图像生成。infer.py是主要的执行程序,调用示例如下:
@@ -183,6 +185,7 @@ STGAN的效果图(图片属性分别为:original image, Bald, Bangs, Black Hai
| StarGAN | [StarGAN的预训练模型](https://paddle-gan-models.bj.bcebos.com/stargan_G.tar.gz) |
| AttGAN | [AttGAN的预训练模型](https://paddle-gan-models.bj.bcebos.com/attgan_G.tar.gz) |
| STGAN | [STGAN的预训练模型](https://paddle-gan-models.bj.bcebos.com/stgan_G.tar.gz) |
+| SPADE | [SPADE的预训练模型]() ([SPADE需要的vgg预训练模型]())
## 进阶使用
@@ -202,6 +205,8 @@ AttGAN利用分类损失和重构损失来保证改变特定的属性,可用
STGAN只输入有变化的标签,引入GRU结构,更好的选择变化的属性,可用于人脸特定属性转换。
+SPADE提出一种考虑空间语义信息的归一化方法,从而更好的保留语义信息,生成更为逼真的图像,可用于图像翻译。
+
### 模型概览
- Pix2Pix由一个生成网络和一个判别网络组成。生成网络中编码部分的网络结构都是采用`convolution-batch norm-ReLU`作为基础结构,解码部分的网络结构由`transpose convolution-batch norm-ReLU`组成,判别网络基本是由`convolution-norm-leaky_ReLU`作为基础结构,详细的网络结构可以查看`network/Pix2pix_network.py`文件。生成网络提供两种可选的网络结构:Unet网络结构和普通的encoder-decoder网络结构。网络利用损失函数学习从输入图像到输出图像的映射,生成网络损失函数由GAN的损失函数和L1损失函数组成,判别网络损失函数由GAN的损失函数组成。生成器的网络结构如下图所示:
@@ -245,6 +250,13 @@ AttGAN的网络结构[8]
STGAN的网络结构[9]
+- SPADE中整体网络结构如下图所示。SPADE在网络中的卷积层使用了[谱归一化](\[[12](#参考文献)\]),把输入图像的语义mask图像作为生成网络输入,拼接了语义mask和生成器的输出为判别网络的输入。SPADE提出了一种基于空间信息的归一化方法\(SPatially-Adaptive \(DE\)normalization\),在进行归一化的时候可以更好的利用语义信息,从而生成更为逼真的图像。更为具体的网络结构可以参考network/SPADE_network.py文件或者论文中的附录部分。
+
+
+
+SPADE整体的网络结构[10]
+
+
注意:网络结构中的norm指的是用户可以选用batch norm或者instance norm来搭建自己的网络。
@@ -291,6 +303,10 @@ STGAN的网络结构[9]
[11] [Deep Learning Face Attributes in the Wild](https://arxiv.org/abs/1411.7766)
+[12] [Spectral Normalization for Generative Adversarial Networks](https://arxiv.org/abs/1802.05957)
+
+[13] [Semantic Image Synthesis with Spatially-Adaptive Normalization](https://arxiv.org/abs/1903.07291)
+
## 版本更新
diff --git a/PaddleCV/PaddleGAN/data_reader.py b/PaddleCV/PaddleGAN/data_reader.py
index 95cdf9568ae75a3456b896920fb1172aaa733729..ef18d7e05a70dfcef605597da55d80c1db794c94 100644
--- a/PaddleCV/PaddleGAN/data_reader.py
+++ b/PaddleCV/PaddleGAN/data_reader.py
@@ -618,6 +618,11 @@ class data_reader(object):
train_list = os.path.join(dataset_dir, 'train.txt')
if self.cfg.train_list is not None:
train_list = self.cfg.train_list
+ if not os.path.exists(train_list):
+ print(
+ "train_list is NOT EXIST!!! Please prepare train list first"
+ )
+ sys.exit(1)
train_reader = triplex_reader_creator(
image_dir=dataset_dir,
list_filename=train_list,
@@ -629,6 +634,11 @@ class data_reader(object):
test_list = os.path.join(dataset_dir, "test.txt")
if self.cfg.test_list is not None:
test_list = self.cfg.test_list
+ if not os.path.exists(test_list):
+ print(
+ "test_list is NOT EXIST!!! Please prepare test list first"
+ )
+ sys.exit(1)
test_reader = triplex_reader_creator(
image_dir=dataset_dir,
list_filename=test_list,
diff --git a/PaddleCV/PaddleGAN/images/spade_net.png b/PaddleCV/PaddleGAN/images/spade_net.png
new file mode 100644
index 0000000000000000000000000000000000000000..569263b121e5dbdd0c18e725186b077b032b98e4
Binary files /dev/null and b/PaddleCV/PaddleGAN/images/spade_net.png differ
diff --git a/PaddleCV/PaddleGAN/infer.py b/PaddleCV/PaddleGAN/infer.py
index 9b2a1202032802d79f3180cfe25ae4145c6127d8..caa777cd9f16162eb9735cf310bd23321a2dc3f5 100644
--- a/PaddleCV/PaddleGAN/infer.py
+++ b/PaddleCV/PaddleGAN/infer.py
@@ -169,12 +169,14 @@ def infer(args):
model = DCGAN_model(args.n_samples)
fake = model.network_G(noise, name="G")
elif args.model_net == 'SPADE':
+ label_shape = [-1, args.label_nc, args.crop_height, args.crop_width]
+ spade_data_shape = [-1, 1, args.crop_height, args.crop_width]
from network.SPADE_network import SPADE_model
model = SPADE_model()
input_label = fluid.layers.data(
- name='input_label', shape=data_shape, dtype='float32')
+ name='input_label', shape=label_shape, dtype='float32')
input_ins = fluid.layers.data(
- name='input_ins', shape=data_shape, dtype='float32')
+ name='input_ins', shape=spade_data_shape, dtype='float32')
input_ = fluid.layers.concat([input_label, input_ins], 1)
fake = model.network_G(input_, "generator", cfg=args, is_test=True)
else:
@@ -319,10 +321,12 @@ def infer(args):
shuffle=False,
batch_size=1,
mode="TEST")
+ id2name = test_reader.id2name
reader_test = test_reader.make_reader(args, return_name=True)
for data in zip(reader_test()):
data_A, data_B, data_C, name = data[0]
- name = name[0]
+ name = id2name[np.array(name).astype('int32')[0]]
+ print("read: ", name)
tensor_A = fluid.LoDTensor()
tensor_C = fluid.LoDTensor()
tensor_A.set(data_A, place)
diff --git a/PaddleCV/PaddleGAN/network/CGAN_network.py b/PaddleCV/PaddleGAN/network/CGAN_network.py
index 5e971ab960b493555ecd4244b33856c8fdc49a81..c15d104522eed90e0bc475f11e5cfc2b7cab847e 100644
--- a/PaddleCV/PaddleGAN/network/CGAN_network.py
+++ b/PaddleCV/PaddleGAN/network/CGAN_network.py
@@ -83,7 +83,7 @@ class CGAN_model(object):
name=name + '_dc2',
output_size=[self.img_w, self.img_h])
out = fluid.layers.reshape(o_dc2, [-1, self.img_w * self.img_h])
- return o_dc2
+ return out
def network_D(self, input, label, name="discriminator"):
# concat image and label
diff --git a/PaddleCV/PaddleGAN/scripts/infer_SPADE.sh b/PaddleCV/PaddleGAN/scripts/infer_SPADE.sh
new file mode 100644
index 0000000000000000000000000000000000000000..fd726dc059ec27fa4c7664b4f12b064bc75dba8f
--- /dev/null
+++ b/PaddleCV/PaddleGAN/scripts/infer_SPADE.sh
@@ -0,0 +1 @@
+python infer.py --model_net SPADE --test_list ./data/cityscapes/test_list --load_height 512 --load_width 1024 --crop_height 512 --crop_width 1024 --dataset_dir ./data/cityscapes/ --init_model ./spade_py37/checkpoints/99/
diff --git a/PaddleCV/PaddleGAN/scripts/run_SPADE.sh b/PaddleCV/PaddleGAN/scripts/run_SPADE.sh
index 3833dc7db480a8a5428abec19f35f96fe8b96ba9..225c69d569697ee083a2cb3cf93266eade68def1 100644
--- a/PaddleCV/PaddleGAN/scripts/run_SPADE.sh
+++ b/PaddleCV/PaddleGAN/scripts/run_SPADE.sh
@@ -1,4 +1,4 @@
export FLAGS_eager_delete_tensor_gb=0.0
export FLAGS_fast_eager_deletion_mode=1
export FLAGS_fraction_of_gpu_memory_to_use=0.01
-CUDA_VISIBLE_DEVICES=0 python train.py --model_net SPADE --dataset cityscapes --train_list train_list --test_list val_list --crop_type Random --batch_size 1 --epoch 200 --load_height 612 --load_width 1124 --crop_height 512 --crop_width 1024 --label_nc 36
+CUDA_VISIBLE_DEVICES=0 python train.py --model_net SPADE --dataset cityscapes --train_list ./data/cityscapes/train_list --test_list ./data/cityscapes/val_list --crop_type Random --batch_size 1 --epoch 200 --load_height 612 --load_width 1124 --crop_height 512 --crop_width 1024 --label_nc 36
diff --git a/PaddleCV/PaddleGAN/trainer/SPADE.py b/PaddleCV/PaddleGAN/trainer/SPADE.py
index 1ef1f4f74f45116ace16b94986e7d23ee95797ae..468d58bed056bd9fb016740126cecbbd753f14b6 100644
--- a/PaddleCV/PaddleGAN/trainer/SPADE.py
+++ b/PaddleCV/PaddleGAN/trainer/SPADE.py
@@ -19,6 +19,7 @@ from network.SPADE_network import SPADE_model
from util import utility
import paddle.fluid as fluid
import sys
+import os
import time
import network.vgg as vgg
import pickle as pkl
@@ -316,6 +317,12 @@ class SPADE(object):
place = fluid.CUDAPlace(0) if self.cfg.use_gpu else fluid.CPUPlace()
exe = fluid.Executor(place)
exe.run(fluid.default_startup_program())
+
+ if not os.path.exists(self.cfg.vgg19_pretrain):
+ print(
+ "directory VGG19_pretrain NOT EXIST!!! Please download VGG19 first."
+ )
+ sys.exit(1)
gen_trainer.vgg.load_vars(exe, gen_trainer.program,
self.cfg.vgg19_pretrain)