├── ppgan ├── apps │ ├── midas │ │ ├── __init__.py │ │ ├── README.md │ │ ├── utils.py │ │ ├── resnext.py │ │ └── midas_net.py │ ├── __init__.py │ ├── face_parse_predictor.py │ ├── styleganv2mixing_predictor.py │ ├── base_predictor.py │ ├── styleganv2editing_predictor.py │ └── photo2cartoon_predictor.py ├── faceutils │ ├── face_detection │ │ ├── detection │ │ │ ├── __init__.py │ │ │ ├── sfd │ │ │ │ ├── __init__.py │ │ │ │ └── sfd_detector.py │ │ │ └── blazeface │ │ │ │ ├── __init__.py │ │ │ │ ├── utils.py │ │ │ │ ├── blazeface_detector.py │ │ │ │ └── detect.py │ │ ├── __init__.py │ │ ├── utils.py │ │ └── api.py │ ├── mask │ │ ├── __init__.py │ │ └── face_parser.py │ ├── face_segmentation │ │ ├── __init__.py │ │ ├── layers.py │ │ └── face_seg.py │ ├── face_enhancement │ │ ├── __init__.py │ │ └── face_enhance.py │ ├── dlibutils │ │ └── __init__.py │ ├── __init__.py │ └── image.py ├── datasets │ ├── preprocess │ │ ├── __init__.py │ │ ├── io.py │ │ └── builder.py │ ├── __init__.py │ ├── single_dataset.py │ ├── paired_dataset.py │ ├── repeat_dataset.py │ ├── base_sr_dataset.py │ ├── builder.py │ ├── common_vision_dataset.py │ ├── image_folder.py │ └── unpaired_dataset.py ├── models │ ├── criterions │ │ ├── __init__.py │ │ └── builder.py │ ├── backbones │ │ └── __init__.py │ ├── builder.py │ ├── generators │ │ ├── builder.py │ │ ├── __init__.py │ │ └── gpen.py │ ├── discriminators │ │ ├── builder.py │ │ ├── __init__.py │ │ ├── discriminator_starganv2.py │ │ ├── discriminator_lapstyle.py │ │ ├── discriminator_animegan.py │ │ └── wav2lip_disc_qual.py │ ├── __init__.py │ ├── mpr_model.py │ ├── sr_model.py │ └── edvr_model.py ├── utils │ ├── audio_config.py │ ├── __init__.py │ ├── timer.py │ ├── setup.py │ ├── animate.py │ ├── filesystem.py │ ├── video.py │ ├── logger.py │ ├── image_pool.py │ └── options.py ├── engine │ └── __init__.py ├── modules │ ├── __init__.py │ ├── fused_act.py │ ├── conv.py │ ├── norm.py │ └── caffevgg.py ├── version.py ├── __init__.py ├── metrics │ ├── __init__.py │ └── builder.py └── solver │ ├── __init__.py │ ├── optimizer.py │ └── builder.py ├── output_dir └── readme.md ├── Fig └── visual_test │ ├── comic_gt.png │ ├── comic_lq.png │ ├── face_gt.png │ ├── face_lq.png │ ├── lenna_gt.png │ ├── lenna_lq.png │ ├── man_gt.png │ ├── man_lq.png │ ├── ppt3_gt.png │ ├── ppt3_lq.png │ ├── zebra_gt.png │ ├── zebra_lq.png │ ├── baboon_gt.png │ ├── baboon_lq.png │ ├── barbara_gt.png │ ├── barbara_lq.png │ ├── bridge_gt.png │ ├── bridge_lq.png │ ├── flowers_gt.png │ ├── flowers_lq.png │ ├── foreman_gt.png │ ├── foreman_lq.png │ ├── man_output.png │ ├── monarch_gt.png │ ├── monarch_lq.png │ ├── pepper_gt.png │ ├── pepper_lq.png │ ├── baboon_output.png │ ├── bridge_output.png │ ├── coastguard_gt.png │ ├── coastguard_lq.png │ ├── comic_output.png │ ├── face_output.png │ ├── lenna_output.png │ ├── pepper_output.png │ ├── ppt3_output.png │ ├── zebra_output.png │ ├── barbara_output.png │ ├── flowers_output.png │ ├── foreman_output.png │ ├── monarch_output.png │ └── coastguard_output.png ├── requirements.txt ├── data ├── realsr_preprocess │ ├── paths.yml │ └── collect_noise.py ├── download_pix2pix_data.py └── download_cyclegan_data.py ├── test_tipc ├── readme.md ├── output │ ├── results_python.log │ └── python_infer_gpu_usetrt_null_precision_null_batchsize_null.log ├── common_func.sh └── configs │ └── rcan │ ├── train_infer_python.txt │ └── train_infer_python_resume.txt ├── applications └── tools │ ├── face_parse.py │ ├── animeganv2.py │ ├── lapstyle.py │ ├── image_restoration.py │ ├── pixel2style2pixel.py │ └── styleganv2mixing.py ├── benchmark ├── benchmark.yaml ├── README.md ├── analysis_log.py └── run_benchmark.sh ├── tools ├── psgan_infer.py ├── extract_weight.py ├── main.py ├── animegan_picmean.py └── export_model.py ├── setup.py └── configs ├── rcan_x4_div2k_tipc.yaml └── rcan_x4_div2k.yaml /ppgan/apps/midas/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /output_dir/readme.md: -------------------------------------------------------------------------------- 1 | ## output_dir文件夹 2 | 3 | 训练与预测产生的文件存放的文件及 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ppgan/faceutils/face_detection/detection/__init__.py: -------------------------------------------------------------------------------- 1 | from .core import FaceDetector 2 | -------------------------------------------------------------------------------- /ppgan/faceutils/face_detection/__init__.py: -------------------------------------------------------------------------------- 1 | from .api import FaceAlignment, LandmarksType, NetworkSize 2 | -------------------------------------------------------------------------------- /Fig/visual_test/comic_gt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kongdebug/RCAN-Paddle/HEAD/Fig/visual_test/comic_gt.png -------------------------------------------------------------------------------- /Fig/visual_test/comic_lq.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kongdebug/RCAN-Paddle/HEAD/Fig/visual_test/comic_lq.png -------------------------------------------------------------------------------- /Fig/visual_test/face_gt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kongdebug/RCAN-Paddle/HEAD/Fig/visual_test/face_gt.png -------------------------------------------------------------------------------- /Fig/visual_test/face_lq.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kongdebug/RCAN-Paddle/HEAD/Fig/visual_test/face_lq.png -------------------------------------------------------------------------------- /Fig/visual_test/lenna_gt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kongdebug/RCAN-Paddle/HEAD/Fig/visual_test/lenna_gt.png -------------------------------------------------------------------------------- /Fig/visual_test/lenna_lq.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kongdebug/RCAN-Paddle/HEAD/Fig/visual_test/lenna_lq.png -------------------------------------------------------------------------------- /Fig/visual_test/man_gt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kongdebug/RCAN-Paddle/HEAD/Fig/visual_test/man_gt.png -------------------------------------------------------------------------------- /Fig/visual_test/man_lq.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kongdebug/RCAN-Paddle/HEAD/Fig/visual_test/man_lq.png -------------------------------------------------------------------------------- /Fig/visual_test/ppt3_gt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kongdebug/RCAN-Paddle/HEAD/Fig/visual_test/ppt3_gt.png -------------------------------------------------------------------------------- /Fig/visual_test/ppt3_lq.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kongdebug/RCAN-Paddle/HEAD/Fig/visual_test/ppt3_lq.png -------------------------------------------------------------------------------- /Fig/visual_test/zebra_gt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kongdebug/RCAN-Paddle/HEAD/Fig/visual_test/zebra_gt.png -------------------------------------------------------------------------------- /Fig/visual_test/zebra_lq.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kongdebug/RCAN-Paddle/HEAD/Fig/visual_test/zebra_lq.png -------------------------------------------------------------------------------- /Fig/visual_test/baboon_gt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kongdebug/RCAN-Paddle/HEAD/Fig/visual_test/baboon_gt.png -------------------------------------------------------------------------------- /Fig/visual_test/baboon_lq.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kongdebug/RCAN-Paddle/HEAD/Fig/visual_test/baboon_lq.png -------------------------------------------------------------------------------- /Fig/visual_test/barbara_gt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kongdebug/RCAN-Paddle/HEAD/Fig/visual_test/barbara_gt.png -------------------------------------------------------------------------------- /Fig/visual_test/barbara_lq.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kongdebug/RCAN-Paddle/HEAD/Fig/visual_test/barbara_lq.png -------------------------------------------------------------------------------- /Fig/visual_test/bridge_gt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kongdebug/RCAN-Paddle/HEAD/Fig/visual_test/bridge_gt.png -------------------------------------------------------------------------------- /Fig/visual_test/bridge_lq.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kongdebug/RCAN-Paddle/HEAD/Fig/visual_test/bridge_lq.png -------------------------------------------------------------------------------- /Fig/visual_test/flowers_gt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kongdebug/RCAN-Paddle/HEAD/Fig/visual_test/flowers_gt.png -------------------------------------------------------------------------------- /Fig/visual_test/flowers_lq.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kongdebug/RCAN-Paddle/HEAD/Fig/visual_test/flowers_lq.png -------------------------------------------------------------------------------- /Fig/visual_test/foreman_gt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kongdebug/RCAN-Paddle/HEAD/Fig/visual_test/foreman_gt.png -------------------------------------------------------------------------------- /Fig/visual_test/foreman_lq.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kongdebug/RCAN-Paddle/HEAD/Fig/visual_test/foreman_lq.png -------------------------------------------------------------------------------- /Fig/visual_test/man_output.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kongdebug/RCAN-Paddle/HEAD/Fig/visual_test/man_output.png -------------------------------------------------------------------------------- /Fig/visual_test/monarch_gt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kongdebug/RCAN-Paddle/HEAD/Fig/visual_test/monarch_gt.png -------------------------------------------------------------------------------- /Fig/visual_test/monarch_lq.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kongdebug/RCAN-Paddle/HEAD/Fig/visual_test/monarch_lq.png -------------------------------------------------------------------------------- /Fig/visual_test/pepper_gt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kongdebug/RCAN-Paddle/HEAD/Fig/visual_test/pepper_gt.png -------------------------------------------------------------------------------- /Fig/visual_test/pepper_lq.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kongdebug/RCAN-Paddle/HEAD/Fig/visual_test/pepper_lq.png -------------------------------------------------------------------------------- /ppgan/faceutils/face_detection/detection/sfd/__init__.py: -------------------------------------------------------------------------------- 1 | from .sfd_detector import SFDDetector as FaceDetector 2 | -------------------------------------------------------------------------------- /Fig/visual_test/baboon_output.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kongdebug/RCAN-Paddle/HEAD/Fig/visual_test/baboon_output.png -------------------------------------------------------------------------------- /Fig/visual_test/bridge_output.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kongdebug/RCAN-Paddle/HEAD/Fig/visual_test/bridge_output.png -------------------------------------------------------------------------------- /Fig/visual_test/coastguard_gt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kongdebug/RCAN-Paddle/HEAD/Fig/visual_test/coastguard_gt.png -------------------------------------------------------------------------------- /Fig/visual_test/coastguard_lq.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kongdebug/RCAN-Paddle/HEAD/Fig/visual_test/coastguard_lq.png -------------------------------------------------------------------------------- /Fig/visual_test/comic_output.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kongdebug/RCAN-Paddle/HEAD/Fig/visual_test/comic_output.png -------------------------------------------------------------------------------- /Fig/visual_test/face_output.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kongdebug/RCAN-Paddle/HEAD/Fig/visual_test/face_output.png -------------------------------------------------------------------------------- /Fig/visual_test/lenna_output.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kongdebug/RCAN-Paddle/HEAD/Fig/visual_test/lenna_output.png -------------------------------------------------------------------------------- /Fig/visual_test/pepper_output.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kongdebug/RCAN-Paddle/HEAD/Fig/visual_test/pepper_output.png -------------------------------------------------------------------------------- /Fig/visual_test/ppt3_output.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kongdebug/RCAN-Paddle/HEAD/Fig/visual_test/ppt3_output.png -------------------------------------------------------------------------------- /Fig/visual_test/zebra_output.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kongdebug/RCAN-Paddle/HEAD/Fig/visual_test/zebra_output.png -------------------------------------------------------------------------------- /Fig/visual_test/barbara_output.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kongdebug/RCAN-Paddle/HEAD/Fig/visual_test/barbara_output.png -------------------------------------------------------------------------------- /Fig/visual_test/flowers_output.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kongdebug/RCAN-Paddle/HEAD/Fig/visual_test/flowers_output.png -------------------------------------------------------------------------------- /Fig/visual_test/foreman_output.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kongdebug/RCAN-Paddle/HEAD/Fig/visual_test/foreman_output.png -------------------------------------------------------------------------------- /Fig/visual_test/monarch_output.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kongdebug/RCAN-Paddle/HEAD/Fig/visual_test/monarch_output.png -------------------------------------------------------------------------------- /Fig/visual_test/coastguard_output.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kongdebug/RCAN-Paddle/HEAD/Fig/visual_test/coastguard_output.png -------------------------------------------------------------------------------- /ppgan/faceutils/face_detection/detection/blazeface/__init__.py: -------------------------------------------------------------------------------- 1 | from .blazeface_detector import BlazeFaceDetector as FaceDetector 2 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | tqdm 2 | PyYAML>=5.1 3 | scikit-image>=0.14.0 4 | scipy>=1.1.0 5 | opencv-python 6 | imageio==2.9.0 7 | imageio-ffmpeg 8 | librosa 9 | numba==0.53.1 10 | easydict 11 | munch 12 | natsort 13 | -------------------------------------------------------------------------------- /ppgan/datasets/preprocess/__init__.py: -------------------------------------------------------------------------------- 1 | from .io import LoadImageFromFile 2 | from .transforms import (PairedRandomCrop, PairedRandomHorizontalFlip, 3 | PairedRandomVerticalFlip, PairedRandomTransposeHW, 4 | SRPairedRandomCrop, SplitPairedImage, SRNoise) 5 | 6 | from .builder import build_preprocess 7 | -------------------------------------------------------------------------------- /ppgan/models/criterions/__init__.py: -------------------------------------------------------------------------------- 1 | from .gan_loss import GANLoss 2 | from .perceptual_loss import PerceptualLoss 3 | from .pixel_loss import L1Loss, MSELoss, CharbonnierLoss, \ 4 | CalcStyleEmdLoss, CalcContentReltLoss, \ 5 | CalcContentLoss, CalcStyleLoss, EdgeLoss 6 | 7 | from .builder import build_criterion 8 | -------------------------------------------------------------------------------- /data/realsr_preprocess/paths.yml: -------------------------------------------------------------------------------- 1 | df2k: 2 | tdsr: 3 | source: './data/ntire20/Corrupted-tr-x' 4 | target: './data/ntire20/Corrupted-tr-y' 5 | valid: 6 | dped: 7 | clean: 8 | hr: 9 | train: './data/ntire20/DPEDiphone-tr-x' 10 | valid: './data/ntire20/DPEDiphone-va' 11 | datasets: 12 | df2k: 'data/DF2K' 13 | dped: 'data/DPED' 14 | -------------------------------------------------------------------------------- /test_tipc/readme.md: -------------------------------------------------------------------------------- 1 | ## Linux端基础训练预测功能测试 2 | 3 | Linux端基础训练预测功能测试的主程序为`test_train_inference_python.sh`,可以测试基于Python的模型训练、评估、推理等基本功能。 4 | 5 | 6 | 7 | 8 | ## 安装依赖 9 | 10 | - 进入本项目文件夹 11 | ``` 12 | cd RCAN-Paddle 13 | ``` 14 | - 安装autolog(规范化日志输出工具) 15 | ``` 16 | git clone https://github.com/LDOUBLEV/AutoLog 17 | cd AutoLog 18 | pip3 install -r requirements.txt 19 | python3 setup.py bdist_wheel 20 | pip3 install ./dist/auto_log-1.0.0-py3-none-any.whl 21 | cd ../ 22 | ``` 23 | 24 | 25 | -------------------------------------------------------------------------------- /ppgan/apps/midas/README.md: -------------------------------------------------------------------------------- 1 | ## Monocular Depth Estimation 2 | 3 | 4 | The implemention of MiDasv2 refers to https://github.com/intel-isl/MiDaS. 5 | 6 | 7 | @article{Ranftl2020, 8 | author = {Ren\'{e} Ranftl and Katrin Lasinger and David Hafner and Konrad Schindler and Vladlen Koltun}, 9 | title = {Towards Robust Monocular Depth Estimation: Mixing Datasets for Zero-shot Cross-dataset Transfer}, 10 | journal = {IEEE Transactions on Pattern Analysis and Machine Intelligence (TPAMI)}, 11 | year = {2020}, 12 | } 13 | -------------------------------------------------------------------------------- /applications/tools/face_parse.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | 3 | import paddle 4 | from ppgan.apps.face_parse_predictor import FaceParsePredictor 5 | 6 | parser = argparse.ArgumentParser() 7 | parser.add_argument("--input_image", type=str, help="path to source image") 8 | 9 | parser.add_argument("--cpu", dest="cpu", action="store_true", help="cpu mode.") 10 | 11 | if __name__ == "__main__": 12 | args = parser.parse_args() 13 | 14 | if args.cpu: 15 | paddle.set_device('cpu') 16 | 17 | predictor = FaceParsePredictor() 18 | predictor.run(args.input_image) 19 | -------------------------------------------------------------------------------- /ppgan/utils/audio_config.py: -------------------------------------------------------------------------------- 1 | from easydict import EasyDict as edict 2 | 3 | _C = edict() 4 | 5 | _C.num_mels = 80 6 | _C.rescale = True 7 | _C.rescaling_max = 0.9 8 | _C.use_lws = False 9 | _C.n_fft = 800 10 | _C.hop_size = 200 11 | _C.win_size = 800 12 | _C.sample_rate = 16000 13 | _C.frame_shift_ms = None 14 | _C.signal_normalization = True 15 | _C.allow_clipping_in_normalization = True 16 | _C.symmetric_mels = True 17 | _C.max_abs_value = 4. 18 | _C.preemphasize = True 19 | _C.preemphasis = 0.97 20 | _C.min_level_db = -100 21 | _C.ref_level_db = 20 22 | _C.fmin = 55 23 | _C.fmax = 7600 24 | _C.fps = 25 25 | 26 | 27 | def get_audio_config(): 28 | return _C 29 | -------------------------------------------------------------------------------- /ppgan/engine/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | -------------------------------------------------------------------------------- /ppgan/modules/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | -------------------------------------------------------------------------------- /ppgan/utils/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | -------------------------------------------------------------------------------- /ppgan/version.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | ppgan_version = '2.0.0' 16 | -------------------------------------------------------------------------------- /ppgan/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from .version import ppgan_version as __version__ 16 | -------------------------------------------------------------------------------- /ppgan/faceutils/mask/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from .face_parser import FaceParser 16 | -------------------------------------------------------------------------------- /ppgan/faceutils/face_segmentation/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from .face_seg import FaceSeg 16 | -------------------------------------------------------------------------------- /ppgan/faceutils/face_enhancement/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from .face_enhance import FaceEnhancement 16 | -------------------------------------------------------------------------------- /ppgan/models/backbones/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from .resnet_backbone import resnet18, resnet34, resnet50, resnet101, resnet152 16 | -------------------------------------------------------------------------------- /ppgan/faceutils/dlibutils/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from .dlib_utils import detect, crop, landmarks, crop_from_array 16 | from .face_align import align_crop 17 | -------------------------------------------------------------------------------- /ppgan/metrics/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from .psnr_ssim import PSNR, SSIM 16 | from .fid import FID 17 | from .lpips import LPIPSMetric 18 | from .builder import build_metric 19 | -------------------------------------------------------------------------------- /ppgan/faceutils/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from . import dlibutils as dlib 16 | from . import mask 17 | from . import image 18 | from . import face_segmentation 19 | from . import face_detection 20 | -------------------------------------------------------------------------------- /ppgan/solver/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from .lr_scheduler import CosineAnnealingRestartLR, LinearDecay, NonLinearDecay 16 | from .optimizer import * 17 | from .builder import build_lr_scheduler 18 | from .builder import build_optimizer 19 | -------------------------------------------------------------------------------- /data/download_pix2pix_data.py: -------------------------------------------------------------------------------- 1 | import os 2 | import argparse 3 | 4 | from ppgan.utils.download import get_path_from_url 5 | 6 | PIX2PIX_URL_ROOT = 'http://efrosgans.eecs.berkeley.edu/pix2pix/datasets/' 7 | 8 | parser = argparse.ArgumentParser(description='download datasets') 9 | parser.add_argument('--name', 10 | type=str, 11 | required=True, 12 | help='dataset name, \ 13 | support dataset name: cityscapes, night2day, edges2handbags, \ 14 | edges2shoes, facades, maps') 15 | 16 | if __name__ == "__main__": 17 | args = parser.parse_args() 18 | 19 | data_url = PIX2PIX_URL_ROOT + args.name + '.tar.gz' 20 | 21 | path = get_path_from_url(data_url) 22 | 23 | dst = os.path.join('data', args.name) 24 | print('symlink {} to {}'.format(path, dst)) 25 | os.symlink(path, dst) 26 | -------------------------------------------------------------------------------- /ppgan/solver/optimizer.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import copy 16 | import paddle 17 | 18 | from .builder import OPTIMIZERS 19 | 20 | OPTIMIZERS.register(paddle.optimizer.Adam) 21 | OPTIMIZERS.register(paddle.optimizer.SGD) 22 | OPTIMIZERS.register(paddle.optimizer.Momentum) 23 | OPTIMIZERS.register(paddle.optimizer.RMSProp) 24 | -------------------------------------------------------------------------------- /ppgan/models/builder.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import copy 16 | import paddle 17 | 18 | from ..utils.registry import Registry 19 | 20 | MODELS = Registry("MODEL") 21 | 22 | 23 | def build_model(cfg): 24 | cfg_ = cfg.copy() 25 | name = cfg_.pop('name', None) 26 | model = MODELS.get(name)(**cfg_) 27 | return model 28 | -------------------------------------------------------------------------------- /ppgan/metrics/builder.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import copy 16 | import paddle 17 | 18 | from ..utils.registry import Registry 19 | 20 | METRICS = Registry("METRIC") 21 | 22 | 23 | def build_metric(cfg): 24 | cfg_ = cfg.copy() 25 | name = cfg_.pop('name', None) 26 | metric = METRICS.get(name)(**cfg_) 27 | return metric 28 | -------------------------------------------------------------------------------- /ppgan/models/generators/builder.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import copy 16 | from ...utils.registry import Registry 17 | 18 | GENERATORS = Registry("GENERATOR") 19 | 20 | 21 | def build_generator(cfg): 22 | cfg_copy = copy.deepcopy(cfg) 23 | name = cfg_copy.pop('name') 24 | generator = GENERATORS.get(name)(**cfg_copy) 25 | return generator 26 | -------------------------------------------------------------------------------- /test_tipc/output/results_python.log: -------------------------------------------------------------------------------- 1 |  Run successfully with command - python3.7 tools/main.py -c configs/rcan_x4_div2k_tipc.yaml --seed 123 -o dataset.train.num_workers=0 log_config.interval=5 output_dir=./test_tipc/output/norm_train_gpus_0_autocast_null total_iters=10 dataset.train.batch_size=16 !  2 |  Run successfully with command - python3.7 tools/export_model.py -c configs/rcan_x4_div2k.yaml --inputs_size="-1,3,-1,-1" --load ./test_tipc/output/norm_train_gpus_0_autocast_null/rcan_x4_div2k_tipc-2021-11-27-21-02/iter_10_checkpoint.pdparams --output_dir ./test_tipc/output/norm_train_gpus_0_autocast_null!  3 |  Run successfully with command - python3.7 tools/inference.py --model_type rcan --seed 123 -c configs/rcan_x4_div2k.yaml --output_path test_tipc/output/ --device=gpu --model_path=./test_tipc/output/norm_train_gpus_0_autocast_null/basesrmodel_generator > ./test_tipc/output/python_infer_gpu_usetrt_null_precision_null_batchsize_null.log 2>&1 !  4 | -------------------------------------------------------------------------------- /ppgan/models/discriminators/builder.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import copy 16 | from ...utils.registry import Registry 17 | 18 | DISCRIMINATORS = Registry("DISCRIMINATOR") 19 | 20 | 21 | def build_discriminator(cfg): 22 | cfg_copy = copy.deepcopy(cfg) 23 | name = cfg_copy.pop('name') 24 | discriminator = DISCRIMINATORS.get(name)(**cfg_copy) 25 | return discriminator 26 | -------------------------------------------------------------------------------- /benchmark/benchmark.yaml: -------------------------------------------------------------------------------- 1 | StyleGANv2: 2 | dataset_web: https://paddlegan.bj.bcebos.com/datasets/ffhq.tar 3 | config: configs/stylegan_v2_256_ffhq.yaml 4 | fp_item: fp32 5 | bs_item: 3 8 6 | total_iters: 300 7 | log_interval: 10 8 | 9 | FOMM: 10 | dataset_web: https://paddlegan.bj.bcebos.com/datasets/fom_test_data.tar 11 | config: configs/firstorder_vox_256.yaml 12 | fp_item: fp32 13 | bs_item: 8 16 14 | epochs: 30 15 | log_interval: 10 16 | 17 | esrgan: 18 | dataset_web: https://paddlegan.bj.bcebos.com/datasets/DIV2KandSet14.tar 19 | config: configs/esrgan_psnr_x4_div2k.yaml 20 | fp_item: fp32 21 | bs_item: 32 64 22 | total_iters: 300 23 | log_interval: 10 24 | 25 | edvr: 26 | dataset: data/REDS 27 | config: configs/edvr_m_wo_tsa.yaml 28 | fp_item: fp32 29 | bs_item: 4 64 30 | total_iters: 300 31 | log_interval: 10 32 | 33 | basicvsr: 34 | dataset: data/REDS 35 | config: configs/basicvsr_reds.yaml 36 | fp_item: fp32 37 | bs_item: 2 4 38 | total_iters: 300 39 | log_interval: 10 40 | -------------------------------------------------------------------------------- /ppgan/faceutils/image.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import numpy as np 16 | import cv2 17 | from io import BytesIO 18 | 19 | 20 | def resize_by_max(image, max_side=512, force=False): 21 | h, w = image.shape[:2] 22 | if max(h, w) < max_side and not force: 23 | return image 24 | ratio = max(h, w) / max_side 25 | 26 | w = int(w / ratio + 0.5) 27 | h = int(h / ratio + 0.5) 28 | return cv2.resize(image, (w, h)) 29 | -------------------------------------------------------------------------------- /ppgan/solver/builder.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from ..utils.registry import Registry 16 | 17 | LRSCHEDULERS = Registry("LRSCHEDULER") 18 | OPTIMIZERS = Registry("OPTIMIZER") 19 | 20 | 21 | def build_lr_scheduler(cfg): 22 | cfg_ = cfg.copy() 23 | name = cfg_.pop('name') 24 | return LRSCHEDULERS.get(name)(**cfg_) 25 | 26 | 27 | def build_optimizer(cfg, lr_scheduler, parameters=None): 28 | cfg_ = cfg.copy() 29 | name = cfg_.pop('name') 30 | return OPTIMIZERS.get(name)(lr_scheduler, parameters=parameters, **cfg_) 31 | -------------------------------------------------------------------------------- /data/download_cyclegan_data.py: -------------------------------------------------------------------------------- 1 | import os 2 | import argparse 3 | 4 | from ppgan.utils.download import get_path_from_url 5 | 6 | CYCLEGAN_URL_ROOT = 'https://people.eecs.berkeley.edu/~taesung_park/CycleGAN/datasets/' 7 | 8 | parser = argparse.ArgumentParser(description='download datasets') 9 | parser.add_argument('--name', 10 | type=str, 11 | required=True, 12 | help='dataset name, \ 13 | support dataset name: apple2orange, summer2winter_yosemite, \ 14 | horse2zebra, monet2photo, cezanne2photo, ukiyoe2photo, \ 15 | vangogh2photo, maps, cityscapes, facades, iphone2dslr_flower, \ 16 | ae_photos, cityscapes') 17 | 18 | if __name__ == "__main__": 19 | args = parser.parse_args() 20 | 21 | data_url = CYCLEGAN_URL_ROOT + args.name + '.zip' 22 | 23 | if args.name == 'cityscapes': 24 | data_url = 'https://paddlegan.bj.bcebos.com/datasets/cityscapes.zip' 25 | 26 | path = get_path_from_url(data_url) 27 | 28 | dst = os.path.join('data', args.name) 29 | print('symlink {} to {}'.format(path, dst)) 30 | os.symlink(path, dst) 31 | -------------------------------------------------------------------------------- /tools/psgan_infer.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import os 16 | import sys 17 | import argparse 18 | 19 | cur_path = os.path.abspath(os.path.dirname(__file__)) 20 | root_path = os.path.split(cur_path)[0] 21 | sys.path.append(root_path) 22 | 23 | from ppgan.utils.options import parse_args 24 | from ppgan.utils.config import get_config 25 | from ppgan.apps.psgan_predictor import PSGANPredictor 26 | 27 | if __name__ == '__main__': 28 | args = parse_args() 29 | cfg = get_config(args.config_file) 30 | predictor = PSGANPredictor(args, cfg) 31 | predictor.run() 32 | -------------------------------------------------------------------------------- /benchmark/README.md: -------------------------------------------------------------------------------- 1 | # PaddGAN模型性能复现 2 | ## 目录 3 | 4 | ``` 5 | ├── README.md # 说明文档 6 | ├── benchmark.yaml # 配置文件,设置测试模型及模型参数 7 | ├── run_all.sh # 执行入口,测试并获取所有生成对抗模型的训练性能 8 | └── run_benchmark.sh # 执行实体,测试单个分割模型的训练性能 9 | ``` 10 | 11 | ## 环境介绍 12 | ### 物理机环境 13 | - 单机(单卡、8卡) 14 | - 系统:CentOS release 7.5 (Final) 15 | - GPU:Tesla V100-SXM2-32GB * 8 16 | - CPU:Intel(R) Xeon(R) Gold 6271C CPU @ 2.60GHz * 80 17 | - CUDA、cudnn Version: cuda10.2-cudnn7 18 | 19 | #### 备注 20 | BasicVSR模型因竞品torch模型只能测4卡,故这里也测4卡。 21 | 22 | ### Docker 镜像 23 | 24 | - **镜像版本**: `registry.baidubce.com/paddlepaddle/paddle:2.1.2-gpu-cuda10.2-cudnn7` 25 | - **paddle 版本**: `2.1.2` 26 | - **CUDA 版本**: `10.2` 27 | - **cuDnn 版本**: `7` 28 | 29 | ## 在PaddleGAN目录下,启动测试脚本的方法如下: 30 | ```script 31 | ImageName="registry.baidubce.com/paddlepaddle/paddle:2.1.2-gpu-cuda10.2-cudnn7" 32 | docker pull ${ImageName} 33 | 34 | run_cmd="set -xe; 35 | cd /workspace ; 36 | bash -x benchmark/run_all.sh" 37 | 38 | nvidia-docker run --name test_paddlegan -i \ 39 | --net=host \ 40 | --shm-size=1g \ 41 | -v $PWD:/workspace \ 42 | ${ImageName} /bin/bash -c "${run_cmd}" 43 | ``` 44 | 45 | ## 输出 46 | 47 | 执行完成后,在PaddleGAN目录会产出模型训练性能数据的文件,比如`esrgan_mp_bs32_fp32_8`等文件。 48 | -------------------------------------------------------------------------------- /ppgan/models/discriminators/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from .vgg_discriminator import VGGDiscriminator128 16 | from .nlayers import NLayerDiscriminator, NLayerDiscriminatorWithClassification 17 | from .discriminator_ugatit import UGATITDiscriminator 18 | from .dcdiscriminator import DCDiscriminator 19 | from .discriminator_animegan import AnimeDiscriminator 20 | from .discriminator_styleganv2 import StyleGANv2Discriminator 21 | from .syncnet import SyncNetColor 22 | from .wav2lip_disc_qual import Wav2LipDiscQual 23 | from .discriminator_starganv2 import StarGANv2Discriminator 24 | from .discriminator_firstorder import FirstOrderDiscriminator 25 | from .discriminator_lapstyle import LapStyleDiscriminator 26 | -------------------------------------------------------------------------------- /applications/tools/animeganv2.py: -------------------------------------------------------------------------------- 1 | import paddle 2 | import os 3 | import sys 4 | sys.path.insert(0, os.getcwd()) 5 | from ppgan.apps import AnimeGANPredictor 6 | import argparse 7 | 8 | if __name__ == "__main__": 9 | parser = argparse.ArgumentParser() 10 | parser.add_argument("--input_image", type=str, help="path to source image") 11 | 12 | parser.add_argument("--output_path", 13 | type=str, 14 | default='output_dir', 15 | help="path to output image dir") 16 | 17 | parser.add_argument("--weight_path", 18 | type=str, 19 | default=None, 20 | help="path to model checkpoint path") 21 | 22 | parser.add_argument("--use_adjust_brightness", 23 | action="store_false", 24 | help="adjust brightness mode.") 25 | 26 | parser.add_argument("--cpu", 27 | dest="cpu", 28 | action="store_true", 29 | help="cpu mode.") 30 | 31 | args = parser.parse_args() 32 | 33 | if args.cpu: 34 | paddle.set_device('cpu') 35 | 36 | predictor = AnimeGANPredictor(args.output_path, args.weight_path, 37 | args.use_adjust_brightness) 38 | predictor.run(args.input_image) 39 | -------------------------------------------------------------------------------- /ppgan/datasets/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from .unpaired_dataset import UnpairedDataset 16 | from .single_dataset import SingleDataset 17 | from .paired_dataset import PairedDataset 18 | from .base_sr_dataset import SRDataset 19 | from .makeup_dataset import MakeupDataset 20 | from .common_vision_dataset import CommonVisionDataset 21 | from .animeganv2_dataset import AnimeGANV2Dataset 22 | from .wav2lip_dataset import Wav2LipDataset 23 | from .starganv2_dataset import StarGANv2Dataset 24 | from .edvr_dataset import REDSDataset 25 | from .firstorder_dataset import FirstOrderDataset 26 | from .lapstyle_dataset import LapStyleDataset 27 | from .sr_reds_multiple_gt_dataset import SRREDSMultipleGTDataset 28 | from .mpr_dataset import MPRTrain, MPRVal, MPRTest 29 | -------------------------------------------------------------------------------- /ppgan/models/discriminators/discriminator_starganv2.py: -------------------------------------------------------------------------------- 1 | 2 | import paddle.nn as nn 3 | import paddle 4 | 5 | from .builder import DISCRIMINATORS 6 | from ..generators.generator_starganv2 import ResBlk 7 | 8 | import numpy as np 9 | 10 | 11 | @DISCRIMINATORS.register() 12 | class StarGANv2Discriminator(nn.Layer): 13 | def __init__(self, img_size=256, num_domains=2, max_conv_dim=512): 14 | super().__init__() 15 | dim_in = 2**14 // img_size 16 | blocks = [] 17 | blocks += [nn.Conv2D(3, dim_in, 3, 1, 1)] 18 | 19 | repeat_num = int(np.log2(img_size)) - 2 20 | for _ in range(repeat_num): 21 | dim_out = min(dim_in*2, max_conv_dim) 22 | blocks += [ResBlk(dim_in, dim_out, downsample=True)] 23 | dim_in = dim_out 24 | 25 | blocks += [nn.LeakyReLU(0.2)] 26 | blocks += [nn.Conv2D(dim_out, dim_out, 4, 1, 0)] 27 | blocks += [nn.LeakyReLU(0.2)] 28 | blocks += [nn.Conv2D(dim_out, num_domains, 1, 1, 0)] 29 | self.main = nn.Sequential(*blocks) 30 | 31 | def forward(self, x, y): 32 | out = self.main(x) 33 | out = paddle.reshape(out, (out.shape[0], -1)) # (batch, num_domains) 34 | idx = paddle.zeros_like(out) 35 | for i in range(idx.shape[0]): 36 | idx[i, y[i]] = 1 37 | s = idx * out 38 | s = paddle.sum(s, axis=1) 39 | return s 40 | -------------------------------------------------------------------------------- /ppgan/utils/timer.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import time 16 | 17 | 18 | class TimeAverager(object): 19 | def __init__(self): 20 | self.reset() 21 | 22 | def reset(self): 23 | self._cnt = 0 24 | self._total_time = 0 25 | self._total_samples = 0 26 | 27 | def record(self, usetime, num_samples=None): 28 | self._cnt += 1 29 | self._total_time += usetime 30 | if num_samples: 31 | self._total_samples += num_samples 32 | 33 | def get_average(self): 34 | if self._cnt == 0: 35 | return 0 36 | return self._total_time / float(self._cnt) 37 | 38 | def get_ips_average(self): 39 | if not self._total_samples or self._cnt == 0: 40 | return 0 41 | return float(self._total_samples) / self._total_time 42 | -------------------------------------------------------------------------------- /tools/extract_weight.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import paddle 16 | import argparse 17 | 18 | 19 | def parse_args(): 20 | parser = argparse.ArgumentParser( 21 | description='This script extracts weights from a checkpoint') 22 | parser.add_argument('checkpoint', help='checkpoint file') 23 | parser.add_argument('--net-name', 24 | type=str, 25 | help='net name in checkpoint dict') 26 | parser.add_argument('--output', type=str, help='destination file name') 27 | args = parser.parse_args() 28 | return args 29 | 30 | 31 | def main(): 32 | args = parse_args() 33 | assert args.output.endswith(".pdparams") 34 | ckpt = paddle.load(args.checkpoint) 35 | state_dict = ckpt[args.net_name] 36 | paddle.save(state_dict, args.output) 37 | 38 | 39 | if __name__ == '__main__': 40 | main() 41 | -------------------------------------------------------------------------------- /ppgan/utils/setup.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import os 16 | import time 17 | import paddle 18 | 19 | from .logger import setup_logger 20 | 21 | 22 | def setup(args, cfg): 23 | if args.evaluate_only: 24 | cfg.is_train = False 25 | else: 26 | cfg.is_train = True 27 | 28 | if args.profiler_options: 29 | cfg.profiler_options = args.profiler_options 30 | else: 31 | cfg.profiler_options = None 32 | 33 | cfg.timestamp = time.strftime('-%Y-%m-%d-%H-%M', time.localtime()) 34 | cfg.output_dir = os.path.join( 35 | cfg.output_dir, 36 | os.path.splitext(os.path.basename(str(args.config_file)))[0] + 37 | cfg.timestamp) 38 | 39 | logger = setup_logger(cfg.output_dir) 40 | 41 | logger.info('Configs: {}'.format(cfg)) 42 | 43 | if paddle.is_compiled_with_cuda(): 44 | paddle.set_device('gpu') 45 | else: 46 | paddle.set_device('cpu') 47 | -------------------------------------------------------------------------------- /ppgan/models/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from .base_model import BaseModel 16 | from .gan_model import GANModel 17 | from .cycle_gan_model import CycleGANModel 18 | from .pix2pix_model import Pix2PixModel 19 | from .sr_model import BaseSRModel 20 | from .makeup_model import MakeupModel 21 | from .esrgan_model import ESRGAN 22 | from .ugatit_model import UGATITModel 23 | from .dc_gan_model import DCGANModel 24 | from .drn_model import DRN 25 | from .animeganv2_model import AnimeGANV2Model, AnimeGANV2PreTrainModel 26 | from .styleganv2_model import StyleGAN2Model 27 | from .wav2lip_model import Wav2LipModel 28 | from .wav2lip_hq_model import Wav2LipModelHq 29 | from .starganv2_model import StarGANv2Model 30 | from .edvr_model import EDVRModel 31 | from .firstorder_model import FirstOrderModel 32 | from .lapstyle_model import LapStyleDraModel, LapStyleRevFirstModel, LapStyleRevSecondModel 33 | from .basicvsr_model import BasicVSRModel 34 | from .mpr_model import MPRModel 35 | -------------------------------------------------------------------------------- /test_tipc/common_func.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | function func_parser_key(){ 4 | strs=$1 5 | IFS=":" 6 | array=(${strs}) 7 | tmp=${array[0]} 8 | echo ${tmp} 9 | } 10 | 11 | function func_parser_value(){ 12 | strs=$1 13 | IFS=":" 14 | array=(${strs}) 15 | tmp=${array[1]} 16 | echo ${tmp} 17 | } 18 | 19 | function func_set_params(){ 20 | key=$1 21 | value=$2 22 | if [ ${key}x = "null"x ];then 23 | echo " " 24 | elif [[ ${value} = "null" ]] || [[ ${value} = " " ]] || [ ${#value} -le 0 ];then 25 | echo " " 26 | else 27 | echo "${key}=${value}" 28 | fi 29 | } 30 | 31 | function func_parser_params(){ 32 | strs=$1 33 | IFS=":" 34 | array=(${strs}) 35 | key=${array[0]} 36 | tmp=${array[1]} 37 | IFS="|" 38 | res="" 39 | for _params in ${tmp[*]}; do 40 | IFS="=" 41 | array=(${_params}) 42 | mode=${array[0]} 43 | value=${array[1]} 44 | if [[ ${mode} = ${MODE} ]]; then 45 | IFS="|" 46 | #echo $(func_set_params "${mode}" "${value}") 47 | echo $value 48 | break 49 | fi 50 | IFS="|" 51 | done 52 | echo ${res} 53 | } 54 | 55 | function status_check(){ 56 | last_status=$1 # the exit code 57 | run_command=$2 58 | run_log=$3 59 | if [ $last_status -eq 0 ]; then 60 | echo -e "\033[33m Run successfully with command - ${run_command}! \033[0m" | tee -a ${run_log} 61 | else 62 | echo -e "\033[33m Run failed with command - ${run_command}! \033[0m" | tee -a ${run_log} 63 | fi 64 | } 65 | 66 | -------------------------------------------------------------------------------- /benchmark/analysis_log.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # encoding=utf-8 vi:ts=4:sw=4:expandtab:ft=python 4 | 5 | import re 6 | import sys 7 | import json 8 | 9 | def analyze(model_name, log_file, res_log_file): 10 | time_pat = re.compile(r"ips: (.*) images/s") 11 | 12 | logs = open(log_file).readlines() 13 | logs = ";".join(logs) 14 | time_res = time_pat.findall(logs) 15 | 16 | fail_flag = 0 17 | run_mode = "" 18 | gpu_num = 0 19 | ips = 0 20 | 21 | if time_res == []: 22 | fail_flag = 1 23 | else: 24 | gpu_num = log_file.split('_')[-1] 25 | run_mode = "sp" if gpu_num == 1 else "mp" 26 | 27 | skip_num = 4 28 | total_time = 0 29 | for i in range(skip_num, len(time_res)): 30 | total_time += float(time_res[i]) 31 | ips = total_time / (len(time_res) - skip_num) 32 | 33 | info = {"log_file": log_file, "model_name": model_name, "mission_name": "图像生成", 34 | "direction_id": 0, "run_mode": run_mode, "index": 1, "gpu_num": gpu_num, 35 | "FINAL_RESULT": ips, "JOB_FAIL_FLAG": fail_flag, "UNIT": "images/s"} 36 | json_info = json.dumps(info) 37 | with open(res_log_file, "w") as of: 38 | of.write(json_info) 39 | 40 | if __name__ == "__main__": 41 | if len(sys.argv) != 4: 42 | print("Usage:" + sys.argv[0] + " model_name path/to/log/file path/to/res/log/file") 43 | sys.exit() 44 | 45 | model_name = sys.argv[1] 46 | log_file = sys.argv[2] 47 | res_log_file = sys.argv[3] 48 | 49 | analyze(model_name, log_file, res_log_file) 50 | 51 | 52 | -------------------------------------------------------------------------------- /test_tipc/configs/rcan/train_infer_python.txt: -------------------------------------------------------------------------------- 1 | ===========================train_params=========================== 2 | model_name:rcan 3 | python:python3.7 4 | gpu_list:0 5 | ## 6 | auto_cast:null 7 | total_iters:lite_train_lite_infer=10|whole_train_whole_infer=400000 8 | output_dir:./output/ 9 | dataset.train.batch_size:lite_train_lite_infer=16|whole_train_whole_infer=16 10 | pretrained_model:null 11 | train_model_name:rcan_x4_div2k_tipc*/*checkpoint.pdparams 12 | train_infer_img_dir:./data/Set14/LRbicx4 13 | null:null 14 | ## 15 | trainer:norm_train 16 | norm_train:tools/main.py -c configs/rcan_x4_div2k_tipc.yaml --seed 123 -o dataset.train.num_workers=0 log_config.interval=5 17 | pact_train:null 18 | fpgm_train:null 19 | distill_train:null 20 | null:null 21 | null:null 22 | ## 23 | ===========================eval_params=========================== 24 | eval:null 25 | null:null 26 | ## 27 | ===========================infer_params=========================== 28 | --output_dir:./output/ 29 | load:null 30 | norm_export:tools/export_model.py -c configs/rcan_x4_div2k.yaml --inputs_size="-1,3,-1,-1" --load 31 | quant_export:null 32 | fpgm_export:null 33 | distill_export:null 34 | export1:null 35 | export2:null 36 | inference_dir:basesrmodel_generator 37 | train_model:./inference/basesr/basesrmodel_generator 38 | infer_export:null 39 | infer_quant:False 40 | inference:tools/inference.py --model_type rcan --seed 123 -c configs/rcan_x4_div2k.yaml --output_path test_tipc/output/ 41 | --device:gpu 42 | null:null 43 | null:null 44 | null:null 45 | null:null 46 | null:null 47 | --model_path: 48 | null:null 49 | null:null 50 | --benchmark:True 51 | null:null 52 | -------------------------------------------------------------------------------- /ppgan/datasets/single_dataset.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from .base_dataset import BaseDataset 16 | from .builder import DATASETS 17 | 18 | 19 | @DATASETS.register() 20 | class SingleDataset(BaseDataset): 21 | """ 22 | """ 23 | def __init__(self, dataroot, preprocess): 24 | """Initialize single dataset class. 25 | 26 | Args: 27 | dataroot (str): Directory of dataset. 28 | preprocess (list[dict]): A sequence of data preprocess config. 29 | """ 30 | super(SingleDataset, self).__init__(preprocess) 31 | self.dataroot = dataroot 32 | self.data_infos = self.prepare_data_infos() 33 | 34 | def prepare_data_infos(self): 35 | """prepare image paths from a folder. 36 | 37 | Returns: 38 | list[dict]: List that contains paired image paths. 39 | """ 40 | data_infos = [] 41 | paths = sorted(self.scan_folder(self.dataroot)) 42 | for path in paths: 43 | data_infos.append(dict(A_path=path)) 44 | 45 | return data_infos 46 | -------------------------------------------------------------------------------- /ppgan/apps/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from .dain_predictor import DAINPredictor 16 | from .deepremaster_predictor import DeepRemasterPredictor 17 | from .deoldify_predictor import DeOldifyPredictor 18 | from .realsr_predictor import RealSRPredictor 19 | from .edvr_predictor import EDVRPredictor 20 | from .first_order_predictor import FirstOrderPredictor 21 | from .face_parse_predictor import FaceParsePredictor 22 | from .animegan_predictor import AnimeGANPredictor 23 | from .midas_predictor import MiDaSPredictor 24 | from .photo2cartoon_predictor import Photo2CartoonPredictor 25 | from .styleganv2_predictor import StyleGANv2Predictor 26 | from .styleganv2fitting_predictor import StyleGANv2FittingPredictor 27 | from .styleganv2mixing_predictor import StyleGANv2MixingPredictor 28 | from .styleganv2editing_predictor import StyleGANv2EditingPredictor 29 | from .pixel2style2pixel_predictor import Pixel2Style2PixelPredictor 30 | from .wav2lip_predictor import Wav2LipPredictor 31 | from .mpr_predictor import MPRPredictor 32 | from .lapstyle_predictor import LapStylePredictor 33 | -------------------------------------------------------------------------------- /test_tipc/configs/rcan/train_infer_python_resume.txt: -------------------------------------------------------------------------------- 1 | ===========================train_params=========================== 2 | model_name:rcan 3 | python:python3.7 4 | gpu_list:0 5 | ## 6 | auto_cast:null 7 | total_iters:lite_train_lite_infer=238010|whole_train_whole_infer=400000 8 | output_dir:./output/ 9 | dataset.train.batch_size:lite_train_lite_infer=16|whole_train_whole_infer=16 10 | pretrained_model:null 11 | train_model_name:rcan_x4_div2k*/*checkpoint.pdparams 12 | train_infer_img_dir:./data/Set14/LRbicx4 13 | null:null 14 | ## 15 | trainer:norm_train 16 | norm_train:tools/main.py -c configs/rcan_x4_div2k.yaml --resume output_dir/iter_238000_checkpoint.pdparams --seed 123 -o dataset.train.num_workers=0 log_config.interval=5 snapshot_config.interval=10 validate.interval=10 17 | pact_train:null 18 | fpgm_train:null 19 | distill_train:null 20 | null:null 21 | null:null 22 | ## 23 | ===========================eval_params=========================== 24 | eval:null 25 | null:null 26 | ## 27 | ===========================infer_params=========================== 28 | --output_dir:./output/ 29 | load:null 30 | norm_export:tools/export_model.py -c configs/rcan_x4_div2k.yaml --inputs_size="-1,3,-1,-1" --load 31 | quant_export:null 32 | fpgm_export:null 33 | distill_export:null 34 | export1:null 35 | export2:null 36 | inference_dir:basesrmodel_generator 37 | train_model:./inference/basesr/basesrmodel_generator 38 | infer_export:null 39 | infer_quant:False 40 | inference:tools/inference.py --model_type rcan --seed 123 -c configs/rcan_x4_div2k.yaml --output_path test_tipc/output/ 41 | --device:gpu 42 | null:null 43 | null:null 44 | null:null 45 | null:null 46 | null:null 47 | --model_path: 48 | null:null 49 | null:null 50 | --benchmark:True 51 | null:null 52 | -------------------------------------------------------------------------------- /ppgan/datasets/paired_dataset.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from .builder import DATASETS 16 | from .base_dataset import BaseDataset 17 | 18 | 19 | @DATASETS.register() 20 | class PairedDataset(BaseDataset): 21 | """A dataset class for paired image dataset. 22 | """ 23 | def __init__(self, dataroot, preprocess): 24 | """Initialize this dataset class. 25 | 26 | Args: 27 | dataroot (str): Directory of dataset. 28 | preprocess (list[dict]): A sequence of data preprocess config. 29 | 30 | """ 31 | super(PairedDataset, self).__init__(preprocess) 32 | self.dataroot = dataroot 33 | self.data_infos = self.prepare_data_infos() 34 | 35 | def prepare_data_infos(self): 36 | """Load paired image paths. 37 | 38 | Returns: 39 | list[dict]: List that contains paired image paths. 40 | """ 41 | data_infos = [] 42 | pair_paths = sorted(self.scan_folder(self.dataroot)) 43 | for pair_path in pair_paths: 44 | data_infos.append(dict(pair_path=pair_path)) 45 | 46 | return data_infos 47 | -------------------------------------------------------------------------------- /ppgan/models/criterions/builder.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. 16 | # 17 | # Licensed under the Apache License, Version 2.0 (the "License"); 18 | # you may not use this file except in compliance with the License. 19 | # You may obtain a copy of the License at 20 | # 21 | # http://www.apache.org/licenses/LICENSE-2.0 22 | # 23 | # Unless required by applicable law or agreed to in writing, software 24 | # distributed under the License is distributed on an "AS IS" BASIS, 25 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 26 | # See the License for the specific language governing permissions and 27 | # limitations under the License. 28 | 29 | from ...utils.registry import Registry 30 | 31 | CRITERIONS = Registry('CRITERION') 32 | 33 | 34 | def build_criterion(cfg): 35 | cfg_ = cfg.copy() 36 | name = cfg_.pop('name') 37 | try: 38 | criterion = CRITERIONS.get(name)(**cfg_) 39 | except Exception as e: 40 | cls_ = CRITERIONS.get(name) 41 | raise RuntimeError('class {} {}'.format(cls_.__name__, e)) 42 | return criterion 43 | -------------------------------------------------------------------------------- /applications/tools/lapstyle.py: -------------------------------------------------------------------------------- 1 | import paddle 2 | import os 3 | import sys 4 | 5 | sys.path.insert(0, os.getcwd()) 6 | from ppgan.apps import LapStylePredictor 7 | import argparse 8 | 9 | if __name__ == "__main__": 10 | parser = argparse.ArgumentParser() 11 | parser.add_argument("--content_img", type=str, help="path to content image") 12 | 13 | parser.add_argument("--output_path", 14 | type=str, 15 | default='output_dir', 16 | help="path to output image dir") 17 | 18 | parser.add_argument("--weight_path", 19 | type=str, 20 | default=None, 21 | help="path to model weight path") 22 | 23 | parser.add_argument( 24 | "--style", 25 | type=str, 26 | default='starrynew', 27 | help= 28 | "if weight_path is None, style can be chosen in 'starrynew', 'circuit', 'ocean' and 'stars'" 29 | ) 30 | 31 | parser.add_argument("--style_image_path", 32 | type=str, 33 | default=None, 34 | help="if weight_path is not None, path to style image") 35 | 36 | parser.add_argument("--cpu", 37 | dest="cpu", 38 | action="store_true", 39 | help="cpu mode.") 40 | 41 | args = parser.parse_args() 42 | 43 | if args.cpu: 44 | paddle.set_device('cpu') 45 | 46 | predictor = LapStylePredictor(output=args.output_path, 47 | style=args.style, 48 | weight_path=args.weight_path, 49 | style_image_path=args.style_image_path) 50 | predictor.run(args.content_img) 51 | -------------------------------------------------------------------------------- /ppgan/models/generators/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from .resnet import ResnetGenerator 16 | from .unet import UnetGenerator 17 | from .rrdb_net import RRDBNet 18 | from .makeup import GeneratorPSGANAttention 19 | from .deep_conv import DeepConvGenerator, ConditionalDeepConvGenerator 20 | from .resnet_ugatit import ResnetUGATITGenerator 21 | from .dcgenerator import DCGenerator 22 | from .generater_animegan import AnimeGenerator, AnimeGeneratorLite 23 | from .wav2lip import Wav2Lip 24 | from .lesrcnn import LESRCNNGenerator 25 | from .resnet_ugatit_p2c import ResnetUGATITP2CGenerator 26 | from .generator_styleganv2 import StyleGANv2Generator 27 | from .generator_pixel2style2pixel import Pixel2Style2Pixel 28 | from .drn import DRNGenerator 29 | from .generator_starganv2 import StarGANv2Generator, StarGANv2Style, StarGANv2Mapping, FAN 30 | from .edvr import EDVRNet 31 | from .generator_firstorder import FirstOrderGenerator 32 | from .generater_lapstyle import DecoderNet, Encoder, RevisionNet 33 | from .basicvsr import BasicVSRNet 34 | from .mpr import MPRNet 35 | from .iconvsr import IconVSR 36 | from .gpen import GPEN 37 | from .pan import PAN 38 | from .rcan import RCAN 39 | -------------------------------------------------------------------------------- /ppgan/datasets/repeat_dataset.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import paddle 16 | 17 | 18 | class RepeatDataset(paddle.io.Dataset): 19 | """A wrapper of repeated dataset. 20 | 21 | The length of repeated dataset will be `times` larger than the original 22 | dataset. This is useful when the data loading time is long but the dataset 23 | is small. Using RepeatDataset can reduce the data loading time between 24 | epochs. 25 | 26 | Args: 27 | dataset (:obj:`Dataset`): The dataset to be repeated. 28 | times (int): Repeat times. 29 | """ 30 | 31 | def __init__(self, dataset, times): 32 | self.dataset = dataset 33 | self.times = times 34 | 35 | self._ori_len = len(self.dataset) 36 | 37 | def __getitem__(self, idx): 38 | """Get item at each call. 39 | 40 | Args: 41 | idx (int): Index for getting each item. 42 | """ 43 | return self.dataset[idx % self._ori_len] 44 | 45 | def __len__(self): 46 | """Length of the dataset. 47 | 48 | Returns: 49 | int: Length of the dataset. 50 | """ 51 | return self.times * self._ori_len 52 | -------------------------------------------------------------------------------- /ppgan/modules/fused_act.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import paddle 16 | import paddle.nn as nn 17 | import paddle.nn.functional as F 18 | 19 | 20 | class FusedLeakyReLU(nn.Layer): 21 | def __init__(self, channel, bias=True, negative_slope=0.2, scale=2 ** 0.5): 22 | super().__init__() 23 | 24 | if bias: 25 | self.bias = self.create_parameter((channel,), default_initializer=nn.initializer.Constant(0.0)) 26 | 27 | else: 28 | self.bias = None 29 | 30 | self.negative_slope = negative_slope 31 | self.scale = scale 32 | 33 | def forward(self, input): 34 | return fused_leaky_relu(input, self.bias, self.negative_slope, self.scale) 35 | 36 | 37 | def fused_leaky_relu(input, bias=None, negative_slope=0.2, scale=2 ** 0.5): 38 | if bias is not None: 39 | rest_dim = [1] * (len(input.shape) - len(bias.shape) - 1) 40 | return ( 41 | F.leaky_relu( 42 | input + bias.reshape((1, bias.shape[0], *rest_dim)), negative_slope=0.2 43 | ) 44 | * scale 45 | ) 46 | 47 | else: 48 | return F.leaky_relu(input, negative_slope=0.2) * scale 49 | -------------------------------------------------------------------------------- /applications/tools/image_restoration.py: -------------------------------------------------------------------------------- 1 | import paddle 2 | import os 3 | import sys 4 | sys.path.insert(0, os.getcwd()) 5 | from ppgan.apps import MPRPredictor 6 | import argparse 7 | 8 | if __name__ == "__main__": 9 | parser = argparse.ArgumentParser() 10 | parser.add_argument("--output_path", 11 | type=str, 12 | default='output_dir', 13 | help="path to output image dir") 14 | 15 | parser.add_argument("--weight_path", 16 | type=str, 17 | default=None, 18 | help="path to model checkpoint path") 19 | 20 | parser.add_argument("--seed", 21 | type=int, 22 | default=None, 23 | help="sample random seed for model's image generation") 24 | 25 | parser.add_argument('--images_path', 26 | default=None, 27 | required=True, 28 | type=str, 29 | help='Single image or images directory.') 30 | 31 | parser.add_argument('--task', 32 | required=True, 33 | type=str, 34 | help='Task to run', 35 | choices=['Deblurring', 'Denoising', 'Deraining']) 36 | 37 | parser.add_argument("--cpu", 38 | dest="cpu", 39 | action="store_true", 40 | help="cpu mode.") 41 | 42 | args = parser.parse_args() 43 | 44 | if args.cpu: 45 | paddle.set_device('cpu') 46 | 47 | predictor = MPRPredictor( 48 | images_path=args.images_path, 49 | output_path=args.output_path, 50 | weight_path=args.weight_path, 51 | seed=args.seed, 52 | task=args.task 53 | ) 54 | predictor.run() 55 | -------------------------------------------------------------------------------- /tools/main.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import os 16 | import sys 17 | 18 | cur_path = os.path.abspath(os.path.dirname(__file__)) 19 | root_path = os.path.split(cur_path)[0] 20 | sys.path.append(root_path) 21 | 22 | from ppgan.utils.options import parse_args 23 | from ppgan.utils.config import get_config 24 | from ppgan.utils.setup import setup 25 | from ppgan.engine.trainer import Trainer 26 | 27 | 28 | def main(args, cfg): 29 | # init environment, include logger, dynamic graph, seed, device, train or test mode... 30 | setup(args, cfg) 31 | # build trainer 32 | trainer = Trainer(cfg) 33 | 34 | # continue train or evaluate, checkpoint need contain epoch and optimizer info 35 | if args.resume: 36 | trainer.resume(args.resume) 37 | # evaluate or finute, only load generator weights 38 | elif args.load: 39 | trainer.load(args.load) 40 | 41 | if args.evaluate_only: 42 | trainer.test() 43 | return 44 | # training, when keyboard interrupt save weights 45 | try: 46 | trainer.train() 47 | except KeyboardInterrupt as e: 48 | trainer.save(trainer.current_epoch) 49 | trainer.close() 50 | 51 | 52 | if __name__ == '__main__': 53 | args = parse_args() 54 | cfg = get_config(args.config_file, args.opt) 55 | 56 | main(args, cfg) 57 | -------------------------------------------------------------------------------- /ppgan/utils/animate.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import numpy as np 16 | from scipy.spatial import ConvexHull 17 | 18 | import paddle 19 | 20 | 21 | def normalize_kp(kp_source, 22 | kp_driving, 23 | kp_driving_initial, 24 | adapt_movement_scale=False, 25 | use_relative_movement=False, 26 | use_relative_jacobian=False): 27 | if adapt_movement_scale: 28 | source_area = ConvexHull(kp_source['value'][0].numpy()).volume 29 | driving_area = ConvexHull(kp_driving_initial['value'][0].numpy()).volume 30 | adapt_movement_scale = np.sqrt(source_area) / np.sqrt(driving_area) 31 | else: 32 | adapt_movement_scale = 1 33 | 34 | kp_new = {k: v for k, v in kp_driving.items()} 35 | 36 | if use_relative_movement: 37 | kp_value_diff = (kp_driving['value'] - kp_driving_initial['value']) 38 | kp_value_diff *= adapt_movement_scale 39 | kp_new['value'] = kp_value_diff + kp_source['value'] 40 | 41 | if use_relative_jacobian: 42 | jacobian_diff = paddle.matmul( 43 | kp_driving['jacobian'], 44 | paddle.inverse(kp_driving_initial['jacobian'])) 45 | kp_new['jacobian'] = paddle.matmul(jacobian_diff, 46 | kp_source['jacobian']) 47 | 48 | return kp_new 49 | -------------------------------------------------------------------------------- /ppgan/datasets/preprocess/io.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | 3 | from .builder import PREPROCESS 4 | 5 | 6 | @PREPROCESS.register() 7 | class LoadImageFromFile(object): 8 | """Load image from file. 9 | 10 | Args: 11 | key (str): Keys in results to find corresponding path. Default: 'image'. 12 | flag (str): Loading flag for images. Default: -1. 13 | to_rgb (str): Convert img to 'rgb' format. Default: True. 14 | backend (str): io backend where images are store. Default: None. 15 | save_original_img (bool): If True, maintain a copy of the image in 16 | `results` dict with name of `f'ori_{key}'`. Default: False. 17 | kwargs (dict): Args for file client. 18 | """ 19 | def __init__(self, 20 | key='image', 21 | flag=-1, 22 | to_rgb=True, 23 | save_original_img=False, 24 | backend=None, 25 | **kwargs): 26 | self.key = key 27 | self.flag = flag 28 | self.to_rgb = to_rgb 29 | self.backend = backend 30 | self.save_original_img = save_original_img 31 | self.kwargs = kwargs 32 | 33 | def __call__(self, results): 34 | """Call function. 35 | 36 | Args: 37 | results (dict): A dict containing the necessary information and 38 | data for augmentation. 39 | 40 | Returns: 41 | dict: A dict containing the processed data and information. 42 | """ 43 | 44 | filepath = str(results[f'{self.key}_path']) 45 | #TODO: use file client to manage io backend 46 | # such as opencv, pil, imdb 47 | img = cv2.imread(filepath, self.flag) 48 | if self.to_rgb: 49 | img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) 50 | 51 | results[self.key] = img 52 | results[f'{self.key}_path'] = filepath 53 | results[f'{self.key}_ori_shape'] = img.shape 54 | if self.save_original_img: 55 | results[f'ori_{self.key}'] = img.copy() 56 | 57 | return results 58 | -------------------------------------------------------------------------------- /tools/animegan_picmean.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | #Licensed under the Apache License, Version 2.0 (the "License"); 4 | #you may not use this file except in compliance with the License. 5 | #You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | #Unless required by applicable law or agreed to in writing, software 10 | #distributed under the License is distributed on an "AS IS" BASIS, 11 | #WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | #See the License for the specific language governing permissions and 13 | #limitations under the License. 14 | 15 | import os 16 | import cv2 17 | import numpy as np 18 | from glob import glob 19 | from tqdm import tqdm 20 | import argparse 21 | 22 | 23 | def read_img(image_path): 24 | img = cv2.imread(image_path) 25 | assert len(img.shape) == 3 26 | B = img[..., 0].mean() 27 | G = img[..., 1].mean() 28 | R = img[..., 2].mean() 29 | return B, G, R 30 | 31 | 32 | def main(dataset): 33 | file_list = glob(os.path.join(dataset, '*.jpg')) 34 | image_num = len(file_list) 35 | print('image_num:', image_num) 36 | 37 | B_total = 0 38 | G_total = 0 39 | R_total = 0 40 | for f in tqdm(file_list): 41 | bgr = read_img(f) 42 | B_total += bgr[0] 43 | G_total += bgr[1] 44 | R_total += bgr[2] 45 | 46 | B_mean, G_mean, R_mean = B_total / image_num, G_total / image_num, R_total / image_num 47 | mean = (B_mean + G_mean + R_mean) / 3 48 | 49 | print('RGB mean diff') 50 | print( 51 | np.asfarray((mean - R_mean, mean - G_mean, mean - B_mean), 52 | dtype='float32')) 53 | 54 | 55 | if __name__ == '__main__': 56 | parser = argparse.ArgumentParser() 57 | parser.add_argument('--dataset', 58 | help="get the mean values of rgb from dataset", 59 | type=str, 60 | default='') 61 | 62 | args = parser.parse_args() 63 | 64 | main(args.dataset) 65 | -------------------------------------------------------------------------------- /ppgan/utils/filesystem.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import os 16 | import six 17 | import pickle 18 | import paddle 19 | 20 | 21 | def makedirs(dir): 22 | if not os.path.exists(dir): 23 | # avoid error when train with multiple gpus 24 | try: 25 | os.makedirs(dir) 26 | except: 27 | pass 28 | 29 | 30 | def save(state_dicts, file_name): 31 | def convert(state_dict): 32 | model_dict = {} 33 | 34 | for k, v in state_dict.items(): 35 | if isinstance( 36 | v, 37 | (paddle.static.Variable, paddle.Tensor)): 38 | model_dict[k] = v.numpy() 39 | else: 40 | model_dict[k] = v 41 | 42 | return model_dict 43 | 44 | final_dict = {} 45 | for k, v in state_dicts.items(): 46 | if isinstance( 47 | v, 48 | (paddle.static.Variable, paddle.Tensor)): 49 | final_dict = convert(state_dicts) 50 | break 51 | elif isinstance(v, dict): 52 | final_dict[k] = convert(v) 53 | else: 54 | final_dict[k] = v 55 | 56 | with open(file_name, 'wb') as f: 57 | pickle.dump(final_dict, f, protocol=2) 58 | 59 | 60 | def load(file_name): 61 | with open(file_name, 'rb') as f: 62 | state_dicts = pickle.load(f) if six.PY2 else pickle.load( 63 | f, encoding='latin1') 64 | return state_dicts 65 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from setuptools import setup 16 | from setuptools import find_packages 17 | from io import open 18 | 19 | from ppgan import __version__ 20 | 21 | with open('requirements.txt', encoding="utf-8-sig") as f: 22 | requirements = f.readlines() 23 | 24 | 25 | def readme(): 26 | with open('README.md', encoding="utf-8-sig") as f: 27 | README = f.read() 28 | return README 29 | 30 | 31 | setup( 32 | name='ppgan', 33 | packages=find_packages(), 34 | include_package_data=True, 35 | entry_points={"console_scripts": ["paddlegan= paddlegan.paddlegan:main"]}, 36 | author='PaddlePaddle Author', 37 | version=__version__, 38 | install_requires=requirements, 39 | license='Apache License 2.0', 40 | description='Awesome GAN toolkits based on PaddlePaddle', 41 | long_description=readme(), 42 | long_description_content_type='text/markdown', 43 | url='https://github.com/PaddlePaddle/PaddleGAN', 44 | download_url='https://github.com/PaddlePaddle/PaddleGAN.git', 45 | keywords=['gan paddlegan'], 46 | classifiers=[ 47 | 'Intended Audience :: Developers', 'Operating System :: OS Independent', 48 | 'Natural Language :: Chinese (Simplified)', 49 | 'Programming Language :: Python :: 3', 50 | 'Programming Language :: Python :: 3.5', 51 | 'Programming Language :: Python :: 3.6', 52 | 'Programming Language :: Python :: 3.7', 'Topic :: Utilities' 53 | ], 54 | ) 55 | -------------------------------------------------------------------------------- /ppgan/utils/video.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import os 16 | import sys 17 | 18 | 19 | def video2frames(video_path, outpath, **kargs): 20 | def _dict2str(kargs): 21 | cmd_str = '' 22 | for k, v in kargs.items(): 23 | cmd_str += (' ' + str(k) + ' ' + str(v)) 24 | return cmd_str 25 | 26 | ffmpeg = ['ffmpeg ', ' -y -loglevel ', ' error '] 27 | vid_name = os.path.basename(video_path).split('.')[0] 28 | out_full_path = os.path.join(outpath, vid_name) 29 | 30 | if not os.path.exists(out_full_path): 31 | os.makedirs(out_full_path) 32 | 33 | # video file name 34 | outformat = os.path.join(out_full_path, '%08d.png') 35 | 36 | cmd = ffmpeg 37 | cmd = ffmpeg + [' -i ', video_path, ' -start_number ', ' 0 ', outformat] 38 | 39 | cmd = ''.join(cmd) + _dict2str(kargs) 40 | 41 | if os.system(cmd) != 0: 42 | raise RuntimeError('ffmpeg process video: {} error'.format(vid_name)) 43 | 44 | sys.stdout.flush() 45 | return out_full_path 46 | 47 | 48 | def frames2video(frame_path, video_path, r): 49 | ffmpeg = ['ffmpeg ', ' -y -loglevel ', ' error '] 50 | cmd = ffmpeg + [ 51 | ' -r ', r, ' -f ', ' image2 ', ' -i ', frame_path, ' -vcodec ', 52 | ' libx264 ', ' -pix_fmt ', ' yuv420p ', ' -crf ', ' 16 ', video_path 53 | ] 54 | cmd = ''.join(cmd) 55 | 56 | if os.system(cmd) != 0: 57 | raise RuntimeError('ffmpeg process video: {} error'.format(video_path)) 58 | 59 | sys.stdout.flush() 60 | -------------------------------------------------------------------------------- /ppgan/modules/conv.py: -------------------------------------------------------------------------------- 1 | import paddle 2 | from paddle import nn 3 | from paddle.nn import functional as F 4 | 5 | 6 | class ConvBNRelu(nn.Layer): 7 | def __init__(self, 8 | cin, 9 | cout, 10 | kernel_size, 11 | stride, 12 | padding, 13 | residual=False, 14 | *args, 15 | **kwargs): 16 | super().__init__(*args, **kwargs) 17 | self.conv_block = nn.Sequential( 18 | nn.Conv2D(cin, cout, kernel_size, stride, padding), 19 | nn.BatchNorm2D(cout)) 20 | self.act = nn.ReLU() 21 | self.residual = residual 22 | 23 | def forward(self, x): 24 | out = self.conv_block(x) 25 | if self.residual: 26 | out += x 27 | return self.act(out) 28 | 29 | 30 | class NonNormConv2d(nn.Layer): 31 | def __init__(self, 32 | cin, 33 | cout, 34 | kernel_size, 35 | stride, 36 | padding, 37 | residual=False, 38 | *args, 39 | **kwargs): 40 | super().__init__(*args, **kwargs) 41 | self.conv_block = nn.Sequential( 42 | nn.Conv2D(cin, cout, kernel_size, stride, padding), ) 43 | self.act = nn.LeakyReLU(0.01) 44 | 45 | def forward(self, x): 46 | out = self.conv_block(x) 47 | return self.act(out) 48 | 49 | 50 | class Conv2dTransposeRelu(nn.Layer): 51 | def __init__(self, 52 | cin, 53 | cout, 54 | kernel_size, 55 | stride, 56 | padding, 57 | output_padding=0, 58 | *args, 59 | **kwargs): 60 | super().__init__(*args, **kwargs) 61 | self.conv_block = nn.Sequential( 62 | nn.Conv2DTranspose(cin, cout, kernel_size, stride, padding, 63 | output_padding), nn.BatchNorm2D(cout)) 64 | self.act = nn.ReLU() 65 | 66 | def forward(self, x): 67 | out = self.conv_block(x) 68 | return self.act(out) 69 | -------------------------------------------------------------------------------- /ppgan/models/discriminators/discriminator_lapstyle.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import paddle 16 | import paddle.nn as nn 17 | 18 | from .builder import DISCRIMINATORS 19 | 20 | 21 | @DISCRIMINATORS.register() 22 | class LapStyleDiscriminator(nn.Layer): 23 | def __init__(self): 24 | super(LapStyleDiscriminator, self).__init__() 25 | num_layer = 3 26 | num_channel = 32 27 | self.head = nn.Sequential( 28 | ('conv', 29 | nn.Conv2D(3, num_channel, kernel_size=3, stride=1, padding=1)), 30 | ('norm', nn.BatchNorm2D(num_channel)), 31 | ('LeakyRelu', nn.LeakyReLU(0.2))) 32 | self.body = nn.Sequential() 33 | for i in range(num_layer - 2): 34 | self.body.add_sublayer( 35 | 'conv%d' % (i + 1), 36 | nn.Conv2D(num_channel, 37 | num_channel, 38 | kernel_size=3, 39 | stride=1, 40 | padding=1)) 41 | self.body.add_sublayer('norm%d' % (i + 1), 42 | nn.BatchNorm2D(num_channel)) 43 | self.body.add_sublayer('LeakyRelu%d' % (i + 1), nn.LeakyReLU(0.2)) 44 | self.tail = nn.Conv2D(num_channel, 45 | 1, 46 | kernel_size=3, 47 | stride=1, 48 | padding=1) 49 | 50 | def forward(self, x): 51 | x = self.head(x) 52 | x = self.body(x) 53 | x = self.tail(x) 54 | return x 55 | -------------------------------------------------------------------------------- /ppgan/faceutils/face_detection/detection/blazeface/utils.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import cv2 16 | import numpy as np 17 | 18 | 19 | def image_resize(image, width=None, height=None, inter=cv2.INTER_AREA): 20 | dim = None 21 | (h, w) = image.shape[:2] 22 | 23 | if width is None and height is None: 24 | return image 25 | 26 | if width is None: 27 | r = height / float(h) 28 | dim = (int(w * r), height) 29 | else: 30 | r = width / float(w) 31 | dim = (width, int(h * r)) 32 | 33 | resized = cv2.resize(image, dim, interpolation=inter) 34 | 35 | return resized 36 | 37 | 38 | def resize_and_crop_image(image, dim): 39 | if image.shape[0] > image.shape[1]: 40 | img = image_resize(image, width=dim) 41 | yshift, xshift = (image.shape[0] - image.shape[1]) // 2, 0 42 | y_start = (img.shape[0] - img.shape[1]) // 2 43 | y_end = y_start + dim 44 | return img[y_start:y_end, :, :], (xshift, yshift) 45 | else: 46 | img = image_resize(image, height=dim) 47 | yshift, xshift = 0, (image.shape[1] - image.shape[0]) // 2 48 | x_start = (img.shape[1] - img.shape[0]) // 2 49 | x_end = x_start + dim 50 | return img[:, x_start:x_end, :], (xshift, yshift) 51 | 52 | 53 | def resize_and_crop_batch(frames, dim): 54 | smframes = [] 55 | xshift, yshift = 0, 0 56 | for i in range(len(frames)): 57 | smframe, (xshift, yshift) = resize_and_crop_image(frames[i], dim) 58 | smframes.append(smframe) 59 | smframes = np.stack(smframes) 60 | return smframes, (xshift, yshift) 61 | -------------------------------------------------------------------------------- /ppgan/faceutils/face_segmentation/layers.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import paddle 16 | import paddle.nn as nn 17 | import paddle.nn.functional as F 18 | 19 | 20 | def SyncBatchNorm(*args, **kwargs): 21 | """In cpu environment nn.SyncBatchNorm does not have kernel so use nn.BatchNorm instead""" 22 | if paddle.get_device() == 'cpu': 23 | return nn.BatchNorm(*args, **kwargs) 24 | else: 25 | return nn.SyncBatchNorm(*args, **kwargs) 26 | 27 | 28 | class ConvBNReLU(nn.Layer): 29 | def __init__(self, 30 | in_channels, 31 | out_channels, 32 | kernel_size, 33 | padding='same', 34 | **kwargs): 35 | super().__init__() 36 | 37 | self._conv = nn.Conv2D( 38 | in_channels, out_channels, kernel_size, padding=padding, **kwargs) 39 | 40 | self._batch_norm = SyncBatchNorm(out_channels) 41 | 42 | def forward(self, x): 43 | x = self._conv(x) 44 | x = self._batch_norm(x) 45 | x = F.relu(x) 46 | return x 47 | 48 | 49 | class ConvBN(nn.Layer): 50 | def __init__(self, 51 | in_channels, 52 | out_channels, 53 | kernel_size, 54 | padding='same', 55 | **kwargs): 56 | super().__init__() 57 | self._conv = nn.Conv2D( 58 | in_channels, out_channels, kernel_size, padding=padding, **kwargs) 59 | self._batch_norm = SyncBatchNorm(out_channels) 60 | 61 | def forward(self, x): 62 | x = self._conv(x) 63 | x = self._batch_norm(x) 64 | return x 65 | 66 | -------------------------------------------------------------------------------- /benchmark/run_benchmark.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -xe 3 | # 运行示例:CUDA_VISIBLE_DEVICES=0 bash run_benchmark.sh ${run_mode} ${bs_item} ${fp_item} 500 ${model_mode} 4 | # 参数说明 5 | function _set_params(){ 6 | run_mode=${1:-"sp"} # 单卡sp|多卡mp 7 | batch_size=${2:-"64"} 8 | fp_item=${3:-"fp32"} # fp32|fp16 9 | mode=${4:-"epochs"} 10 | max_iter=${5:-"500"} # 可选,如果需要修改代码提前中断 11 | model_name=${6:-"model_name"} 12 | config=${7:-"config"} 13 | log_interval=${8:-"1"} 14 | run_log_path=${TRAIN_LOG_DIR:-$(pwd)} # TRAIN_LOG_DIR 后续QA设置该参数 15 | 16 | # 以下不用修改 17 | device=${CUDA_VISIBLE_DEVICES//,/ } 18 | arr=(${device}) 19 | num_gpu_devices=${#arr[*]} 20 | log_file=${run_log_path}/${model_name}_${run_mode}_bs${batch_size}_${fp_item}_${num_gpu_devices} 21 | res_log_file=${run_log_path}/${model_name}_${run_mode}_bs${batch_size}_${fp_item}_${num_gpu_devices}_speed 22 | } 23 | 24 | function _analysis_log(){ 25 | python benchmark/analysis_log.py ${model_name} ${log_file} ${res_log_file} 26 | } 27 | 28 | function _train(){ 29 | echo "Train on ${num_gpu_devices} GPUs" 30 | echo "current CUDA_VISIBLE_DEVICES=$CUDA_VISIBLE_DEVICES, gpus=$num_gpu_devices, batch_size=$batch_size" 31 | 32 | train_cmd="--config-file=${config} 33 | -o dataset.train.batch_size=${batch_size} 34 | log_config.interval=${log_interval} 35 | ${mode}=${max_iter} " 36 | case ${run_mode} in 37 | sp) train_cmd="python -u tools/main.py "${train_cmd} ;; 38 | mp) 39 | train_cmd="python -m paddle.distributed.launch --log_dir=./mylog --gpus=$CUDA_VISIBLE_DEVICES tools/main.py "${train_cmd} 40 | log_parse_file="mylog/workerlog.0" ;; 41 | *) echo "choose run_mode(sp or mp)"; exit 1; 42 | esac 43 | # 以下不用修改 44 | timeout 15m ${train_cmd} > ${log_file} 2>&1 45 | if [ $? -ne 0 ];then 46 | echo -e "${model_name}, FAIL" 47 | export job_fail_flag=1 48 | else 49 | echo -e "${model_name}, SUCCESS" 50 | export job_fail_flag=0 51 | fi 52 | trap 'for pid in $(jobs -pr); do kill -KILL $pid; done' INT QUIT TERM 53 | 54 | if [ $run_mode = "mp" -a -d mylog ]; then 55 | rm ${log_file} 56 | cp mylog/workerlog.0 ${log_file} 57 | fi 58 | 59 | _analysis_log 60 | 61 | } 62 | 63 | _set_params $@ 64 | _train 65 | -------------------------------------------------------------------------------- /ppgan/apps/face_parse_predictor.py: -------------------------------------------------------------------------------- 1 | # copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import os 16 | import sys 17 | import argparse 18 | 19 | from PIL import Image 20 | import numpy as np 21 | import cv2 22 | 23 | import ppgan.faceutils as futils 24 | from ppgan.utils.preprocess import * 25 | from ppgan.utils.visual import mask2image 26 | from .base_predictor import BasePredictor 27 | 28 | 29 | class FaceParsePredictor(BasePredictor): 30 | def __init__(self, output_path='output'): 31 | self.output_path = output_path 32 | self.input_size = (512, 512) 33 | self.up_ratio = 0.6 / 0.85 34 | self.down_ratio = 0.2 / 0.85 35 | self.width_ratio = 0.2 / 0.85 36 | self.face_parser = futils.mask.FaceParser() 37 | 38 | def run(self, image): 39 | image = Image.open(image).convert("RGB") 40 | face = futils.dlib.detect(image) 41 | 42 | if not face: 43 | return 44 | face_on_image = face[0] 45 | image, face, crop_face = futils.dlib.crop(image, face_on_image, 46 | self.up_ratio, 47 | self.down_ratio, 48 | self.width_ratio) 49 | np_image = np.array(image) 50 | mask = self.face_parser.parse( 51 | np.float32(cv2.resize(np_image, self.input_size))) 52 | mask = cv2.resize(mask.numpy(), (256, 256)) 53 | mask = mask.astype(np.uint8) 54 | mask = mask2image(mask) 55 | if not os.path.exists(self.output_path): 56 | os.makedirs(self.output_path) 57 | save_path = os.path.join(self.output_path, 'face_parse.png') 58 | cv2.imwrite(save_path, mask) 59 | return mask 60 | -------------------------------------------------------------------------------- /ppgan/faceutils/face_segmentation/face_seg.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import os.path as osp 16 | import cv2 17 | import numpy as np 18 | import paddle 19 | from paddle.utils.download import get_path_from_url 20 | 21 | from .fcn import FCN 22 | from .hrnet import HRNet_W18 23 | 24 | 25 | BISENET_WEIGHT_URL = 'https://paddlegan.bj.bcebos.com/models/faceseg_FCN-HRNetW18.pdparams' 26 | 27 | 28 | class FaceSeg: 29 | def __init__(self): 30 | save_pth = get_path_from_url(BISENET_WEIGHT_URL, osp.split(osp.realpath(__file__))[0]) 31 | 32 | self.net = FCN(num_classes=2, backbone=HRNet_W18()) 33 | state_dict = paddle.load(save_pth) 34 | self.net.set_state_dict(state_dict) 35 | self.net.eval() 36 | 37 | def __call__(self, image): 38 | image_input = self.input_transform(image) # RGB image 39 | 40 | with paddle.no_grad(): 41 | logits = self.net(image_input) 42 | pred = paddle.argmax(logits[0], axis=1) 43 | pred = pred.numpy() 44 | mask = np.squeeze(pred).astype(np.uint8) 45 | 46 | mask = self.output_transform(mask, shape=image.shape[:2]) 47 | return mask 48 | 49 | def input_transform(self, image): 50 | image_input = cv2.resize(image, (384, 384), interpolation=cv2.INTER_AREA) 51 | image_input = (image_input / 255.)[np.newaxis, :, :, :] 52 | image_input = np.transpose(image_input, (0, 3, 1, 2)).astype(np.float32) 53 | image_input = paddle.to_tensor(image_input) 54 | return image_input 55 | 56 | @staticmethod 57 | def output_transform(output, shape): 58 | output = cv2.resize(output, (shape[1], shape[0])) 59 | image_output = np.clip((output * 255), 0, 255).astype(np.uint8) 60 | return image_output 61 | -------------------------------------------------------------------------------- /ppgan/datasets/base_sr_dataset.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import os 16 | import copy 17 | 18 | from pathlib import Path 19 | from .base_dataset import BaseDataset 20 | from .builder import DATASETS 21 | 22 | 23 | @DATASETS.register() 24 | class SRDataset(BaseDataset): 25 | """Base super resulotion dataset for image restoration.""" 26 | def __init__(self, 27 | lq_folder, 28 | gt_folder, 29 | preprocess, 30 | scale, 31 | filename_tmpl='{}'): 32 | super(SRDataset, self).__init__(preprocess) 33 | self.lq_folder = lq_folder 34 | self.gt_folder = gt_folder 35 | self.scale = scale 36 | self.filename_tmpl = filename_tmpl 37 | 38 | self.prepare_data_infos() 39 | 40 | def prepare_data_infos(self): 41 | """Load annoations for SR dataset. 42 | 43 | It loads the LQ and GT image path from folders. 44 | 45 | Returns: 46 | dict: Returned dict for LQ and GT pairs. 47 | """ 48 | self.data_infos = [] 49 | lq_paths = self.scan_folder(self.lq_folder) 50 | gt_paths = self.scan_folder(self.gt_folder) 51 | assert len(lq_paths) == len(gt_paths), ( 52 | f'gt and lq datasets have different number of images: ' 53 | f'{len(lq_paths)}, {len(gt_paths)}.') 54 | for gt_path in gt_paths: 55 | basename, ext = os.path.splitext(os.path.basename(gt_path)) 56 | lq_path = os.path.join(self.lq_folder, 57 | (f'{self.filename_tmpl.format(basename)}' 58 | f'{ext}')) 59 | assert lq_path in lq_paths, f'{lq_path} is not in lq_paths.' 60 | self.data_infos.append(dict(lq_path=lq_path, gt_path=gt_path)) 61 | return self.data_infos 62 | -------------------------------------------------------------------------------- /ppgan/modules/norm.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import paddle 16 | import functools 17 | import paddle.nn as nn 18 | from .nn import Spectralnorm 19 | 20 | 21 | class Identity(nn.Layer): 22 | def forward(self, x): 23 | return x 24 | 25 | 26 | def build_norm_layer(norm_type='instance'): 27 | """Return a normalization layer 28 | 29 | Args: 30 | norm_type (str) -- the name of the normalization layer: batch | instance | none 31 | 32 | For BatchNorm, we use learnable affine parameters and track running statistics (mean/stddev). 33 | For InstanceNorm, we do not use learnable affine parameters. We do not track running statistics. 34 | """ 35 | if norm_type == 'batch': 36 | norm_layer = functools.partial( 37 | nn.BatchNorm, 38 | param_attr=paddle.ParamAttr( 39 | initializer=nn.initializer.Normal(1.0, 0.02)), 40 | bias_attr=paddle.ParamAttr( 41 | initializer=nn.initializer.Constant(0.0)), 42 | trainable_statistics=True) 43 | elif norm_type == 'instance': 44 | norm_layer = functools.partial( 45 | nn.InstanceNorm2D, 46 | weight_attr=paddle.ParamAttr( 47 | initializer=nn.initializer.Constant(1.0), 48 | learning_rate=0.0, 49 | trainable=False), 50 | bias_attr=paddle.ParamAttr(initializer=nn.initializer.Constant(0.0), 51 | learning_rate=0.0, 52 | trainable=False)) 53 | elif norm_type == 'spectral': 54 | norm_layer = functools.partial(Spectralnorm) 55 | elif norm_type == 'none': 56 | 57 | def norm_layer(x): 58 | return Identity() 59 | else: 60 | raise NotImplementedError('normalization layer [%s] is not found' % 61 | norm_type) 62 | return norm_layer 63 | -------------------------------------------------------------------------------- /ppgan/datasets/preprocess/builder.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import copy 16 | import traceback 17 | 18 | from ...utils.registry import Registry, build_from_config 19 | 20 | LOAD_PIPELINE = Registry("LOAD_PIPELINE") 21 | TRANSFORMS = Registry("TRANSFORM") 22 | PREPROCESS = Registry("PREPROCESS") 23 | 24 | 25 | class Compose(object): 26 | """ 27 | Composes several transforms together use for composing list of transforms 28 | together for a dataset transform. 29 | 30 | Args: 31 | functions (list[callable]): List of functions to compose. 32 | 33 | Returns: 34 | A compose object which is callable, __call__ for this Compose 35 | object will call each given :attr:`transforms` sequencely. 36 | 37 | """ 38 | def __init__(self, functions): 39 | self.functions = functions 40 | 41 | def __call__(self, datas): 42 | 43 | for func in self.functions: 44 | try: 45 | datas = func(datas) 46 | except Exception as e: 47 | stack_info = traceback.format_exc() 48 | print("fail to perform fuction [{}] with error: " 49 | "{} and stack:\n{}".format(func, e, str(stack_info))) 50 | raise RuntimeError 51 | return datas 52 | 53 | 54 | def build_preprocess(cfg): 55 | preproccess = [] 56 | if not isinstance(cfg, (list, tuple)): 57 | cfg = [cfg] 58 | 59 | for cfg_ in cfg: 60 | process = build_from_config(cfg_, PREPROCESS) 61 | preproccess.append(process) 62 | 63 | preproccess = Compose(preproccess) 64 | return preproccess 65 | 66 | 67 | def build_transforms(cfg): 68 | transforms = [] 69 | 70 | for trans_cfg in cfg: 71 | temp_trans_cfg = copy.deepcopy(trans_cfg) 72 | name = temp_trans_cfg.pop('name') 73 | transforms.append(TRANSFORMS.get(name)(**temp_trans_cfg)) 74 | 75 | transforms = Compose(transforms) 76 | return transforms 77 | -------------------------------------------------------------------------------- /ppgan/apps/midas/utils.py: -------------------------------------------------------------------------------- 1 | # Refer https://github.com/intel-isl/MiDaS 2 | """Utils for monoDepth. 3 | """ 4 | import sys 5 | import re 6 | import numpy as np 7 | import cv2 8 | 9 | 10 | def write_pfm(path, image, scale=1): 11 | """Write pfm file. 12 | 13 | Args: 14 | path (str): pathto file 15 | image (array): data 16 | scale (int, optional): Scale. Defaults to 1. 17 | """ 18 | 19 | with open(path, "wb") as file: 20 | color = None 21 | 22 | if image.dtype.name != "float32": 23 | raise Exception("Image dtype must be float32.") 24 | 25 | image = np.flipud(image) 26 | 27 | if len(image.shape) == 3 and image.shape[2] == 3: # color image 28 | color = True 29 | elif (len(image.shape) == 2 30 | or len(image.shape) == 3 and image.shape[2] == 1): # greyscale 31 | color = False 32 | else: 33 | raise Exception( 34 | "Image must have H x W x 3, H x W x 1 or H x W dimensions.") 35 | 36 | file.write("PF\n" if color else "Pf\n".encode()) 37 | file.write("%d %d\n".encode() % (image.shape[1], image.shape[0])) 38 | 39 | endian = image.dtype.byteorder 40 | 41 | if endian == "<" or endian == "=" and sys.byteorder == "little": 42 | scale = -scale 43 | 44 | file.write("%f\n".encode() % scale) 45 | 46 | image.tofile(file) 47 | 48 | 49 | def read_image(path): 50 | """Read image and output RGB image (0-1). 51 | 52 | Args: 53 | path (str): path to file 54 | 55 | Returns: 56 | array: RGB image (0-1) 57 | """ 58 | img = cv2.imread(path) 59 | if img.ndim == 2: 60 | img = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR) 61 | img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) / 255.0 62 | return img 63 | 64 | 65 | def write_depth(path, depth, bits=1): 66 | """Write depth map to pfm and png file. 67 | 68 | Args: 69 | path (str): filepath without extension 70 | depth (array): depth 71 | """ 72 | write_pfm(path + ".pfm", depth.astype(np.float32)) 73 | 74 | depth_min = depth.min() 75 | depth_max = depth.max() 76 | 77 | max_val = (2**(8 * bits)) - 1 78 | 79 | if depth_max - depth_min > np.finfo("float").eps: 80 | out = max_val * (depth - depth_min) / (depth_max - depth_min) 81 | else: 82 | out = np.zeros(depth.shape, dtype=depth.type) 83 | 84 | if bits == 1: 85 | cv2.imwrite(path + ".png", out.astype("uint8")) 86 | elif bits == 2: 87 | cv2.imwrite(path + ".png", out.astype("uint16")) 88 | return path + '.pfm', path + ".png" 89 | -------------------------------------------------------------------------------- /ppgan/apps/styleganv2mixing_predictor.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import os 16 | import cv2 17 | import numpy as np 18 | import paddle 19 | from .styleganv2_predictor import StyleGANv2Predictor 20 | 21 | 22 | def make_image(tensor): 23 | return (((tensor.detach() + 1) / 2 * 255).clip(min=0, max=255).transpose( 24 | (0, 2, 3, 1)).numpy().astype('uint8')) 25 | 26 | 27 | class StyleGANv2MixingPredictor(StyleGANv2Predictor): 28 | @paddle.no_grad() 29 | def run(self, latent1, latent2, weights=[0.5] * 18): 30 | 31 | latent1 = paddle.to_tensor(np.load(latent1)).unsqueeze(0) 32 | latent2 = paddle.to_tensor(np.load(latent2)).unsqueeze(0) 33 | assert latent1.shape[1] == latent2.shape[1] == len( 34 | weights 35 | ), 'latents and their weights should have the same level nums.' 36 | mix_latent = [] 37 | for i, weight in enumerate(weights): 38 | mix_latent.append(latent1[:, i:i + 1] * weight + 39 | latent2[:, i:i + 1] * (1 - weight)) 40 | mix_latent = paddle.concat(mix_latent, 1) 41 | latent_n = paddle.concat([latent1, latent2, mix_latent], 0) 42 | generator = self.generator 43 | img_gen, _ = generator([latent_n], 44 | input_is_latent=True, 45 | randomize_noise=False) 46 | imgs = make_image(img_gen) 47 | src_img1 = imgs[0] 48 | src_img2 = imgs[1] 49 | dst_img = imgs[2] 50 | 51 | os.makedirs(self.output_path, exist_ok=True) 52 | save_src_path = os.path.join(self.output_path, 'src1.mixing.png') 53 | cv2.imwrite(save_src_path, cv2.cvtColor(src_img1, cv2.COLOR_RGB2BGR)) 54 | save_src_path = os.path.join(self.output_path, 'src2.mixing.png') 55 | cv2.imwrite(save_src_path, cv2.cvtColor(src_img2, cv2.COLOR_RGB2BGR)) 56 | save_dst_path = os.path.join(self.output_path, 'dst.mixing.png') 57 | cv2.imwrite(save_dst_path, cv2.cvtColor(dst_img, cv2.COLOR_RGB2BGR)) 58 | 59 | return src_img1, src_img2, dst_img 60 | -------------------------------------------------------------------------------- /test_tipc/output/python_infer_gpu_usetrt_null_precision_null_batchsize_null.log: -------------------------------------------------------------------------------- 1 | W1127 21:03:35.364223 20721 analysis_predictor.cc:715] The one-time configuration of analysis predictor failed, which may be due to native predictor called first and its configurations taken effect. 2 | --- Running analysis [ir_graph_build_pass] 3 | --- Running analysis [ir_graph_clean_pass] 4 | --- Running analysis [ir_analysis_pass] 5 | --- Running IR pass [is_test_pass] 6 | --- Running IR pass [simplify_with_basic_ops_pass] 7 | --- Running IR pass [conv_affine_channel_fuse_pass] 8 | --- Running IR pass [conv_eltwiseadd_affine_channel_fuse_pass] 9 | --- Running IR pass [conv_bn_fuse_pass] 10 | --- Running IR pass [conv_eltwiseadd_bn_fuse_pass] 11 | --- Running IR pass [embedding_eltwise_layernorm_fuse_pass] 12 | --- Running IR pass [multihead_matmul_fuse_pass_v2] 13 | --- Running IR pass [squeeze2_matmul_fuse_pass] 14 | --- Running IR pass [reshape2_matmul_fuse_pass] 15 | --- Running IR pass [flatten2_matmul_fuse_pass] 16 | --- Running IR pass [map_matmul_to_mul_pass] 17 | --- Running IR pass [fc_fuse_pass] 18 | --- Running IR pass [fc_elementwise_layernorm_fuse_pass] 19 | --- Running IR pass [conv_elementwise_add_act_fuse_pass] 20 | I1127 21:04:27.777726 20721 graph_pattern_detector.cc:91] --- detected 400 subgraphs 21 | --- Running IR pass [conv_elementwise_add2_act_fuse_pass] 22 | --- Running IR pass [conv_elementwise_add_fuse_pass] 23 | I1127 21:04:32.524188 20721 graph_pattern_detector.cc:91] --- detected 417 subgraphs 24 | --- Running IR pass [transpose_flatten_concat_fuse_pass] 25 | --- Running IR pass [runtime_context_cache_pass] 26 | --- Running analysis [ir_params_sync_among_devices_pass] 27 | I1127 21:04:33.063933 20721 ir_params_sync_among_devices_pass.cc:45] Sync params from CPU to GPU 28 | --- Running analysis [adjust_cudnn_workspace_size_pass] 29 | --- Running analysis [inference_op_replace_pass] 30 | --- Running analysis [ir_graph_to_program_pass] 31 | I1127 21:04:39.724141 20721 analysis_predictor.cc:636] ======= optimize end ======= 32 | I1127 21:04:39.830312 20721 naive_executor.cc:98] --- skip [feed], feed -> x 33 | I1127 21:04:39.866837 20721 naive_executor.cc:98] --- skip [save_infer_model/scale_0.tmp_1], fetch -> fetch 34 | W1127 21:04:40.013715 20721 device_context.cc:404] Please NOTE: device: 0, GPU Compute Capability: 7.0, Driver API Version: 10.1, Runtime API Version: 10.1 35 | W1127 21:04:40.018028 20721 device_context.cc:422] device: 0, cuDNN Version: 7.6. 36 | -------------------------------------------------------------------------------- /ppgan/faceutils/face_detection/detection/sfd/sfd_detector.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import os 16 | import cv2 17 | from paddle.utils.download import get_weights_path_from_url 18 | 19 | from ..core import FaceDetector 20 | 21 | from .net_s3fd import s3fd 22 | from .bbox import * 23 | from .detect import * 24 | 25 | models_urls = { 26 | 's3fd': 'https://paddlegan.bj.bcebos.com/models/s3fd_paddle.pdparams', 27 | } 28 | 29 | 30 | class SFDDetector(FaceDetector): 31 | def __init__(self, path_to_detector=None, verbose=False): 32 | super(SFDDetector, self).__init__(verbose) 33 | 34 | # Initialise the face detector 35 | if path_to_detector is None: 36 | model_weights_path = get_weights_path_from_url(models_urls['s3fd']) 37 | model_weights = paddle.load(model_weights_path) 38 | else: 39 | model_weights = paddle.load(path_to_detector) 40 | 41 | self.face_detector = s3fd() 42 | self.face_detector.load_dict(model_weights) 43 | self.face_detector.eval() 44 | 45 | def detect_from_image(self, tensor_or_path): 46 | image = self.tensor_or_path_to_ndarray(tensor_or_path) 47 | 48 | bboxlist = detect(self.face_detector, image) 49 | keep = nms(bboxlist, 0.3) 50 | bboxlist = bboxlist[keep, :] 51 | bboxlist = [x for x in bboxlist if x[-1] > 0.5] 52 | 53 | return bboxlist 54 | 55 | def detect_from_batch(self, images): 56 | bboxlists = batch_detect(self.face_detector, images) 57 | keeps = [ 58 | nms(bboxlists[:, i, :], 0.3) for i in range(bboxlists.shape[1]) 59 | ] 60 | bboxlists = [bboxlists[keep, i, :] for i, keep in enumerate(keeps)] 61 | bboxlists = [[x for x in bboxlist if x[-1] > 0.5] 62 | for bboxlist in bboxlists] 63 | 64 | return bboxlists 65 | 66 | @property 67 | def reference_scale(self): 68 | return 195 69 | 70 | @property 71 | def reference_x_shift(self): 72 | return 0 73 | 74 | @property 75 | def reference_y_shift(self): 76 | return 0 77 | -------------------------------------------------------------------------------- /ppgan/datasets/builder.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import time 16 | import paddle 17 | import numbers 18 | import numpy as np 19 | 20 | from paddle.distributed import ParallelEnv 21 | from paddle.io import DistributedBatchSampler 22 | 23 | from .repeat_dataset import RepeatDataset 24 | from ..utils.registry import Registry, build_from_config 25 | 26 | DATASETS = Registry("DATASETS") 27 | 28 | 29 | def build_dataset(cfg): 30 | name = cfg.pop('name') 31 | 32 | if name == 'RepeatDataset': 33 | dataset_ = build_from_config(cfg['dataset'], DATASETS) 34 | dataset = RepeatDataset(dataset_, cfg['times']) 35 | else: 36 | dataset = dataset = DATASETS.get(name)(**cfg) 37 | 38 | return dataset 39 | 40 | 41 | def build_dataloader(cfg, is_train=True, distributed=True): 42 | cfg_ = cfg.copy() 43 | 44 | batch_size = cfg_.pop('batch_size', 1) 45 | num_workers = cfg_.pop('num_workers', 0) 46 | use_shared_memory = cfg_.pop('use_shared_memory', True) 47 | 48 | dataset = build_dataset(cfg_) 49 | 50 | if distributed: 51 | sampler = DistributedBatchSampler(dataset, 52 | batch_size=batch_size, 53 | shuffle=True if is_train else False, 54 | drop_last=True if is_train else False) 55 | 56 | dataloader = paddle.io.DataLoader(dataset, 57 | batch_sampler=sampler, 58 | num_workers=num_workers, 59 | use_shared_memory=use_shared_memory) 60 | else: 61 | dataloader = paddle.io.DataLoader(dataset, 62 | batch_size=batch_size, 63 | shuffle=True if is_train else False, 64 | drop_last=True if is_train else False, 65 | use_shared_memory=use_shared_memory, 66 | num_workers=num_workers) 67 | 68 | return dataloader 69 | -------------------------------------------------------------------------------- /configs/rcan_x4_div2k_tipc.yaml: -------------------------------------------------------------------------------- 1 | total_iters: 12 2 | output_dir: output_dir 3 | # tensor range for function tensor2img 4 | min_max: 5 | (0., 255.) 6 | 7 | model: 8 | name: BaseSRModel 9 | generator: 10 | name: RCAN 11 | pixel_criterion: 12 | name: L1Loss 13 | 14 | dataset: 15 | train: 16 | name: SRDataset 17 | gt_folder: data/DIV2K/DIV2K_train_HR 18 | lq_folder: data/DIV2K/DIV2K_train_LR_bicubic/X4 19 | num_workers: 4 20 | batch_size: 16 21 | scale: 4 22 | preprocess: 23 | - name: LoadImageFromFile 24 | key: lq 25 | - name: LoadImageFromFile 26 | key: gt 27 | - name: Transforms 28 | input_keys: [lq, gt] 29 | pipeline: 30 | - name: SRPairedRandomCrop 31 | gt_patch_size: 192 32 | scale: 4 33 | keys: [image, image] 34 | - name: PairedRandomHorizontalFlip 35 | keys: [image, image] 36 | - name: PairedRandomVerticalFlip 37 | keys: [image, image] 38 | - name: PairedRandomTransposeHW 39 | keys: [image, image] 40 | - name: Transpose 41 | keys: [image, image] 42 | - name: Normalize 43 | mean: [0., .0, 0.] 44 | std: [1., 1., 1.] 45 | keys: [image, image] 46 | test: 47 | name: SRDataset 48 | gt_folder: data/Set14/GTmod12 49 | lq_folder: data/Set14/LRbicx4 50 | scale: 4 51 | preprocess: 52 | - name: LoadImageFromFile 53 | key: lq 54 | - name: LoadImageFromFile 55 | key: gt 56 | - name: Transforms 57 | input_keys: [lq, gt] 58 | pipeline: 59 | - name: Transpose 60 | keys: [image, image] 61 | - name: Normalize 62 | mean: [0., .0, 0.] 63 | std: [1., 1., 1.] 64 | keys: [image, image] 65 | 66 | lr_scheduler: 67 | name: CosineAnnealingRestartLR 68 | learning_rate: 0.0001 69 | periods: [3, 3, 3, 3] 70 | restart_weights: [1, 1, 1, 1] 71 | eta_min: !!float 1e-7 72 | 73 | optimizer: 74 | name: Adam 75 | # add parameters of net_name to optim 76 | # name should in self.nets 77 | net_names: 78 | - generator 79 | beta1: 0.9 80 | beta2: 0.99 81 | 82 | validate: 83 | interval: 10 84 | save_img: True 85 | 86 | metrics: 87 | psnr: # metric name, can be arbitrary 88 | name: PSNR 89 | crop_border: 4 90 | test_y_channel: True 91 | ssim: 92 | name: SSIM 93 | crop_border: 4 94 | test_y_channel: True 95 | 96 | log_config: 97 | interval: 100 98 | visiual_interval: 5 99 | 100 | snapshot_config: 101 | interval: 10 102 | 103 | export_model: 104 | - {name: 'generator', inputs_num: 1} 105 | -------------------------------------------------------------------------------- /configs/rcan_x4_div2k.yaml: -------------------------------------------------------------------------------- 1 | total_iters: 400000 2 | output_dir: output_dir 3 | # tensor range for function tensor2img 4 | min_max: 5 | (0., 255.) 6 | 7 | model: 8 | name: BaseSRModel 9 | generator: 10 | name: RCAN 11 | pixel_criterion: 12 | name: L1Loss 13 | 14 | dataset: 15 | train: 16 | name: SRDataset 17 | gt_folder: data/DIV2K/DIV2K_train_HR 18 | lq_folder: data/DIV2K/DIV2K_train_LR_bicubic/X4 19 | num_workers: 4 20 | batch_size: 16 21 | scale: 4 22 | preprocess: 23 | - name: LoadImageFromFile 24 | key: lq 25 | - name: LoadImageFromFile 26 | key: gt 27 | - name: Transforms 28 | input_keys: [lq, gt] 29 | pipeline: 30 | - name: SRPairedRandomCrop 31 | gt_patch_size: 192 32 | scale: 4 33 | keys: [image, image] 34 | - name: PairedRandomHorizontalFlip 35 | keys: [image, image] 36 | - name: PairedRandomVerticalFlip 37 | keys: [image, image] 38 | - name: PairedRandomTransposeHW 39 | keys: [image, image] 40 | - name: Transpose 41 | keys: [image, image] 42 | - name: Normalize 43 | mean: [0., .0, 0.] 44 | std: [1., 1., 1.] 45 | keys: [image, image] 46 | test: 47 | name: SRDataset 48 | gt_folder: data/Set14/GTmod12 49 | lq_folder: data/Set14/LRbicx4 50 | scale: 4 51 | preprocess: 52 | - name: LoadImageFromFile 53 | key: lq 54 | - name: LoadImageFromFile 55 | key: gt 56 | - name: Transforms 57 | input_keys: [lq, gt] 58 | pipeline: 59 | - name: Transpose 60 | keys: [image, image] 61 | - name: Normalize 62 | mean: [0., .0, 0.] 63 | std: [1., 1., 1.] 64 | keys: [image, image] 65 | 66 | lr_scheduler: 67 | name: CosineAnnealingRestartLR 68 | learning_rate: 0.0001 69 | periods: [100000, 100000, 100000, 100000] 70 | restart_weights: [1, 1, 1, 1] 71 | eta_min: !!float 1e-7 72 | 73 | optimizer: 74 | name: Adam 75 | # add parameters of net_name to optim 76 | # name should in self.nets 77 | net_names: 78 | - generator 79 | beta1: 0.9 80 | beta2: 0.99 81 | 82 | validate: 83 | interval: 2000 84 | save_img: True 85 | 86 | metrics: 87 | psnr: # metric name, can be arbitrary 88 | name: PSNR 89 | crop_border: 4 90 | test_y_channel: True 91 | ssim: 92 | name: SSIM 93 | crop_border: 4 94 | test_y_channel: True 95 | 96 | log_config: 97 | interval: 100 98 | visiual_interval: 500 99 | 100 | snapshot_config: 101 | interval: 2000 102 | 103 | export_model: 104 | - {name: 'generator', inputs_num: 1} 105 | -------------------------------------------------------------------------------- /tools/export_model.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import os 16 | import sys 17 | import argparse 18 | 19 | sys.path.append(os.path.dirname(__file__) + os.sep + '../') 20 | import ppgan 21 | from ppgan.utils.config import get_config 22 | from ppgan.utils.setup import setup 23 | from ppgan.engine.trainer import Trainer 24 | 25 | 26 | def parse_args(): 27 | parser = argparse.ArgumentParser() 28 | parser.add_argument('-c', 29 | '--config-file', 30 | metavar="FILE", 31 | required=True, 32 | help="config file path") 33 | parser.add_argument("--load", 34 | type=str, 35 | default=None, 36 | required=True, 37 | help="put the path to resuming file if needed") 38 | # config options 39 | parser.add_argument("-o", 40 | "--opt", 41 | nargs="+", 42 | help="set configuration options") 43 | parser.add_argument("-s", 44 | "--inputs_size", 45 | type=str, 46 | default=None, 47 | required=True, 48 | help="the inputs size") 49 | parser.add_argument( 50 | "--output_dir", 51 | default=None, 52 | type=str, 53 | help="The path prefix of inference model to be used.", 54 | ) 55 | args = parser.parse_args() 56 | return args 57 | 58 | 59 | def main(args, cfg): 60 | inputs_size = [[int(size) for size in input_size.split(',')] 61 | for input_size in args.inputs_size.split(';')] 62 | model = ppgan.models.builder.build_model(cfg.model) 63 | model.setup_train_mode(is_train=False) 64 | state_dicts = ppgan.utils.filesystem.load(args.load) 65 | for net_name, net in model.nets.items(): 66 | if net_name in state_dicts: 67 | net.set_state_dict(state_dicts[net_name]) 68 | model.export_model(cfg.export_model, args.output_dir, inputs_size) 69 | 70 | 71 | if __name__ == "__main__": 72 | args = parse_args() 73 | cfg = get_config(args.config_file, args.opt) 74 | main(args, cfg) 75 | -------------------------------------------------------------------------------- /ppgan/faceutils/mask/face_parser.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import os.path as osp 16 | 17 | import numpy as np 18 | import cv2 19 | from PIL import Image 20 | import paddle 21 | import paddle.vision.transforms as T 22 | from paddle.utils.download import get_path_from_url 23 | import pickle 24 | from .model import BiSeNet 25 | 26 | BISENET_WEIGHT_URL = 'https://paddlegan.bj.bcebos.com/models/bisenet.pdparams' 27 | 28 | 29 | class FaceParser: 30 | def __init__(self, device="cpu"): 31 | self.mapper = { 32 | 0: 0, 33 | 1: 1, 34 | 2: 2, 35 | 3: 3, 36 | 4: 4, 37 | 5: 5, 38 | 6: 0, 39 | 7: 11, 40 | 8: 12, 41 | 9: 0, 42 | 10: 6, 43 | 11: 8, 44 | 12: 7, 45 | 13: 9, 46 | 14: 13, 47 | 15: 0, 48 | 16: 0, 49 | 17: 10, 50 | 18: 0 51 | } 52 | #self.dict = paddle.to_tensor(mapper) 53 | self.save_pth = get_path_from_url(BISENET_WEIGHT_URL, 54 | osp.split(osp.realpath(__file__))[0]) 55 | 56 | self.net = BiSeNet(n_classes=19) 57 | 58 | self.transforms = T.Compose([ 59 | T.Normalize((0.485, 0.456, 0.406), (0.229, 0.224, 0.225)), 60 | ]) 61 | 62 | def parse(self, image): 63 | assert image.shape[:2] == (512, 512) 64 | image = image / 255.0 65 | image = image.transpose((2, 0, 1)) 66 | image = self.transforms(image) 67 | 68 | state_dict = paddle.load(self.save_pth) 69 | self.net.set_dict(state_dict) 70 | self.net.eval() 71 | 72 | with paddle.no_grad(): 73 | image = paddle.to_tensor(image) 74 | image = image.unsqueeze(0) 75 | out = self.net(image)[0] 76 | parsing = out.squeeze(0).argmax(0) #argmax(0).astype('float32') 77 | 78 | parse_np = parsing.numpy() 79 | h, w = parse_np.shape 80 | result = np.zeros((h, w)) 81 | for i in range(h): 82 | for j in range(w): 83 | result[i][j] = self.mapper[parse_np[i][j]] 84 | 85 | result = paddle.to_tensor(result).astype('float32') 86 | return result 87 | -------------------------------------------------------------------------------- /ppgan/faceutils/face_detection/detection/blazeface/blazeface_detector.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import os 16 | import cv2 17 | from paddle.utils.download import get_weights_path_from_url 18 | 19 | from ..core import FaceDetector 20 | 21 | from .net_blazeface import BlazeFace 22 | from .detect import * 23 | 24 | blazeface_weights = 'https://paddlegan.bj.bcebos.com/models/blazeface.pdparams' 25 | blazeface_anchors = 'https://paddlegan.bj.bcebos.com/models/anchors.npy' 26 | 27 | 28 | class BlazeFaceDetector(FaceDetector): 29 | def __init__(self, 30 | path_to_detector=None, 31 | path_to_anchor=None, 32 | verbose=False, 33 | min_score_thresh=0.5, 34 | min_suppression_threshold=0.3): 35 | super(BlazeFaceDetector, self).__init__(verbose) 36 | 37 | # Initialise the face detector 38 | if path_to_detector is None: 39 | model_weights_path = get_weights_path_from_url(blazeface_weights) 40 | model_weights = paddle.load(model_weights_path) 41 | model_anchors = np.load( 42 | get_weights_path_from_url(blazeface_anchors)) 43 | else: 44 | model_weights = paddle.load(path_to_detector) 45 | model_anchors = np.load(path_to_anchor) 46 | 47 | self.face_detector = BlazeFace() 48 | self.face_detector.load_dict(model_weights) 49 | self.face_detector.load_anchors_from_npy(model_anchors) 50 | 51 | self.face_detector.min_score_thresh = min_score_thresh 52 | self.face_detector.min_suppression_threshold = min_suppression_threshold 53 | 54 | self.face_detector.eval() 55 | 56 | def detect_from_image(self, tensor_or_path): 57 | image = self.tensor_or_path_to_ndarray(tensor_or_path) 58 | 59 | bboxlist = detect(self.face_detector, image)[0] 60 | 61 | return bboxlist 62 | 63 | def detect_from_batch(self, tensor): 64 | bboxlists = batch_detect(self.face_detector, tensor) 65 | return bboxlists 66 | 67 | @property 68 | def reference_scale(self): 69 | return 195 70 | 71 | @property 72 | def reference_x_shift(self): 73 | return 0 74 | 75 | @property 76 | def reference_y_shift(self): 77 | return 0 78 | -------------------------------------------------------------------------------- /ppgan/datasets/common_vision_dataset.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import numpy as np 16 | import paddle 17 | 18 | from .builder import DATASETS 19 | from .base_dataset import BaseDataset 20 | from .preprocess.builder import build_transforms 21 | 22 | 23 | @DATASETS.register() 24 | class CommonVisionDataset(paddle.io.Dataset): 25 | """ 26 | Dataset for using paddle vision default datasets, such as mnist, flowers. 27 | """ 28 | def __init__(self, 29 | dataset_name, 30 | transforms=None, 31 | return_label=True, 32 | params=None): 33 | """Initialize this dataset class. 34 | 35 | Args: 36 | dataset_name (str): return a dataset from paddle.vision.datasets by this option. 37 | transforms (list[dict]): A sequence of data transforms config. 38 | return_label (bool): whether to retuan a label of a sample. 39 | params (dict): paramters of paddle.vision.datasets. 40 | """ 41 | super(CommonVisionDataset, self).__init__() 42 | 43 | dataset_cls = getattr(paddle.vision.datasets, dataset_name) 44 | transform = build_transforms(transforms) 45 | self.return_label = return_label 46 | 47 | param_dict = {} 48 | param_names = list(dataset_cls.__init__.__code__.co_varnames) 49 | if 'transform' in param_names: 50 | param_dict['transform'] = transform 51 | 52 | if params is not None: 53 | for name in param_names: 54 | if name in params: 55 | param_dict[name] = params[name] 56 | 57 | self.dataset = dataset_cls(**param_dict) 58 | 59 | def __getitem__(self, index): 60 | return_dict = {} 61 | return_list = self.dataset[index] 62 | if isinstance(return_list, (tuple, list)): 63 | if len(return_list) == 2: 64 | return_dict['img'] = return_list[0] 65 | if self.return_label: 66 | return_dict['class_id'] = np.asarray(return_list[1]) 67 | else: 68 | return_dict['img'] = return_list[0] 69 | else: 70 | return_dict['img'] = return_list 71 | 72 | return return_dict 73 | 74 | def __len__(self): 75 | return len(self.dataset) 76 | -------------------------------------------------------------------------------- /ppgan/models/discriminators/discriminator_animegan.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | #Licensed under the Apache License, Version 2.0 (the "License"); 4 | #you may not use this file except in compliance with the License. 5 | #You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | #Unless required by applicable law or agreed to in writing, software 10 | #distributed under the License is distributed on an "AS IS" BASIS, 11 | #WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | #See the License for the specific language governing permissions and 13 | #limitations under the License. 14 | 15 | import paddle.nn as nn 16 | import paddle.nn.functional as F 17 | 18 | from .builder import DISCRIMINATORS 19 | from ...modules.utils import spectral_norm 20 | 21 | 22 | @DISCRIMINATORS.register() 23 | class AnimeDiscriminator(nn.Layer): 24 | def __init__(self, channel: int = 64, nblocks: int = 3) -> None: 25 | super().__init__() 26 | channel = channel // 2 27 | last_channel = channel 28 | f = [ 29 | spectral_norm( 30 | nn.Conv2D(3, channel, 3, stride=1, padding=1, bias_attr=False)), 31 | nn.LeakyReLU(0.2) 32 | ] 33 | in_h = 256 34 | for i in range(1, nblocks): 35 | f.extend([ 36 | spectral_norm( 37 | nn.Conv2D(last_channel, 38 | channel * 2, 39 | 3, 40 | stride=2, 41 | padding=1, 42 | bias_attr=False)), 43 | nn.LeakyReLU(0.2), 44 | spectral_norm( 45 | nn.Conv2D(channel * 2, 46 | channel * 4, 47 | 3, 48 | stride=1, 49 | padding=1, 50 | bias_attr=False)), 51 | nn.GroupNorm(1, channel * 4), 52 | nn.LeakyReLU(0.2) 53 | ]) 54 | last_channel = channel * 4 55 | channel = channel * 2 56 | in_h = in_h // 2 57 | 58 | self.body = nn.Sequential(*f) 59 | 60 | self.head = nn.Sequential(*[ 61 | spectral_norm( 62 | nn.Conv2D(last_channel, 63 | channel * 2, 64 | 3, 65 | stride=1, 66 | padding=1, 67 | bias_attr=False)), 68 | nn.GroupNorm(1, channel * 2), 69 | nn.LeakyReLU(0.2), 70 | spectral_norm( 71 | nn.Conv2D( 72 | channel * 2, 1, 3, stride=1, padding=1, bias_attr=False)) 73 | ]) 74 | 75 | def forward(self, x): 76 | x = self.body(x) 77 | x = self.head(x) 78 | return x 79 | -------------------------------------------------------------------------------- /ppgan/utils/logger.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import logging 16 | import os 17 | import sys 18 | 19 | from paddle.distributed import ParallelEnv 20 | 21 | logger_initialized = [] 22 | 23 | 24 | def setup_logger(output=None, name="ppgan"): 25 | """ 26 | Initialize the ppgan logger and set its verbosity level to "INFO". 27 | 28 | Args: 29 | output (str): a file name or a directory to save log. If None, will not save log file. 30 | If ends with ".txt" or ".log", assumed to be a file name. 31 | Otherwise, logs will be saved to `output/log.txt`. 32 | name (str): the root module name of this logger 33 | 34 | Returns: 35 | logging.Logger: a logger 36 | """ 37 | logger = logging.getLogger(name) 38 | if name in logger_initialized: 39 | return logger 40 | logger.setLevel(logging.INFO) 41 | logger.propagate = False 42 | 43 | plain_formatter = logging.Formatter( 44 | "[%(asctime)s] %(name)s %(levelname)s: %(message)s", 45 | datefmt="%m/%d %H:%M:%S") 46 | # stdout logging: master only 47 | local_rank = ParallelEnv().local_rank 48 | if local_rank == 0: 49 | ch = logging.StreamHandler(stream=sys.stdout) 50 | ch.setLevel(logging.DEBUG) 51 | formatter = plain_formatter 52 | ch.setFormatter(formatter) 53 | logger.addHandler(ch) 54 | 55 | # file logging: all workers 56 | if output is not None: 57 | if output.endswith(".txt") or output.endswith(".log"): 58 | filename = output 59 | else: 60 | filename = os.path.join(output, "log.txt") 61 | if local_rank > 0: 62 | filename = filename + ".rank{}".format(local_rank) 63 | 64 | # PathManager.mkdirs(os.path.dirname(filename)) 65 | os.makedirs(os.path.dirname(filename), exist_ok=True) 66 | 67 | # fh = logging.StreamHandler(_cached_log_stream(filename) 68 | fh = logging.FileHandler(filename, mode='a') 69 | fh.setLevel(logging.DEBUG) 70 | fh.setFormatter(plain_formatter) 71 | logger.addHandler(fh) 72 | logger_initialized.append(name) 73 | return logger 74 | 75 | 76 | def get_logger(name='ppgan'): 77 | logger = logging.getLogger(name) 78 | if name in logger_initialized: 79 | return logger 80 | 81 | return setup_logger(name=name) 82 | -------------------------------------------------------------------------------- /ppgan/apps/base_predictor.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | #Licensed under the Apache License, Version 2.0 (the "License"); 4 | #you may not use this file except in compliance with the License. 5 | #You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | #Unless required by applicable law or agreed to in writing, software 10 | #distributed under the License is distributed on an "AS IS" BASIS, 11 | #WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | #See the License for the specific language governing permissions and 13 | #limitations under the License. 14 | 15 | import os 16 | import cv2 17 | import numpy as np 18 | from PIL import Image 19 | import paddle 20 | 21 | 22 | class BasePredictor(object): 23 | def __init__(self): 24 | pass 25 | 26 | def build_inference_model(self): 27 | if paddle.in_dynamic_mode(): 28 | # todo self.model = build_model(self.cfg) 29 | pass 30 | else: 31 | place = paddle.get_device() 32 | self.exe = paddle.static.Executor(place) 33 | file_names = os.listdir(self.weight_path) 34 | for file_name in file_names: 35 | if file_name.find('model') > -1: 36 | model_file = file_name 37 | elif file_name.find('param') > -1: 38 | param_file = file_name 39 | 40 | self.program, self.feed_names, self.fetch_targets = paddle.static.load_inference_model( 41 | self.weight_path, 42 | executor=self.exe, 43 | model_filename=model_file, 44 | params_filename=param_file) 45 | 46 | def base_forward(self, inputs): 47 | if paddle.in_dynamic_mode(): 48 | out = self.model(inputs) 49 | else: 50 | feed_dict = {} 51 | if isinstance(inputs, dict): 52 | feed_dict = inputs 53 | elif isinstance(inputs, (list, tuple)): 54 | for i, feed_name in enumerate(self.feed_names): 55 | feed_dict[feed_name] = inputs[i] 56 | else: 57 | feed_dict[self.feed_names[0]] = inputs 58 | 59 | out = self.exe.run(self.program, 60 | fetch_list=self.fetch_targets, 61 | feed=feed_dict) 62 | 63 | return out 64 | 65 | def is_image(self, input): 66 | try: 67 | if isinstance(input, (np.ndarray, Image.Image)): 68 | return True 69 | elif isinstance(input, str): 70 | if not os.path.isfile(input): 71 | raise ValueError('input must be a file') 72 | img = Image.open(input) 73 | _ = img.size 74 | return True 75 | else: 76 | return False 77 | except: 78 | return False 79 | 80 | def run(self): 81 | raise NotImplementedError 82 | -------------------------------------------------------------------------------- /ppgan/datasets/image_folder.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | """A modified image folder class 15 | 16 | We modify the official PyTorch image folder (https://github.com/pytorch/vision/blob/master/torchvision/datasets/folder.py) 17 | so that this class can load images from both current directory and its subdirectories. 18 | """ 19 | 20 | from paddle.io import Dataset 21 | from PIL import Image 22 | import os 23 | import os.path 24 | 25 | IMG_EXTENSIONS = [ 26 | '.jpg', 27 | '.JPG', 28 | '.jpeg', 29 | '.JPEG', 30 | '.png', 31 | '.PNG', 32 | '.ppm', 33 | '.PPM', 34 | '.bmp', 35 | '.BMP', 36 | '.tif', 37 | '.TIF', 38 | '.tiff', 39 | '.TIFF', 40 | ] 41 | 42 | 43 | def is_image_file(filename): 44 | return any(filename.endswith(extension) for extension in IMG_EXTENSIONS) 45 | 46 | 47 | def make_dataset(dir, max_dataset_size=float("inf")): 48 | images = [] 49 | assert os.path.isdir(dir), '%s is not a valid directory' % dir 50 | 51 | for root, _, fnames in sorted(os.walk(dir)): 52 | for fname in fnames: 53 | if is_image_file(fname): 54 | path = os.path.join(root, fname) 55 | images.append(path) 56 | 57 | return images[:min(float(max_dataset_size), len(images))] 58 | 59 | 60 | def default_loader(path): 61 | return Image.open(path).convert('RGB') 62 | 63 | 64 | class ImageFolder(Dataset): 65 | def __init__(self, 66 | root, 67 | transform=None, 68 | return_paths=False, 69 | loader=default_loader): 70 | imgs = make_dataset(root) 71 | if len(imgs) == 0: 72 | raise (RuntimeError("Found 0 images in: " + root + "\n" 73 | "Supported image extensions are: " + 74 | ",".join(IMG_EXTENSIONS))) 75 | 76 | self.root = root 77 | self.imgs = imgs 78 | self.transform = transform 79 | self.return_paths = return_paths 80 | self.loader = loader 81 | 82 | def __getitem__(self, index): 83 | path = self.imgs[index] 84 | img = self.loader(path) 85 | if self.transform is not None: 86 | img = self.transform(img) 87 | if self.return_paths: 88 | return img, path 89 | else: 90 | return img 91 | 92 | def __len__(self): 93 | return len(self.imgs) 94 | -------------------------------------------------------------------------------- /ppgan/apps/styleganv2editing_predictor.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import os 16 | import cv2 17 | import numpy as np 18 | import paddle 19 | 20 | from ppgan.utils.download import get_path_from_url 21 | from .styleganv2_predictor import StyleGANv2Predictor 22 | 23 | model_cfgs = { 24 | 'ffhq-config-f': { 25 | 'direction_urls': 26 | 'https://paddlegan.bj.bcebos.com/models/stylegan2-ffhq-config-f-directions.pdparams' 27 | } 28 | } 29 | 30 | 31 | def make_image(tensor): 32 | return (((tensor.detach() + 1) / 2 * 255).clip(min=0, max=255).transpose( 33 | (0, 2, 3, 1)).numpy().astype('uint8')) 34 | 35 | 36 | class StyleGANv2EditingPredictor(StyleGANv2Predictor): 37 | def __init__(self, model_type=None, direction_path=None, **kwargs): 38 | super().__init__(model_type=model_type, **kwargs) 39 | 40 | if direction_path is None and model_type is not None: 41 | assert model_type in model_cfgs, f'There is not any pretrained direction file for {model_type} model.' 42 | direction_path = get_path_from_url( 43 | model_cfgs[model_type]['direction_urls']) 44 | self.directions = paddle.load(direction_path) 45 | 46 | @paddle.no_grad() 47 | def run(self, latent, direction, offset): 48 | 49 | latent = paddle.to_tensor( 50 | np.load(latent)).unsqueeze(0).astype('float32') 51 | direction = self.directions[direction].unsqueeze(0).astype('float32') 52 | 53 | latent_n = paddle.concat([latent, latent + offset * direction], 0) 54 | generator = self.generator 55 | img_gen, _ = generator([latent_n], 56 | input_is_latent=True, 57 | randomize_noise=False) 58 | imgs = make_image(img_gen) 59 | src_img = imgs[0] 60 | dst_img = imgs[1] 61 | 62 | dst_latent = (latent + offset * direction)[0].numpy().astype('float32') 63 | 64 | os.makedirs(self.output_path, exist_ok=True) 65 | save_src_path = os.path.join(self.output_path, 'src.editing.png') 66 | cv2.imwrite(save_src_path, cv2.cvtColor(src_img, cv2.COLOR_RGB2BGR)) 67 | save_dst_path = os.path.join(self.output_path, 'dst.editing.png') 68 | cv2.imwrite(save_dst_path, cv2.cvtColor(dst_img, cv2.COLOR_RGB2BGR)) 69 | save_npy_path = os.path.join(self.output_path, 'dst.editing.npy') 70 | np.save(save_npy_path, dst_latent) 71 | 72 | return src_img, dst_img, dst_latent 73 | -------------------------------------------------------------------------------- /ppgan/faceutils/face_detection/detection/blazeface/detect.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import paddle 16 | import paddle.nn.functional as F 17 | 18 | import cv2 19 | import numpy as np 20 | 21 | from .utils import * 22 | 23 | 24 | def detect(net, img, device): 25 | H, W, C = img.shape 26 | orig_size = min(H, W) 27 | img, (xshift, yshift) = resize_and_crop_image(img, 128) 28 | preds = net.predict_on_image(img.astype('float32')).numpy() 29 | 30 | if 0 == len(preds): 31 | return [[]] 32 | 33 | shift = np.array([xshift, yshift] * 2) 34 | scores = preds[:, -1:] 35 | 36 | locs = np.concatenate( 37 | (preds[:, 1:2], preds[:, 0:1], preds[:, 3:4], preds[:, 2:3]), axis=1) 38 | return [np.concatenate((locs * orig_size + shift, scores), axis=1)] 39 | 40 | 41 | def batch_detect(net, img_batch): 42 | """ 43 | Inputs: 44 | - img_batch: a numpy array or tensor of shape (Batch size, Channels, Height, Width) 45 | Outputs: 46 | - list of 2-dim numpy arrays with shape (faces_on_this_image, 5): x1, y1, x2, y2, confidence 47 | (x1, y1) - top left corner, (x2, y2) - bottom right corner 48 | """ 49 | B, H, W, C = img_batch.shape 50 | orig_size = min(H, W) 51 | 52 | if isinstance(img_batch, paddle.Tensor): 53 | img_batch = img_batch.numpy() 54 | 55 | imgs, (xshift, yshift) = resize_and_crop_batch(img_batch, 128) 56 | preds = net.predict_on_batch(imgs.astype('float32')) 57 | bboxlists = [] 58 | for pred in preds: 59 | pred = pred.numpy() 60 | shift = np.array([xshift, yshift] * 2) 61 | scores = pred[:, -1:] 62 | xmin = pred[:, 1:2] 63 | ymin = pred[:, 0:1] 64 | xmax = pred[:, 3:4] 65 | ymax = pred[:, 2:3] 66 | locs = np.concatenate((xmin, ymin, xmax, ymax), axis=1) 67 | bboxlists.append( 68 | np.concatenate((locs * orig_size + shift, scores), axis=1)) 69 | 70 | return bboxlists 71 | 72 | 73 | def flip_detect(net, img): 74 | img = cv2.flip(img, 1) 75 | b = detect(net, img) 76 | 77 | bboxlist = np.zeros(b.shape) 78 | bboxlist[:, 0] = img.shape[1] - b[:, 2] 79 | bboxlist[:, 1] = b[:, 1] 80 | bboxlist[:, 2] = img.shape[1] - b[:, 0] 81 | bboxlist[:, 3] = b[:, 3] 82 | bboxlist[:, 4] = b[:, 4] 83 | return bboxlist 84 | 85 | 86 | def pts_to_bb(pts): 87 | min_x, min_y = np.min(pts, axis=0) 88 | max_x, max_y = np.max(pts, axis=0) 89 | return np.array([min_x, min_y, max_x, max_y]) 90 | -------------------------------------------------------------------------------- /data/realsr_preprocess/collect_noise.py: -------------------------------------------------------------------------------- 1 | from PIL import Image 2 | import numpy as np 3 | import os.path as osp 4 | import glob 5 | import os 6 | import argparse 7 | import yaml 8 | 9 | parser = argparse.ArgumentParser(description='create a dataset') 10 | parser.add_argument('--dataset', 11 | default='df2k', 12 | type=str, 13 | help='selecting different datasets') 14 | parser.add_argument('--artifacts', 15 | default='', 16 | type=str, 17 | help='selecting different artifacts type') 18 | parser.add_argument('--cleanup_factor', 19 | default=2, 20 | type=int, 21 | help='downscaling factor for image cleanup') 22 | parser.add_argument('--upscale_factor', 23 | default=4, 24 | type=int, 25 | choices=[4], 26 | help='super resolution upscale factor') 27 | opt = parser.parse_args() 28 | 29 | # define input and target directories 30 | cur_path = os.path.abspath(os.path.dirname(__file__)) 31 | with open(os.path.join(cur_path, './paths.yml'), 'r') as stream: 32 | PATHS = yaml.load(stream, Loader=yaml.SafeLoader) 33 | 34 | 35 | def noise_patch(rgb_img, sp, max_var, min_mean): 36 | img = rgb_img.convert('L') 37 | rgb_img = np.array(rgb_img) 38 | img = np.array(img) 39 | 40 | w, h = img.shape 41 | collect_patchs = [] 42 | 43 | for i in range(0, w - sp, sp): 44 | for j in range(0, h - sp, sp): 45 | patch = img[i:i + sp, j:j + sp] 46 | var_global = np.var(patch) 47 | mean_global = np.mean(patch) 48 | if var_global < max_var and mean_global > min_mean: 49 | rgb_patch = rgb_img[i:i + sp, j:j + sp, :] 50 | collect_patchs.append(rgb_patch) 51 | 52 | return collect_patchs 53 | 54 | 55 | if __name__ == '__main__': 56 | 57 | if opt.dataset == 'df2k': 58 | img_dir = PATHS[opt.dataset][opt.artifacts]['source'] 59 | noise_dir = PATHS['datasets']['df2k'] + '/Corrupted_noise' 60 | sp = 256 61 | max_var = 20 62 | min_mean = 0 63 | else: 64 | img_dir = PATHS[opt.dataset][opt.artifacts]['hr']['train'] 65 | noise_dir = PATHS['datasets']['dped'] + '/DPEDiphone_noise' 66 | sp = 256 67 | max_var = 20 68 | min_mean = 50 69 | 70 | assert not os.path.exists(noise_dir) 71 | os.mkdir(noise_dir) 72 | 73 | img_paths = sorted(glob.glob(osp.join(img_dir, '*.png'))) 74 | cnt = 0 75 | for path in img_paths: 76 | img_name = osp.splitext(osp.basename(path))[0] 77 | print('**********', img_name, '**********') 78 | img = Image.open(path).convert('RGB') 79 | patchs = noise_patch(img, sp, max_var, min_mean) 80 | for idx, patch in enumerate(patchs): 81 | save_path = osp.join(noise_dir, 82 | '{}_{:03}.png'.format(img_name, idx)) 83 | cnt += 1 84 | print('collect:', cnt, save_path) 85 | Image.fromarray(patch).save(save_path) 86 | -------------------------------------------------------------------------------- /applications/tools/pixel2style2pixel.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import argparse 16 | 17 | import paddle 18 | from ppgan.apps import Pixel2Style2PixelPredictor 19 | 20 | if __name__ == "__main__": 21 | parser = argparse.ArgumentParser() 22 | parser.add_argument("--input_image", type=str, help="path to source image") 23 | 24 | parser.add_argument("--output_path", 25 | type=str, 26 | default='output_dir', 27 | help="path to output image dir") 28 | 29 | parser.add_argument("--weight_path", 30 | type=str, 31 | default=None, 32 | help="path to model checkpoint path") 33 | 34 | parser.add_argument("--model_type", 35 | type=str, 36 | default=None, 37 | help="type of model for loading pretrained model") 38 | 39 | parser.add_argument("--seed", 40 | type=int, 41 | default=None, 42 | help="sample random seed for model's image generation") 43 | 44 | parser.add_argument("--size", 45 | type=int, 46 | default=1024, 47 | help="resolution of output image") 48 | 49 | parser.add_argument("--style_dim", 50 | type=int, 51 | default=512, 52 | help="number of style dimension") 53 | 54 | parser.add_argument("--n_mlp", 55 | type=int, 56 | default=8, 57 | help="number of mlp layer depth") 58 | 59 | parser.add_argument("--channel_multiplier", 60 | type=int, 61 | default=2, 62 | help="number of channel multiplier") 63 | 64 | parser.add_argument("--cpu", 65 | dest="cpu", 66 | action="store_true", 67 | help="cpu mode.") 68 | 69 | args = parser.parse_args() 70 | 71 | if args.cpu: 72 | paddle.set_device('cpu') 73 | 74 | predictor = Pixel2Style2PixelPredictor( 75 | output_path=args.output_path, 76 | weight_path=args.weight_path, 77 | model_type=args.model_type, 78 | seed=args.seed, 79 | size=args.size, 80 | style_dim=args.style_dim, 81 | n_mlp=args.n_mlp, 82 | channel_multiplier=args.channel_multiplier) 83 | predictor.run(args.input_image) 84 | -------------------------------------------------------------------------------- /ppgan/apps/midas/resnext.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from __future__ import division 16 | from __future__ import print_function 17 | 18 | import paddle 19 | import paddle.nn as nn 20 | from paddle.vision.models.resnet import ResNet 21 | from paddle.vision.models.resnet import BottleneckBlock 22 | 23 | from paddle.utils.download import get_weights_path_from_url 24 | 25 | __all__ = ['resnext101_32x8d_wsl'] 26 | 27 | 28 | class ResNetEx(ResNet): 29 | """ResNet extention model, support ResNeXt. 30 | """ 31 | def __init__(self, 32 | block, 33 | depth, 34 | num_classes=1000, 35 | with_pool=True, 36 | groups=1, 37 | width_per_group=64): 38 | self.groups = groups 39 | self.base_width = width_per_group 40 | 41 | super(ResNetEx, self).__init__(block, depth, num_classes, with_pool) 42 | 43 | def _make_layer(self, block, planes, blocks, stride=1, dilate=False): 44 | norm_layer = self._norm_layer 45 | downsample = None 46 | previous_dilation = self.dilation 47 | if dilate: 48 | self.dilation *= stride 49 | stride = 1 50 | if stride != 1 or self.inplanes != planes * block.expansion: 51 | downsample = nn.Sequential( 52 | nn.Conv2D(self.inplanes, 53 | planes * block.expansion, 54 | 1, 55 | stride=stride, 56 | bias_attr=False), 57 | norm_layer(planes * block.expansion), 58 | ) 59 | 60 | layers = [] 61 | layers.append( 62 | block(self.inplanes, planes, stride, downsample, self.groups, 63 | self.base_width, previous_dilation, norm_layer)) 64 | self.inplanes = planes * block.expansion 65 | for _ in range(1, blocks): 66 | layers.append( 67 | block(self.inplanes, 68 | planes, 69 | groups=self.groups, 70 | base_width=self.base_width, 71 | norm_layer=norm_layer)) 72 | 73 | return nn.Sequential(*layers) 74 | 75 | 76 | def _resnext(arch, Block, depth, **kwargs): 77 | model = ResNetEx(Block, depth, **kwargs) 78 | return model 79 | 80 | 81 | def resnext101_32x8d_wsl(**kwargs): 82 | """ResNet101 32x8d wsl model 83 | """ 84 | kwargs['groups'] = 32 85 | kwargs['width_per_group'] = 8 86 | return _resnext('resnet101_32x8d', BottleneckBlock, 101, **kwargs) 87 | -------------------------------------------------------------------------------- /ppgan/apps/photo2cartoon_predictor.py: -------------------------------------------------------------------------------- 1 | # copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import os 16 | 17 | import cv2 18 | from PIL import Image 19 | import numpy as np 20 | 21 | import paddle 22 | from paddle.utils.download import get_path_from_url 23 | from ppgan.faceutils.dlibutils import align_crop 24 | from ppgan.faceutils.face_segmentation import FaceSeg 25 | from ppgan.models.generators import ResnetUGATITP2CGenerator 26 | 27 | from .base_predictor import BasePredictor 28 | 29 | 30 | P2C_WEIGHT_URL = "https://paddlegan.bj.bcebos.com/models/photo2cartoon_genA2B_weight.pdparams" 31 | 32 | 33 | class Photo2CartoonPredictor(BasePredictor): 34 | def __init__(self, output_path='output', weight_path=None): 35 | self.output_path = output_path 36 | if not os.path.exists(self.output_path): 37 | os.makedirs(self.output_path) 38 | 39 | if weight_path is None: 40 | cur_path = os.path.abspath(os.path.dirname(__file__)) 41 | weight_path = get_path_from_url(P2C_WEIGHT_URL, cur_path) 42 | 43 | self.genA2B = ResnetUGATITP2CGenerator() 44 | params = paddle.load(weight_path) 45 | self.genA2B.set_state_dict(params) 46 | self.genA2B.eval() 47 | 48 | self.faceseg = FaceSeg() 49 | 50 | def run(self, image_path): 51 | image = Image.open(image_path) 52 | face_image = align_crop(image) 53 | face_mask = self.faceseg(face_image) 54 | 55 | face_image = cv2.resize(face_image, (256, 256), interpolation=cv2.INTER_AREA) 56 | face_mask = cv2.resize(face_mask, (256, 256))[:, :, np.newaxis] / 255. 57 | face = (face_image * face_mask + (1 - face_mask) * 255) / 127.5 - 1 58 | 59 | face = np.transpose(face[np.newaxis, :, :, :], (0, 3, 1, 2)).astype(np.float32) 60 | face = paddle.to_tensor(face) 61 | 62 | # inference 63 | with paddle.no_grad(): 64 | cartoon = self.genA2B(face)[0][0] 65 | 66 | # post-process 67 | cartoon = np.transpose(cartoon.numpy(), (1, 2, 0)) 68 | cartoon = (cartoon + 1) * 127.5 69 | cartoon = (cartoon * face_mask + (1 - face_mask) * 255).astype(np.uint8) 70 | 71 | pnoto_save_path = os.path.join(self.output_path, 'p2c_photo.png') 72 | cv2.imwrite(pnoto_save_path, cv2.cvtColor(face_image, cv2.COLOR_RGB2BGR)) 73 | cartoon_save_path = os.path.join(self.output_path, 'p2c_cartoon.png') 74 | cv2.imwrite(cartoon_save_path, cv2.cvtColor(cartoon, cv2.COLOR_RGB2BGR)) 75 | 76 | print("Cartoon image has been saved at '{}'.".format(cartoon_save_path)) 77 | return cartoon 78 | -------------------------------------------------------------------------------- /ppgan/faceutils/face_detection/utils.py: -------------------------------------------------------------------------------- 1 | import time 2 | import paddle 3 | import math 4 | import numpy as np 5 | import cv2 6 | 7 | 8 | def transform(point, center, scale, resolution, invert=False): 9 | """Generate and affine transformation matrix. 10 | 11 | Given a set of points, a center, a scale and a targer resolution, the 12 | function generates and affine transformation matrix. If invert is ``True`` 13 | it will produce the inverse transformation. 14 | 15 | Args: 16 | point {paddle.tensor} -- the input 2D point 17 | center {paddle.tensor or numpy.array} -- the center around which to perform the transformations 18 | scale {float} -- the scale of the face/object 19 | resolution {float} -- the output resolution 20 | invert {bool} -- define wherever the function should produce the direct or the 21 | inverse transformation matrix (default: {False}) 22 | """ 23 | _pt = paddle.ones([3]) 24 | _pt[0] = point[0] 25 | _pt[1] = point[1] 26 | 27 | h = 200.0 * scale 28 | t = paddle.eye(3) 29 | t[0, 0] = resolution / h 30 | t[1, 1] = resolution / h 31 | t[0, 2] = resolution * (-center[0] / h + 0.5) 32 | t[1, 2] = resolution * (-center[1] / h + 0.5) 33 | 34 | if invert: 35 | t = paddle.inverse(t) 36 | 37 | new_point = (paddle.matmul(t, _pt))[0:2] 38 | 39 | return new_point.astype('int32') 40 | 41 | 42 | def crop(image, center, scale, resolution=256.0): 43 | """Center crops an image or set of heatmaps 44 | 45 | Args: 46 | image {numpy.array} -- an rgb image 47 | center {numpy.array} -- the center of the object, usually the same as of the bounding box 48 | scale {float} -- scale of the face 49 | resolution {float} -- the size of the output cropped image (default: {256.0}) 50 | 51 | """ 52 | """ Crops the image around the center. Input is expected to be an np.ndarray """ 53 | ul = transform([1, 1], center, scale, resolution, True) 54 | ul = ul.numpy() 55 | br = transform([resolution, resolution], center, scale, resolution, True) 56 | br = br.numpy() 57 | if image.ndim > 2: 58 | newDim = np.array([br[1] - ul[1], br[0] - ul[0], image.shape[2]], 59 | dtype=np.int32) 60 | newImg = np.zeros(newDim, dtype=np.uint8) 61 | else: 62 | newDim = np.array([br[1] - ul[1], br[0] - ul[0]], dtype=np.int) 63 | newImg = np.zeros(newDim, dtype=np.uint8) 64 | ht = image.shape[0] 65 | wd = image.shape[1] 66 | newX = np.array( 67 | [max(1, -ul[0] + 1), min(br[0], wd) - ul[0]], dtype=np.int32) 68 | newY = np.array( 69 | [max(1, -ul[1] + 1), min(br[1], ht) - ul[1]], dtype=np.int32) 70 | oldX = np.array([max(1, ul[0] + 1), min(br[0], wd)], dtype=np.int32) 71 | oldY = np.array([max(1, ul[1] + 1), min(br[1], ht)], dtype=np.int32) 72 | newImg[newY[0] - 1:newY[1], 73 | newX[0] - 1:newX[1]] = image[oldY[0] - 1:oldY[1], 74 | oldX[0] - 1:oldX[1], :] 75 | newImg = cv2.resize(newImg, 76 | dsize=(int(resolution), int(resolution)), 77 | interpolation=cv2.INTER_LINEAR) 78 | return newImg 79 | -------------------------------------------------------------------------------- /ppgan/models/mpr_model.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import paddle 16 | import paddle.nn as nn 17 | 18 | from .builder import MODELS 19 | from .base_model import BaseModel 20 | from .generators.builder import build_generator 21 | from .criterions.builder import build_criterion 22 | from ..modules.init import reset_parameters, init_weights 23 | 24 | 25 | @MODELS.register() 26 | class MPRModel(BaseModel): 27 | """MPR Model. 28 | 29 | Paper: MPR: Multi-Stage Progressive Image Restoration (CVPR 2021). 30 | https://arxiv.org/abs/2102.02808 31 | """ 32 | def __init__(self, generator, char_criterion=None, edge_criterion=None): 33 | """Initialize the MPR class. 34 | 35 | Args: 36 | generator (dict): config of generator. 37 | char_criterion (dict): config of char criterion. 38 | edge_criterion (dict): config of edge criterion. 39 | """ 40 | super(MPRModel, self).__init__(generator) 41 | self.current_iter = 1 42 | 43 | self.nets['generator'] = build_generator(generator) 44 | init_weights(self.nets['generator']) 45 | 46 | if char_criterion: 47 | self.char_criterion = build_criterion(char_criterion) 48 | if edge_criterion: 49 | self.edge_criterion = build_criterion(edge_criterion) 50 | 51 | def setup_input(self, input): 52 | self.target = input[0] 53 | self.input_ = input[1] 54 | 55 | def train_iter(self, optims=None): 56 | optims['optim'].clear_gradients() 57 | 58 | restored = self.nets['generator'](self.input_) 59 | 60 | loss_char = [] 61 | loss_edge = [] 62 | 63 | for i in range(len(restored)): 64 | loss_char.append(self.char_criterion(restored[i], self.target)) 65 | loss_edge.append(self.edge_criterion(restored[i], self.target)) 66 | loss_char = paddle.stack(loss_char) 67 | loss_edge = paddle.stack(loss_edge) 68 | loss_char = paddle.sum(loss_char) 69 | loss_edge = paddle.sum(loss_edge) 70 | 71 | loss = (loss_char) + (0.05 * loss_edge) 72 | 73 | loss.backward() 74 | optims['optim'].step() 75 | self.losses['loss'] = loss.numpy() 76 | 77 | def forward(self): 78 | """Run forward pass; called by both functions and .""" 79 | pass 80 | 81 | 82 | def init_edvr_weight(net): 83 | def reset_func(m): 84 | if hasattr(m, 'weight') and (not isinstance( 85 | m, (nn.BatchNorm, nn.BatchNorm2D))): 86 | reset_parameters(m) 87 | 88 | net.apply(reset_func) 89 | -------------------------------------------------------------------------------- /ppgan/utils/image_pool.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import random 16 | import paddle 17 | 18 | 19 | class ImagePool(): 20 | """This class implements an image buffer that stores previously generated images. 21 | 22 | This buffer enables us to update discriminators using a history of generated images 23 | rather than the ones produced by the latest generators. 24 | """ 25 | def __init__(self, pool_size): 26 | """Initialize the ImagePool class 27 | 28 | Parameters: 29 | pool_size (int) -- the size of image buffer, if pool_size=0, no buffer will be created 30 | """ 31 | self.pool_size = pool_size 32 | if self.pool_size > 0: # create an empty pool 33 | self.num_imgs = 0 34 | self.images = [] 35 | 36 | def query(self, images): 37 | """Return an image from the pool. 38 | 39 | Parameters: 40 | images: the latest generated images from the generator 41 | 42 | Returns images from the buffer. 43 | 44 | By 50/100, the buffer will return input images. 45 | By 50/100, the buffer will return images previously stored in the buffer, 46 | and insert the current images to the buffer. 47 | """ 48 | if self.pool_size == 0: # if the buffer size is 0, do nothing 49 | return images 50 | return_images = [] 51 | for image in images: 52 | image = paddle.unsqueeze(image, 0) 53 | if self.num_imgs < self.pool_size: # if the buffer is not full; keep inserting current images to the buffer 54 | self.num_imgs = self.num_imgs + 1 55 | self.images.append(image) 56 | return_images.append(image) 57 | else: 58 | p = random.uniform(0, 1) 59 | if p > 0.5: # by 50% chance, the buffer will return a previously stored image, and insert the current image into the buffer 60 | random_id = random.randint(0, self.pool_size - 61 | 1) # randint is inclusive 62 | # FIXME: clone 63 | # tmp = (self.images[random_id]).detach() #.clone() 64 | tmp = self.images[random_id] #.clone() 65 | self.images[random_id] = image 66 | return_images.append(tmp) 67 | else: # by another 50% chance, the buffer will return the current image 68 | return_images.append(image) 69 | return_images = paddle.concat(return_images, 70 | 0) # collect all the images and return 71 | return return_images 72 | -------------------------------------------------------------------------------- /ppgan/utils/options.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import argparse 16 | 17 | 18 | def parse_args(): 19 | parser = argparse.ArgumentParser(description='PaddleGAN') 20 | parser.add_argument('-c', 21 | '--config-file', 22 | metavar="FILE", 23 | help='config file path') 24 | # cuda setting 25 | parser.add_argument('--no-cuda', 26 | action='store_true', 27 | default=False, 28 | help='disables CUDA training') 29 | # checkpoint and log 30 | parser.add_argument('--resume', 31 | type=str, 32 | default=None, 33 | help='put the path to resuming file if needed') 34 | parser.add_argument('--load', 35 | type=str, 36 | default=None, 37 | help='put the path to resuming file if needed') 38 | # for evaluation 39 | parser.add_argument('--val-interval', 40 | type=int, 41 | default=1, 42 | help='run validation every interval') 43 | parser.add_argument('--evaluate-only', 44 | action='store_true', 45 | default=False, 46 | help='skip validation during training') 47 | # config options 48 | parser.add_argument("-o", 49 | "--opt", 50 | nargs='+', 51 | help="set configuration options") 52 | 53 | #for inference 54 | parser.add_argument("--source_path", 55 | default="", 56 | metavar="FILE", 57 | help="path to source image") 58 | parser.add_argument("--reference_dir", 59 | default="", 60 | help="path to reference images") 61 | parser.add_argument("--model_path", default=None, help="model for loading") 62 | 63 | # for profiler 64 | parser.add_argument('-p', 65 | '--profiler_options', 66 | type=str, 67 | default=None, 68 | help='The option of profiler, which should be in format \"key1=value1;key2=value2;key3=value3\".' 69 | ) 70 | # fix random numbers by setting seed 71 | parser.add_argument('--seed', 72 | type=int, 73 | default=None, 74 | help='fix random numbers by setting seed\".' 75 | ) 76 | args = parser.parse_args() 77 | 78 | return args 79 | -------------------------------------------------------------------------------- /ppgan/modules/caffevgg.py: -------------------------------------------------------------------------------- 1 | import paddle 2 | import paddle.nn as nn 3 | import numpy as np 4 | from ppgan.utils.download import get_path_from_url 5 | model_urls = { 6 | 'caffevgg19': ('https://paddlegan.bj.bcebos.com/models/vgg19_no_fc.npy', 7 | '8ea1ef2374f8684b6cea9f300849be81') 8 | } 9 | 10 | 11 | class CaffeVGG19(nn.Layer): 12 | cfg = [ 13 | 64, 64, 'M', 128, 128, 'M', 256, 256, 256, 256, 'M', 512, 512, 512, 512, 14 | 'M', 512, 512, 512, 512, 'M' 15 | ] 16 | 17 | def __init__(self, output_index: int = 26) -> None: 18 | super().__init__() 19 | arch = 'caffevgg19' 20 | weights_path = get_path_from_url(model_urls[arch][0], 21 | model_urls[arch][1]) 22 | data_dict: dict = np.load(weights_path, 23 | encoding='latin1', 24 | allow_pickle=True).item() 25 | self.features = self.make_layers(self.cfg, data_dict) 26 | del data_dict 27 | self.features = nn.Sequential(*self.features.sublayers()[:output_index]) 28 | mean = paddle.to_tensor([103.939, 116.779, 123.68]) 29 | self.mean = mean.unsqueeze(0).unsqueeze(-1).unsqueeze(-1) 30 | 31 | def _process(self, x): 32 | rgb = (x * 0.5 + 0.5) * 255 # value to 255 33 | bgr = paddle.stack((rgb[:, 2, :, :], rgb[:, 1, :, :], rgb[:, 0, :, :]), 34 | 1) # rgb to bgr 35 | return bgr - self.mean # vgg norm 36 | 37 | def _forward_impl(self, x): 38 | x = self._process(x) 39 | # NOTE get output with out relu activation 40 | x = self.features(x) 41 | return x 42 | 43 | def forward(self, x): 44 | return self._forward_impl(x) 45 | 46 | @staticmethod 47 | def get_conv_filter(data_dict, name): 48 | return data_dict[name][0] 49 | 50 | @staticmethod 51 | def get_bias(data_dict, name): 52 | return data_dict[name][1] 53 | 54 | @staticmethod 55 | def get_fc_weight(data_dict, name): 56 | return data_dict[name][0] 57 | 58 | def make_layers(self, cfg, data_dict, batch_norm=False) -> nn.Sequential: 59 | layers = [] 60 | in_channels = 3 61 | block = 1 62 | number = 1 63 | for v in cfg: 64 | if v == 'M': 65 | layers += [nn.MaxPool2D(kernel_size=2, stride=2)] 66 | block += 1 67 | number = 1 68 | else: 69 | conv2d = nn.Conv2D(in_channels, v, kernel_size=3, padding=1) 70 | """ set value """ 71 | weight = paddle.to_tensor( 72 | self.get_conv_filter(data_dict, f'conv{block}_{number}')) 73 | weight = weight.transpose((3, 2, 0, 1)) 74 | bias = paddle.to_tensor( 75 | self.get_bias(data_dict, f'conv{block}_{number}')) 76 | conv2d.weight.set_value(weight) 77 | conv2d.bias.set_value(bias) 78 | number += 1 79 | if batch_norm: 80 | layers += [conv2d, nn.BatchNorm2D(v), nn.ReLU()] 81 | else: 82 | layers += [conv2d, nn.ReLU()] 83 | in_channels = v 84 | 85 | return nn.Sequential(*layers) 86 | -------------------------------------------------------------------------------- /ppgan/apps/midas/midas_net.py: -------------------------------------------------------------------------------- 1 | # Refer https://github.com/intel-isl/MiDaS 2 | """MidashNet: Network for monocular depth estimation trained by mixing several datasets. 3 | """ 4 | import numpy as np 5 | import paddle 6 | import paddle.nn as nn 7 | 8 | from .blocks import FeatureFusionBlock, _make_encoder 9 | 10 | 11 | class BaseModel(paddle.nn.Layer): 12 | def load(self, path): 13 | """Load model from file. 14 | 15 | Args: 16 | path (str): file path 17 | """ 18 | parameters = paddle.load(path) 19 | self.set_dict(parameters) 20 | 21 | 22 | class MidasNet(BaseModel): 23 | """Network for monocular depth estimation. 24 | """ 25 | def __init__(self, path=None, features=256, non_negative=True): 26 | """Init. 27 | 28 | Args: 29 | path (str, optional): Path to saved model. Defaults to None. 30 | features (int, optional): Number of features. Defaults to 256. 31 | backbone (str, optional): Backbone network for encoder. Defaults to resnet50 32 | """ 33 | print("Loading weights: ", path) 34 | 35 | super(MidasNet, self).__init__() 36 | 37 | use_pretrained = False if path is None else True 38 | 39 | self.pretrained, self.scratch = _make_encoder( 40 | backbone="resnext101_wsl", 41 | features=features, 42 | use_pretrained=use_pretrained) 43 | 44 | self.scratch.refinenet4 = FeatureFusionBlock(features) 45 | self.scratch.refinenet3 = FeatureFusionBlock(features) 46 | self.scratch.refinenet2 = FeatureFusionBlock(features) 47 | self.scratch.refinenet1 = FeatureFusionBlock(features) 48 | 49 | output_conv = [ 50 | nn.Conv2D(features, 128, kernel_size=3, stride=1, padding=1), 51 | nn.Upsample(scale_factor=2, mode="bilinear"), 52 | nn.Conv2D(128, 32, kernel_size=3, stride=1, padding=1), 53 | nn.ReLU(), 54 | nn.Conv2D(32, 1, kernel_size=1, stride=1, padding=0), 55 | nn.ReLU() if non_negative else nn.Identity(), 56 | ] 57 | if non_negative: 58 | output_conv.append(nn.ReLU()) 59 | 60 | self.scratch.output_conv = nn.Sequential(*output_conv) 61 | 62 | if path: 63 | self.load(path) 64 | 65 | def forward(self, x): 66 | """Forward pass. 67 | 68 | Args: 69 | x (tensor): input data (image) 70 | 71 | Returns: 72 | tensor: depth 73 | """ 74 | 75 | layer_1 = self.pretrained.layer1(x) 76 | layer_2 = self.pretrained.layer2(layer_1) 77 | layer_3 = self.pretrained.layer3(layer_2) 78 | layer_4 = self.pretrained.layer4(layer_3) 79 | 80 | layer_1_rn = self.scratch.layer1_rn(layer_1) 81 | layer_2_rn = self.scratch.layer2_rn(layer_2) 82 | layer_3_rn = self.scratch.layer3_rn(layer_3) 83 | layer_4_rn = self.scratch.layer4_rn(layer_4) 84 | 85 | path_4 = self.scratch.refinenet4(layer_4_rn) 86 | path_3 = self.scratch.refinenet3(path_4, layer_3_rn) 87 | path_2 = self.scratch.refinenet2(path_3, layer_2_rn) 88 | path_1 = self.scratch.refinenet1(path_2, layer_1_rn) 89 | 90 | out = self.scratch.output_conv(path_1) 91 | 92 | return paddle.squeeze(out, axis=1) 93 | -------------------------------------------------------------------------------- /ppgan/datasets/unpaired_dataset.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import random 16 | import os.path 17 | 18 | from .base_dataset import BaseDataset 19 | from .builder import DATASETS 20 | 21 | 22 | @DATASETS.register() 23 | class UnpairedDataset(BaseDataset): 24 | """ 25 | """ 26 | def __init__(self, dataroot_a, dataroot_b, max_size, is_train, preprocess): 27 | """Initialize unpaired dataset class. 28 | 29 | Args: 30 | dataroot_a (str): Directory of dataset a. 31 | dataroot_b (str): Directory of dataset b. 32 | max_size (int): max size of dataset size. 33 | is_train (int): whether in train mode. 34 | preprocess (list[dict]): A sequence of data preprocess config. 35 | 36 | """ 37 | super(UnpairedDataset, self).__init__(preprocess) 38 | self.dir_A = os.path.join(dataroot_a) 39 | self.dir_B = os.path.join(dataroot_b) 40 | self.is_train = is_train 41 | self.data_infos_a = self.prepare_data_infos(self.dir_A) 42 | self.data_infos_b = self.prepare_data_infos(self.dir_B) 43 | self.size_a = len(self.data_infos_a) 44 | self.size_b = len(self.data_infos_b) 45 | 46 | def prepare_data_infos(self, dataroot): 47 | """Load unpaired image paths of one domain. 48 | 49 | Args: 50 | dataroot (str): Path to the folder root for unpaired images of 51 | one domain. 52 | 53 | Returns: 54 | list[dict]: List that contains unpaired image paths of one domain. 55 | """ 56 | data_infos = [] 57 | paths = sorted(self.scan_folder(dataroot)) 58 | for path in paths: 59 | data_infos.append(dict(path=path)) 60 | return data_infos 61 | 62 | def __getitem__(self, idx): 63 | if self.is_train: 64 | img_a_path = self.data_infos_a[idx % self.size_a]['path'] 65 | idx_b = random.randint(0, self.size_b - 1) 66 | img_b_path = self.data_infos_b[idx_b]['path'] 67 | datas = dict(A_path=img_a_path, B_path=img_b_path) 68 | else: 69 | img_a_path = self.data_infos_a[idx % self.size_a]['path'] 70 | img_b_path = self.data_infos_b[idx % self.size_b]['path'] 71 | datas = dict(A_path=img_a_path, B_path=img_b_path) 72 | 73 | if self.preprocess: 74 | datas = self.preprocess(datas) 75 | 76 | return datas 77 | 78 | def __len__(self): 79 | """Return the total number of images in the dataset. 80 | 81 | As we have two datasets with potentially different number of images, 82 | we take a maximum of 83 | """ 84 | return max(self.size_a, self.size_b) 85 | -------------------------------------------------------------------------------- /ppgan/faceutils/face_enhancement/face_enhance.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import paddle 16 | import paddle.nn as nn 17 | import math 18 | import cv2 19 | import numpy as np 20 | from ppgan.utils.download import get_path_from_url 21 | from ppgan.models.generators import GPEN 22 | from ppgan.faceutils.face_detection.detection.blazeface.utils import * 23 | 24 | GPEN_weights = 'https://paddlegan.bj.bcebos.com/models/GPEN-512.pdparams' 25 | 26 | 27 | class FaceEnhancement(object): 28 | def __init__(self, 29 | path_to_enhance=None, 30 | size = 512, 31 | batch_size=1 32 | ): 33 | super(FaceEnhancement, self).__init__() 34 | 35 | # Initialise the face detector 36 | if path_to_enhance is None: 37 | model_weights_path = get_path_from_url(GPEN_weights) 38 | model_weights = paddle.load(model_weights_path) 39 | else: 40 | model_weights = paddle.load(path_to_enhance) 41 | 42 | self.face_enhance = GPEN(size=512, style_dim=512, n_mlp=8) 43 | self.face_enhance.load_dict(model_weights) 44 | self.face_enhance.eval() 45 | self.size = size 46 | self.mask = np.zeros((512, 512), np.float32) 47 | cv2.rectangle(self.mask, (26, 26), (486, 486), (1, 1, 1), -1, cv2.LINE_AA) 48 | self.mask = cv2.GaussianBlur(self.mask, (101, 101), 11) 49 | self.mask = cv2.GaussianBlur(self.mask, (101, 101), 11) 50 | self.mask = paddle.tile(paddle.to_tensor(self.mask).unsqueeze(0).unsqueeze(-1), repeat_times=[batch_size,1,1,3]).numpy() 51 | 52 | 53 | def enhance_from_image(self, img): 54 | if isinstance(img, np.ndarray): 55 | img, _ = resize_and_crop_image(img, 512) 56 | img = paddle.to_tensor(img).transpose([2, 0, 1]) 57 | else: 58 | assert img.shape == [3, 512, 512] 59 | return self.enhance_from_batch(img.unsqueeze(0))[0] 60 | 61 | def enhance_from_batch(self, img): 62 | if isinstance(img, np.ndarray): 63 | img_ori, _ = resize_and_crop_batch(img, 512) 64 | img = paddle.to_tensor(img_ori).transpose([0, 3, 1, 2]) 65 | else: 66 | assert img.shape[1:] == [3, 512, 512] 67 | img_ori = img.transpose([0, 2, 3, 1]).numpy() 68 | img_t = (img/255. - 0.5) / 0.5 69 | 70 | with paddle.no_grad(): 71 | out, __ = self.face_enhance(img_t) 72 | 73 | image_tensor = out * 0.5 + 0.5 74 | image_tensor = image_tensor.transpose([0, 2, 3, 1]) # RGB 75 | image_numpy = paddle.clip(image_tensor, 0, 1) * 255.0 76 | 77 | out = image_numpy.astype(np.uint8).cpu().numpy() 78 | return out * self.mask + (1-self.mask) * img_ori 79 | -------------------------------------------------------------------------------- /ppgan/models/sr_model.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import paddle 16 | import paddle.nn as nn 17 | 18 | from .generators.builder import build_generator 19 | from .criterions.builder import build_criterion 20 | from .base_model import BaseModel 21 | from .builder import MODELS 22 | from ..utils.visual import tensor2img 23 | from ..modules.init import reset_parameters 24 | 25 | 26 | @MODELS.register() 27 | class BaseSRModel(BaseModel): 28 | """Base SR model for single image super-resolution. 29 | """ 30 | def __init__(self, generator, pixel_criterion=None, use_init_weight=False): 31 | """ 32 | Args: 33 | generator (dict): config of generator. 34 | pixel_criterion (dict): config of pixel criterion. 35 | """ 36 | super(BaseSRModel, self).__init__() 37 | 38 | self.nets['generator'] = build_generator(generator) 39 | 40 | if pixel_criterion: 41 | self.pixel_criterion = build_criterion(pixel_criterion) 42 | if use_init_weight: 43 | init_sr_weight(self.nets['generator']) 44 | 45 | def setup_input(self, input): 46 | self.lq = paddle.to_tensor(input['lq']) 47 | self.visual_items['lq'] = self.lq 48 | if 'gt' in input: 49 | self.gt = paddle.to_tensor(input['gt']) 50 | self.visual_items['gt'] = self.gt 51 | self.image_paths = input['lq_path'] 52 | 53 | def forward(self): 54 | pass 55 | 56 | def train_iter(self, optims=None): 57 | optims['optim'].clear_grad() 58 | 59 | self.output = self.nets['generator'](self.lq) 60 | self.visual_items['output'] = self.output 61 | # pixel loss 62 | loss_pixel = self.pixel_criterion(self.output, self.gt) 63 | self.losses['loss_pixel'] = loss_pixel 64 | 65 | loss_pixel.backward() 66 | optims['optim'].step() 67 | 68 | def test_iter(self, metrics=None): 69 | self.nets['generator'].eval() 70 | with paddle.no_grad(): 71 | self.output = self.nets['generator'](self.lq) 72 | self.visual_items['output'] = self.output 73 | self.nets['generator'].train() 74 | 75 | out_img = [] 76 | gt_img = [] 77 | for out_tensor, gt_tensor in zip(self.output, self.gt): 78 | out_img.append(tensor2img(out_tensor, (0., 1.))) 79 | gt_img.append(tensor2img(gt_tensor, (0., 1.))) 80 | 81 | if metrics is not None: 82 | for metric in metrics.values(): 83 | metric.update(out_img, gt_img) 84 | 85 | 86 | def init_sr_weight(net): 87 | def reset_func(m): 88 | if hasattr(m, 'weight') and (not isinstance( 89 | m, (nn.BatchNorm, nn.BatchNorm2D))): 90 | reset_parameters(m) 91 | 92 | net.apply(reset_func) 93 | -------------------------------------------------------------------------------- /applications/tools/styleganv2mixing.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import argparse 16 | 17 | import paddle 18 | from ppgan.apps import StyleGANv2MixingPredictor 19 | 20 | if __name__ == "__main__": 21 | parser = argparse.ArgumentParser() 22 | parser.add_argument("--latent1", 23 | type=str, 24 | help="path to first image latent codes") 25 | 26 | parser.add_argument("--latent2", 27 | type=str, 28 | help="path to second image latent codes") 29 | 30 | parser.add_argument( 31 | "--weights", 32 | type=float, 33 | nargs="+", 34 | default=[0.5] * 18, 35 | help="different weights at each level of two latent codes") 36 | 37 | parser.add_argument("--output_path", 38 | type=str, 39 | default='output_dir', 40 | help="path to output image dir") 41 | 42 | parser.add_argument("--weight_path", 43 | type=str, 44 | default=None, 45 | help="path to model checkpoint path") 46 | 47 | parser.add_argument("--model_type", 48 | type=str, 49 | default=None, 50 | help="type of model for loading pretrained model") 51 | 52 | parser.add_argument("--size", 53 | type=int, 54 | default=1024, 55 | help="resolution of output image") 56 | 57 | parser.add_argument("--style_dim", 58 | type=int, 59 | default=512, 60 | help="number of style dimension") 61 | 62 | parser.add_argument("--n_mlp", 63 | type=int, 64 | default=8, 65 | help="number of mlp layer depth") 66 | 67 | parser.add_argument("--channel_multiplier", 68 | type=int, 69 | default=2, 70 | help="number of channel multiplier") 71 | 72 | parser.add_argument("--cpu", 73 | dest="cpu", 74 | action="store_true", 75 | help="cpu mode.") 76 | 77 | args = parser.parse_args() 78 | 79 | if args.cpu: 80 | paddle.set_device('cpu') 81 | 82 | predictor = StyleGANv2MixingPredictor( 83 | output_path=args.output_path, 84 | weight_path=args.weight_path, 85 | model_type=args.model_type, 86 | seed=None, 87 | size=args.size, 88 | style_dim=args.style_dim, 89 | n_mlp=args.n_mlp, 90 | channel_multiplier=args.channel_multiplier) 91 | predictor.run(args.latent1, args.latent2, args.weights) 92 | -------------------------------------------------------------------------------- /ppgan/faceutils/face_detection/api.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import paddle 16 | from enum import Enum 17 | import numpy as np 18 | import cv2 19 | 20 | from .utils import * 21 | import sys 22 | 23 | 24 | class LandmarksType(Enum): 25 | """Enum class defining the type of landmarks to detect. 26 | 27 | ``_2D`` - the detected points ``(x,y)`` are detected in a 2D space and follow the visible contour of the face 28 | ``_2halfD`` - this points represent the projection of the 3D points into 3D 29 | ``_3D`` - detect the points ``(x,y,z)``` in a 3D space 30 | 31 | """ 32 | _2D = 1 33 | _2halfD = 2 34 | _3D = 3 35 | 36 | 37 | class NetworkSize(Enum): 38 | # TINY = 1 39 | # SMALL = 2 40 | # MEDIUM = 3 41 | LARGE = 4 42 | 43 | def __new__(cls, value): 44 | member = object.__new__(cls) 45 | member._value_ = value 46 | return member 47 | 48 | def __int__(self): 49 | return self.value 50 | 51 | 52 | class FaceAlignment: 53 | def __init__(self, 54 | landmarks_type, 55 | network_size=NetworkSize.LARGE, 56 | flip_input=False, 57 | face_detector='sfd', 58 | verbose=False): 59 | self.flip_input = flip_input 60 | self.landmarks_type = landmarks_type 61 | self.verbose = verbose 62 | 63 | network_size = int(network_size) 64 | 65 | # Get the face detector 66 | face_detector_module = __import__( 67 | 'ppgan.faceutils.face_detection.detection.' + face_detector, 68 | globals(), locals(), [face_detector], 0) 69 | self.face_detector = face_detector_module.FaceDetector(verbose=verbose) 70 | 71 | def get_detections_for_batch(self, images): 72 | images = images[..., ::-1] 73 | detected_faces = self.face_detector.detect_from_batch(images.copy()) 74 | results = [] 75 | 76 | for i, d in enumerate(detected_faces): 77 | if len(d) == 0: 78 | results.append(None) 79 | continue 80 | d = d[0] 81 | d = np.clip(d, 0, None) 82 | 83 | x1, y1, x2, y2 = map(int, d[:4]) 84 | results.append((x1, y1, x2, y2)) 85 | 86 | return results 87 | 88 | def get_detections_for_image(self, images): 89 | images = images[..., ::-1] 90 | detected_faces = self.face_detector.detect_from_batch(images.copy()) 91 | results = [] 92 | 93 | for i, d in enumerate(detected_faces[0]): 94 | if len(d) == 0: 95 | results.append(None) 96 | continue 97 | d = np.clip(d, 0, None) 98 | 99 | x1, y1, x2, y2 = map(int, d[:-1]) 100 | results.append((x1, y1, x2, y2)) 101 | 102 | return results 103 | -------------------------------------------------------------------------------- /ppgan/models/edvr_model.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import paddle 16 | import paddle.nn as nn 17 | 18 | from .builder import MODELS 19 | from .sr_model import BaseSRModel 20 | from .generators.edvr import ResidualBlockNoBN, DCNPack 21 | from ..modules.init import reset_parameters 22 | 23 | 24 | @MODELS.register() 25 | class EDVRModel(BaseSRModel): 26 | """EDVR Model. 27 | 28 | Paper: EDVR: Video Restoration with Enhanced Deformable Convolutional Networks. 29 | """ 30 | def __init__(self, generator, tsa_iter, pixel_criterion=None): 31 | """Initialize the EDVR class. 32 | 33 | Args: 34 | generator (dict): config of generator. 35 | tsa_iter (dict): config of tsa_iter. 36 | pixel_criterion (dict): config of pixel criterion. 37 | """ 38 | super(EDVRModel, self).__init__(generator, pixel_criterion) 39 | self.tsa_iter = tsa_iter 40 | self.current_iter = 1 41 | init_edvr_weight(self.nets['generator']) 42 | 43 | def setup_input(self, input): 44 | self.lq = input['lq'] 45 | self.visual_items['lq'] = self.lq[:, 2, :, :, :] 46 | self.visual_items['lq-2'] = self.lq[:, 0, :, :, :] 47 | self.visual_items['lq-1'] = self.lq[:, 1, :, :, :] 48 | self.visual_items['lq+1'] = self.lq[:, 3, :, :, :] 49 | self.visual_items['lq+2'] = self.lq[:, 4, :, :, :] 50 | if 'gt' in input: 51 | self.gt = input['gt'] 52 | self.visual_items['gt'] = self.gt 53 | self.image_paths = input['lq_path'] 54 | 55 | def train_iter(self, optims=None): 56 | optims['optim'].clear_grad() 57 | if self.tsa_iter: 58 | if self.current_iter == 1: 59 | print('Only train TSA module for', self.tsa_iter, 'iters.') 60 | for name, param in self.nets['generator'].named_parameters(): 61 | if 'TSAModule' not in name: 62 | param.trainable = False 63 | elif self.current_iter == self.tsa_iter + 1: 64 | print('Train all the parameters.') 65 | for param in self.nets['generator'].parameters(): 66 | param.trainable = True 67 | self.output = self.nets['generator'](self.lq) 68 | self.visual_items['output'] = self.output 69 | # pixel loss 70 | loss_pixel = self.pixel_criterion(self.output, self.gt) 71 | self.losses['loss_pixel'] = loss_pixel 72 | 73 | loss_pixel.backward() 74 | optims['optim'].step() 75 | self.current_iter += 1 76 | 77 | 78 | def init_edvr_weight(net): 79 | def reset_func(m): 80 | if hasattr(m, 'weight') and (not isinstance( 81 | m, (nn.BatchNorm, nn.BatchNorm2D))) and ( 82 | not isinstance(m, ResidualBlockNoBN) and 83 | (not isinstance(m, DCNPack))): 84 | reset_parameters(m) 85 | 86 | net.apply(reset_func) 87 | -------------------------------------------------------------------------------- /ppgan/models/generators/gpen.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # code was heavily based on https://github.com/yangxy/GPEN 16 | 17 | import paddle 18 | import paddle.nn as nn 19 | import math 20 | from ppgan.models.generators import StyleGANv2Generator 21 | from ppgan.models.discriminators.discriminator_styleganv2 import ConvLayer 22 | from ppgan.modules.equalized import EqualLinear 23 | 24 | class GPEN(nn.Layer): 25 | def __init__( 26 | self, 27 | size, 28 | style_dim, 29 | n_mlp, 30 | channel_multiplier=2, 31 | blur_kernel=[1, 3, 3, 1], 32 | lr_mlp=0.01, 33 | ): 34 | super(GPEN, self).__init__() 35 | channels = { 36 | 4: 512, 37 | 8: 512, 38 | 16: 512, 39 | 32: 512, 40 | 64: 256 * channel_multiplier, 41 | 128: 128 * channel_multiplier, 42 | 256: 64 * channel_multiplier, 43 | 512: 32 * channel_multiplier, 44 | 1024: 16 * channel_multiplier, 45 | } 46 | 47 | self.log_size = int(math.log(size, 2)) 48 | self.generator = StyleGANv2Generator(size, 49 | style_dim, 50 | n_mlp, 51 | channel_multiplier=channel_multiplier, 52 | blur_kernel=blur_kernel, 53 | lr_mlp=lr_mlp, 54 | is_concat=True) 55 | 56 | conv = [ConvLayer(3, channels[size], 1)] 57 | self.ecd0 = nn.Sequential(*conv) 58 | in_channel = channels[size] 59 | 60 | self.names = ['ecd%d'%i for i in range(self.log_size-1)] 61 | for i in range(self.log_size, 2, -1): 62 | out_channel = channels[2 ** (i - 1)] 63 | conv = [ConvLayer(in_channel, out_channel, 3, downsample=True)] 64 | setattr(self, self.names[self.log_size-i+1], nn.Sequential(*conv)) 65 | in_channel = out_channel 66 | self.final_linear = nn.Sequential(EqualLinear(channels[4] * 4 * 4, style_dim, activation='fused_lrelu')) 67 | 68 | def forward(self, 69 | inputs, 70 | return_latents=False, 71 | inject_index=None, 72 | truncation=1, 73 | truncation_latent=None, 74 | input_is_latent=False, 75 | ): 76 | noise = [] 77 | for i in range(self.log_size-1): 78 | ecd = getattr(self, self.names[i]) 79 | inputs = ecd(inputs) 80 | noise.append(inputs) 81 | inputs = inputs.reshape([inputs.shape[0], -1]) 82 | outs = self.final_linear(inputs) 83 | outs = self.generator([outs], return_latents, inject_index, truncation, 84 | truncation_latent, input_is_latent, 85 | noise=noise[::-1]) 86 | return outs 87 | 88 | 89 | -------------------------------------------------------------------------------- /ppgan/models/discriminators/wav2lip_disc_qual.py: -------------------------------------------------------------------------------- 1 | import paddle 2 | from paddle import nn 3 | from paddle.nn import functional as F 4 | 5 | from ...modules.conv import ConvBNRelu, NonNormConv2d, Conv2dTransposeRelu 6 | from .builder import DISCRIMINATORS 7 | 8 | 9 | @DISCRIMINATORS.register() 10 | class Wav2LipDiscQual(nn.Layer): 11 | def __init__(self): 12 | super(Wav2LipDiscQual, self).__init__() 13 | 14 | self.face_encoder_blocks = nn.LayerList([ 15 | nn.Sequential( 16 | NonNormConv2d(3, 32, kernel_size=7, stride=1, 17 | padding=3)), # 48,96 18 | nn.Sequential( 19 | NonNormConv2d(32, 64, kernel_size=5, stride=(1, 2), 20 | padding=2), # 48,48 21 | NonNormConv2d(64, 64, kernel_size=5, stride=1, padding=2)), 22 | nn.Sequential( 23 | NonNormConv2d(64, 128, kernel_size=5, stride=2, 24 | padding=2), # 24,24 25 | NonNormConv2d(128, 128, kernel_size=5, stride=1, padding=2)), 26 | nn.Sequential( 27 | NonNormConv2d(128, 256, kernel_size=5, stride=2, 28 | padding=2), # 12,12 29 | NonNormConv2d(256, 256, kernel_size=5, stride=1, padding=2)), 30 | nn.Sequential( 31 | NonNormConv2d(256, 512, kernel_size=3, stride=2, 32 | padding=1), # 6,6 33 | NonNormConv2d(512, 512, kernel_size=3, stride=1, padding=1)), 34 | nn.Sequential( 35 | NonNormConv2d(512, 512, kernel_size=3, stride=2, 36 | padding=1), # 3,3 37 | NonNormConv2d(512, 512, kernel_size=3, stride=1, padding=1), 38 | ), 39 | nn.Sequential( 40 | NonNormConv2d(512, 512, kernel_size=3, stride=1, 41 | padding=0), # 1, 1 42 | NonNormConv2d(512, 512, kernel_size=1, stride=1, padding=0)), 43 | ]) 44 | 45 | self.binary_pred = nn.Sequential( 46 | nn.Conv2D(512, 1, kernel_size=1, stride=1, padding=0), nn.Sigmoid()) 47 | self.label_noise = .0 48 | 49 | def get_lower_half(self, face_sequences): 50 | return face_sequences[:, :, face_sequences.shape[2] // 2:] 51 | 52 | def to_2d(self, face_sequences): 53 | B = face_sequences.shape[0] 54 | face_sequences = paddle.concat( 55 | [face_sequences[:, :, i] for i in range(face_sequences.shape[2])], 56 | axis=0) 57 | return face_sequences 58 | 59 | def perceptual_forward(self, false_face_sequences): 60 | false_face_sequences = self.to_2d(false_face_sequences) 61 | false_face_sequences = self.get_lower_half(false_face_sequences) 62 | 63 | false_feats = false_face_sequences 64 | for f in self.face_encoder_blocks: 65 | false_feats = f(false_feats) 66 | 67 | binary_pred = self.binary_pred(false_feats).reshape( 68 | (len(false_feats), -1)) 69 | 70 | false_pred_loss = F.binary_cross_entropy( 71 | binary_pred, paddle.ones((len(false_feats), 1))) 72 | 73 | return false_pred_loss 74 | 75 | def forward(self, face_sequences): 76 | face_sequences = self.to_2d(face_sequences) 77 | face_sequences = self.get_lower_half(face_sequences) 78 | 79 | x = face_sequences 80 | for f in self.face_encoder_blocks: 81 | x = f(x) 82 | 83 | return paddle.reshape(self.binary_pred(x), (len(x), -1)) 84 | --------------------------------------------------------------------------------