Denis commited on
Commit
2302223
0 Parent(s):
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .cog/tmp/build810670618/cog-0.0.1.dev-py3-none-any.whl +0 -0
  2. .cog/tmp/cog-0.0.1.dev-py3-none-any.whl +0 -0
  3. .gitattributes +1 -0
  4. .gitignore +2 -0
  5. LICENSE +21 -0
  6. README.md +308 -0
  7. __pycache__/predict.cpython-38.pyc +0 -0
  8. cog.yaml +24 -0
  9. configs/__init__.py +0 -0
  10. configs/__pycache__/__init__.cpython-38.pyc +0 -0
  11. configs/__pycache__/paths_config.cpython-38.pyc +0 -0
  12. configs/data_configs.py +13 -0
  13. configs/paths_config.py +12 -0
  14. configs/transforms_config.py +37 -0
  15. criteria/__init__.py +0 -0
  16. criteria/aging_loss.py +59 -0
  17. criteria/id_loss.py +55 -0
  18. criteria/lpips/__init__.py +0 -0
  19. criteria/lpips/lpips.py +35 -0
  20. criteria/lpips/networks.py +96 -0
  21. criteria/lpips/utils.py +30 -0
  22. criteria/w_norm.py +14 -0
  23. datasets/__init__.py +0 -0
  24. datasets/__pycache__/__init__.cpython-38.pyc +0 -0
  25. datasets/__pycache__/augmentations.cpython-38.pyc +0 -0
  26. datasets/augmentations.py +24 -0
  27. datasets/images_dataset.py +33 -0
  28. datasets/inference_dataset.py +29 -0
  29. environment/sam_env.yaml +36 -0
  30. licenses/LICENSE_InterDigitalInc +150 -0
  31. licenses/LICENSE_S-aiueo32 +25 -0
  32. licenses/LICENSE_TreB1eN +21 -0
  33. licenses/LICENSE_eladrich +21 -0
  34. licenses/LICENSE_lessw2020 +201 -0
  35. licenses/LICENSE_rosinality +21 -0
  36. models/__init__.py +0 -0
  37. models/__pycache__/__init__.cpython-38.pyc +0 -0
  38. models/__pycache__/psp.cpython-38.pyc +0 -0
  39. models/dex_vgg.py +65 -0
  40. models/encoders/__init__.py +0 -0
  41. models/encoders/__pycache__/__init__.cpython-38.pyc +0 -0
  42. models/encoders/__pycache__/helpers.cpython-38.pyc +0 -0
  43. models/encoders/__pycache__/psp_encoders.cpython-38.pyc +0 -0
  44. models/encoders/helpers.py +119 -0
  45. models/encoders/model_irse.py +48 -0
  46. models/encoders/psp_encoders.py +114 -0
  47. models/psp.py +131 -0
  48. models/stylegan2/__init__.py +0 -0
  49. models/stylegan2/__pycache__/__init__.cpython-38.pyc +0 -0
  50. models/stylegan2/__pycache__/model.cpython-38.pyc +0 -0
.cog/tmp/build810670618/cog-0.0.1.dev-py3-none-any.whl ADDED
Binary file (31.4 kB). View file
 
.cog/tmp/cog-0.0.1.dev-py3-none-any.whl ADDED
Binary file (13.5 kB). View file
 
.gitattributes ADDED
@@ -0,0 +1 @@
 
 
1
+ *.dat filter=lfs diff=lfs merge=lfs -text
.gitignore ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ docs/
2
+ output.*
LICENSE ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ MIT License
2
+
3
+ Copyright (c) 2021 Yuval Alaluf
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
README.md ADDED
@@ -0,0 +1,308 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Only a Matter of Style: Age Transformation Using a Style-Based Regression Model (SIGGRAPH 2021)
2
+
3
+ > The task of age transformation illustrates the change of an individual's appearance over time. Accurately modeling this complex transformation over an input facial image is extremely challenging as it requires making convincing and possibly large changes to facial features and head shape, while still preserving the input identity. In this work, we present an image-to-image translation method that learns to directly encode real facial images into the latent space of a pre-trained unconditional GAN (e.g., StyleGAN) subject to a given aging shift. We employ a pre-trained age regression network used to explicitly guide the encoder to generate the latent codes corresponding to the desired age. In this formulation, our method approaches the continuous aging process as a regression task between the input age and desired target age, providing fine-grained control on the generated image. Moreover, unlike other approaches that operate solely in the latent space using a prior on the path controlling age, our method learns a more disentangled, non-linear path. We demonstrate that the end-to-end nature of our approach, coupled with the rich semantic latent space of StyleGAN, allows for further editing of the generated images. Qualitative and quantitative evaluations show the advantages of our method compared to state-of-the-art approaches.
4
+
5
+ <a href="https://arxiv.org/abs/2102.02754"><img src="https://img.shields.io/badge/arXiv-2008.00951-b31b1b.svg" height=22.5></a>
6
+ <a href="https://opensource.org/licenses/MIT"><img src="https://img.shields.io/badge/License-MIT-yellow.svg" height=22.5></a>
7
+
8
+ <a href="https://www.youtube.com/watch?v=zDTUbtmUbG8"><img src="https://img.shields.io/static/v1?label=Two Minute Papers&message=SAM Video&color=red" height=22.5></a>
9
+ <a href="https://youtu.be/X_pYC_LtBFw"><img src="https://img.shields.io/static/v1?label=SIGGRAPH 2021 &message=5 Minute Video&color=red" height=22.5></a>
10
+ <a href="https://replicate.ai/yuval-alaluf/sam"><img src="https://img.shields.io/static/v1?label=Replicate&message=Demo and Docker Image&color=darkgreen" height=22.5></a>
11
+
12
+
13
+ Inference Notebook: &nbsp;<a href="http://colab.research.google.com/github/yuval-alaluf/SAM/blob/master/notebooks/inference_playground.ipynb"><img src="https://colab.research.google.com/assets/colab-badge.svg" height=22.5></a>
14
+ Animation Notebook: <a href="http://colab.research.google.com/github/yuval-alaluf/SAM/blob/master/notebooks/animation_inference_playground.ipynb"><img src="https://colab.research.google.com/assets/colab-badge.svg" height=22.5></a>
15
+
16
+
17
+ <p align="center">
18
+ <img src="docs/teaser.jpeg" width="800px"/>
19
+ </p>
20
+
21
+ ## Description
22
+ Official Implementation of our Style-based Age Manipulation (SAM) paper for both training and evaluation. SAM
23
+ allows modeling fine-grained age transformation using a single input facial image
24
+
25
+ <p align="center">
26
+ <img src="docs/2195.jpg" width="800px"/>
27
+ <img src="docs/1936.jpg" width="800px"/>
28
+ </p>
29
+
30
+
31
+ ## Getting Started
32
+ ### Prerequisites
33
+ - Linux or macOS
34
+ - NVIDIA GPU + CUDA CuDNN (CPU may be possible with some modifications, but is not inherently supported)
35
+ - Python 3
36
+
37
+ ### Installation
38
+ - Dependencies:
39
+ We recommend running this repository using [Anaconda](https://docs.anaconda.com/anaconda/install/).
40
+ All dependencies for defining the environment are provided in `environment/sam_env.yaml`.
41
+
42
+ ## Pretrained Models
43
+ Please download the pretrained aging model from the following links.
44
+
45
+ | Path | Description
46
+ | :--- | :----------
47
+ |[SAM](https://drive.google.com/file/d/1XyumF6_fdAxFmxpFcmPf-q84LU_22EMC/view?usp=sharing) | SAM trained on the FFHQ dataset for age transformation.
48
+
49
+ You can run this to download it to the right place:
50
+
51
+ ```
52
+ mkdir pretrained_models
53
+ pip install gdown
54
+ gdown "https://drive.google.com/u/0/uc?id=1XyumF6_fdAxFmxpFcmPf-q84LU_22EMC&export=download" -O pretrained_models/sam_ffhq_aging.pt
55
+ wget "https://github.com/italojs/facial-landmarks-recognition/raw/master/shape_predictor_68_face_landmarks.dat"
56
+ ```
57
+
58
+ In addition, we provide various auxiliary models needed for training your own SAM model from scratch.
59
+ This includes the pretrained pSp encoder model for generating the encodings of the input image and the aging classifier
60
+ used to compute the aging loss during training.
61
+
62
+ | Path | Description
63
+ | :--- | :----------
64
+ |[pSp Encoder](https://drive.google.com/file/d/1bMTNWkh5LArlaWSc_wa8VKyq2V42T2z0/view?usp=sharing) | pSp taken from [pixel2style2pixel](https://github.com/eladrich/pixel2style2pixel) trained on the FFHQ dataset for StyleGAN inversion.
65
+ |[FFHQ StyleGAN](https://drive.google.com/file/d/1EM87UquaoQmk17Q8d5kYIAHqu0dkYqdT/view?usp=sharing) | StyleGAN model pretrained on FFHQ taken from [rosinality](https://github.com/rosinality/stylegan2-pytorch) with 1024x1024 output resolution.
66
+ |[IR-SE50 Model](https://drive.google.com/file/d/1KW7bjndL3QG3sxBbZxreGHigcCCpsDgn/view?usp=sharing) | Pretrained IR-SE50 model taken from [TreB1eN](https://github.com/TreB1eN/InsightFace_Pytorch) for use in our ID loss during training.
67
+ |[VGG Age Classifier](https://drive.google.com/file/d/1atzjZm_dJrCmFWCqWlyspSpr3nI6Evsh/view?usp=sharing) | VGG age classifier from DEX and fine-tuned on the FFHQ-Aging dataset for use in our aging loss
68
+
69
+ By default, we assume that all auxiliary models are downloaded and saved to the directory `pretrained_models`.
70
+ However, you may use your own paths by changing the necessary values in `configs/path_configs.py`.
71
+
72
+ ## Training
73
+ ### Preparing your Data
74
+ Please refer to `configs/paths_config.py` to define the necessary data paths and model paths for training and inference.
75
+ Then, refer to `configs/data_configs.py` to define the source/target data paths for the train and test sets as well as the
76
+ transforms to be used for training and inference.
77
+
78
+ As an example, we can first go to `configs/paths_config.py` and define:
79
+ ```
80
+ dataset_paths = {
81
+ 'ffhq': '/path/to/ffhq/images256x256'
82
+ 'celeba_test': '/path/to/CelebAMask-HQ/test_img',
83
+ }
84
+ ```
85
+ Then, in `configs/data_configs.py`, we define:
86
+ ```
87
+ DATASETS = {
88
+ 'ffhq_aging': {
89
+ 'transforms': transforms_config.AgingTransforms,
90
+ 'train_source_root': dataset_paths['ffhq'],
91
+ 'train_target_root': dataset_paths['ffhq'],
92
+ 'test_source_root': dataset_paths['celeba_test'],
93
+ 'test_target_root': dataset_paths['celeba_test'],
94
+ }
95
+ }
96
+ ```
97
+ When defining the datasets for training and inference, we will use the values defined in the above dictionary.
98
+
99
+
100
+ ### Training SAM
101
+ The main training script can be found in `scripts/train.py`.
102
+ Intermediate training results are saved to `opts.exp_dir`. This includes checkpoints, train outputs, and test outputs.
103
+ Additionally, if you have tensorboard installed, you can visualize tensorboard logs in `opts.exp_dir/logs`.
104
+
105
+ Training SAM with the settings used in the paper can be done by running the following command:
106
+ ```
107
+ python scripts/train.py \
108
+ --dataset_type=ffhq_aging \
109
+ --exp_dir=/path/to/experiment \
110
+ --workers=6 \
111
+ --batch_size=6 \
112
+ --test_batch_size=6 \
113
+ --test_workers=6 \
114
+ --val_interval=2500 \
115
+ --save_interval=10000 \
116
+ --start_from_encoded_w_plus \
117
+ --id_lambda=0.1 \
118
+ --lpips_lambda=0.1 \
119
+ --lpips_lambda_aging=0.1 \
120
+ --lpips_lambda_crop=0.6 \
121
+ --l2_lambda=0.25 \
122
+ --l2_lambda_aging=0.25 \
123
+ --l2_lambda_crop=1 \
124
+ --w_norm_lambda=0.005 \
125
+ --aging_lambda=5 \
126
+ --cycle_lambda=1 \
127
+ --input_nc=4 \
128
+ --target_age=uniform_random \
129
+ --use_weighted_id_loss
130
+ ```
131
+
132
+ ### Additional Notes
133
+ - See `options/train_options.py` for all training-specific flags.
134
+ - Note that using the flag `--start_from_encoded_w_plus` requires you to specify the path to the pretrained pSp encoder.
135
+ By default, this path is taken from `configs.paths_config.model_paths['pretrained_psp']`.
136
+ - If you wish to resume from a specific checkpoint (e.g. a pretrained SAM model), you may do so using `--checkpoint_path`.
137
+
138
+
139
+ ## Notebooks
140
+ ### Inference Notebook
141
+ To help visualize the results of SAM we provide a Jupyter notebook found in `notebooks/inference_playground.ipynb`.
142
+ The notebook will download the pretrained aging model and run inference on the images found in `notebooks/images`.
143
+
144
+ In addition, [Replicate](https://replicate.ai/) have created a demo for SAM where you can easily upload an image and run SAM on a desired set of ages! Check
145
+ out the demo [here](https://replicate.ai/yuval-alaluf/sam).
146
+
147
+ ### MP4 Notebook
148
+ To show full lifespan results using SAM we provide an additional notebook `notebooks/animation_inference_playground.ipynb` that will
149
+ run aging on multiple ages between 0 and 100 and interpolate between the results to display full aging.
150
+ The results will be saved as an MP4 files in `notebooks/animations` showing the aging and de-aging results.
151
+
152
+ ## Testing
153
+ ### Inference
154
+ Having trained your model or if you're using a pretrained SAM model, you can use `scripts/inference.py` to run inference
155
+ on a set of images.
156
+ For example,
157
+ ```
158
+ python scripts/inference.py \
159
+ --exp_dir=/path/to/experiment \
160
+ --checkpoint_path=experiment/checkpoints/best_model.pt \
161
+ --data_path=/path/to/test_data \
162
+ --test_batch_size=4 \
163
+ --test_workers=4 \
164
+ --couple_outputs
165
+ --target_age=0,10,20,30,40,50,60,70,80
166
+ ```
167
+ Additional notes to consider:
168
+ - During inference, the options used during training are loaded from the saved checkpoint and are then updated using the
169
+ test options passed to the inference script.
170
+ - Adding the flag `--couple_outputs` will save an additional image containing the input and output images side-by-side in the sub-directory
171
+ `inference_coupled`. Otherwise, only the output image is saved to the sub-directory `inference_results`.
172
+ - In the above example, we will run age transformation with target ages 0,10,...,80.
173
+ - The results of each target age are saved to the sub-directories `inference_results/TARGET_AGE` and `inference_coupled/TARGET_AGE`.
174
+ - By default, the images will be saved at resolution of 1024x1024, the original output size of StyleGAN.
175
+ - If you wish to save outputs resized to resolutions of 256x256, you can do so by adding the flag `--resize_outputs`.
176
+
177
+ ### Side-by-Side Inference
178
+ The above inference script will save each aging result in a different sub-directory for each target age. Sometimes,
179
+ however, it is more convenient to save all aging results of a given input side-by-side like the following:
180
+
181
+ <p align="center">
182
+ <img src="docs/866.jpg" width="800px"/>
183
+ </p>
184
+
185
+ To do so, we provide a script `inference_side_by_side.py` that works in a similar manner as the regular inference script:
186
+ ```
187
+ python scripts/inference_side_by_side.py \
188
+ --exp_dir=/path/to/experiment \
189
+ --checkpoint_path=experiment/checkpoints/best_model.pt \
190
+ --data_path=/path/to/test_data \
191
+ --test_batch_size=4 \
192
+ --test_workers=4 \
193
+ --target_age=0,10,20,30,40,50,60,70,80
194
+ ```
195
+ Here, all aging results 0,10,...,80 will be save side-by-side with the original input image.
196
+
197
+ ### Reference-Guided Inference
198
+ In the paper, we demonstrated how one can perform style-mixing on the fine-level style inputs with a reference image
199
+ to control global features such as hair color. For example,
200
+
201
+ <p align="center">
202
+ <img src="docs/1005_style_mixing.jpg" width="800px"/>
203
+ </p>
204
+
205
+ To perform style mixing using reference images, we provide the script `reference_guided_inference.py`. Here,
206
+ we first perform aging using the specified target age(s). Then, style mixing is performed using the specified
207
+ reference images and the specified layers. For example, one can run:
208
+ ```
209
+ python scripts/reference_guided_inference.py \
210
+ --exp_dir=/path/to/experiment \
211
+ --checkpoint_path=experiment/checkpoints/best_model.pt \
212
+ --data_path=/path/to/test_data \
213
+ --test_batch_size=4 \
214
+ --test_workers=4 \
215
+ --ref_images_paths_file=/path/to/ref_list.txt \
216
+ --latent_mask=8,9 \
217
+ --target_age=50,60,70,80
218
+ ```
219
+ Here, the reference images should be specified in the file defined by `--ref_images_paths_file` and should have the
220
+ following format:
221
+ ```
222
+ /path/to/reference/1.jpg
223
+ /path/to/reference/2.jpg
224
+ /path/to/reference/3.jpg
225
+ /path/to/reference/4.jpg
226
+ /path/to/reference/5.jpg
227
+ ```
228
+ In the above example, we will aging using 4 different target ages. For each target age, we first transform the
229
+ test samples defined by `--data_path` and then perform style mixing on layers 8,9 defined by `--latent_mask`.
230
+ The results of each target age are saved in its own sub-directory.
231
+
232
+ ### Style Mixing
233
+ Instead of performing style mixing using a reference image, you can perform style mixing using randomly generated
234
+ w latent vectors by running the script `style_mixing.py`. This script works in a similar manner to the reference
235
+ guided inference except you do not need to specify the `--ref_images_paths_file` flag.
236
+
237
+ ## Repository structure
238
+ | Path | Description <img width=200>
239
+ | :--- | :---
240
+ | SAM | Repository root folder
241
+ | &boxvr;&nbsp; configs | Folder containing configs defining model/data paths and data transforms
242
+ | &boxvr;&nbsp; criteria | Folder containing various loss criterias for training
243
+ | &boxvr;&nbsp; datasets | Folder with various dataset objects and augmentations
244
+ | &boxvr;&nbsp; docs | Folder containing images displayed in the README
245
+ | &boxvr;&nbsp; environment | Folder containing Anaconda environment used in our experiments
246
+ | &boxvr; models | Folder containing all the models and training objects
247
+ | &boxv;&nbsp; &boxvr;&nbsp; encoders | Folder containing various architecture implementations
248
+ | &boxv;&nbsp; &boxvr;&nbsp; stylegan2 | StyleGAN2 model from [rosinality](https://github.com/rosinality/stylegan2-pytorch)
249
+ | &boxv;&nbsp; &boxvr;&nbsp; psp.py | Implementation of pSp encoder
250
+ | &boxv;&nbsp; &boxur;&nbsp; dex_vgg.py | Implementation of DEX VGG classifier used in computation of aging loss
251
+ | &boxvr;&nbsp; notebook | Folder with jupyter notebook containing SAM inference playground
252
+ | &boxvr;&nbsp; options | Folder with training and test command-line options
253
+ | &boxvr;&nbsp; scripts | Folder with running scripts for training and inference
254
+ | &boxvr;&nbsp; training | Folder with main training logic and Ranger implementation from [lessw2020](https://github.com/lessw2020/Ranger-Deep-Learning-Optimizer)
255
+ | &boxvr;&nbsp; utils | Folder with various utility functions
256
+ | <img width=300> | <img>
257
+
258
+
259
+ ## Credits
260
+ **StyleGAN2 model and implementation:**
261
+ https://github.com/rosinality/stylegan2-pytorch
262
+ Copyright (c) 2019 Kim Seonghyeon
263
+ License (MIT) https://github.com/rosinality/stylegan2-pytorch/blob/master/LICENSE
264
+
265
+ **IR-SE50 model and implementations:**
266
+ https://github.com/TreB1eN/InsightFace_Pytorch
267
+ Copyright (c) 2018 TreB1eN
268
+ License (MIT) https://github.com/TreB1eN/InsightFace_Pytorch/blob/master/LICENSE
269
+
270
+ **Ranger optimizer implementation:**
271
+ https://github.com/lessw2020/Ranger-Deep-Learning-Optimizer
272
+ License (Apache License 2.0) https://github.com/lessw2020/Ranger-Deep-Learning-Optimizer/blob/master/LICENSE
273
+
274
+ **LPIPS model and implementation:**
275
+ https://github.com/S-aiueo32/lpips-pytorch
276
+ Copyright (c) 2020, Sou Uchida
277
+ License (BSD 2-Clause) https://github.com/S-aiueo32/lpips-pytorch/blob/master/LICENSE
278
+
279
+ **DEX VGG model and implementation:**
280
+ https://github.com/InterDigitalInc/HRFAE
281
+ Copyright (c) 2020, InterDigital R&D France
282
+ https://github.com/InterDigitalInc/HRFAE/blob/master/LICENSE.txt
283
+
284
+ **pSp model and implementation:**
285
+ https://github.com/eladrich/pixel2style2pixel
286
+ Copyright (c) 2020 Elad Richardson, Yuval Alaluf
287
+ https://github.com/eladrich/pixel2style2pixel/blob/master/LICENSE
288
+
289
+ ## Acknowledgments
290
+ This code borrows heavily from [pixel2style2pixel](https://github.com/eladrich/pixel2style2pixel)
291
+
292
+ ## Citation
293
+ If you use this code for your research, please cite our paper <a href="https://arxiv.org/abs/2102.02754">Only a Matter of Style: Age Transformation Using a Style-Based Regression Model</a>:
294
+
295
+ ```
296
+ @article{alaluf2021matter,
297
+ author = {Alaluf, Yuval and Patashnik, Or and Cohen-Or, Daniel},
298
+ title = {Only a Matter of Style: Age Transformation Using a Style-Based Regression Model},
299
+ journal = {ACM Trans. Graph.},
300
+ issue_date = {August 2021},
301
+ volume = {40},
302
+ number = {4},
303
+ year = {2021},
304
+ articleno = {45},
305
+ publisher = {Association for Computing Machinery},
306
+ url = {https://doi.org/10.1145/3450626.3459805}
307
+ }
308
+ ```
__pycache__/predict.cpython-38.pyc ADDED
Binary file (3.15 kB). View file
 
cog.yaml ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ image: "r8.im/yuval-alaluf/sam"
2
+ build:
3
+ gpu: true
4
+ python_version: "3.8"
5
+ system_packages:
6
+ - "cmake"
7
+ - "libgl1-mesa-glx"
8
+ - "libglib2.0-0"
9
+ - "ninja-build"
10
+ python_packages:
11
+ - "Pillow==8.3.1"
12
+ - "cmake==3.21.1"
13
+ - "dlib==19.22.1"
14
+ - "imageio==2.9.0"
15
+ - "ipython==7.21.0"
16
+ - "matplotlib==3.1.3"
17
+ - "numpy==1.21.1"
18
+ - "opencv-python==4.5.3.56"
19
+ - "scipy==1.4.1"
20
+ - "tensorboard==2.2.1"
21
+ - "torch==1.8.0"
22
+ - "torchvision==0.9.0"
23
+ - "tqdm==4.42.1"
24
+ predict: "predict.py:Predictor"
configs/__init__.py ADDED
File without changes
configs/__pycache__/__init__.cpython-38.pyc ADDED
Binary file (115 Bytes). View file
 
configs/__pycache__/paths_config.cpython-38.pyc ADDED
Binary file (493 Bytes). View file
 
configs/data_configs.py ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from configs import transforms_config
2
+ from configs.paths_config import dataset_paths
3
+
4
+
5
+ DATASETS = {
6
+ 'ffhq_aging': {
7
+ 'transforms': transforms_config.AgingTransforms,
8
+ 'train_source_root': dataset_paths['ffhq'],
9
+ 'train_target_root': dataset_paths['ffhq'],
10
+ 'test_source_root': dataset_paths['celeba_test'],
11
+ 'test_target_root': dataset_paths['celeba_test'],
12
+ }
13
+ }
configs/paths_config.py ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ dataset_paths = {
2
+ 'celeba_test': '',
3
+ 'ffhq': '',
4
+ }
5
+
6
+ model_paths = {
7
+ 'pretrained_psp_encoder': 'pretrained_models/psp_ffhq_encode.pt',
8
+ 'ir_se50': 'pretrained_models/model_ir_se50.pth',
9
+ 'stylegan_ffhq': 'pretrained_models/stylegan2-ffhq-config-f.pt',
10
+ 'shape_predictor': 'shape_predictor_68_face_landmarks.dat',
11
+ 'age_predictor': 'pretrained_models/dex_age_classifier.pth'
12
+ }
configs/transforms_config.py ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from abc import abstractmethod
2
+ import torchvision.transforms as transforms
3
+
4
+
5
+ class TransformsConfig(object):
6
+
7
+ def __init__(self, opts):
8
+ self.opts = opts
9
+
10
+ @abstractmethod
11
+ def get_transforms(self):
12
+ pass
13
+
14
+
15
+ class AgingTransforms(TransformsConfig):
16
+
17
+ def __init__(self, opts):
18
+ super(AgingTransforms, self).__init__(opts)
19
+
20
+ def get_transforms(self):
21
+ transforms_dict = {
22
+ 'transform_gt_train': transforms.Compose([
23
+ transforms.Resize((256, 256)),
24
+ transforms.RandomHorizontalFlip(0.5),
25
+ transforms.ToTensor(),
26
+ transforms.Normalize([0.5, 0.5, 0.5], [0.5, 0.5, 0.5])]),
27
+ 'transform_source': None,
28
+ 'transform_test': transforms.Compose([
29
+ transforms.Resize((256, 256)),
30
+ transforms.ToTensor(),
31
+ transforms.Normalize([0.5, 0.5, 0.5], [0.5, 0.5, 0.5])]),
32
+ 'transform_inference': transforms.Compose([
33
+ transforms.Resize((256, 256)),
34
+ transforms.ToTensor(),
35
+ transforms.Normalize([0.5, 0.5, 0.5], [0.5, 0.5, 0.5])])
36
+ }
37
+ return transforms_dict
criteria/__init__.py ADDED
File without changes
criteria/aging_loss.py ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ from torch import nn
3
+ import torch.nn.functional as F
4
+
5
+ from configs.paths_config import model_paths
6
+ from models.dex_vgg import VGG
7
+
8
+
9
+ class AgingLoss(nn.Module):
10
+
11
+ def __init__(self, opts):
12
+ super(AgingLoss, self).__init__()
13
+ self.age_net = VGG()
14
+ ckpt = torch.load(model_paths['age_predictor'], map_location="cpu")['state_dict']
15
+ ckpt = {k.replace('-', '_'): v for k, v in ckpt.items()}
16
+ self.age_net.load_state_dict(ckpt)
17
+ self.age_net.cuda()
18
+ self.age_net.eval()
19
+ self.min_age = 0
20
+ self.max_age = 100
21
+ self.opts = opts
22
+
23
+ def __get_predicted_age(self, age_pb):
24
+ predict_age_pb = F.softmax(age_pb)
25
+ predict_age = torch.zeros(age_pb.size(0)).type_as(predict_age_pb)
26
+ for i in range(age_pb.size(0)):
27
+ for j in range(age_pb.size(1)):
28
+ predict_age[i] += j * predict_age_pb[i][j]
29
+ return predict_age
30
+
31
+ def extract_ages(self, x):
32
+ x = F.interpolate(x, size=(224, 224), mode='bilinear')
33
+ predict_age_pb = self.age_net(x)['fc8']
34
+ predicted_age = self.__get_predicted_age(predict_age_pb)
35
+ return predicted_age
36
+
37
+ def forward(self, y_hat, y, target_ages, id_logs, label=None):
38
+ n_samples = y.shape[0]
39
+
40
+ if id_logs is None:
41
+ id_logs = []
42
+
43
+ input_ages = self.extract_ages(y) / 100.
44
+ output_ages = self.extract_ages(y_hat) / 100.
45
+
46
+ for i in range(n_samples):
47
+ # if id logs for the same exists, update the dictionary
48
+ if len(id_logs) > i:
49
+ id_logs[i].update({f'input_age_{label}': float(input_ages[i]) * 100,
50
+ f'output_age_{label}': float(output_ages[i]) * 100,
51
+ f'target_age_{label}': float(target_ages[i]) * 100})
52
+ # otherwise, create a new entry for the sample
53
+ else:
54
+ id_logs.append({f'input_age_{label}': float(input_ages[i]) * 100,
55
+ f'output_age_{label}': float(output_ages[i]) * 100,
56
+ f'target_age_{label}': float(target_ages[i]) * 100})
57
+
58
+ loss = F.mse_loss(output_ages, target_ages)
59
+ return loss, id_logs
criteria/id_loss.py ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ from torch import nn
3
+ from configs.paths_config import model_paths
4
+ from models.encoders.model_irse import Backbone
5
+
6
+
7
+ class IDLoss(nn.Module):
8
+ def __init__(self):
9
+ super(IDLoss, self).__init__()
10
+ print('Loading ResNet ArcFace')
11
+ self.facenet = Backbone(input_size=112, num_layers=50, drop_ratio=0.6, mode='ir_se')
12
+ self.facenet.load_state_dict(torch.load(model_paths['ir_se50']))
13
+ self.face_pool = torch.nn.AdaptiveAvgPool2d((112, 112))
14
+ self.facenet.eval()
15
+
16
+ def extract_feats(self, x):
17
+ x = x[:, :, 35:223, 32:220] # Crop interesting region
18
+ x = self.face_pool(x)
19
+ x_feats = self.facenet(x)
20
+ return x_feats
21
+
22
+ def forward(self, y_hat, y, x, label=None, weights=None):
23
+ n_samples = x.shape[0]
24
+ x_feats = self.extract_feats(x)
25
+ y_feats = self.extract_feats(y)
26
+ y_hat_feats = self.extract_feats(y_hat)
27
+ y_feats = y_feats.detach()
28
+ total_loss = 0
29
+ sim_improvement = 0
30
+ id_logs = []
31
+ count = 0
32
+ for i in range(n_samples):
33
+ diff_target = y_hat_feats[i].dot(y_feats[i])
34
+ diff_input = y_hat_feats[i].dot(x_feats[i])
35
+ diff_views = y_feats[i].dot(x_feats[i])
36
+
37
+ if label is None:
38
+ id_logs.append({'diff_target': float(diff_target),
39
+ 'diff_input': float(diff_input),
40
+ 'diff_views': float(diff_views)})
41
+ else:
42
+ id_logs.append({f'diff_target_{label}': float(diff_target),
43
+ f'diff_input_{label}': float(diff_input),
44
+ f'diff_views_{label}': float(diff_views)})
45
+
46
+ loss = 1 - diff_target
47
+ if weights is not None:
48
+ loss = weights[i] * loss
49
+
50
+ total_loss += loss
51
+ id_diff = float(diff_target) - float(diff_views)
52
+ sim_improvement += id_diff
53
+ count += 1
54
+
55
+ return total_loss / count, sim_improvement / count, id_logs
criteria/lpips/__init__.py ADDED
File without changes
criteria/lpips/lpips.py ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ import torch.nn as nn
3
+
4
+ from criteria.lpips.networks import get_network, LinLayers
5
+ from criteria.lpips.utils import get_state_dict
6
+
7
+
8
+ class LPIPS(nn.Module):
9
+ r"""Creates a criterion that measures
10
+ Learned Perceptual Image Patch Similarity (LPIPS).
11
+ Arguments:
12
+ net_type (str): the network type to compare the features:
13
+ 'alex' | 'squeeze' | 'vgg'. Default: 'alex'.
14
+ version (str): the version of LPIPS. Default: 0.1.
15
+ """
16
+ def __init__(self, net_type: str = 'alex', version: str = '0.1'):
17
+
18
+ assert version in ['0.1'], 'v0.1 is only supported now'
19
+
20
+ super(LPIPS, self).__init__()
21
+
22
+ # pretrained network
23
+ self.net = get_network(net_type).to("cuda")
24
+
25
+ # linear layers
26
+ self.lin = LinLayers(self.net.n_channels_list).to("cuda")
27
+ self.lin.load_state_dict(get_state_dict(net_type, version))
28
+
29
+ def forward(self, x: torch.Tensor, y: torch.Tensor):
30
+ feat_x, feat_y = self.net(x), self.net(y)
31
+
32
+ diff = [(fx - fy) ** 2 for fx, fy in zip(feat_x, feat_y)]
33
+ res = [l(d).mean((2, 3), True) for d, l in zip(diff, self.lin)]
34
+
35
+ return torch.sum(torch.cat(res, 0)) / x.shape[0]
criteria/lpips/networks.py ADDED
@@ -0,0 +1,96 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from typing import Sequence
2
+
3
+ from itertools import chain
4
+
5
+ import torch
6
+ import torch.nn as nn
7
+ from torchvision import models
8
+
9
+ from criteria.lpips.utils import normalize_activation
10
+
11
+
12
+ def get_network(net_type: str):
13
+ if net_type == 'alex':
14
+ return AlexNet()
15
+ elif net_type == 'squeeze':
16
+ return SqueezeNet()
17
+ elif net_type == 'vgg':
18
+ return VGG16()
19
+ else:
20
+ raise NotImplementedError('choose net_type from [alex, squeeze, vgg].')
21
+
22
+
23
+ class LinLayers(nn.ModuleList):
24
+ def __init__(self, n_channels_list: Sequence[int]):
25
+ super(LinLayers, self).__init__([
26
+ nn.Sequential(
27
+ nn.Identity(),
28
+ nn.Conv2d(nc, 1, 1, 1, 0, bias=False)
29
+ ) for nc in n_channels_list
30
+ ])
31
+
32
+ for param in self.parameters():
33
+ param.requires_grad = False
34
+
35
+
36
+ class BaseNet(nn.Module):
37
+ def __init__(self):
38
+ super(BaseNet, self).__init__()
39
+
40
+ # register buffer
41
+ self.register_buffer(
42
+ 'mean', torch.Tensor([-.030, -.088, -.188])[None, :, None, None])
43
+ self.register_buffer(
44
+ 'std', torch.Tensor([.458, .448, .450])[None, :, None, None])
45
+
46
+ def set_requires_grad(self, state: bool):
47
+ for param in chain(self.parameters(), self.buffers()):
48
+ param.requires_grad = state
49
+
50
+ def z_score(self, x: torch.Tensor):
51
+ return (x - self.mean) / self.std
52
+
53
+ def forward(self, x: torch.Tensor):
54
+ x = self.z_score(x)
55
+
56
+ output = []
57
+ for i, (_, layer) in enumerate(self.layers._modules.items(), 1):
58
+ x = layer(x)
59
+ if i in self.target_layers:
60
+ output.append(normalize_activation(x))
61
+ if len(output) == len(self.target_layers):
62
+ break
63
+ return output
64
+
65
+
66
+ class SqueezeNet(BaseNet):
67
+ def __init__(self):
68
+ super(SqueezeNet, self).__init__()
69
+
70
+ self.layers = models.squeezenet1_1(True).features
71
+ self.target_layers = [2, 5, 8, 10, 11, 12, 13]
72
+ self.n_channels_list = [64, 128, 256, 384, 384, 512, 512]
73
+
74
+ self.set_requires_grad(False)
75
+
76
+
77
+ class AlexNet(BaseNet):
78
+ def __init__(self):
79
+ super(AlexNet, self).__init__()
80
+
81
+ self.layers = models.alexnet(True).features
82
+ self.target_layers = [2, 5, 8, 10, 12]
83
+ self.n_channels_list = [64, 192, 384, 256, 256]
84
+
85
+ self.set_requires_grad(False)
86
+
87
+
88
+ class VGG16(BaseNet):
89
+ def __init__(self):
90
+ super(VGG16, self).__init__()
91
+
92
+ self.layers = models.vgg16(True).features
93
+ self.target_layers = [4, 9, 16, 23, 30]
94
+ self.n_channels_list = [64, 128, 256, 512, 512]
95
+
96
+ self.set_requires_grad(False)
criteria/lpips/utils.py ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from collections import OrderedDict
2
+
3
+ import torch
4
+
5
+
6
+ def normalize_activation(x, eps=1e-10):
7
+ norm_factor = torch.sqrt(torch.sum(x ** 2, dim=1, keepdim=True))
8
+ return x / (norm_factor + eps)
9
+
10
+
11
+ def get_state_dict(net_type: str = 'alex', version: str = '0.1'):
12
+ # build url
13
+ url = 'https://raw.githubusercontent.com/richzhang/PerceptualSimilarity/' \
14
+ + f'master/lpips/weights/v{version}/{net_type}.pth'
15
+
16
+ # download
17
+ old_state_dict = torch.hub.load_state_dict_from_url(
18
+ url, progress=True,
19
+ map_location=None if torch.cuda.is_available() else torch.device('cpu')
20
+ )
21
+
22
+ # rename keys
23
+ new_state_dict = OrderedDict()
24
+ for key, val in old_state_dict.items():
25
+ new_key = key
26
+ new_key = new_key.replace('lin', '')
27
+ new_key = new_key.replace('model.', '')
28
+ new_state_dict[new_key] = val
29
+
30
+ return new_state_dict
criteria/w_norm.py ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ from torch import nn
3
+
4
+
5
+ class WNormLoss(nn.Module):
6
+
7
+ def __init__(self, opts):
8
+ super(WNormLoss, self).__init__()
9
+ self.opts = opts
10
+
11
+ def forward(self, latent, latent_avg=None):
12
+ if self.opts.start_from_latent_avg or self.opts.start_from_encoded_w_plus:
13
+ latent = latent - latent_avg
14
+ return torch.sum(latent.norm(2, dim=(1, 2))) / latent.shape[0]
datasets/__init__.py ADDED
File without changes
datasets/__pycache__/__init__.cpython-38.pyc ADDED
Binary file (116 Bytes). View file
 
datasets/__pycache__/augmentations.cpython-38.pyc ADDED
Binary file (1.18 kB). View file
 
datasets/augmentations.py ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+ import torch
3
+
4
+
5
+ class AgeTransformer(object):
6
+
7
+ def __init__(self, target_age):
8
+ self.target_age = target_age
9
+
10
+ def __call__(self, img):
11
+ img = self.add_aging_channel(img)
12
+ return img
13
+
14
+ def add_aging_channel(self, img):
15
+ target_age = self.__get_target_age()
16
+ target_age = int(target_age) / 100 # normalize aging amount to be in range [-1,1]
17
+ img = torch.cat((img, target_age * torch.ones((1, img.shape[1], img.shape[2]))))
18
+ return img
19
+
20
+ def __get_target_age(self):
21
+ if self.target_age == "uniform_random":
22
+ return np.random.randint(low=0., high=101, size=1)[0]
23
+ else:
24
+ return self.target_age
datasets/images_dataset.py ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from torch.utils.data import Dataset
2
+ from PIL import Image
3
+ from utils import data_utils
4
+
5
+
6
+ class ImagesDataset(Dataset):
7
+
8
+ def __init__(self, source_root, target_root, opts, target_transform=None, source_transform=None):
9
+ self.source_paths = sorted(data_utils.make_dataset(source_root))
10
+ self.target_paths = sorted(data_utils.make_dataset(target_root))
11
+ self.source_transform = source_transform
12
+ self.target_transform = target_transform
13
+ self.opts = opts
14
+
15
+ def __len__(self):
16
+ return len(self.source_paths)
17
+
18
+ def __getitem__(self, index):
19
+ from_path = self.source_paths[index]
20
+ from_im = Image.open(from_path)
21
+ from_im = from_im.convert('RGB') if self.opts.label_nc == 0 else from_im.convert('L')
22
+
23
+ to_path = self.target_paths[index]
24
+ to_im = Image.open(to_path).convert('RGB')
25
+ if self.target_transform:
26
+ to_im = self.target_transform(to_im)
27
+
28
+ if self.source_transform:
29
+ from_im = self.source_transform(from_im)
30
+ else:
31
+ from_im = to_im
32
+
33
+ return from_im, to_im
datasets/inference_dataset.py ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from torch.utils.data import Dataset
2
+ from PIL import Image
3
+ from utils import data_utils
4
+
5
+
6
+ class InferenceDataset(Dataset):
7
+
8
+ def __init__(self, root=None, paths_list=None, opts=None, transform=None, return_path=False):
9
+ if paths_list is None:
10
+ self.paths = sorted(data_utils.make_dataset(root))
11
+ else:
12
+ self.paths = data_utils.make_dataset_from_paths_list(paths_list)
13
+ self.transform = transform
14
+ self.opts = opts
15
+ self.return_path = return_path
16
+
17
+ def __len__(self):
18
+ return len(self.paths)
19
+
20
+ def __getitem__(self, index):
21
+ from_path = self.paths[index]
22
+ from_im = Image.open(from_path)
23
+ from_im = from_im.convert('RGB') if self.opts.label_nc == 0 else from_im.convert('L')
24
+ if self.transform:
25
+ from_im = self.transform(from_im)
26
+ if self.return_path:
27
+ return from_im, from_path
28
+ else:
29
+ return from_im
environment/sam_env.yaml ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ name: sam_env
2
+ channels:
3
+ - conda-forge
4
+ - defaults
5
+ dependencies:
6
+ - _libgcc_mutex=0.1=main
7
+ - ca-certificates=2020.4.5.1=hecc5488_0
8
+ - certifi=2020.4.5.1=py36h9f0ad1d_0
9
+ - libedit=3.1.20181209=hc058e9b_0
10
+ - libffi=3.2.1=hd88cf55_4
11
+ - libgcc-ng=9.1.0=hdf63c60_0
12
+ - libstdcxx-ng=9.1.0=hdf63c60_0
13
+ - ncurses=6.2=he6710b0_1
14
+ - ninja=1.10.0=hc9558a2_0
15
+ - openssl=1.1.1g=h516909a_0
16
+ - pip=20.0.2=py36_3
17
+ - python=3.6.7=h0371630_0
18
+ - python_abi=3.6=1_cp36m
19
+ - readline=7.0=h7b6447c_5
20
+ - setuptools=46.4.0=py36_0
21
+ - sqlite=3.31.1=h62c20be_1
22
+ - tk=8.6.8=hbc83047_0
23
+ - wheel=0.34.2=py36_0
24
+ - xz=5.2.5=h7b6447c_0
25
+ - zlib=1.2.11=h7b6447c_3
26
+ - pip:
27
+ - scipy==1.4.1
28
+ - matplotlib==3.2.1
29
+ - tqdm==4.46.0
30
+ - numpy==1.18.4
31
+ - opencv-python==4.2.0.34
32
+ - pillow==7.1.2
33
+ - tensorboard==2.2.1
34
+ - torch==1.6.0
35
+ - torchvision==0.4.2
36
+ prefix: ~/anaconda3/envs/sam_env
licenses/LICENSE_InterDigitalInc ADDED
@@ -0,0 +1,150 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ LIMITED SOFTWARE EVALUATION LICENSE AGREEMENT
2
+
3
+
4
+
5
+ This Limited Software Evaluation License Agreement (the “Agreement”) is entered into as of April 9th 2020, (“Effective Date”)
6
+
7
+ The following limited software evaluation license agreement (“the Agreement”) constitute an agreement between you (the “licensee”) and InterDigital R&D France, a French company existing and organized under the laws of France with its registered offices located at 975 avenue des champs blancs 35510 Cesson-Sévigné, FRANCE (hereinafter “InterDigital”)
8
+ This Agreement governs the download and use of the Software (as defined below). Your use of the Software is subject to the terms and conditions set forth in this Agreement. By installing, using, accessing or copying the Software, you hereby irrevocably accept the terms and conditions of this Agreement. If you do not accept all or parts of the terms and conditions of this Agreement you cannot install, use, access nor copy the Software
9
+
10
+ Article 1. Definitions
11
+
12
+ “Affiliate” as used herein shall mean any entity that, directly or indirectly, through one or more intermediates, is controlled by, controls, or is under common control with InterDigital or The Licensee, as the case may be. For purposes of this definition only, the term “control” means the possession of the power to direct or cause the direction of the management and policies of an entity, whether by ownership of voting stock or partnership interest, by contract, or otherwise, including direct or indirect ownership of more than fifty percent (50%) of the voting interest in the entity in question.
13
+
14
+ “Authorized Purpose” means any use of the Software for research on the Software and evaluation of the Software exclusively, and academic research using the Software without any commercial use. For the avoidance of doubt, a commercial use includes, but is not limited to:
15
+ - using the Software in advertisements of any kind,
16
+ - licensing or selling of the Software,
17
+ - use the Software to provide any service to any third Party
18
+ - use the Software to develop a competitive product of the Software
19
+
20
+ “Documentation” means textual materials delivered by InterDigital to the Licensee pursuant to this Agreement relating to the Software, in written or electronic format, including but not limited to: technical reference manuals, technical notes, user manuals, and application guides.
21
+
22
+ “Limited Period” means the life of the copyright owned by InterDigital on the Software in each and every country where such copyright would exist.
23
+
24
+ “Intellectual Property Rights” means all copyrights, trademarks, trade secrets, patents, mask works and other intellectual property rights recognized in any jurisdiction worldwide, including all applications and registrations with respect thereto.
25
+
26
+ "Open Source software" shall mean any software, including where appropriate, any and all modifications, derivative works, enhancements, upgrades, improvements, fixed bugs, and/or statically linked to the source code of such software, released under a free software license, that requires as a condition of royalty-free usage, copy, modification and/or redistribution of the Open Source Software to:
27
+ • Redistribute the Open Source Software royalty-free, and/or;
28
+ • Redistribute the Open Source Software under the same license/distribution terms as those contained in the open source or free software license under which it has originally been released and/or;
29
+ • Release to the public, disclose or otherwise make available the source code of the Open Source Software.
30
+
31
+ For purposes of the Agreement, by means of example and without limitation, any software that is released or distributed under any of the following licenses shall be qualified as Open Source Software: (A) GNU General Public License (GPL), (B) GNU Lesser/Library GPL (LGPL), (C) the Artistic License, (D) the Mozilla Public License, (E) the Common Public License, (F) the Sun Community Source License (SCSL), (G) the Sun Industry Standards Source License (SISSL), (H) BSD License, (I) MIT License, (J) Apache Software License, (K) Open SSL License, (L) IBM Public License, (M) Open Software License.
32
+
33
+ “Software” means any computer programming code, in object and/or source version, and related Documentation delivered by InterDigital to the Licensee pursuant to this Agreement as described in Exhibit A attached and incorporated herein by reference.
34
+
35
+ Article 2. License
36
+
37
+ InterDigital grants Licensee a free, worldwide, non-exclusive, license on copyright owned on the Software to download, use, modify and reproduce solely for the Authorized Purpose for the Limited Period.
38
+
39
+ The Licensee shall not pay any royalty, license fee or maintenance fee, or other fee of any nature under this Agreement.
40
+
41
+ The Licensee shall have the right to correct, adapt, modify, reverse engineer, disassemble, decompile and any action leading to the transformation of Software provided that such action is made to accomplish the Authorized Purpose.
42
+
43
+ Licensee shall have the right to make a demonstration of the Software, provided that it is in the Purpose and provided that Licensee shall maintain control of the Software at all time. This includes the control of any computer or server on which the Software is installed: no third party shall have access to such computer or server under any circumstances. No computer nor server containing the Software will be left in the possession of any third Party.
44
+
45
+ Article 3. Restrictions on use of the Software
46
+
47
+ Licensee shall not remove, obscure or modify any copyright, trademark or other proprietary rights notices, marks or labels contained on or within the Software, falsify or delete any author attributions, legal notices or other labels of the origin or source of the material.
48
+
49
+ Licensee shall not have the right to distribute the Software, either modified or not, to any third Party.
50
+
51
+ The rights granted here above do not include any rights to automatically obtain any upgrade or update of the Software, acquired or otherwise made available by InterDigital. Such deliverance shall be discussed on a case by case basis by the Parties.
52
+
53
+ Article 4. Ownership
54
+
55
+ Title to and ownership of the Software, the Documentation and/or any Intellectual Property Right protecting the Software or/and the Documentation shall, at all times, remain with InterDigital. Licensee agrees that except for the rights granted on copyright on the Software set forth in Section 2 above, in no event does anything in this Agreement grant, provide or convey any other rights, immunities or interest in or to any Intellectual Property Rights (including especially patents) of InterDigital or any of its Affiliates whether by implication, estoppel or otherwise.
56
+
57
+
58
+ Article 5. Publication/Communication
59
+
60
+ Any publication or oral communication resulting from the use of the Software shall be elaborated in good faith and shall not be driven by a deliberate will to denigrate InterDigital or any of its products. In any publication and on any support joined to an oral communication (for instance a PowerPoint document) resulting from the use of the Software, the following statement shall be inserted:
61
+
62
+ “HRFAE is an InterDigital product”
63
+
64
+ And in any publication, the latest publication about the software shall be properly cited. The latest publication currently is:
65
+ "Arxiv preprint (ref to come shortly)”
66
+
67
+ In any oral communication resulting from the use of the Software, the Licensee shall orally indicate that the Software is InterDigital’s property.
68
+
69
+ Article 6. No Warranty - Disclaimer
70
+
71
+ THE SOFTWARE AND DOCUMENTATION ARE PROVIDED TO LICENSEE ON AN “AS IS” BASIS. INTERDIGITAL MAKES NO WARRANTY THAT THE LICENSED TECHNOLOGY WILL OPERATE ON ANY PARTICULAR HARDWARE, PLATFORM, OR ENVIRONMENT. THERE IS NO WARRANTY THAT THE OPERATION OF THE LICENSED TECHNOLOGY SHALL BE UNINTERRUPTED, WITHOUT BUGS OR ERROR FREE. THE SOFTWARE AND DOCUMENTATION ARE PROVIDED HEREUNDER WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY IMPLIED LIABILITIES AND WARRANTIES OF NONINFRINGEMENT OF INTELLECTUAL PROPERTY, FREEDOM FROM INHERENT DEFECTS, CONFORMITY TO A SAMPLE OR MODEL, MERCHANTABILITY, FITNESS AND/OR SUITABILITY FOR A SPECIFIC OR GENERAL PURPOSE AND THOSE ARISING BY STATUTE OR BY LAW, OR FROM A CAUSE OF DEALING OR USAGE OF TRADE.
72
+
73
+ InterDigital shall not be obliged to perform any modifications, derivative works, enhancements, upgrades, updates or improvements of the Software or to fix any bug that could arise.
74
+
75
+ Hence, the Licensee uses the Software at his own cost, risks and responsibility. InterDigital shall not be liable for any damage that could arise to Licensee by using the Software, either in accordance with this Agreement or not.
76
+
77
+ InterDigital shall not be liable for any consequential or indirect losses, including any indirect loss of profits, revenues, business, and/or anticipated savings, whether or not in the contemplation of the Parties at the time of entering into the Agreement unless expressly set out in the Agreement, or arising from gross negligence, willful misconduct or fraud.
78
+
79
+ Licensee agrees that it will defend, indemnify and hold harmless InterDigital and its Affiliates against any and all losses, damages, costs and expenses arising from a breach by the Licensee of any of its obligations or representations hereunder, including, without limitation, any third party, and/or any claims in connection with any such breach and/or any use of the Software, including any claim from third party arising from access, use or any other activity in relation to this Software.
80
+
81
+ The Licensee shall not make any warranty, representation, or commitment on behalf of InterDigital to any other third party.
82
+
83
+ Article 7. Open Source Software
84
+
85
+ InterDigital hereby notifies the Licensee, and the Licensee hereby acknowledges and accepts, that the Software contains Open Source Software. The list of such Open Source Software is enclosed in exhibit B and the relevant license are contained at the root of the Software when downloaded. Hence, the Licensee shall comply with such license and agree on its terms on at its own risks.
86
+
87
+ The Licensee hereby represents, warrants and covenants to InterDigital that The Licensee’s use of the Software shall not result in the Contamination of all or part of the Software, directly or indirectly, or of any Intellectual Property of InterDigital or its Affiliates.
88
+
89
+ Contamination effect shall mean that the licensing terms under which one Open Source software, distinct from the Software, is released would also apply, by viral effect, to the software to which such Open Source software is linked to, combined with or otherwise connected to.
90
+
91
+ Article 8. No Future Contract Obligation
92
+
93
+ Neither this Agreement nor the furnishing of the Software, nor any other Confidential Information shall be construed to obligate either party to: (a) enter into any further agreement or negotiation concerning the deployment of the Software; (b) refrain from entering into any agreement or negotiation with any other third party regarding the same or any other subject matter; or (c) refrain from pursuing its business in whatever manner it elects even if this involves competing with the other party.
94
+
95
+ Article 9. Term and Termination
96
+
97
+ This Agreement shall terminate at the end of the Limited Period, unless earlier terminated by either party on the ground of material breach by the other party, which breach is not remedied after thirty (30) days advance written notice, specifying the breach with reasonable particularity and referencing this Agreement.
98
+
99
+ Article 10. General Provisions
100
+
101
+ 12.1 Severability. If any provision of this Agreement shall be held to be in contravention of applicable law, this Agreement shall be construed as if such provision were not a part thereof, and in all other respects the terms hereof shall remain in full force and effect.
102
+
103
+ 12.2 Governing Law. Regardless of the place of execution, delivery, performance or any other aspect of this Agreement, this Agreement and all of the rights of the parties under this Agreement shall be governed by, construed under and enforced in accordance with the substantive law of the France without regard to conflicts of law principles. In case of a dispute that could not be settled amicably, the courts of Nanterre shall be exclusively competent.
104
+
105
+ 12.3 Survival. The provisions of articles 1, 3, 4, 6, 7, 9, 10.2 and 10.6 shall survive termination of this Agreement.
106
+ 12.4 Assignment. InterDigital may assign this license to any third Party. Such assignment will be announced on the website as defined in article 5. Licensee may not assign this agreement to any third party without the previous written agreement from InterDigital.
107
+
108
+ 12.5 Entire Agreement. This Agreement constitutes the entire agreement between the parties hereto with respect to the subject matter hereof and supersedes any prior agreements or understanding.
109
+
110
+ 12.6 Notices. To have legal effect, notices must be provided by registered or certified mail, return receipt requested, to the representatives of InterDigital at the following address:
111
+
112
+ InterDigital
113
+ Legal Dept
114
+ 975 avenue des champs blancs
115
+ 35510 Cesson-Sévigné
116
+ FRANCE
117
+
118
+ =======================================================================
119
+
120
+ Exhibit A
121
+ Software
122
+
123
+
124
+ The Software is comprised of the following software and Documentation:
125
+
126
+ - README.md file that explains the content of the software and the procedure to use it.
127
+ - Source python files, as well as pretrained models
128
+
129
+ =======================================================================
130
+
131
+ Exhibit B
132
+ Open Source licenses
133
+
134
+
135
+ PIL http://www.pythonware.com/products/pil/license.htm
136
+
137
+ numpy https://numpy.org/license.html
138
+
139
+ tensorboardX https://github.com/lanpa/tensorboardX/blob/master/LICENSE
140
+
141
+ pytorch https://github.com/pytorch/pytorch/blob/master/LICENSE
142
+
143
+ torchvision https://github.com/pytorch/vision/blob/master/LICENSE
144
+
145
+ tensorboard_logger https://github.com/TeamHG-Memex/tensorboard_logger/blob/master/LICENSE
146
+
147
+ argparse https://github.com/ThomasWaldmann/argparse/blob/master/LICENSE.txt
148
+
149
+ yaml https://github.com/yaml/pyyaml/blob/master/LICENSE
150
+
licenses/LICENSE_S-aiueo32 ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ BSD 2-Clause License
2
+
3
+ Copyright (c) 2020, Sou Uchida
4
+ All rights reserved.
5
+
6
+ Redistribution and use in source and binary forms, with or without
7
+ modification, are permitted provided that the following conditions are met:
8
+
9
+ 1. Redistributions of source code must retain the above copyright notice, this
10
+ list of conditions and the following disclaimer.
11
+
12
+ 2. Redistributions in binary form must reproduce the above copyright notice,
13
+ this list of conditions and the following disclaimer in the documentation
14
+ and/or other materials provided with the distribution.
15
+
16
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
20
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
licenses/LICENSE_TreB1eN ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ MIT License
2
+
3
+ Copyright (c) 2018 TreB1eN
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
licenses/LICENSE_eladrich ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ MIT License
2
+
3
+ Copyright (c) 2020 Elad Richardson, Yuval Alaluf
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
licenses/LICENSE_lessw2020 ADDED
@@ -0,0 +1,201 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction,
10
+ and distribution as defined by Sections 1 through 9 of this document.
11
+
12
+ "Licensor" shall mean the copyright owner or entity authorized by
13
+ the copyright owner that is granting the License.
14
+
15
+ "Legal Entity" shall mean the union of the acting entity and all
16
+ other entities that control, are controlled by, or are under common
17
+ control with that entity. For the purposes of this definition,
18
+ "control" means (i) the power, direct or indirect, to cause the
19
+ direction or management of such entity, whether by contract or
20
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
+ outstanding shares, or (iii) beneficial ownership of such entity.
22
+
23
+ "You" (or "Your") shall mean an individual or Legal Entity
24
+ exercising permissions granted by this License.
25
+
26
+ "Source" form shall mean the preferred form for making modifications,
27
+ including but not limited to software source code, documentation
28
+ source, and configuration files.
29
+
30
+ "Object" form shall mean any form resulting from mechanical
31
+ transformation or translation of a Source form, including but
32
+ not limited to compiled object code, generated documentation,
33
+ and conversions to other media types.
34
+
35
+ "Work" shall mean the work of authorship, whether in Source or
36
+ Object form, made available under the License, as indicated by a
37
+ copyright notice that is included in or attached to the work
38
+ (an example is provided in the Appendix below).
39
+
40
+ "Derivative Works" shall mean any work, whether in Source or Object
41
+ form, that is based on (or derived from) the Work and for which the
42
+ editorial revisions, annotations, elaborations, or other modifications
43
+ represent, as a whole, an original work of authorship. For the purposes
44
+ of this License, Derivative Works shall not include works that remain
45
+ separable from, or merely link (or bind by name) to the interfaces of,
46
+ the Work and Derivative Works thereof.
47
+
48
+ "Contribution" shall mean any work of authorship, including
49
+ the original version of the Work and any modifications or additions
50
+ to that Work or Derivative Works thereof, that is intentionally
51
+ submitted to Licensor for inclusion in the Work by the copyright owner
52
+ or by an individual or Legal Entity authorized to submit on behalf of
53
+ the copyright owner. For the purposes of this definition, "submitted"
54
+ means any form of electronic, verbal, or written communication sent
55
+ to the Licensor or its representatives, including but not limited to
56
+ communication on electronic mailing lists, source code control systems,
57
+ and issue tracking systems that are managed by, or on behalf of, the
58
+ Licensor for the purpose of discussing and improving the Work, but
59
+ excluding communication that is conspicuously marked or otherwise
60
+ designated in writing by the copyright owner as "Not a Contribution."
61
+
62
+ "Contributor" shall mean Licensor and any individual or Legal Entity
63
+ on behalf of whom a Contribution has been received by Licensor and
64
+ subsequently incorporated within the Work.
65
+
66
+ 2. Grant of Copyright License. Subject to the terms and conditions of
67
+ this License, each Contributor hereby grants to You a perpetual,
68
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
+ copyright license to reproduce, prepare Derivative Works of,
70
+ publicly display, publicly perform, sublicense, and distribute the
71
+ Work and such Derivative Works in Source or Object form.
72
+
73
+ 3. Grant of Patent License. Subject to the terms and conditions of
74
+ this License, each Contributor hereby grants to You a perpetual,
75
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
+ (except as stated in this section) patent license to make, have made,
77
+ use, offer to sell, sell, import, and otherwise transfer the Work,
78
+ where such license applies only to those patent claims licensable
79
+ by such Contributor that are necessarily infringed by their
80
+ Contribution(s) alone or by combination of their Contribution(s)
81
+ with the Work to which such Contribution(s) was submitted. If You
82
+ institute patent litigation against any entity (including a
83
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
84
+ or a Contribution incorporated within the Work constitutes direct
85
+ or contributory patent infringement, then any patent licenses
86
+ granted to You under this License for that Work shall terminate
87
+ as of the date such litigation is filed.
88
+
89
+ 4. Redistribution. You may reproduce and distribute copies of the
90
+ Work or Derivative Works thereof in any medium, with or without
91
+ modifications, and in Source or Object form, provided that You
92
+ meet the following conditions:
93
+
94
+ (a) You must give any other recipients of the Work or
95
+ Derivative Works a copy of this License; and
96
+
97
+ (b) You must cause any modified files to carry prominent notices
98
+ stating that You changed the files; and
99
+
100
+ (c) You must retain, in the Source form of any Derivative Works
101
+ that You distribute, all copyright, patent, trademark, and
102
+ attribution notices from the Source form of the Work,
103
+ excluding those notices that do not pertain to any part of
104
+ the Derivative Works; and
105
+
106
+ (d) If the Work includes a "NOTICE" text file as part of its
107
+ distribution, then any Derivative Works that You distribute must
108
+ include a readable copy of the attribution notices contained
109
+ within such NOTICE file, excluding those notices that do not
110
+ pertain to any part of the Derivative Works, in at least one
111
+ of the following places: within a NOTICE text file distributed
112
+ as part of the Derivative Works; within the Source form or
113
+ documentation, if provided along with the Derivative Works; or,
114
+ within a display generated by the Derivative Works, if and
115
+ wherever such third-party notices normally appear. The contents
116
+ of the NOTICE file are for informational purposes only and
117
+ do not modify the License. You may add Your own attribution
118
+ notices within Derivative Works that You distribute, alongside
119
+ or as an addendum to the NOTICE text from the Work, provided
120
+ that such additional attribution notices cannot be construed
121
+ as modifying the License.
122
+
123
+ You may add Your own copyright statement to Your modifications and
124
+ may provide additional or different license terms and conditions
125
+ for use, reproduction, or distribution of Your modifications, or
126
+ for any such Derivative Works as a whole, provided Your use,
127
+ reproduction, and distribution of the Work otherwise complies with
128
+ the conditions stated in this License.
129
+
130
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
131
+ any Contribution intentionally submitted for inclusion in the Work
132
+ by You to the Licensor shall be under the terms and conditions of
133
+ this License, without any additional terms or conditions.
134
+ Notwithstanding the above, nothing herein shall supersede or modify
135
+ the terms of any separate license agreement you may have executed
136
+ with Licensor regarding such Contributions.
137
+
138
+ 6. Trademarks. This License does not grant permission to use the trade
139
+ names, trademarks, service marks, or product names of the Licensor,
140
+ except as required for reasonable and customary use in describing the
141
+ origin of the Work and reproducing the content of the NOTICE file.
142
+
143
+ 7. Disclaimer of Warranty. Unless required by applicable law or
144
+ agreed to in writing, Licensor provides the Work (and each
145
+ Contributor provides its Contributions) on an "AS IS" BASIS,
146
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
+ implied, including, without limitation, any warranties or conditions
148
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
+ PARTICULAR PURPOSE. You are solely responsible for determining the
150
+ appropriateness of using or redistributing the Work and assume any
151
+ risks associated with Your exercise of permissions under this License.
152
+
153
+ 8. Limitation of Liability. In no event and under no legal theory,
154
+ whether in tort (including negligence), contract, or otherwise,
155
+ unless required by applicable law (such as deliberate and grossly
156
+ negligent acts) or agreed to in writing, shall any Contributor be
157
+ liable to You for damages, including any direct, indirect, special,
158
+ incidental, or consequential damages of any character arising as a
159
+ result of this License or out of the use or inability to use the
160
+ Work (including but not limited to damages for loss of goodwill,
161
+ work stoppage, computer failure or malfunction, or any and all
162
+ other commercial damages or losses), even if such Contributor
163
+ has been advised of the possibility of such damages.
164
+
165
+ 9. Accepting Warranty or Additional Liability. While redistributing
166
+ the Work or Derivative Works thereof, You may choose to offer,
167
+ and charge a fee for, acceptance of support, warranty, indemnity,
168
+ or other liability obligations and/or rights consistent with this
169
+ License. However, in accepting such obligations, You may act only
170
+ on Your own behalf and on Your sole responsibility, not on behalf
171
+ of any other Contributor, and only if You agree to indemnify,
172
+ defend, and hold each Contributor harmless for any liability
173
+ incurred by, or claims asserted against, such Contributor by reason
174
+ of your accepting any such warranty or additional liability.
175
+
176
+ END OF TERMS AND CONDITIONS
177
+
178
+ APPENDIX: How to apply the Apache License to your work.
179
+
180
+ To apply the Apache License to your work, attach the following
181
+ boilerplate notice, with the fields enclosed by brackets "[]"
182
+ replaced with your own identifying information. (Don't include
183
+ the brackets!) The text should be enclosed in the appropriate
184
+ comment syntax for the file format. We also recommend that a
185
+ file or class name and description of purpose be included on the
186
+ same "printed page" as the copyright notice for easier
187
+ identification within third-party archives.
188
+
189
+ Copyright [yyyy] [name of copyright owner]
190
+
191
+ Licensed under the Apache License, Version 2.0 (the "License");
192
+ you may not use this file except in compliance with the License.
193
+ You may obtain a copy of the License at
194
+
195
+ http://www.apache.org/licenses/LICENSE-2.0
196
+
197
+ Unless required by applicable law or agreed to in writing, software
198
+ distributed under the License is distributed on an "AS IS" BASIS,
199
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200
+ See the License for the specific language governing permissions and
201
+ limitations under the License.
licenses/LICENSE_rosinality ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ MIT License
2
+
3
+ Copyright (c) 2019 Kim Seonghyeon
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
models/__init__.py ADDED
File without changes
models/__pycache__/__init__.cpython-38.pyc ADDED
Binary file (114 Bytes). View file
 
models/__pycache__/psp.cpython-38.pyc ADDED
Binary file (4.61 kB). View file
 
models/dex_vgg.py ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch.nn as nn
2
+ import torch.nn.functional as F
3
+
4
+ """
5
+ VGG implementation from [InterDigitalInc](https://github.com/InterDigitalInc/HRFAE/blob/master/nets.py)
6
+ """
7
+
8
+ class VGG(nn.Module):
9
+ def __init__(self, pool='max'):
10
+ super(VGG, self).__init__()
11
+ # vgg modules
12
+ self.conv1_1 = nn.Conv2d(3, 64, kernel_size=3, padding=1)
13
+ self.conv1_2 = nn.Conv2d(64, 64, kernel_size=3, padding=1)
14
+ self.conv2_1 = nn.Conv2d(64, 128, kernel_size=3, padding=1)
15
+ self.conv2_2 = nn.Conv2d(128, 128, kernel_size=3, padding=1)
16
+ self.conv3_1 = nn.Conv2d(128, 256, kernel_size=3, padding=1)
17
+ self.conv3_2 = nn.Conv2d(256, 256, kernel_size=3, padding=1)
18
+ self.conv3_3 = nn.Conv2d(256, 256, kernel_size=3, padding=1)
19
+ self.conv4_1 = nn.Conv2d(256, 512, kernel_size=3, padding=1)
20
+ self.conv4_2 = nn.Conv2d(512, 512, kernel_size=3, padding=1)
21
+ self.conv4_3 = nn.Conv2d(512, 512, kernel_size=3, padding=1)
22
+ self.conv5_1 = nn.Conv2d(512, 512, kernel_size=3, padding=1)
23
+ self.conv5_2 = nn.Conv2d(512, 512, kernel_size=3, padding=1)
24
+ self.conv5_3 = nn.Conv2d(512, 512, kernel_size=3, padding=1)
25
+ self.fc6 = nn.Linear(25088, 4096, bias=True)
26
+ self.fc7 = nn.Linear(4096, 4096, bias=True)
27
+ self.fc8_101 = nn.Linear(4096, 101, bias=True)
28
+ if pool == 'max':
29
+ self.pool1 = nn.MaxPool2d(kernel_size=2, stride=2)
30
+ self.pool2 = nn.MaxPool2d(kernel_size=2, stride=2)
31
+ self.pool3 = nn.MaxPool2d(kernel_size=2, stride=2)
32
+ self.pool4 = nn.MaxPool2d(kernel_size=2, stride=2)
33
+ self.pool5 = nn.MaxPool2d(kernel_size=2, stride=2)
34
+ elif pool == 'avg':
35
+ self.pool1 = nn.AvgPool2d(kernel_size=2, stride=2)
36
+ self.pool2 = nn.AvgPool2d(kernel_size=2, stride=2)
37
+ self.pool3 = nn.AvgPool2d(kernel_size=2, stride=2)
38
+ self.pool4 = nn.AvgPool2d(kernel_size=2, stride=2)
39
+ self.pool5 = nn.AvgPool2d(kernel_size=2, stride=2)
40
+
41
+ def forward(self, x):
42
+ out = {}
43
+ out['r11'] = F.relu(self.conv1_1(x))
44
+ out['r12'] = F.relu(self.conv1_2(out['r11']))
45
+ out['p1'] = self.pool1(out['r12'])
46
+ out['r21'] = F.relu(self.conv2_1(out['p1']))
47
+ out['r22'] = F.relu(self.conv2_2(out['r21']))
48
+ out['p2'] = self.pool2(out['r22'])
49
+ out['r31'] = F.relu(self.conv3_1(out['p2']))
50
+ out['r32'] = F.relu(self.conv3_2(out['r31']))
51
+ out['r33'] = F.relu(self.conv3_3(out['r32']))
52
+ out['p3'] = self.pool3(out['r33'])
53
+ out['r41'] = F.relu(self.conv4_1(out['p3']))
54
+ out['r42'] = F.relu(self.conv4_2(out['r41']))
55
+ out['r43'] = F.relu(self.conv4_3(out['r42']))
56
+ out['p4'] = self.pool4(out['r43'])
57
+ out['r51'] = F.relu(self.conv5_1(out['p4']))
58
+ out['r52'] = F.relu(self.conv5_2(out['r51']))
59
+ out['r53'] = F.relu(self.conv5_3(out['r52']))
60
+ out['p5'] = self.pool5(out['r53'])
61
+ out['p5'] = out['p5'].view(out['p5'].size(0), -1)
62
+ out['fc6'] = F.relu(self.fc6(out['p5']))
63
+ out['fc7'] = F.relu(self.fc7(out['fc6']))
64
+ out['fc8'] = self.fc8_101(out['fc7'])
65
+ return out
models/encoders/__init__.py ADDED
File without changes
models/encoders/__pycache__/__init__.cpython-38.pyc ADDED
Binary file (123 Bytes). View file
 
models/encoders/__pycache__/helpers.cpython-38.pyc ADDED
Binary file (4.07 kB). View file
 
models/encoders/__pycache__/psp_encoders.cpython-38.pyc ADDED
Binary file (4.04 kB). View file
 
models/encoders/helpers.py ADDED
@@ -0,0 +1,119 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from collections import namedtuple
2
+ import torch
3
+ from torch.nn import Conv2d, BatchNorm2d, PReLU, ReLU, Sigmoid, MaxPool2d, AdaptiveAvgPool2d, Sequential, Module
4
+
5
+ """
6
+ ArcFace implementation from [TreB1eN](https://github.com/TreB1eN/InsightFace_Pytorch)
7
+ """
8
+
9
+
10
+ class Flatten(Module):
11
+ def forward(self, input):
12
+ return input.view(input.size(0), -1)
13
+
14
+
15
+ def l2_norm(input, axis=1):
16
+ norm = torch.norm(input, 2, axis, True)
17
+ output = torch.div(input, norm)
18
+ return output
19
+
20
+
21
+ class Bottleneck(namedtuple('Block', ['in_channel', 'depth', 'stride'])):
22
+ """ A named tuple describing a ResNet block. """
23
+
24
+
25
+ def get_block(in_channel, depth, num_units, stride=2):
26
+ return [Bottleneck(in_channel, depth, stride)] + [Bottleneck(depth, depth, 1) for i in range(num_units - 1)]
27
+
28
+
29
+ def get_blocks(num_layers):
30
+ if num_layers == 50:
31
+ blocks = [
32
+ get_block(in_channel=64, depth=64, num_units=3),
33
+ get_block(in_channel=64, depth=128, num_units=4),
34
+ get_block(in_channel=128, depth=256, num_units=14),
35
+ get_block(in_channel=256, depth=512, num_units=3)
36
+ ]
37
+ elif num_layers == 100:
38
+ blocks = [
39
+ get_block(in_channel=64, depth=64, num_units=3),
40
+ get_block(in_channel=64, depth=128, num_units=13),
41
+ get_block(in_channel=128, depth=256, num_units=30),
42
+ get_block(in_channel=256, depth=512, num_units=3)
43
+ ]
44
+ elif num_layers == 152:
45
+ blocks = [
46
+ get_block(in_channel=64, depth=64, num_units=3),
47
+ get_block(in_channel=64, depth=128, num_units=8),
48
+ get_block(in_channel=128, depth=256, num_units=36),
49
+ get_block(in_channel=256, depth=512, num_units=3)
50
+ ]
51
+ else:
52
+ raise ValueError("Invalid number of layers: {}. Must be one of [50, 100, 152]".format(num_layers))
53
+ return blocks
54
+
55
+
56
+ class SEModule(Module):
57
+ def __init__(self, channels, reduction):
58
+ super(SEModule, self).__init__()
59
+ self.avg_pool = AdaptiveAvgPool2d(1)
60
+ self.fc1 = Conv2d(channels, channels // reduction, kernel_size=1, padding=0, bias=False)
61
+ self.relu = ReLU(inplace=True)
62
+ self.fc2 = Conv2d(channels // reduction, channels, kernel_size=1, padding=0, bias=False)
63
+ self.sigmoid = Sigmoid()
64
+
65
+ def forward(self, x):
66
+ module_input = x
67
+ x = self.avg_pool(x)
68
+ x = self.fc1(x)
69
+ x = self.relu(x)
70
+ x = self.fc2(x)
71
+ x = self.sigmoid(x)
72
+ return module_input * x
73
+
74
+
75
+ class bottleneck_IR(Module):
76
+ def __init__(self, in_channel, depth, stride):
77
+ super(bottleneck_IR, self).__init__()
78
+ if in_channel == depth:
79
+ self.shortcut_layer = MaxPool2d(1, stride)
80
+ else:
81
+ self.shortcut_layer = Sequential(
82
+ Conv2d(in_channel, depth, (1, 1), stride, bias=False),
83
+ BatchNorm2d(depth)
84
+ )
85
+ self.res_layer = Sequential(
86
+ BatchNorm2d(in_channel),
87
+ Conv2d(in_channel, depth, (3, 3), (1, 1), 1, bias=False), PReLU(depth),
88
+ Conv2d(depth, depth, (3, 3), stride, 1, bias=False), BatchNorm2d(depth)
89
+ )
90
+
91
+ def forward(self, x):
92
+ shortcut = self.shortcut_layer(x)
93
+ res = self.res_layer(x)
94
+ return res + shortcut
95
+
96
+
97
+ class bottleneck_IR_SE(Module):
98
+ def __init__(self, in_channel, depth, stride):
99
+ super(bottleneck_IR_SE, self).__init__()
100
+ if in_channel == depth:
101
+ self.shortcut_layer = MaxPool2d(1, stride)
102
+ else:
103
+ self.shortcut_layer = Sequential(
104
+ Conv2d(in_channel, depth, (1, 1), stride, bias=False),
105
+ BatchNorm2d(depth)
106
+ )
107
+ self.res_layer = Sequential(
108
+ BatchNorm2d(in_channel),
109
+ Conv2d(in_channel, depth, (3, 3), (1, 1), 1, bias=False),
110
+ PReLU(depth),
111
+ Conv2d(depth, depth, (3, 3), stride, 1, bias=False),
112
+ BatchNorm2d(depth),
113
+ SEModule(depth, 16)
114
+ )
115
+
116
+ def forward(self, x):
117
+ shortcut = self.shortcut_layer(x)
118
+ res = self.res_layer(x)
119
+ return res + shortcut
models/encoders/model_irse.py ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from torch.nn import Linear, Conv2d, BatchNorm1d, BatchNorm2d, PReLU, Dropout, Sequential, Module
2
+ from models.encoders.helpers import get_blocks, Flatten, bottleneck_IR, bottleneck_IR_SE, l2_norm
3
+
4
+ """
5
+ Modified Backbone implementation from [TreB1eN](https://github.com/TreB1eN/InsightFace_Pytorch)
6
+ """
7
+
8
+
9
+ class Backbone(Module):
10
+ def __init__(self, input_size, num_layers, mode='ir', drop_ratio=0.4, affine=True):
11
+ super(Backbone, self).__init__()
12
+ assert input_size in [112, 224], "input_size should be 112 or 224"
13
+ assert num_layers in [50, 100, 152], "num_layers should be 50, 100 or 152"
14
+ assert mode in ['ir', 'ir_se'], "mode should be ir or ir_se"
15
+ blocks = get_blocks(num_layers)
16
+ if mode == 'ir':
17
+ unit_module = bottleneck_IR
18
+ elif mode == 'ir_se':
19
+ unit_module = bottleneck_IR_SE
20
+ self.input_layer = Sequential(Conv2d(3, 64, (3, 3), 1, 1, bias=False),
21
+ BatchNorm2d(64),
22
+ PReLU(64))
23
+ if input_size == 112:
24
+ self.output_layer = Sequential(BatchNorm2d(512),
25
+ Dropout(drop_ratio),
26
+ Flatten(),
27
+ Linear(512 * 7 * 7, 512),
28
+ BatchNorm1d(512, affine=affine))
29
+ else:
30
+ self.output_layer = Sequential(BatchNorm2d(512),
31
+ Dropout(drop_ratio),
32
+ Flatten(),
33
+ Linear(512 * 14 * 14, 512),
34
+ BatchNorm1d(512, affine=affine))
35
+
36
+ modules = []
37
+ for block in blocks:
38
+ for bottleneck in block:
39
+ modules.append(unit_module(bottleneck.in_channel,
40
+ bottleneck.depth,
41
+ bottleneck.stride))
42
+ self.body = Sequential(*modules)
43
+
44
+ def forward(self, x):
45
+ x = self.input_layer(x)
46
+ x = self.body(x)
47
+ x = self.output_layer(x)
48
+ return l2_norm(x)
models/encoders/psp_encoders.py ADDED
@@ -0,0 +1,114 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+ import torch
3
+ import torch.nn.functional as F
4
+ from torch import nn
5
+ from torch.nn import Conv2d, BatchNorm2d, PReLU, Sequential, Module
6
+
7
+ from models.encoders.helpers import get_blocks, bottleneck_IR, bottleneck_IR_SE
8
+ from models.stylegan2.model import EqualLinear
9
+
10
+
11
+ class GradualStyleBlock(Module):
12
+ def __init__(self, in_c, out_c, spatial):
13
+ super(GradualStyleBlock, self).__init__()
14
+ self.out_c = out_c
15
+ self.spatial = spatial
16
+ num_pools = int(np.log2(spatial))
17
+ modules = []
18
+ modules += [Conv2d(in_c, out_c, kernel_size=3, stride=2, padding=1), nn.LeakyReLU()]
19
+ for i in range(num_pools - 1):
20
+ modules += [
21
+ Conv2d(out_c, out_c, kernel_size=3, stride=2, padding=1), nn.LeakyReLU()
22
+ ]
23
+ self.convs = nn.Sequential(*modules)
24
+ self.linear = EqualLinear(out_c, out_c, lr_mul=1)
25
+
26
+ def forward(self, x):
27
+ x = self.convs(x)
28
+ x = x.view(-1, self.out_c)
29
+ x = self.linear(x)
30
+ return x
31
+
32
+
33
+ class GradualStyleEncoder(Module):
34
+ def __init__(self, num_layers, mode='ir', n_styles=18, opts=None):
35
+ super(GradualStyleEncoder, self).__init__()
36
+ assert num_layers in [50, 100, 152], 'num_layers should be 50,100, or 152'
37
+ assert mode in ['ir', 'ir_se'], 'mode should be ir or ir_se'
38
+ blocks = get_blocks(num_layers)
39
+ if mode == 'ir':
40
+ unit_module = bottleneck_IR
41
+ elif mode == 'ir_se':
42
+ unit_module = bottleneck_IR_SE
43
+ self.input_layer = Sequential(Conv2d(opts.input_nc, 64, (3, 3), 1, 1, bias=False),
44
+ BatchNorm2d(64),
45
+ PReLU(64))
46
+ modules = []
47
+ for block in blocks:
48
+ for bottleneck in block:
49
+ modules.append(unit_module(bottleneck.in_channel,
50
+ bottleneck.depth,
51
+ bottleneck.stride))
52
+ self.body = Sequential(*modules)
53
+
54
+ self.styles = nn.ModuleList()
55
+ self.style_count = n_styles
56
+ self.coarse_ind = 3
57
+ self.middle_ind = 7
58
+ for i in range(self.style_count):
59
+ if i < self.coarse_ind:
60
+ style = GradualStyleBlock(512, 512, 16)
61
+ elif i < self.middle_ind:
62
+ style = GradualStyleBlock(512, 512, 32)
63
+ else:
64
+ style = GradualStyleBlock(512, 512, 64)
65
+ self.styles.append(style)
66
+ self.latlayer1 = nn.Conv2d(256, 512, kernel_size=1, stride=1, padding=0)
67
+ self.latlayer2 = nn.Conv2d(128, 512, kernel_size=1, stride=1, padding=0)
68
+
69
+ def _upsample_add(self, x, y):
70
+ '''Upsample and add two feature maps.
71
+ Args:
72
+ x: (Variable) top feature map to be upsampled.
73
+ y: (Variable) lateral feature map.
74
+ Returns:
75
+ (Variable) added feature map.
76
+ Note in PyTorch, when input size is odd, the upsampled feature map
77
+ with `F.upsample(..., scale_factor=2, mode='nearest')`
78
+ maybe not equal to the lateral feature map size.
79
+ e.g.
80
+ original input size: [N,_,15,15] ->
81
+ conv2d feature map size: [N,_,8,8] ->
82
+ upsampled feature map size: [N,_,16,16]
83
+ So we choose bilinear upsample which supports arbitrary output sizes.
84
+ '''
85
+ _, _, H, W = y.size()
86
+ return F.interpolate(x, size=(H, W), mode='bilinear', align_corners=True) + y
87
+
88
+ def forward(self, x):
89
+ x = self.input_layer(x)
90
+
91
+ latents = []
92
+ modulelist = list(self.body._modules.values())
93
+ for i, l in enumerate(modulelist):
94
+ x = l(x)
95
+ if i == 6:
96
+ c1 = x
97
+ elif i == 20:
98
+ c2 = x
99
+ elif i == 23:
100
+ c3 = x
101
+
102
+ for j in range(self.coarse_ind):
103
+ latents.append(self.styles[j](c3))
104
+
105
+ p2 = self._upsample_add(c3, self.latlayer1(c2))
106
+ for j in range(self.coarse_ind, self.middle_ind):
107
+ latents.append(self.styles[j](p2))
108
+
109
+ p1 = self._upsample_add(p2, self.latlayer2(c1))
110
+ for j in range(self.middle_ind, self.style_count):
111
+ latents.append(self.styles[j](p1))
112
+
113
+ out = torch.stack(latents, dim=1)
114
+ return out
models/psp.py ADDED
@@ -0,0 +1,131 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ This file defines the core research contribution
3
+ """
4
+ import copy
5
+ from argparse import Namespace
6
+
7
+ import torch
8
+ from torch import nn
9
+ import math
10
+
11
+ from configs.paths_config import model_paths
12
+ from models.encoders import psp_encoders
13
+ from models.stylegan2.model import Generator
14
+
15
+
16
+ class pSp(nn.Module):
17
+
18
+ def __init__(self, opts):
19
+ super(pSp, self).__init__()
20
+ self.set_opts(opts)
21
+ self.n_styles = int(math.log(self.opts.output_size, 2)) * 2 - 2
22
+ # Define architecture
23
+ self.encoder = self.set_encoder()
24
+ self.decoder = Generator(self.opts.output_size, 512, 8)
25
+ self.face_pool = torch.nn.AdaptiveAvgPool2d((256, 256))
26
+ # Load weights if needed
27
+ self.load_weights()
28
+
29
+ def set_encoder(self):
30
+ return psp_encoders.GradualStyleEncoder(50, 'ir_se', self.n_styles, self.opts)
31
+
32
+ def load_weights(self):
33
+ if self.opts.checkpoint_path is not None:
34
+ print(f'Loading SAM from checkpoint: {self.opts.checkpoint_path}')
35
+ ckpt = torch.load(self.opts.checkpoint_path, map_location='cpu')
36
+ self.encoder.load_state_dict(self.__get_keys(ckpt, 'encoder'), strict=False)
37
+ self.decoder.load_state_dict(self.__get_keys(ckpt, 'decoder'), strict=True)
38
+ if self.opts.start_from_encoded_w_plus:
39
+ self.pretrained_encoder = self.__get_pretrained_psp_encoder()
40
+ self.pretrained_encoder.load_state_dict(self.__get_keys(ckpt, 'pretrained_encoder'), strict=True)
41
+ self.__load_latent_avg(ckpt)
42
+ else:
43
+ print('Loading encoders weights from irse50!')
44
+ encoder_ckpt = torch.load(model_paths['ir_se50'])
45
+ # Transfer the RGB input of the irse50 network to the first 3 input channels of SAM's encoder
46
+ if self.opts.input_nc != 3:
47
+ shape = encoder_ckpt['input_layer.0.weight'].shape
48
+ altered_input_layer = torch.randn(shape[0], self.opts.input_nc, shape[2], shape[3], dtype=torch.float32)
49
+ altered_input_layer[:, :3, :, :] = encoder_ckpt['input_layer.0.weight']
50
+ encoder_ckpt['input_layer.0.weight'] = altered_input_layer
51
+ self.encoder.load_state_dict(encoder_ckpt, strict=False)
52
+ print(f'Loading decoder weights from pretrained path: {self.opts.stylegan_weights}')
53
+ ckpt = torch.load(self.opts.stylegan_weights)
54
+ self.decoder.load_state_dict(ckpt['g_ema'], strict=True)
55
+ self.__load_latent_avg(ckpt, repeat=self.n_styles)
56
+ if self.opts.start_from_encoded_w_plus:
57
+ self.pretrained_encoder = self.__load_pretrained_psp_encoder()
58
+ self.pretrained_encoder.eval()
59
+
60
+ def forward(self, x, resize=True, latent_mask=None, input_code=False, randomize_noise=True,
61
+ inject_latent=None, return_latents=False, alpha=None, input_is_full=False):
62
+ if input_code:
63
+ codes = x
64
+ else:
65
+ codes = self.encoder(x)
66
+ # normalize with respect to the center of an average face
67
+ if self.opts.start_from_latent_avg:
68
+ codes = codes + self.latent_avg
69
+ # normalize with respect to the latent of the encoded image of pretrained pSp encoder
70
+ elif self.opts.start_from_encoded_w_plus:
71
+ with torch.no_grad():
72
+ encoded_latents = self.pretrained_encoder(x[:, :-1, :, :])
73
+ encoded_latents = encoded_latents + self.latent_avg
74
+ codes = codes + encoded_latents
75
+
76
+ if latent_mask is not None:
77
+ for i in latent_mask:
78
+ if inject_latent is not None:
79
+ if alpha is not None:
80
+ codes[:, i] = alpha * inject_latent[:, i] + (1 - alpha) * codes[:, i]
81
+ else:
82
+ codes[:, i] = inject_latent[:, i]
83
+ else:
84
+ codes[:, i] = 0
85
+
86
+ input_is_latent = (not input_code) or (input_is_full)
87
+ images, result_latent = self.decoder([codes],
88
+ input_is_latent=input_is_latent,
89
+ randomize_noise=randomize_noise,
90
+ return_latents=return_latents)
91
+
92
+ if resize:
93
+ images = self.face_pool(images)
94
+
95
+ if return_latents:
96
+ return images, result_latent
97
+ else:
98
+ return images
99
+
100
+ def set_opts(self, opts):
101
+ self.opts = opts
102
+
103
+ def __load_latent_avg(self, ckpt, repeat=None):
104
+ if 'latent_avg' in ckpt:
105
+ self.latent_avg = ckpt['latent_avg'].to(self.opts.device)
106
+ if repeat is not None:
107
+ self.latent_avg = self.latent_avg.repeat(repeat, 1)
108
+ else:
109
+ self.latent_avg = None
110
+
111
+ def __get_pretrained_psp_encoder(self):
112
+ opts_encoder = vars(copy.deepcopy(self.opts))
113
+ opts_encoder['input_nc'] = 3
114
+ opts_encoder = Namespace(**opts_encoder)
115
+ encoder = psp_encoders.GradualStyleEncoder(50, 'ir_se', self.n_styles, opts_encoder)
116
+ return encoder
117
+
118
+ def __load_pretrained_psp_encoder(self):
119
+ print(f'Loading pSp encoder from checkpoint: {self.opts.pretrained_psp_path}')
120
+ ckpt = torch.load(self.opts.pretrained_psp_path, map_location='cpu')
121
+ encoder_ckpt = self.__get_keys(ckpt, name='encoder')
122
+ encoder = self.__get_pretrained_psp_encoder()
123
+ encoder.load_state_dict(encoder_ckpt, strict=False)
124
+ return encoder
125
+
126
+ @staticmethod
127
+ def __get_keys(d, name):
128
+ if 'state_dict' in d:
129
+ d = d['state_dict']
130
+ d_filt = {k[len(name) + 1:]: v for k, v in d.items() if k[:len(name)] == name}
131
+ return d_filt
models/stylegan2/__init__.py ADDED
File without changes
models/stylegan2/__pycache__/__init__.cpython-38.pyc ADDED
Binary file (124 Bytes). View file
 
models/stylegan2/__pycache__/model.cpython-38.pyc ADDED
Binary file (15.9 kB). View file