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)