hail75 commited on
Commit
5b83793
·
1 Parent(s): 4c757df

fix importing issues

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. models/SRFlow/35000_G.pth +3 -0
  2. models/SRFlow/__pycache__/srflow.cpython-311.pyc +0 -0
  3. models/SRFlow/code/Measure.py +134 -0
  4. models/SRFlow/code/__init__.py +86 -0
  5. models/SRFlow/code/__pycache__/__init__.cpython-311.pyc +0 -0
  6. models/SRFlow/code/a.py +27 -0
  7. models/SRFlow/code/confs/RRDB_CelebA_8X.yml +83 -0
  8. models/SRFlow/code/confs/RRDB_DF2K_4X.yml +85 -0
  9. models/SRFlow/code/confs/RRDB_DF2K_8X.yml +85 -0
  10. models/SRFlow/code/confs/SRFlow_CelebA_8X.yml +107 -0
  11. models/SRFlow/code/confs/SRFlow_DF2K_4X.yml +106 -0
  12. models/SRFlow/code/confs/SRFlow_DF2K_8X.yml +112 -0
  13. models/SRFlow/code/data/LRHR_PKL_dataset.py +179 -0
  14. models/SRFlow/code/data/__init__.py +51 -0
  15. models/SRFlow/code/demo_on_pretrained.ipynb +0 -0
  16. models/SRFlow/code/imresize.py +180 -0
  17. models/SRFlow/code/models/SRFlow_model.py +280 -0
  18. models/SRFlow/code/models/SR_model.py +217 -0
  19. models/SRFlow/code/models/__init__.py +52 -0
  20. models/SRFlow/code/models/__pycache__/SRFlow_model.cpython-311.pyc +0 -0
  21. models/SRFlow/code/models/__pycache__/__init__.cpython-311.pyc +0 -0
  22. models/SRFlow/code/models/__pycache__/base_model.cpython-311.pyc +0 -0
  23. models/SRFlow/code/models/__pycache__/lr_scheduler.cpython-311.pyc +0 -0
  24. models/SRFlow/code/models/__pycache__/networks.cpython-311.pyc +0 -0
  25. models/SRFlow/code/models/base_model.py +154 -0
  26. models/SRFlow/code/models/lr_scheduler.py +163 -0
  27. models/SRFlow/code/models/modules/FlowActNorms.py +142 -0
  28. models/SRFlow/code/models/modules/FlowAffineCouplingsAblation.py +136 -0
  29. models/SRFlow/code/models/modules/FlowStep.py +139 -0
  30. models/SRFlow/code/models/modules/FlowUpsamplerNet.py +310 -0
  31. models/SRFlow/code/models/modules/Permutations.py +59 -0
  32. models/SRFlow/code/models/modules/RRDBNet_arch.py +150 -0
  33. models/SRFlow/code/models/modules/SRFlowNet_arch.py +160 -0
  34. models/SRFlow/code/models/modules/Split.py +87 -0
  35. models/SRFlow/code/models/modules/__init__.py +0 -0
  36. models/SRFlow/code/models/modules/__pycache__/FlowActNorms.cpython-311.pyc +0 -0
  37. models/SRFlow/code/models/modules/__pycache__/FlowAffineCouplingsAblation.cpython-311.pyc +0 -0
  38. models/SRFlow/code/models/modules/__pycache__/FlowStep.cpython-311.pyc +0 -0
  39. models/SRFlow/code/models/modules/__pycache__/FlowUpsamplerNet.cpython-311.pyc +0 -0
  40. models/SRFlow/code/models/modules/__pycache__/Permutations.cpython-311.pyc +0 -0
  41. models/SRFlow/code/models/modules/__pycache__/RRDBNet_arch.cpython-311.pyc +0 -0
  42. models/SRFlow/code/models/modules/__pycache__/SRFlowNet_arch.cpython-311.pyc +0 -0
  43. models/SRFlow/code/models/modules/__pycache__/Split.cpython-311.pyc +0 -0
  44. models/SRFlow/code/models/modules/__pycache__/__init__.cpython-311.pyc +0 -0
  45. models/SRFlow/code/models/modules/__pycache__/flow.cpython-311.pyc +0 -0
  46. models/SRFlow/code/models/modules/__pycache__/glow_arch.cpython-311.pyc +0 -0
  47. models/SRFlow/code/models/modules/__pycache__/module_util.cpython-311.pyc +0 -0
  48. models/SRFlow/code/models/modules/__pycache__/thops.cpython-311.pyc +0 -0
  49. models/SRFlow/code/models/modules/flow.py +167 -0
  50. models/SRFlow/code/models/modules/glow_arch.py +28 -0
models/SRFlow/35000_G.pth ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:040fcffde66ec3ef658a843d58832b8aa153734a2f04342d841e3018b498a511
3
+ size 158819348
models/SRFlow/__pycache__/srflow.cpython-311.pyc ADDED
Binary file (2.18 kB). View file
 
models/SRFlow/code/Measure.py ADDED
@@ -0,0 +1,134 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) 2020 Huawei Technologies Co., Ltd.
2
+ # Licensed under CC BY-NC-SA 4.0 (Attribution-NonCommercial-ShareAlike 4.0 International) (the "License");
3
+ # you may not use this file except in compliance with the License.
4
+ # You may obtain a copy of the License at
5
+ #
6
+ # https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode
7
+ #
8
+ # The code is released for academic research use only. For commercial use, please contact Huawei Technologies Co., Ltd.
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 glob
16
+ import os
17
+ import time
18
+ from collections import OrderedDict
19
+
20
+ import numpy as np
21
+ import torch
22
+ import cv2
23
+ import argparse
24
+
25
+ from natsort import natsort
26
+ from skimage.metrics import structural_similarity as ssim
27
+ from skimage.metrics import peak_signal_noise_ratio as psnr
28
+ import lpips
29
+
30
+
31
+ class Measure():
32
+ def __init__(self, net='alex', use_gpu=False):
33
+ self.device = 'cuda' if use_gpu else 'cpu'
34
+ self.model = lpips.LPIPS(net=net)
35
+ self.model.to(self.device)
36
+
37
+ def measure(self, imgA, imgB):
38
+ return [float(f(imgA, imgB)) for f in [self.psnr, self.ssim, self.lpips]]
39
+
40
+ def lpips(self, imgA, imgB, model=None):
41
+ tA = t(imgA).to(self.device)
42
+ tB = t(imgB).to(self.device)
43
+ dist01 = self.model.forward(tA, tB).item()
44
+ return dist01
45
+
46
+ def ssim(self, imgA, imgB):
47
+ # multichannel: If True, treat the last dimension of the array as channels. Similarity calculations are done independently for each channel then averaged.
48
+ score, diff = ssim(imgA, imgB, full=True, multichannel=True, channel_axis=-1)
49
+ return score
50
+
51
+ def psnr(self, imgA, imgB):
52
+ psnr_val = psnr(imgA, imgB)
53
+ return psnr_val
54
+
55
+
56
+ def t(img):
57
+ def to_4d(img):
58
+ assert len(img.shape) == 3
59
+ assert img.dtype == np.uint8
60
+ img_new = np.expand_dims(img, axis=0)
61
+ assert len(img_new.shape) == 4
62
+ return img_new
63
+
64
+ def to_CHW(img):
65
+ return np.transpose(img, [2, 0, 1])
66
+
67
+ def to_tensor(img):
68
+ return torch.Tensor(img)
69
+
70
+ return to_tensor(to_4d(to_CHW(img))) / 127.5 - 1
71
+
72
+
73
+ def fiFindByWildcard(wildcard):
74
+ return natsort.natsorted(glob.glob(wildcard, recursive=True))
75
+
76
+
77
+ def imread(path):
78
+ return cv2.imread(path)[:, :, [2, 1, 0]]
79
+
80
+
81
+ def format_result(psnr, ssim, lpips):
82
+ return f'{psnr:0.2f}, {ssim:0.3f}, {lpips:0.3f}'
83
+
84
+ def measure_dirs(dirA, dirB, use_gpu, verbose=False):
85
+ if verbose:
86
+ vprint = lambda x: print(x)
87
+ else:
88
+ vprint = lambda x: None
89
+
90
+
91
+ t_init = time.time()
92
+
93
+ paths_A = fiFindByWildcard(os.path.join(dirA, f'*.{type}'))
94
+ paths_B = fiFindByWildcard(os.path.join(dirB, f'*.{type}'))
95
+
96
+ vprint("Comparing: ")
97
+ vprint(dirA)
98
+ vprint(dirB)
99
+
100
+ measure = Measure(use_gpu=use_gpu)
101
+
102
+ results = []
103
+ for pathA, pathB in zip(paths_A, paths_B):
104
+ result = OrderedDict()
105
+
106
+ t = time.time()
107
+ result['psnr'], result['ssim'], result['lpips'] = measure.measure(imread(pathA), imread(pathB))
108
+ d = time.time() - t
109
+ vprint(f"{pathA.split('/')[-1]}, {pathB.split('/')[-1]}, {format_result(**result)}, {d:0.1f}")
110
+
111
+ results.append(result)
112
+
113
+ psnr = np.mean([result['psnr'] for result in results])
114
+ ssim = np.mean([result['ssim'] for result in results])
115
+ lpips = np.mean([result['lpips'] for result in results])
116
+
117
+ vprint(f"Final Result: {format_result(psnr, ssim, lpips)}, {time.time() - t_init:0.1f}s")
118
+
119
+
120
+ if __name__ == "__main__":
121
+ parser = argparse.ArgumentParser()
122
+ parser.add_argument('-dirA', default='', type=str)
123
+ parser.add_argument('-dirB', default='', type=str)
124
+ parser.add_argument('-type', default='png')
125
+ parser.add_argument('--use_gpu', action='store_true', default=False)
126
+ args = parser.parse_args()
127
+
128
+ dirA = args.dirA
129
+ dirB = args.dirB
130
+ type = args.type
131
+ use_gpu = args.use_gpu
132
+
133
+ if len(dirA) > 0 and len(dirB) > 0:
134
+ measure_dirs(dirA, dirB, use_gpu=use_gpu, verbose=True)
models/SRFlow/code/__init__.py ADDED
@@ -0,0 +1,86 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) 2020 Huawei Technologies Co., Ltd.
2
+ # Licensed under CC BY-NC-SA 4.0 (Attribution-NonCommercial-ShareAlike 4.0 International) (the "License");
3
+ # you may not use this file except in compliance with the License.
4
+ # You may obtain a copy of the License at
5
+ #
6
+ # https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode
7
+ #
8
+ # The code is released for academic research use only. For commercial use, please contact Huawei Technologies Co., Ltd.
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
+ # This file contains content licensed by https://github.com/xinntao/BasicSR/blob/master/LICENSE/LICENSE
16
+
17
+
18
+ import glob
19
+ import sys
20
+
21
+ sys.path.append('../..')
22
+ from natsort import natsort
23
+ import SRFlow.code.options.options as option
24
+
25
+ from SRFlow.code.models import create_model
26
+ import torch
27
+ from SRFlow.code.utils.util import opt_get
28
+ from SRFlow.code.models.SRFlow_model import SRFlowModel
29
+ import numpy as np
30
+ import os
31
+ import cv2
32
+
33
+
34
+ def fiFindByWildcard(wildcard):
35
+ return natsort.natsorted(glob.glob(wildcard, recursive=True))
36
+
37
+
38
+ def load_model(conf_path):
39
+ opt = option.parse(conf_path, is_train=False)
40
+ opt['gpu_ids'] = None
41
+ opt = option.dict_to_nonedict(opt)
42
+ model = SRFlowModel(opt, 0)
43
+
44
+ model_path = opt_get(opt, ['model_path'], None)
45
+ model.load_network(load_path='models/SRFlow/35000_G.pth', network=model.netG)
46
+ return model, opt
47
+
48
+
49
+ def predict(model, lr):
50
+ model.feed_data({"LQ": t(lr)}, need_GT=False)
51
+ model.test()
52
+ visuals = model.get_current_visuals(need_GT=False)
53
+ return visuals.get('rlt', visuals.get("SR"))
54
+
55
+
56
+ def t(array): return torch.Tensor(np.expand_dims(array.transpose([2, 0, 1]), axis=0).astype(np.float32)) / 255
57
+
58
+
59
+ def rgb(t): return (
60
+ np.clip((t[0] if len(t.shape) == 4 else t).detach().cpu().numpy().transpose([1, 2, 0]), 0, 1) * 255).astype(
61
+ np.uint8)
62
+
63
+
64
+ def imread(path):
65
+ return cv2.imread(path)[:, :, [2, 1, 0]]
66
+
67
+
68
+ def imwrite(path, img):
69
+ os.makedirs(os.path.dirname(path), exist_ok=True)
70
+ cv2.imwrite(path, img[:, :, [2, 1, 0]])
71
+
72
+
73
+ def imCropCenter(img, size):
74
+ h, w, c = img.shape
75
+
76
+ h_start = max(h // 2 - size // 2, 0)
77
+ h_end = min(h_start + size, h)
78
+
79
+ w_start = max(w // 2 - size // 2, 0)
80
+ w_end = min(w_start + size, w)
81
+
82
+ return img[h_start:h_end, w_start:w_end]
83
+
84
+
85
+ def impad(img, top=0, bottom=0, left=0, right=0, color=255):
86
+ return np.pad(img, [(top, bottom), (left, right), (0, 0)], 'reflect')
models/SRFlow/code/__pycache__/__init__.cpython-311.pyc ADDED
Binary file (4.88 kB). View file
 
models/SRFlow/code/a.py ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import pickle
2
+ import numpy as np
3
+ import os
4
+ import matplotlib.pyplot as plt
5
+
6
+ def load_pkls(path):
7
+ assert os.path.isfile(path), path
8
+ images = []
9
+ with open(path, "rb") as f:
10
+ images += pickle.load(f)
11
+ assert len(images) > 0, path
12
+ images = [np.transpose(image, [2, 0, 1]) for image in images]
13
+ return images
14
+
15
+ path = 'datasets/DIV2K-va.pklv4'
16
+ loaded_images = load_pkls(path)
17
+ print(len(loaded_images))
18
+ # Display the first image
19
+ if loaded_images:
20
+ first_image = loaded_images[11]
21
+ plt.imshow(np.transpose(first_image, [1, 2, 0])) # Transpose image to original shape [height, width, channels]
22
+ plt.title('First Image')
23
+ plt.axis('off') # Hide axis
24
+ plt.show()
25
+ else:
26
+ print("No images loaded from the pickle file.")
27
+ print(loaded_images[11])
models/SRFlow/code/confs/RRDB_CelebA_8X.yml ADDED
@@ -0,0 +1,83 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) 2020 Huawei Technologies Co., Ltd.
2
+ # Licensed under CC BY-NC-SA 4.0 (Attribution-NonCommercial-ShareAlike 4.0 International) (the "License");
3
+ # you may not use this file except in compliance with the License.
4
+ # You may obtain a copy of the License at
5
+ #
6
+ # https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode
7
+ #
8
+ # The code is released for academic research use only. For commercial use, please contact Huawei Technologies Co., Ltd.
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
+ # This file contains content licensed by https://github.com/xinntao/BasicSR/blob/master/LICENSE/LICENSE
16
+
17
+ #### general settings
18
+ name: train
19
+ use_tb_logger: true
20
+ model: SR
21
+ distortion: sr
22
+ scale: 8
23
+ #gpu_ids: [ 0 ]
24
+
25
+ #### datasets
26
+ datasets:
27
+ train:
28
+ name: CelebA_160_tr
29
+ mode: LRHR_PKL
30
+ dataroot_GT: ../datasets/celebA-train-gt_1pct.pklv4
31
+ dataroot_LQ: ../datasets/celebA-train-x8_1pct.pklv4
32
+
33
+ use_shuffle: true
34
+ n_workers: 0 # per GPU
35
+ batch_size: 16
36
+ GT_size: 160
37
+ use_flip: true
38
+ use_rot: true
39
+ color: RGB
40
+ val:
41
+ name: CelebA_160_va
42
+ mode: LRHR_PKL
43
+ dataroot_GT: ../datasets/celebA-valid-gt_1pct.pklv4
44
+ dataroot_LQ: ../datasets/celebA-valid-x8_1pct.pklv4
45
+ n_max: 10
46
+
47
+ #### network structures
48
+ network_G:
49
+ which_model_G: RRDBNet
50
+ in_nc: 3
51
+ out_nc: 3
52
+ nf: 64
53
+ nb: 23
54
+
55
+ #### path
56
+ path:
57
+ pretrain_model_G: ~
58
+ strict_load: true
59
+ resume_state: auto
60
+
61
+ #### training settings: learning rate scheme, loss
62
+ train:
63
+ lr_G: !!float 2e-4
64
+ lr_scheme: CosineAnnealingLR_Restart
65
+ beta1: 0.9
66
+ beta2: 0.99
67
+ niter: 200000
68
+ warmup_iter: -1 # no warm up
69
+ T_period: [ 50000, 50000, 50000, 50000 ]
70
+ restarts: [ 50000, 100000, 150000 ]
71
+ restart_weights: [ 1, 1, 1 ]
72
+ eta_min: !!float 1e-7
73
+
74
+ pixel_criterion: l1
75
+ pixel_weight: 1.0
76
+
77
+ manual_seed: 10
78
+ val_freq: !!float 5e3
79
+
80
+ #### logger
81
+ logger:
82
+ print_freq: 100
83
+ save_checkpoint_freq: !!float 1e3
models/SRFlow/code/confs/RRDB_DF2K_4X.yml ADDED
@@ -0,0 +1,85 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) 2020 Huawei Technologies Co., Ltd.
2
+ # Licensed under CC BY-NC-SA 4.0 (Attribution-NonCommercial-ShareAlike 4.0 International) (the "License");
3
+ # you may not use this file except in compliance with the License.
4
+ # You may obtain a copy of the License at
5
+ #
6
+ # https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode
7
+ #
8
+ # The code is released for academic research use only. For commercial use, please contact Huawei Technologies Co., Ltd.
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
+ # This file contains content licensed by https://github.com/xinntao/BasicSR/blob/master/LICENSE/LICENSE
16
+
17
+ #### general settings
18
+ name: train
19
+ use_tb_logger: true
20
+ model: SR
21
+ distortion: sr
22
+ scale: 4
23
+ gpu_ids: [ 0 ]
24
+
25
+ #### datasets
26
+ datasets:
27
+ train:
28
+ name: CelebA_160_tr
29
+ mode: LRHR_PKL
30
+ dataroot_GT: ../datasets/DF2K-train-gt_1pct.pklv4
31
+ dataroot_LQ: ../datasets/DF2K-train-x4_1pct.pklv4
32
+ quant: 32
33
+
34
+ use_shuffle: true
35
+ n_workers: 3 # per GPU
36
+ batch_size: 16
37
+ GT_size: 160
38
+ use_flip: true
39
+ color: RGB
40
+ val:
41
+ name: CelebA_160_va
42
+ mode: LRHR_PKL
43
+ dataroot_GT: ../datasets/DF2K-valid-gt_1pct.pklv4
44
+ dataroot_LQ: ../datasets/DF2K-valid-x4_1pct.pklv4
45
+ quant: 32
46
+ n_max: 20
47
+
48
+ #### network structures
49
+ network_G:
50
+ which_model_G: RRDBNet
51
+ use_orig: True
52
+ in_nc: 3
53
+ out_nc: 3
54
+ nf: 64
55
+ nb: 23
56
+
57
+ #### path
58
+ path:
59
+ pretrain_model_G: ~
60
+ strict_load: true
61
+ resume_state: auto
62
+
63
+ #### training settings: learning rate scheme, loss
64
+ train:
65
+ lr_G: !!float 2e-4
66
+ lr_scheme: CosineAnnealingLR_Restart
67
+ beta1: 0.9
68
+ beta2: 0.99
69
+ niter: 1000000
70
+ warmup_iter: -1 # no warm up
71
+ T_period: [ 50000, 50000, 50000, 50000 ]
72
+ restarts: [ 50000, 100000, 150000 ]
73
+ restart_weights: [ 1, 1, 1 ]
74
+ eta_min: !!float 1e-7
75
+
76
+ pixel_criterion: l1
77
+ pixel_weight: 1.0
78
+
79
+ manual_seed: 10
80
+ val_freq: !!float 5e3
81
+
82
+ #### logger
83
+ logger:
84
+ print_freq: 100
85
+ save_checkpoint_freq: !!float 1e3
models/SRFlow/code/confs/RRDB_DF2K_8X.yml ADDED
@@ -0,0 +1,85 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) 2020 Huawei Technologies Co., Ltd.
2
+ # Licensed under CC BY-NC-SA 4.0 (Attribution-NonCommercial-ShareAlike 4.0 International) (the "License");
3
+ # you may not use this file except in compliance with the License.
4
+ # You may obtain a copy of the License at
5
+ #
6
+ # https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode
7
+ #
8
+ # The code is released for academic research use only. For commercial use, please contact Huawei Technologies Co., Ltd.
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
+ # This file contains content licensed by https://github.com/xinntao/BasicSR/blob/master/LICENSE/LICENSE
16
+
17
+ #### general settings
18
+ name: train
19
+ use_tb_logger: true
20
+ model: SR
21
+ distortion: sr
22
+ scale: 8
23
+ gpu_ids: [ 0 ]
24
+
25
+ #### datasets
26
+ datasets:
27
+ train:
28
+ name: CelebA_160_tr
29
+ mode: LRHR_PKL
30
+ dataroot_GT: ../datasets/DF2K-train-gt_1pct.pklv4
31
+ dataroot_LQ: ../datasets/DF2K-train-x8_1pct.pklv4
32
+ quant: 32
33
+
34
+ use_shuffle: true
35
+ n_workers: 3 # per GPU
36
+ batch_size: 16
37
+ GT_size: 160
38
+ use_flip: true
39
+ color: RGB
40
+
41
+ val:
42
+ name: CelebA_160_va
43
+ mode: LRHR_PKL
44
+ dataroot_GT: ../datasets/DF2K-valid-gt_1pct.pklv4
45
+ dataroot_LQ: ../datasets/DF2K-valid-x8_1pct.pklv4
46
+ quant: 32
47
+ n_max: 20
48
+
49
+ #### network structures
50
+ network_G:
51
+ which_model_G: RRDBNet
52
+ in_nc: 3
53
+ out_nc: 3
54
+ nf: 64
55
+ nb: 23
56
+
57
+ #### path
58
+ path:
59
+ pretrain_model_G: ~
60
+ strict_load: true
61
+ resume_state: auto
62
+
63
+ #### training settings: learning rate scheme, loss
64
+ train:
65
+ lr_G: !!float 2e-4
66
+ lr_scheme: CosineAnnealingLR_Restart
67
+ beta1: 0.9
68
+ beta2: 0.99
69
+ niter: 200000
70
+ warmup_iter: -1 # no warm up
71
+ T_period: [ 50000, 50000, 50000, 50000 ]
72
+ restarts: [ 50000, 100000, 150000 ]
73
+ restart_weights: [ 1, 1, 1 ]
74
+ eta_min: !!float 1e-7
75
+
76
+ pixel_criterion: l1
77
+ pixel_weight: 1.0
78
+
79
+ manual_seed: 10
80
+ val_freq: !!float 5e3
81
+
82
+ #### logger
83
+ logger:
84
+ print_freq: 100
85
+ save_checkpoint_freq: !!float 1e3
models/SRFlow/code/confs/SRFlow_CelebA_8X.yml ADDED
@@ -0,0 +1,107 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) 2020 Huawei Technologies Co., Ltd.
2
+ # Licensed under CC BY-NC-SA 4.0 (Attribution-NonCommercial-ShareAlike 4.0 International) (the "License");
3
+ # you may not use this file except in compliance with the License.
4
+ # You may obtain a copy of the License at
5
+ #
6
+ # https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode
7
+ #
8
+ # The code is released for academic research use only. For commercial use, please contact Huawei Technologies Co., Ltd.
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
+ # This file contains content licensed by https://github.com/xinntao/BasicSR/blob/master/LICENSE/LICENSE
16
+
17
+ #### general settings
18
+ name: train
19
+ use_tb_logger: true
20
+ model: SRFlow
21
+ distortion: sr
22
+ scale: 8
23
+ gpu_ids: [ 0 ]
24
+
25
+ #### datasets
26
+ datasets:
27
+ train:
28
+ name: CelebA_160_tr
29
+ mode: LRHR_PKL
30
+ dataroot_GT: ../datasets/celebA-train-gt.pklv4
31
+ dataroot_LQ: ../datasets/celebA-train-x8.pklv4
32
+ quant: 32
33
+
34
+ use_shuffle: true
35
+ n_workers: 3 # per GPU
36
+ batch_size: 16
37
+ GT_size: 160
38
+ use_flip: true
39
+ color: RGB
40
+ val:
41
+ name: CelebA_160_va
42
+ mode: LRHR_PKL
43
+ dataroot_GT: ../datasets/celebA-train-gt.pklv4
44
+ dataroot_LQ: ../datasets/celebA-train-x8.pklv4
45
+ quant: 32
46
+ n_max: 20
47
+
48
+ #### Test Settings
49
+ dataroot_GT: ../datasets/celebA-validation-gt
50
+ dataroot_LR: ../datasets/celebA-validation-x8
51
+ model_path: ../pretrained_models/SRFlow_CelebA_8X.pth
52
+ heat: 0.9 # This is the standard deviation of the latent vectors
53
+
54
+ #### network structures
55
+ network_G:
56
+ which_model_G: SRFlowNet
57
+ in_nc: 3
58
+ out_nc: 3
59
+ nf: 64
60
+ nb: 8
61
+ upscale: 8
62
+ train_RRDB: false
63
+ train_RRDB_delay: 0.5
64
+
65
+ flow:
66
+ K: 16
67
+ L: 4
68
+ noInitialInj: true
69
+ coupling: CondAffineSeparatedAndCond
70
+ additionalFlowNoAffine: 2
71
+ split:
72
+ enable: true
73
+ fea_up0: true
74
+ stackRRDB:
75
+ blocks: [ 1, 3, 5, 7 ]
76
+ concat: true
77
+
78
+ #### path
79
+ path:
80
+ pretrain_model_G: ../pretrained_models/RRDB_CelebA_8X.pth
81
+ strict_load: true
82
+ resume_state: auto
83
+
84
+ #### training settings: learning rate scheme, loss
85
+ train:
86
+ manual_seed: 10
87
+ lr_G: !!float 5e-4
88
+ weight_decay_G: 0
89
+ beta1: 0.9
90
+ beta2: 0.99
91
+ lr_scheme: MultiStepLR
92
+ warmup_iter: -1 # no warm up
93
+ lr_steps_rel: [ 0.5, 0.75, 0.9, 0.95 ]
94
+ lr_gamma: 0.5
95
+
96
+ niter: 200000
97
+ val_freq: 40000
98
+
99
+ #### validation settings
100
+ val:
101
+ heats: [ 0.0, 0.5, 0.75, 1.0 ]
102
+ n_sample: 3
103
+
104
+ #### logger
105
+ logger:
106
+ print_freq: 100
107
+ save_checkpoint_freq: !!float 1e3
models/SRFlow/code/confs/SRFlow_DF2K_4X.yml ADDED
@@ -0,0 +1,106 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) 2020 Huawei Technologies Co., Ltd.
2
+ # Licensed under CC BY-NC-SA 4.0 (Attribution-NonCommercial-ShareAlike 4.0 International) (the "License");
3
+ # you may not use this file except in compliance with the License.
4
+ # You may obtain a copy of the License at
5
+ #
6
+ # https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode
7
+ #
8
+ # The code is released for academic research use only. For commercial use, please contact Huawei Technologies Co., Ltd.
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
+ # This file contains content licensed by https://github.com/xinntao/BasicSR/blob/master/LICENSE/LICENSE
16
+
17
+ #### general settings
18
+ name: train
19
+ use_tb_logger: true
20
+ model: SRFlow
21
+ distortion: sr
22
+ scale: 4
23
+ gpu_ids: [ 0 ]
24
+
25
+ #### datasets
26
+ datasets:
27
+ train:
28
+ name: DF2K_256_tr
29
+ mode: LRHR_PKL
30
+ dataroot_GT: /kaggle/input/srflow0103/SRFlow/datasets/DF2K-tr.pklv4
31
+ dataroot_LQ: /kaggle/input/srflow0103/SRFlow/datasets/DF2K-tr_X4.pklv4
32
+ quant: 32
33
+
34
+ use_shuffle: true
35
+ n_workers: 3 # per GPU
36
+ batch_size: 12
37
+ GT_size: 256
38
+ use_flip: true
39
+ color: RGB
40
+ val:
41
+ name: DF2K_256_tr
42
+ mode: LRHR_PKL
43
+ dataroot_GT: ../datasets/DIV2K-va.pklv4
44
+ dataroot_LQ: ../datasets/DIV2K-va_X4.pklv4
45
+ quant: 32
46
+ n_max: 20
47
+
48
+ #### Test Settings
49
+ dataroot: /kaggle/input/test-set/test set
50
+ model_path: models/SRFlow/35000_G
51
+ heat: 0.6 # This is the standard deviation of the latent vectors
52
+
53
+ #### network structures
54
+ network_G:
55
+ which_model_G: SRFlowNet
56
+ in_nc: 3
57
+ out_nc: 3
58
+ nf: 64
59
+ nb: 23
60
+ upscale: 4
61
+ train_RRDB: false
62
+ train_RRDB_delay: 0.5
63
+
64
+ flow:
65
+ K: 16
66
+ L: 3
67
+ noInitialInj: true
68
+ coupling: CondAffineSeparatedAndCond
69
+ additionalFlowNoAffine: 2
70
+ split:
71
+ enable: true
72
+ fea_up0: true
73
+ stackRRDB:
74
+ blocks: [ 1, 8, 15, 22 ]
75
+ concat: true
76
+
77
+ #### path
78
+ path:
79
+ pretrain_model_G:
80
+ strict_load: true
81
+ resume_state: auto
82
+
83
+ #### training settings: learning rate scheme, loss
84
+ train:
85
+ manual_seed: 10
86
+ lr_G: !!float 2.5e-4
87
+ weight_decay_G: 0
88
+ beta1: 0.9
89
+ beta2: 0.99
90
+ lr_scheme: MultiStepLR
91
+ warmup_iter: -1 # no warm up
92
+ lr_steps_rel: [ 0.5, 0.75, 0.9, 0.95 ]
93
+ lr_gamma: 0.5
94
+
95
+ niter: 64185
96
+ val_freq: 40000
97
+
98
+ #### validation settings
99
+ val:
100
+ heats: [ 0.0, 0.5, 0.75, 1.0 ]
101
+ n_sample: 3
102
+
103
+ #### logger
104
+ logger:
105
+ print_freq: 100
106
+ save_checkpoint_freq: !!float 5e3
models/SRFlow/code/confs/SRFlow_DF2K_8X.yml ADDED
@@ -0,0 +1,112 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) 2020 Huawei Technologies Co., Ltd.
2
+ # Licensed under CC BY-NC-SA 4.0 (Attribution-NonCommercial-ShareAlike 4.0 International) (the "License");
3
+ # you may not use this file except in compliance with the License.
4
+ # You may obtain a copy of the License at
5
+ #
6
+ # https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode
7
+ #
8
+ # The code is released for academic research use only. For commercial use, please contact Huawei Technologies Co., Ltd.
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
+ # This file contains content licensed by https://github.com/xinntao/BasicSR/blob/master/LICENSE/LICENSE
16
+
17
+ #### general settings
18
+ name: train
19
+ use_tb_logger: true
20
+ model: SRFlow
21
+ distortion: sr
22
+ scale: 8
23
+ gpu_ids: [ 0 ]
24
+
25
+ #### datasets
26
+ datasets:
27
+ train:
28
+ name: CelebA_160_tr
29
+ mode: LRHR_PKL
30
+ dataroot_GT: ../datasets/DF2K-tr.pklv4
31
+ dataroot_LQ: ../datasets/DF2K-tr_X8.pklv4
32
+ quant: 32
33
+
34
+ use_shuffle: true
35
+ n_workers: 3 # per GPU
36
+ batch_size: 16
37
+ GT_size: 160
38
+ use_flip: true
39
+ color: RGB
40
+
41
+ val:
42
+ name: CelebA_160_va
43
+ mode: LRHR_PKL
44
+ dataroot_GT: ../datasets/DIV2K-va.pklv4
45
+ dataroot_LQ: ../datasets/DIV2K-va_X8.pklv4
46
+ quant: 32
47
+ n_max: 20
48
+
49
+ #### Test Settings
50
+ dataroot_GT: ../datasets/div2k-validation-modcrop8-gt
51
+ dataroot_LR: ../datasets/div2k-validation-modcrop8-x8
52
+ model_path: ../pretrained_models/SRFlow_DF2K_8X.pth
53
+ heat: 0.9 # This is the standard deviation of the latent vectors
54
+
55
+ #### network structures
56
+ network_G:
57
+ which_model_G: SRFlowNet
58
+ in_nc: 3
59
+ out_nc: 3
60
+ nf: 64
61
+ nb: 23
62
+ upscale: 8
63
+ train_RRDB: false
64
+ train_RRDB_delay: 0.5
65
+
66
+ flow:
67
+ K: 16
68
+ L: 4
69
+ noInitialInj: true
70
+ coupling: CondAffineSeparatedAndCond
71
+ additionalFlowNoAffine: 2
72
+ split:
73
+ enable: true
74
+ fea_up0: true
75
+ stackRRDB:
76
+ blocks: [ 1, 3, 5, 7 ]
77
+ concat: true
78
+
79
+ #### path
80
+ path:
81
+ pretrain_model_G: ../pretrained_models/RRDB_DF2K_8X.pth
82
+ strict_load: true
83
+ resume_state: auto
84
+
85
+ #### training settings: learning rate scheme, loss
86
+ train:
87
+ manual_seed: 10
88
+ lr_G: !!float 5e-4
89
+ weight_decay_G: 0
90
+ beta1: 0.9
91
+ beta2: 0.99
92
+ lr_scheme: MultiStepLR
93
+ warmup_iter: -1 # no warm up
94
+ lr_steps_rel: [ 0.5, 0.75, 0.9, 0.95 ]
95
+ lr_gamma: 0.5
96
+
97
+ niter: 200000
98
+ val_freq: 40000
99
+
100
+ #### validation settings
101
+ val:
102
+ heats: [ 0.0, 0.5, 0.75, 1.0 ]
103
+ n_sample: 3
104
+
105
+ test:
106
+ heats: [ 0.0, 0.7, 0.8, 0.9 ]
107
+
108
+ #### logger
109
+ logger:
110
+ # Debug print_freq: 100
111
+ print_freq: 100
112
+ save_checkpoint_freq: !!float 1e3
models/SRFlow/code/data/LRHR_PKL_dataset.py ADDED
@@ -0,0 +1,179 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) 2020 Huawei Technologies Co., Ltd.
2
+ # Licensed under CC BY-NC-SA 4.0 (Attribution-NonCommercial-ShareAlike 4.0 International) (the "License");
3
+ # you may not use this file except in compliance with the License.
4
+ # You may obtain a copy of the License at
5
+ #
6
+ # https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode
7
+ #
8
+ # The code is released for academic research use only. For commercial use, please contact Huawei Technologies Co., Ltd.
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
+ # This file contains content licensed by https://github.com/xinntao/BasicSR/blob/master/LICENSE/LICENSE
16
+
17
+ import os
18
+ import subprocess
19
+ import torch.utils.data as data
20
+ import numpy as np
21
+ import time
22
+ import torch
23
+
24
+ import pickle
25
+
26
+
27
+ class LRHR_PKLDataset(data.Dataset):
28
+ def __init__(self, opt):
29
+ super(LRHR_PKLDataset, self).__init__()
30
+ self.opt = opt
31
+ self.crop_size = opt.get("GT_size", None)
32
+ self.scale = None
33
+ self.random_scale_list = [1]
34
+
35
+ hr_file_path = opt["dataroot_GT"]
36
+ lr_file_path = opt["dataroot_LQ"]
37
+ y_labels_file_path = opt['dataroot_y_labels']
38
+
39
+ gpu = True
40
+ augment = True
41
+
42
+ self.use_flip = opt["use_flip"] if "use_flip" in opt.keys() else False
43
+ self.use_rot = opt["use_rot"] if "use_rot" in opt.keys() else False
44
+ self.use_crop = opt["use_crop"] if "use_crop" in opt.keys() else False
45
+ self.center_crop_hr_size = opt.get("center_crop_hr_size", None)
46
+
47
+ n_max = opt["n_max"] if "n_max" in opt.keys() else int(1e8)
48
+
49
+ t = time.time()
50
+ self.lr_images = self.load_pkls(lr_file_path, n_max)
51
+ self.hr_images = self.load_pkls(hr_file_path, n_max)
52
+
53
+ min_val_hr = np.min([i.min() for i in self.hr_images[:20]])
54
+ max_val_hr = np.max([i.max() for i in self.hr_images[:20]])
55
+
56
+ min_val_lr = np.min([i.min() for i in self.lr_images[:20]])
57
+ max_val_lr = np.max([i.max() for i in self.lr_images[:20]])
58
+
59
+ t = time.time() - t
60
+ print("Loaded {} HR images with [{:.2f}, {:.2f}] in {:.2f}s from {}".
61
+ format(len(self.hr_images), min_val_hr, max_val_hr, t, hr_file_path))
62
+ print("Loaded {} LR images with [{:.2f}, {:.2f}] in {:.2f}s from {}".
63
+ format(len(self.lr_images), min_val_lr, max_val_lr, t, lr_file_path))
64
+
65
+ self.gpu = gpu
66
+ self.augment = augment
67
+
68
+ self.measures = None
69
+
70
+ def load_pkls(self, path, n_max):
71
+ assert os.path.isfile(path), path
72
+ images = []
73
+ with open(path, "rb") as f:
74
+ images += pickle.load(f)
75
+ assert len(images) > 0, path
76
+ images = images[:n_max]
77
+ images = [np.transpose(image, [2, 0, 1]) for image in images]
78
+ return images
79
+
80
+ def __len__(self):
81
+ return len(self.hr_images)
82
+
83
+ def __getitem__(self, item):
84
+ hr = self.hr_images[item]
85
+ lr = self.lr_images[item]
86
+
87
+ if self.scale == None:
88
+ self.scale = hr.shape[1] // lr.shape[1]
89
+ assert hr.shape[1] == self.scale * lr.shape[1], ('non-fractional ratio', lr.shape, hr.shape)
90
+
91
+ if self.use_crop:
92
+ hr, lr = random_crop(hr, lr, self.crop_size, self.scale, self.use_crop)
93
+
94
+ if self.center_crop_hr_size:
95
+ hr, lr = center_crop(hr, self.center_crop_hr_size), center_crop(lr, self.center_crop_hr_size // self.scale)
96
+
97
+ if self.use_flip:
98
+ hr, lr = random_flip(hr, lr)
99
+
100
+ if self.use_rot:
101
+ hr, lr = random_rotation(hr, lr)
102
+
103
+ hr = hr / 255.0
104
+ lr = lr / 255.0
105
+
106
+ if self.measures is None or np.random.random() < 0.05:
107
+ if self.measures is None:
108
+ self.measures = {}
109
+ self.measures['hr_means'] = np.mean(hr)
110
+ self.measures['hr_stds'] = np.std(hr)
111
+ self.measures['lr_means'] = np.mean(lr)
112
+ self.measures['lr_stds'] = np.std(lr)
113
+
114
+ hr = torch.Tensor(hr)
115
+ lr = torch.Tensor(lr)
116
+
117
+ # if self.gpu:
118
+ # hr = hr.cuda()
119
+ # lr = lr.cuda()
120
+
121
+ return {'LQ': lr, 'GT': hr, 'LQ_path': str(item), 'GT_path': str(item)}
122
+
123
+ def print_and_reset(self, tag):
124
+ m = self.measures
125
+ kvs = []
126
+ for k in sorted(m.keys()):
127
+ kvs.append("{}={:.2f}".format(k, m[k]))
128
+ print("[KPI] " + tag + ": " + ", ".join(kvs))
129
+ self.measures = None
130
+
131
+
132
+ def random_flip(img, seg):
133
+ random_choice = np.random.choice([True, False])
134
+ img = img if random_choice else np.flip(img, 2).copy()
135
+ seg = seg if random_choice else np.flip(seg, 2).copy()
136
+ return img, seg
137
+
138
+
139
+ def random_rotation(img, seg):
140
+ random_choice = np.random.choice([0, 1, 3])
141
+ img = np.rot90(img, random_choice, axes=(1, 2)).copy()
142
+ seg = np.rot90(seg, random_choice, axes=(1, 2)).copy()
143
+ return img, seg
144
+
145
+
146
+ def random_crop(hr, lr, size_hr, scale, random):
147
+ size_lr = size_hr // scale
148
+
149
+ size_lr_x = lr.shape[1]
150
+ size_lr_y = lr.shape[2]
151
+
152
+ start_x_lr = np.random.randint(low=0, high=(size_lr_x - size_lr) + 1) if size_lr_x > size_lr else 0
153
+ start_y_lr = np.random.randint(low=0, high=(size_lr_y - size_lr) + 1) if size_lr_y > size_lr else 0
154
+
155
+ # LR Patch
156
+ lr_patch = lr[:, start_x_lr:start_x_lr + size_lr, start_y_lr:start_y_lr + size_lr]
157
+
158
+ # HR Patch
159
+ start_x_hr = start_x_lr * scale
160
+ start_y_hr = start_y_lr * scale
161
+ hr_patch = hr[:, start_x_hr:start_x_hr + size_hr, start_y_hr:start_y_hr + size_hr]
162
+
163
+ return hr_patch, lr_patch
164
+
165
+
166
+ def center_crop(img, size):
167
+ assert img.shape[1] == img.shape[2], img.shape
168
+ border_double = img.shape[1] - size
169
+ assert border_double % 2 == 0, (img.shape, size)
170
+ border = border_double // 2
171
+ return img[:, border:-border, border:-border]
172
+
173
+
174
+ def center_crop_tensor(img, size):
175
+ assert img.shape[2] == img.shape[3], img.shape
176
+ border_double = img.shape[2] - size
177
+ assert border_double % 2 == 0, (img.shape, size)
178
+ border = border_double // 2
179
+ return img[:, :, border:-border, border:-border]
models/SRFlow/code/data/__init__.py ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) 2020 Huawei Technologies Co., Ltd.
2
+ # Licensed under CC BY-NC-SA 4.0 (Attribution-NonCommercial-ShareAlike 4.0 International) (the "License");
3
+ # you may not use this file except in compliance with the License.
4
+ # You may obtain a copy of the License at
5
+ #
6
+ # https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode
7
+ #
8
+ # The code is released for academic research use only. For commercial use, please contact Huawei Technologies Co., Ltd.
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
+ # This file contains content licensed by https://github.com/xinntao/BasicSR/blob/master/LICENSE/LICENSE
16
+
17
+ '''create dataset and dataloader'''
18
+ import logging
19
+ import torch
20
+ import torch.utils.data
21
+
22
+
23
+ def create_dataloader(dataset, dataset_opt, opt=None, sampler=None):
24
+ phase = dataset_opt.get('phase', 'test')
25
+ if phase == 'train':
26
+ gpu_ids = opt.get('gpu_ids', None)
27
+ gpu_ids = gpu_ids if gpu_ids else []
28
+ num_workers = dataset_opt['n_workers'] * len(gpu_ids)
29
+ batch_size = dataset_opt['batch_size']
30
+ shuffle = True
31
+ return torch.utils.data.DataLoader(dataset, batch_size=batch_size, shuffle=shuffle,
32
+ num_workers=num_workers, sampler=sampler, drop_last=True,
33
+ pin_memory=False)
34
+ else:
35
+ return torch.utils.data.DataLoader(dataset, batch_size=1, shuffle=False, num_workers=1,
36
+ pin_memory=True)
37
+
38
+
39
+ def create_dataset(dataset_opt):
40
+ print(dataset_opt)
41
+ mode = dataset_opt['mode']
42
+ if mode == 'LRHR_PKL':
43
+ from data.LRHR_PKL_dataset import LRHR_PKLDataset as D
44
+ else:
45
+ raise NotImplementedError('Dataset [{:s}] is not recognized.'.format(mode))
46
+ dataset = D(dataset_opt)
47
+
48
+ logger = logging.getLogger('base')
49
+ logger.info('Dataset [{:s} - {:s}] is created.'.format(dataset.__class__.__name__,
50
+ dataset_opt['name']))
51
+ return dataset
models/SRFlow/code/demo_on_pretrained.ipynb ADDED
The diff for this file is too large to render. See raw diff
 
models/SRFlow/code/imresize.py ADDED
@@ -0,0 +1,180 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # https://github.com/fatheral/matlab_imresize
2
+ #
3
+ # MIT License
4
+ #
5
+ # Copyright (c) 2020 Alex
6
+ #
7
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
8
+ # of this software and associated documentation files (the "Software"), to deal
9
+ # in the Software without restriction, including without limitation the rights
10
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ # copies of the Software, and to permit persons to whom the Software is
12
+ # furnished to do so, subject to the following conditions:
13
+ #
14
+ # The above copyright notice and this permission notice shall be included in all
15
+ # copies or substantial portions of the Software.
16
+ #
17
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23
+ # SOFTWARE.
24
+
25
+
26
+ from __future__ import print_function
27
+ import numpy as np
28
+ from math import ceil, floor
29
+
30
+
31
+ def deriveSizeFromScale(img_shape, scale):
32
+ output_shape = []
33
+ for k in range(2):
34
+ output_shape.append(int(ceil(scale[k] * img_shape[k])))
35
+ return output_shape
36
+
37
+
38
+ def deriveScaleFromSize(img_shape_in, img_shape_out):
39
+ scale = []
40
+ for k in range(2):
41
+ scale.append(1.0 * img_shape_out[k] / img_shape_in[k])
42
+ return scale
43
+
44
+
45
+ def triangle(x):
46
+ x = np.array(x).astype(np.float64)
47
+ lessthanzero = np.logical_and((x >= -1), x < 0)
48
+ greaterthanzero = np.logical_and((x <= 1), x >= 0)
49
+ f = np.multiply((x + 1), lessthanzero) + np.multiply((1 - x), greaterthanzero)
50
+ return f
51
+
52
+
53
+ def cubic(x):
54
+ x = np.array(x).astype(np.float64)
55
+ absx = np.absolute(x)
56
+ absx2 = np.multiply(absx, absx)
57
+ absx3 = np.multiply(absx2, absx)
58
+ f = np.multiply(1.5 * absx3 - 2.5 * absx2 + 1, absx <= 1) + np.multiply(-0.5 * absx3 + 2.5 * absx2 - 4 * absx + 2,
59
+ (1 < absx) & (absx <= 2))
60
+ return f
61
+
62
+
63
+ def contributions(in_length, out_length, scale, kernel, k_width):
64
+ if scale < 1:
65
+ h = lambda x: scale * kernel(scale * x)
66
+ kernel_width = 1.0 * k_width / scale
67
+ else:
68
+ h = kernel
69
+ kernel_width = k_width
70
+ x = np.arange(1, out_length + 1).astype(np.float64)
71
+ u = x / scale + 0.5 * (1 - 1 / scale)
72
+ left = np.floor(u - kernel_width / 2)
73
+ P = int(ceil(kernel_width)) + 2
74
+ ind = np.expand_dims(left, axis=1) + np.arange(P) - 1 # -1 because indexing from 0
75
+ indices = ind.astype(np.int32)
76
+ weights = h(np.expand_dims(u, axis=1) - indices - 1) # -1 because indexing from 0
77
+ weights = np.divide(weights, np.expand_dims(np.sum(weights, axis=1), axis=1))
78
+ aux = np.concatenate((np.arange(in_length), np.arange(in_length - 1, -1, step=-1))).astype(np.int32)
79
+ indices = aux[np.mod(indices, aux.size)]
80
+ ind2store = np.nonzero(np.any(weights, axis=0))
81
+ weights = weights[:, ind2store]
82
+ indices = indices[:, ind2store]
83
+ return weights, indices
84
+
85
+
86
+ def imresizemex(inimg, weights, indices, dim):
87
+ in_shape = inimg.shape
88
+ w_shape = weights.shape
89
+ out_shape = list(in_shape)
90
+ out_shape[dim] = w_shape[0]
91
+ outimg = np.zeros(out_shape)
92
+ if dim == 0:
93
+ for i_img in range(in_shape[1]):
94
+ for i_w in range(w_shape[0]):
95
+ w = weights[i_w, :]
96
+ ind = indices[i_w, :]
97
+ im_slice = inimg[ind, i_img].astype(np.float64)
98
+ outimg[i_w, i_img] = np.sum(np.multiply(np.squeeze(im_slice, axis=0), w.T), axis=0)
99
+ elif dim == 1:
100
+ for i_img in range(in_shape[0]):
101
+ for i_w in range(w_shape[0]):
102
+ w = weights[i_w, :]
103
+ ind = indices[i_w, :]
104
+ im_slice = inimg[i_img, ind].astype(np.float64)
105
+ outimg[i_img, i_w] = np.sum(np.multiply(np.squeeze(im_slice, axis=0), w.T), axis=0)
106
+ if inimg.dtype == np.uint8:
107
+ outimg = np.clip(outimg, 0, 255)
108
+ return np.around(outimg).astype(np.uint8)
109
+ else:
110
+ return outimg
111
+
112
+
113
+ def imresizevec(inimg, weights, indices, dim):
114
+ wshape = weights.shape
115
+ if dim == 0:
116
+ weights = weights.reshape((wshape[0], wshape[2], 1, 1))
117
+ outimg = np.sum(weights * ((inimg[indices].squeeze(axis=1)).astype(np.float64)), axis=1)
118
+ elif dim == 1:
119
+ weights = weights.reshape((1, wshape[0], wshape[2], 1))
120
+ outimg = np.sum(weights * ((inimg[:, indices].squeeze(axis=2)).astype(np.float64)), axis=2)
121
+ if inimg.dtype == np.uint8:
122
+ outimg = np.clip(outimg, 0, 255)
123
+ return np.around(outimg).astype(np.uint8)
124
+ else:
125
+ return outimg
126
+
127
+
128
+ def resizeAlongDim(A, dim, weights, indices, mode="vec"):
129
+ if mode == "org":
130
+ out = imresizemex(A, weights, indices, dim)
131
+ else:
132
+ out = imresizevec(A, weights, indices, dim)
133
+ return out
134
+
135
+
136
+ def imresize(I, scalar_scale=None, method='bicubic', output_shape=None, mode="vec"):
137
+ if method is 'bicubic':
138
+ kernel = cubic
139
+ elif method is 'bilinear':
140
+ kernel = triangle
141
+ else:
142
+ print('Error: Unidentified method supplied')
143
+
144
+ kernel_width = 4.0
145
+ # Fill scale and output_size
146
+ if scalar_scale is not None:
147
+ scalar_scale = float(scalar_scale)
148
+ scale = [scalar_scale, scalar_scale]
149
+ output_size = deriveSizeFromScale(I.shape, scale)
150
+ elif output_shape is not None:
151
+ scale = deriveScaleFromSize(I.shape, output_shape)
152
+ output_size = list(output_shape)
153
+ else:
154
+ print('Error: scalar_scale OR output_shape should be defined!')
155
+ return
156
+ scale_np = np.array(scale)
157
+ order = np.argsort(scale_np)
158
+ weights = []
159
+ indices = []
160
+ for k in range(2):
161
+ w, ind = contributions(I.shape[k], output_size[k], scale[k], kernel, kernel_width)
162
+ weights.append(w)
163
+ indices.append(ind)
164
+ B = np.copy(I)
165
+ flag2D = False
166
+ if B.ndim == 2:
167
+ B = np.expand_dims(B, axis=2)
168
+ flag2D = True
169
+ for k in range(2):
170
+ dim = order[k]
171
+ B = resizeAlongDim(B, dim, weights[dim], indices[dim], mode)
172
+ if flag2D:
173
+ B = np.squeeze(B, axis=2)
174
+ return B
175
+
176
+
177
+ def convertDouble2Byte(I):
178
+ B = np.clip(I, 0.0, 1.0)
179
+ B = 255 * B
180
+ return np.around(B).astype(np.uint8)
models/SRFlow/code/models/SRFlow_model.py ADDED
@@ -0,0 +1,280 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) 2020 Huawei Technologies Co., Ltd.
2
+ # Licensed under CC BY-NC-SA 4.0 (Attribution-NonCommercial-ShareAlike 4.0 International) (the "License");
3
+ # you may not use this file except in compliance with the License.
4
+ # You may obtain a copy of the License at
5
+ #
6
+ # https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode
7
+ #
8
+ # The code is released for academic research use only. For commercial use, please contact Huawei Technologies Co., Ltd.
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
+ # This file contains content licensed by https://github.com/xinntao/BasicSR/blob/master/LICENSE/LICENSE
16
+
17
+ import logging
18
+ import sys
19
+ sys.path.append('../..')
20
+ from collections import OrderedDict
21
+ from SRFlow.code.utils.util import get_resume_paths, opt_get
22
+
23
+ import torch
24
+ import torch.nn as nn
25
+ from torch.nn.parallel import DataParallel, DistributedDataParallel
26
+ import SRFlow.code.models.networks as networks
27
+ import SRFlow.code.models.lr_scheduler as lr_scheduler
28
+ from .base_model import BaseModel
29
+
30
+ logger = logging.getLogger('base')
31
+
32
+
33
+ class SRFlowModel(BaseModel):
34
+ def __init__(self, opt, step):
35
+ super(SRFlowModel, self).__init__(opt)
36
+ self.opt = opt
37
+
38
+ self.heats = opt['val']['heats']
39
+ self.n_sample = opt['val']['n_sample']
40
+ self.hr_size = opt_get(opt, ['datasets', 'train', 'center_crop_hr_size'])
41
+ self.hr_size = 256 if self.hr_size is None else self.hr_size
42
+ self.lr_size = self.hr_size // opt['scale']
43
+
44
+ if opt['dist']:
45
+ self.rank = torch.distributed.get_rank()
46
+ else:
47
+ self.rank = -1 # non dist training
48
+ train_opt = opt['train']
49
+
50
+ # define network and load pretrained models
51
+ self.netG = networks.define_Flow(opt, step).to(self.device)
52
+ if opt['dist']:
53
+ self.netG = DistributedDataParallel(self.netG, device_ids=[torch.cuda.current_device()])
54
+ else:
55
+ self.netG = DataParallel(self.netG)
56
+ # print network
57
+ self.print_network()
58
+
59
+ if opt_get(opt, ['path', 'resume_state'], 1) is not None:
60
+ self.load()
61
+ else:
62
+ print("WARNING: skipping initial loading, due to resume_state None")
63
+
64
+ if self.is_train:
65
+ self.netG.train()
66
+
67
+ self.init_optimizer_and_scheduler(train_opt)
68
+ self.log_dict = OrderedDict()
69
+
70
+ def to(self, device):
71
+ self.device = device
72
+ self.netG.to(device)
73
+
74
+ def init_optimizer_and_scheduler(self, train_opt):
75
+ # optimizers
76
+ self.optimizers = []
77
+ wd_G = train_opt['weight_decay_G'] if train_opt['weight_decay_G'] else 0
78
+ optim_params_RRDB = []
79
+ optim_params_other = []
80
+ for k, v in self.netG.named_parameters(): # can optimize for a part of the model
81
+ print(k, v.requires_grad)
82
+ if v.requires_grad:
83
+ if '.RRDB.' in k:
84
+ optim_params_RRDB.append(v)
85
+ print('opt', k)
86
+ else:
87
+ optim_params_other.append(v)
88
+ if self.rank <= 0:
89
+ logger.warning('Params [{:s}] will not optimize.'.format(k))
90
+
91
+ print('rrdb params', len(optim_params_RRDB))
92
+
93
+ self.optimizer_G = torch.optim.Adam(
94
+ [
95
+ {"params": optim_params_other, "lr": train_opt['lr_G'], 'beta1': train_opt['beta1'],
96
+ 'beta2': train_opt['beta2'], 'weight_decay': wd_G},
97
+ {"params": optim_params_RRDB, "lr": train_opt.get('lr_RRDB', train_opt['lr_G']),
98
+ 'beta1': train_opt['beta1'],
99
+ 'beta2': train_opt['beta2'], 'weight_decay': wd_G}
100
+ ],
101
+ )
102
+
103
+ self.optimizers.append(self.optimizer_G)
104
+ # schedulers
105
+ if train_opt['lr_scheme'] == 'MultiStepLR':
106
+ for optimizer in self.optimizers:
107
+ self.schedulers.append(
108
+ lr_scheduler.MultiStepLR_Restart(optimizer, train_opt['lr_steps'],
109
+ restarts=train_opt['restarts'],
110
+ weights=train_opt['restart_weights'],
111
+ gamma=train_opt['lr_gamma'],
112
+ clear_state=train_opt['clear_state'],
113
+ lr_steps_invese=train_opt.get('lr_steps_inverse', [])))
114
+ elif train_opt['lr_scheme'] == 'CosineAnnealingLR_Restart':
115
+ for optimizer in self.optimizers:
116
+ self.schedulers.append(
117
+ lr_scheduler.CosineAnnealingLR_Restart(
118
+ optimizer, train_opt['T_period'], eta_min=train_opt['eta_min'],
119
+ restarts=train_opt['restarts'], weights=train_opt['restart_weights']))
120
+ else:
121
+ raise NotImplementedError('MultiStepLR learning rate scheme is enough.')
122
+
123
+ def add_optimizer_and_scheduler_RRDB(self, train_opt):
124
+ # optimizers
125
+ assert len(self.optimizers) == 1, self.optimizers
126
+ assert len(self.optimizer_G.param_groups[1]['params']) == 0, self.optimizer_G.param_groups[1]
127
+ for k, v in self.netG.named_parameters(): # can optimize for a part of the model
128
+ if v.requires_grad:
129
+ if '.RRDB.' in k:
130
+ self.optimizer_G.param_groups[1]['params'].append(v)
131
+ assert len(self.optimizer_G.param_groups[1]['params']) > 0
132
+
133
+ def feed_data(self, data, need_GT=True):
134
+ self.var_L = data['LQ'].to(self.device) # LQ
135
+ if need_GT:
136
+ self.real_H = data['GT'].to(self.device) # GT
137
+
138
+ def optimize_parameters(self, step):
139
+
140
+ train_RRDB_delay = opt_get(self.opt, ['network_G', 'train_RRDB_delay'])
141
+ if train_RRDB_delay is not None and step > int(train_RRDB_delay * self.opt['train']['niter']) \
142
+ and not self.netG.module.RRDB_training:
143
+ if self.netG.module.set_rrdb_training(True):
144
+ self.add_optimizer_and_scheduler_RRDB(self.opt['train'])
145
+
146
+ # self.print_rrdb_state()
147
+
148
+ self.netG.train()
149
+ self.log_dict = OrderedDict()
150
+ self.optimizer_G.zero_grad()
151
+
152
+ losses = {}
153
+ weight_fl = opt_get(self.opt, ['train', 'weight_fl'])
154
+ weight_fl = 1 if weight_fl is None else weight_fl
155
+ if weight_fl > 0:
156
+ z, nll, y_logits = self.netG(gt=self.real_H, lr=self.var_L, reverse=False)
157
+ nll_loss = torch.mean(nll)
158
+ losses['nll_loss'] = nll_loss * weight_fl
159
+
160
+ weight_l1 = opt_get(self.opt, ['train', 'weight_l1']) or 0
161
+ if weight_l1 > 0:
162
+ z = self.get_z(heat=0, seed=None, batch_size=self.var_L.shape[0], lr_shape=self.var_L.shape)
163
+ sr, logdet = self.netG(lr=self.var_L, z=z, eps_std=0, reverse=True, reverse_with_grad=True)
164
+ l1_loss = (sr - self.real_H).abs().mean()
165
+ losses['l1_loss'] = l1_loss * weight_l1
166
+
167
+ total_loss = sum(losses.values())
168
+ total_loss.backward()
169
+ self.optimizer_G.step()
170
+
171
+ mean = total_loss.item()
172
+ return mean
173
+
174
+ def print_rrdb_state(self):
175
+ for name, param in self.netG.module.named_parameters():
176
+ if "RRDB.conv_first.weight" in name:
177
+ print(name, param.requires_grad, param.data.abs().sum())
178
+ print('params', [len(p['params']) for p in self.optimizer_G.param_groups])
179
+
180
+ def test(self):
181
+ self.netG.eval()
182
+ self.fake_H = {}
183
+ for heat in self.heats:
184
+ for i in range(self.n_sample):
185
+ z = self.get_z(heat, seed=None, batch_size=self.var_L.shape[0], lr_shape=self.var_L.shape)
186
+ with torch.no_grad():
187
+ self.fake_H[(heat, i)], logdet = self.netG(lr=self.var_L, z=z, eps_std=heat, reverse=True)
188
+ with torch.no_grad():
189
+ _, nll, _ = self.netG(gt=self.real_H, lr=self.var_L, reverse=False)
190
+ self.netG.train()
191
+ return nll.mean().item()
192
+
193
+ def get_encode_nll(self, lq, gt):
194
+ self.netG.eval()
195
+ with torch.no_grad():
196
+ _, nll, _ = self.netG(gt=gt, lr=lq, reverse=False)
197
+ self.netG.train()
198
+ return nll.mean().item()
199
+
200
+ def get_sr(self, lq, heat=None, seed=None, z=None, epses=None):
201
+ return self.get_sr_with_z(lq, heat, seed, z, epses)[0]
202
+
203
+ def get_encode_z(self, lq, gt, epses=None, add_gt_noise=True):
204
+ self.netG.eval()
205
+ with torch.no_grad():
206
+ z, _, _ = self.netG(gt=gt, lr=lq, reverse=False, epses=epses, add_gt_noise=add_gt_noise)
207
+ self.netG.train()
208
+ return z
209
+
210
+ def get_encode_z_and_nll(self, lq, gt, epses=None, add_gt_noise=True):
211
+ self.netG.eval()
212
+ with torch.no_grad():
213
+ z, nll, _ = self.netG(gt=gt, lr=lq, reverse=False, epses=epses, add_gt_noise=add_gt_noise)
214
+ self.netG.train()
215
+ return z, nll
216
+
217
+ def get_sr_with_z(self, lq, heat=None, seed=None, z=None, epses=None):
218
+ self.netG.eval()
219
+
220
+ z = self.get_z(heat, seed, batch_size=lq.shape[0], lr_shape=lq.shape) if z is None and epses is None else z
221
+
222
+ with torch.no_grad():
223
+ sr, logdet = self.netG(lr=lq, z=z, eps_std=heat, reverse=True, epses=epses)
224
+ self.netG.train()
225
+ return sr, z
226
+
227
+ def get_z(self, heat, seed=None, batch_size=1, lr_shape=None):
228
+ if seed: torch.manual_seed(seed)
229
+ if opt_get(self.opt, ['network_G', 'flow', 'split', 'enable']):
230
+ C = self.netG.module.flowUpsamplerNet.C
231
+ H = int(self.opt['scale'] * lr_shape[2] // self.netG.module.flowUpsamplerNet.scaleH)
232
+ W = int(self.opt['scale'] * lr_shape[3] // self.netG.module.flowUpsamplerNet.scaleW)
233
+ z = torch.normal(mean=0, std=heat, size=(batch_size, C, H, W)) if heat > 0 else torch.zeros(
234
+ (batch_size, C, H, W))
235
+ else:
236
+ L = opt_get(self.opt, ['network_G', 'flow', 'L']) or 3
237
+ fac = 2 ** (L - 3)
238
+ z_size = int(self.lr_size // (2 ** (L - 3)))
239
+ z = torch.normal(mean=0, std=heat, size=(batch_size, 3 * 8 * 8 * fac * fac, z_size, z_size))
240
+ return z
241
+
242
+ def get_current_log(self):
243
+ return self.log_dict
244
+
245
+ def get_current_visuals(self, need_GT=True):
246
+ out_dict = OrderedDict()
247
+ out_dict['LQ'] = self.var_L.detach()[0].float().cpu()
248
+ for heat in self.heats:
249
+ for i in range(self.n_sample):
250
+ out_dict[('SR', heat, i)] = self.fake_H[(heat, i)].detach()[0].float().cpu()
251
+ if need_GT:
252
+ out_dict['GT'] = self.real_H.detach()[0].float().cpu()
253
+ return out_dict
254
+
255
+ def print_network(self):
256
+ s, n = self.get_network_description(self.netG)
257
+ if isinstance(self.netG, nn.DataParallel) or isinstance(self.netG, DistributedDataParallel):
258
+ net_struc_str = '{} - {}'.format(self.netG.__class__.__name__,
259
+ self.netG.module.__class__.__name__)
260
+ else:
261
+ net_struc_str = '{}'.format(self.netG.__class__.__name__)
262
+ if self.rank <= 0:
263
+ logger.info('Network G structure: {}, with parameters: {:,d}'.format(net_struc_str, n))
264
+ logger.info(s)
265
+
266
+ def load(self):
267
+ _, get_resume_model_path = get_resume_paths(self.opt)
268
+ if get_resume_model_path is not None:
269
+ self.load_network(get_resume_model_path, self.netG, strict=True, submodule=None)
270
+ return
271
+
272
+ load_path_G = self.opt['path']['pretrain_model_G']
273
+ load_submodule = self.opt['path']['load_submodule'] if 'load_submodule' in self.opt['path'].keys() else 'RRDB'
274
+ if load_path_G is not None:
275
+ logger.info('Loading model for G [{:s}] ...'.format(load_path_G))
276
+ self.load_network(load_path_G, self.netG, self.opt['path'].get('strict_load', True),
277
+ submodule=load_submodule)
278
+
279
+ def save(self, iter_label):
280
+ self.save_network(self.netG, 'G', iter_label)
models/SRFlow/code/models/SR_model.py ADDED
@@ -0,0 +1,217 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) 2020 Huawei Technologies Co., Ltd.
2
+ # Licensed under CC BY-NC-SA 4.0 (Attribution-NonCommercial-ShareAlike 4.0 International) (the "License");
3
+ # you may not use this file except in compliance with the License.
4
+ # You may obtain a copy of the License at
5
+ #
6
+ # https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode
7
+ #
8
+ # The code is released for academic research use only. For commercial use, please contact Huawei Technologies Co., Ltd.
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
+ # This file contains content licensed by https://github.com/xinntao/BasicSR/blob/master/LICENSE/LICENSE
16
+
17
+ import logging
18
+ from collections import OrderedDict
19
+
20
+ import torch
21
+ import torch.nn as nn
22
+ from torch.nn.parallel import DataParallel, DistributedDataParallel
23
+ import models.networks as networks
24
+ import models.lr_scheduler as lr_scheduler
25
+ from utils.util import opt_get
26
+ from .base_model import BaseModel
27
+ from models.modules.loss import CharbonnierLoss
28
+
29
+ logger = logging.getLogger('base')
30
+
31
+
32
+ class SRModel(BaseModel):
33
+ def __init__(self, opt, step):
34
+ super(SRModel, self).__init__(opt)
35
+
36
+ self.step = step
37
+
38
+ if opt['dist']:
39
+ self.rank = torch.distributed.get_rank()
40
+ else:
41
+ self.rank = -1 # non dist training
42
+ train_opt = opt['train']
43
+
44
+ # define network and load pretrained_models models
45
+ self.netG = networks.define_G(opt).to(self.device)
46
+ if opt['dist']:
47
+ self.netG = DistributedDataParallel(self.netG, device_ids=[torch.cuda.current_device()])
48
+ else:
49
+ self.netG = DataParallel(self.netG)
50
+ # print network
51
+ self.print_network()
52
+ self.load()
53
+
54
+ if self.is_train:
55
+ self.netG.train()
56
+
57
+ # loss
58
+ loss_type = train_opt['pixel_criterion']
59
+ if loss_type == 'l1':
60
+ self.cri_pix = nn.L1Loss().to(self.device)
61
+ elif loss_type == 'l2':
62
+ self.cri_pix = nn.MSELoss().to(self.device)
63
+ elif loss_type == 'cb':
64
+ self.cri_pix = CharbonnierLoss().to(self.device)
65
+ else:
66
+ raise NotImplementedError('Loss type [{:s}] is not recognized.'.format(loss_type))
67
+ self.l_pix_w = train_opt['pixel_weight']
68
+
69
+ # optimizers
70
+ wd_G = train_opt['weight_decay_G'] if train_opt['weight_decay_G'] else 0
71
+ optim_params = []
72
+ for k, v in self.netG.named_parameters(): # can optimize for a part of the model
73
+ if v.requires_grad:
74
+ optim_params.append(v)
75
+ else:
76
+ if self.rank <= 0:
77
+ logger.warning('Params [{:s}] will not optimize.'.format(k))
78
+ self.optimizer_G = torch.optim.Adam(optim_params, lr=train_opt['lr_G'],
79
+ weight_decay=wd_G,
80
+ betas=(train_opt['beta1'], train_opt['beta2']))
81
+ self.optimizers.append(self.optimizer_G)
82
+
83
+ # schedulers
84
+ if train_opt['lr_scheme'] == 'MultiStepLR':
85
+ for optimizer in self.optimizers:
86
+ self.schedulers.append(
87
+ lr_scheduler.MultiStepLR_Restart(optimizer, train_opt['lr_steps'],
88
+ restarts=train_opt['restarts'],
89
+ weights=train_opt['restart_weights'],
90
+ gamma=train_opt['lr_gamma'],
91
+ clear_state=train_opt['clear_state']))
92
+ elif train_opt['lr_scheme'] == 'CosineAnnealingLR_Restart':
93
+ for optimizer in self.optimizers:
94
+ self.schedulers.append(
95
+ lr_scheduler.CosineAnnealingLR_Restart(
96
+ optimizer, train_opt['T_period'], eta_min=train_opt['eta_min'],
97
+ restarts=train_opt['restarts'], weights=train_opt['restart_weights']))
98
+ else:
99
+ raise NotImplementedError('MultiStepLR learning rate scheme is enough.')
100
+
101
+ self.log_dict = OrderedDict()
102
+
103
+ def feed_data(self, data, need_GT=True):
104
+ self.var_L = data['LQ'].to(self.device) # LQ
105
+ if need_GT:
106
+ self.real_H = data['GT'].to(self.device) # GT
107
+
108
+ def to(self, device):
109
+ self.device = device
110
+ self.netG.to(device)
111
+
112
+ def optimize_parameters(self, step):
113
+ def getEnv(name): import os; return True if name in os.environ.keys() else False
114
+
115
+ if getEnv("DEBUG_FEED_IMAGES"):
116
+ import imageio
117
+ import random
118
+ i = random.randint(0, 10000)
119
+ label = self.var_L.cpu().numpy()[0].transpose([1, 2, 0])
120
+ print("var_L", label.min(), label.max(), label.shape)
121
+ imageio.imwrite("/tmp/{}_l.png".format(i), label)
122
+ image = self.real_H.cpu().numpy()[0].transpose([1, 2, 0])
123
+ print("self.real_H", image.min(), image.max(), image.shape)
124
+ imageio.imwrite("/tmp/{}_gt.png".format(i), image)
125
+ self.optimizer_G.zero_grad()
126
+ self.fake_H = self.netG(self.var_L)
127
+ l_pix = self.l_pix_w * self.cri_pix(self.fake_H, self.real_H.to(self.fake_H.device))
128
+ l_pix.backward()
129
+ self.optimizer_G.step()
130
+
131
+ # set log
132
+ self.log_dict['l_pix'] = l_pix.item()
133
+
134
+ def test(self):
135
+ self.netG.eval()
136
+ with torch.no_grad():
137
+ self.fake_H = self.netG(self.var_L)
138
+ self.netG.train()
139
+
140
+ def get_encode_nll(self, lq, gt):
141
+ return torch.ones(1) * 1e14
142
+
143
+ def get_sr(self, lq, heat=None, seed=None):
144
+ self.netG.eval()
145
+ sr = self.netG(lq)
146
+ self.netG.train()
147
+ return sr
148
+
149
+ def test_x8(self):
150
+ # from https://github.com/thstkdgus35/EDSR-PyTorch
151
+ self.netG.eval()
152
+
153
+ def _transform(v, op):
154
+ # if self.precision != 'single': v = v.float()
155
+ v2np = v.data.cpu().numpy()
156
+ if op == 'v':
157
+ tfnp = v2np[:, :, :, ::-1].copy()
158
+ elif op == 'h':
159
+ tfnp = v2np[:, :, ::-1, :].copy()
160
+ elif op == 't':
161
+ tfnp = v2np.transpose((0, 1, 3, 2)).copy()
162
+
163
+ ret = torch.Tensor(tfnp).to(self.device)
164
+ # if self.precision == 'half': ret = ret.half()
165
+
166
+ return ret
167
+
168
+ lr_list = [self.var_L]
169
+ for tf in 'v', 'h', 't':
170
+ lr_list.extend([_transform(t, tf) for t in lr_list])
171
+ with torch.no_grad():
172
+ sr_list = [self.netG(aug) for aug in lr_list]
173
+ for i in range(len(sr_list)):
174
+ if i > 3:
175
+ sr_list[i] = _transform(sr_list[i], 't')
176
+ if i % 4 > 1:
177
+ sr_list[i] = _transform(sr_list[i], 'h')
178
+ if (i % 4) % 2 == 1:
179
+ sr_list[i] = _transform(sr_list[i], 'v')
180
+
181
+ output_cat = torch.cat(sr_list, dim=0)
182
+ self.fake_H = output_cat.mean(dim=0, keepdim=True)
183
+ self.netG.train()
184
+
185
+ def get_current_log(self):
186
+ return self.log_dict
187
+
188
+ def get_current_visuals(self, need_GT=True):
189
+ out_dict = OrderedDict()
190
+ out_dict['LQ'] = self.var_L.detach()[0].float().cpu()
191
+ out_dict['SR'] = self.fake_H.detach()[0].float().cpu()
192
+ if need_GT:
193
+ out_dict['GT'] = self.real_H.detach()[0].float().cpu()
194
+ return out_dict
195
+
196
+ def print_network(self):
197
+ s, n = self.get_network_description(self.netG)
198
+ if isinstance(self.netG, nn.DataParallel) or isinstance(self.netG, DistributedDataParallel):
199
+ net_struc_str = '{} - {}'.format(self.netG.__class__.__name__,
200
+ self.netG.module.__class__.__name__)
201
+ else:
202
+ net_struc_str = '{}'.format(self.netG.__class__.__name__)
203
+ if self.rank <= 0:
204
+ logger.info('Network G structure: {}, with parameters: {:,d}'.format(net_struc_str, n))
205
+ logger.info(s)
206
+
207
+ def load(self):
208
+ load_path_G = self.opt['path']['pretrain_model_G']
209
+ if load_path_G is not None:
210
+ logger.info('Loading model for G [{:s}] ...'.format(load_path_G))
211
+ self.load_network(load_path_G, self.netG, self.opt['path']['strict_load'])
212
+
213
+ def save(self, iter_label):
214
+ self.save_network(self.netG, 'G', iter_label)
215
+
216
+ def get_encode_z_and_nll(self, *args, **kwargs):
217
+ return [], torch.zeros(1)
models/SRFlow/code/models/__init__.py ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import importlib
2
+ import logging
3
+ import os
4
+
5
+ try:
6
+ import local_config
7
+ except:
8
+ local_config = None
9
+
10
+
11
+ logger = logging.getLogger('base')
12
+
13
+
14
+ def find_model_using_name(model_name):
15
+ # Given the option --model [modelname],
16
+ # the file "models/modelname_model.py"
17
+ # will be imported.
18
+ model_filename = "SRFlow.code.models." + model_name + "_model"
19
+ modellib = importlib.import_module(model_filename)
20
+
21
+ # In the file, the class called ModelNameModel() will
22
+ # be instantiated. It has to be a subclass of torch.nn.Module,
23
+ # and it is case-insensitive.
24
+ model = None
25
+ target_model_name = model_name.replace('_', '') + 'Model'
26
+ for name, cls in modellib.__dict__.items():
27
+ if name.lower() == target_model_name.lower():
28
+ model = cls
29
+
30
+ if model is None:
31
+ print(
32
+ "In %s.py, there should be a subclass of torch.nn.Module with class name that matches %s." % (
33
+ model_filename, target_model_name))
34
+ exit(0)
35
+
36
+ return model
37
+
38
+
39
+ def create_model(opt, step=0, **opt_kwargs):
40
+ if local_config is not None:
41
+ opt['path']['pretrain_model_G'] = os.path.join(local_config.checkpoint_path, os.path.basename(opt['path']['results_root'] + '.pth'))
42
+
43
+ for k, v in opt_kwargs.items():
44
+ opt[k] = v
45
+
46
+ model = opt['model']
47
+
48
+ M = find_model_using_name(model)
49
+
50
+ m = M(opt, step)
51
+ logger.info('Model [{:s}] is created.'.format(m.__class__.__name__))
52
+ return m
models/SRFlow/code/models/__pycache__/SRFlow_model.cpython-311.pyc ADDED
Binary file (20.7 kB). View file
 
models/SRFlow/code/models/__pycache__/__init__.cpython-311.pyc ADDED
Binary file (2.4 kB). View file
 
models/SRFlow/code/models/__pycache__/base_model.cpython-311.pyc ADDED
Binary file (11.2 kB). View file
 
models/SRFlow/code/models/__pycache__/lr_scheduler.cpython-311.pyc ADDED
Binary file (9.95 kB). View file
 
models/SRFlow/code/models/__pycache__/networks.cpython-311.pyc ADDED
Binary file (4.41 kB). View file
 
models/SRFlow/code/models/base_model.py ADDED
@@ -0,0 +1,154 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) 2020 Huawei Technologies Co., Ltd.
2
+ # Licensed under CC BY-NC-SA 4.0 (Attribution-NonCommercial-ShareAlike 4.0 International) (the "License");
3
+ # you may not use this file except in compliance with the License.
4
+ # You may obtain a copy of the License at
5
+ #
6
+ # https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode
7
+ #
8
+ # The code is released for academic research use only. For commercial use, please contact Huawei Technologies Co., Ltd.
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
+ # This file contains content licensed by https://github.com/xinntao/BasicSR/blob/master/LICENSE/LICENSE
16
+
17
+ import os
18
+ from collections import OrderedDict
19
+ import torch
20
+ import torch.nn as nn
21
+ from torch.nn.parallel import DistributedDataParallel
22
+ import natsort
23
+ import glob
24
+
25
+
26
+ class BaseModel():
27
+ def __init__(self, opt):
28
+ self.opt = opt
29
+ self.device = torch.device('cuda' if opt.get('gpu_ids', None) is not None else 'cpu')
30
+ self.is_train = opt['is_train']
31
+ self.schedulers = []
32
+ self.optimizers = []
33
+
34
+ def feed_data(self, data):
35
+ pass
36
+
37
+ def optimize_parameters(self):
38
+ pass
39
+
40
+ def get_current_visuals(self):
41
+ pass
42
+
43
+ def get_current_losses(self):
44
+ pass
45
+
46
+ def print_network(self):
47
+ pass
48
+
49
+ def save(self, label):
50
+ pass
51
+
52
+ def load(self):
53
+ pass
54
+
55
+ def _set_lr(self, lr_groups_l):
56
+ ''' set learning rate for warmup,
57
+ lr_groups_l: list for lr_groups. each for a optimizer'''
58
+ for optimizer, lr_groups in zip(self.optimizers, lr_groups_l):
59
+ for param_group, lr in zip(optimizer.param_groups, lr_groups):
60
+ param_group['lr'] = lr
61
+
62
+ def _get_init_lr(self):
63
+ # get the initial lr, which is set by the scheduler
64
+ init_lr_groups_l = []
65
+ for optimizer in self.optimizers:
66
+ init_lr_groups_l.append([v['initial_lr'] for v in optimizer.param_groups])
67
+ return init_lr_groups_l
68
+
69
+ def update_learning_rate(self, cur_iter, warmup_iter=-1):
70
+ for scheduler in self.schedulers:
71
+ scheduler.step()
72
+ #### set up warm up learning rate
73
+ if cur_iter < warmup_iter:
74
+ # get initial lr for each group
75
+ init_lr_g_l = self._get_init_lr()
76
+ # modify warming-up learning rates
77
+ warm_up_lr_l = []
78
+ for init_lr_g in init_lr_g_l:
79
+ warm_up_lr_l.append([v / warmup_iter * cur_iter for v in init_lr_g])
80
+ # set learning rate
81
+ self._set_lr(warm_up_lr_l)
82
+
83
+ def get_current_learning_rate(self):
84
+ # return self.schedulers[0].get_lr()[0]
85
+ return self.optimizers[0].param_groups[0]['lr']
86
+
87
+ def get_network_description(self, network):
88
+ '''Get the string and total parameters of the network'''
89
+ if isinstance(network, nn.DataParallel) or isinstance(network, DistributedDataParallel):
90
+ network = network.module
91
+ s = str(network)
92
+ n = sum(map(lambda x: x.numel(), network.parameters()))
93
+ return s, n
94
+
95
+ def save_network(self, network, network_label, iter_label):
96
+ paths = natsort.natsorted(glob.glob(os.path.join(self.opt['path']['models'], "*_{}.pth".format(network_label))),
97
+ reverse=True)
98
+ paths = [p for p in paths if
99
+ "latest_" not in p and not any([str(i * 10000) in p.split("/")[-1].split("_") for i in range(101)])]
100
+ if len(paths) > 2:
101
+ for path in paths[2:]:
102
+ os.remove(path)
103
+ save_filename = '{}_{}.pth'.format(iter_label, network_label)
104
+ save_path = os.path.join(self.opt['path']['models'], save_filename)
105
+ if isinstance(network, nn.DataParallel) or isinstance(network, DistributedDataParallel):
106
+ network = network.module
107
+ state_dict = network.state_dict()
108
+ for key, param in state_dict.items():
109
+ state_dict[key] = param.cpu()
110
+ torch.save(state_dict, save_path)
111
+
112
+ def load_network(self, load_path, network, strict=True, submodule=None):
113
+ if isinstance(network, nn.DataParallel) or isinstance(network, DistributedDataParallel):
114
+ network = network.module
115
+ if not (submodule is None or submodule.lower() == 'none'.lower()):
116
+ network = network.__getattr__(submodule)
117
+ load_net = torch.load(load_path)
118
+ load_net_clean = OrderedDict() # remove unnecessary 'module.'
119
+ for k, v in load_net.items():
120
+ if k.startswith('module.'):
121
+ load_net_clean[k[7:]] = v
122
+ else:
123
+ load_net_clean[k] = v
124
+ network.load_state_dict(load_net_clean, strict=strict)
125
+
126
+ def save_training_state(self, epoch, iter_step):
127
+ '''Saves training state during training, which will be used for resuming'''
128
+ state = {'epoch': epoch, 'iter': iter_step, 'schedulers': [], 'optimizers': []}
129
+ for s in self.schedulers:
130
+ state['schedulers'].append(s.state_dict())
131
+ for o in self.optimizers:
132
+ state['optimizers'].append(o.state_dict())
133
+ save_filename = '{}.state'.format(iter_step)
134
+ save_path = os.path.join(self.opt['path']['training_state'], save_filename)
135
+
136
+ paths = natsort.natsorted(glob.glob(os.path.join(self.opt['path']['training_state'], "*.state")),
137
+ reverse=True)
138
+ paths = [p for p in paths if "latest_" not in p]
139
+ if len(paths) > 2:
140
+ for path in paths[2:]:
141
+ os.remove(path)
142
+
143
+ torch.save(state, save_path)
144
+
145
+ def resume_training(self, resume_state):
146
+ '''Resume the optimizers and schedulers for training'''
147
+ resume_optimizers = resume_state['optimizers']
148
+ resume_schedulers = resume_state['schedulers']
149
+ assert len(resume_optimizers) == len(self.optimizers), 'Wrong lengths of optimizers'
150
+ assert len(resume_schedulers) == len(self.schedulers), 'Wrong lengths of schedulers'
151
+ for i, o in enumerate(resume_optimizers):
152
+ self.optimizers[i].load_state_dict(o)
153
+ for i, s in enumerate(resume_schedulers):
154
+ self.schedulers[i].load_state_dict(s)
models/SRFlow/code/models/lr_scheduler.py ADDED
@@ -0,0 +1,163 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) 2020 Huawei Technologies Co., Ltd.
2
+ # Licensed under CC BY-NC-SA 4.0 (Attribution-NonCommercial-ShareAlike 4.0 International) (the "License");
3
+ # you may not use this file except in compliance with the License.
4
+ # You may obtain a copy of the License at
5
+ #
6
+ # https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode
7
+ #
8
+ # The code is released for academic research use only. For commercial use, please contact Huawei Technologies Co., Ltd.
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
+ # This file contains content licensed by https://github.com/xinntao/BasicSR/blob/master/LICENSE/LICENSE
16
+
17
+ import math
18
+ from collections import Counter
19
+ from collections import defaultdict
20
+ import torch
21
+ from torch.optim.lr_scheduler import _LRScheduler
22
+
23
+
24
+ class MultiStepLR_Restart(_LRScheduler):
25
+ def __init__(self, optimizer, milestones, restarts=None, weights=None, gamma=0.1,
26
+ clear_state=False, last_epoch=-1, lr_steps_invese=None):
27
+ assert lr_steps_invese is not None, "Use empty list"
28
+ self.milestones = Counter(milestones)
29
+ self.lr_steps_inverse = Counter(lr_steps_invese)
30
+ self.gamma = gamma
31
+ self.clear_state = clear_state
32
+ self.restarts = restarts if restarts else [0]
33
+ self.restart_weights = weights if weights else [1]
34
+ assert len(self.restarts) == len(
35
+ self.restart_weights), 'restarts and their weights do not match.'
36
+ super(MultiStepLR_Restart, self).__init__(optimizer, last_epoch)
37
+
38
+ def get_lr(self):
39
+ if self.last_epoch in self.restarts:
40
+ if self.clear_state:
41
+ self.optimizer.state = defaultdict(dict)
42
+ weight = self.restart_weights[self.restarts.index(self.last_epoch)]
43
+ return [group['initial_lr'] * weight for group in self.optimizer.param_groups]
44
+ if self.last_epoch not in self.milestones and self.last_epoch not in self.lr_steps_inverse:
45
+ return [group['lr'] for group in self.optimizer.param_groups]
46
+ return [
47
+ group['lr'] * (self.gamma ** self.milestones[self.last_epoch]) *
48
+ (self.gamma ** (-self.lr_steps_inverse[self.last_epoch]))
49
+ for group in self.optimizer.param_groups
50
+ ]
51
+
52
+
53
+ class CosineAnnealingLR_Restart(_LRScheduler):
54
+ def __init__(self, optimizer, T_period, restarts=None, weights=None, eta_min=0, last_epoch=-1):
55
+ self.T_period = T_period
56
+ self.T_max = self.T_period[0] # current T period
57
+ self.eta_min = eta_min
58
+ self.restarts = restarts if restarts else [0]
59
+ self.restart_weights = weights if weights else [1]
60
+ self.last_restart = 0
61
+ assert len(self.restarts) == len(
62
+ self.restart_weights), 'restarts and their weights do not match.'
63
+ super(CosineAnnealingLR_Restart, self).__init__(optimizer, last_epoch)
64
+
65
+ def get_lr(self):
66
+ if self.last_epoch == 0:
67
+ return self.base_lrs
68
+ elif self.last_epoch in self.restarts:
69
+ self.last_restart = self.last_epoch
70
+ self.T_max = self.T_period[self.restarts.index(self.last_epoch) + 1]
71
+ weight = self.restart_weights[self.restarts.index(self.last_epoch)]
72
+ return [group['initial_lr'] * weight for group in self.optimizer.param_groups]
73
+ elif (self.last_epoch - self.last_restart - 1 - self.T_max) % (2 * self.T_max) == 0:
74
+ return [
75
+ group['lr'] + (base_lr - self.eta_min) * (1 - math.cos(math.pi / self.T_max)) / 2
76
+ for base_lr, group in zip(self.base_lrs, self.optimizer.param_groups)
77
+ ]
78
+ return [(1 + math.cos(math.pi * (self.last_epoch - self.last_restart) / self.T_max)) /
79
+ (1 + math.cos(math.pi * ((self.last_epoch - self.last_restart) - 1) / self.T_max)) *
80
+ (group['lr'] - self.eta_min) + self.eta_min
81
+ for group in self.optimizer.param_groups]
82
+
83
+
84
+ if __name__ == "__main__":
85
+ optimizer = torch.optim.Adam([torch.zeros(3, 64, 3, 3)], lr=2e-4, weight_decay=0,
86
+ betas=(0.9, 0.99))
87
+ ##############################
88
+ # MultiStepLR_Restart
89
+ ##############################
90
+ ## Original
91
+ lr_steps = [200000, 400000, 600000, 800000]
92
+ restarts = None
93
+ restart_weights = None
94
+
95
+ ## two
96
+ lr_steps = [100000, 200000, 300000, 400000, 490000, 600000, 700000, 800000, 900000, 990000]
97
+ restarts = [500000]
98
+ restart_weights = [1]
99
+
100
+ ## four
101
+ lr_steps = [
102
+ 50000, 100000, 150000, 200000, 240000, 300000, 350000, 400000, 450000, 490000, 550000,
103
+ 600000, 650000, 700000, 740000, 800000, 850000, 900000, 950000, 990000
104
+ ]
105
+ restarts = [250000, 500000, 750000]
106
+ restart_weights = [1, 1, 1]
107
+
108
+ scheduler = MultiStepLR_Restart(optimizer, lr_steps, restarts, restart_weights, gamma=0.5,
109
+ clear_state=False)
110
+
111
+ ##############################
112
+ # Cosine Annealing Restart
113
+ ##############################
114
+ ## two
115
+ T_period = [500000, 500000]
116
+ restarts = [500000]
117
+ restart_weights = [1]
118
+
119
+ ## four
120
+ T_period = [250000, 250000, 250000, 250000]
121
+ restarts = [250000, 500000, 750000]
122
+ restart_weights = [1, 1, 1]
123
+
124
+ scheduler = CosineAnnealingLR_Restart(optimizer, T_period, eta_min=1e-7, restarts=restarts,
125
+ weights=restart_weights)
126
+
127
+ ##############################
128
+ # Draw figure
129
+ ##############################
130
+ N_iter = 1000000
131
+ lr_l = list(range(N_iter))
132
+ for i in range(N_iter):
133
+ scheduler.step()
134
+ current_lr = optimizer.param_groups[0]['lr']
135
+ lr_l[i] = current_lr
136
+
137
+ import matplotlib as mpl
138
+ from matplotlib import pyplot as plt
139
+ import matplotlib.ticker as mtick
140
+
141
+ mpl.style.use('default')
142
+ import seaborn
143
+
144
+ seaborn.set(style='whitegrid')
145
+ seaborn.set_context('paper')
146
+
147
+ plt.figure(1)
148
+ plt.subplot(111)
149
+ plt.ticklabel_format(style='sci', axis='x', scilimits=(0, 0))
150
+ plt.title('Title', fontsize=16, color='k')
151
+ plt.plot(list(range(N_iter)), lr_l, linewidth=1.5, label='learning rate scheme')
152
+ legend = plt.legend(loc='upper right', shadow=False)
153
+ ax = plt.gca()
154
+ labels = ax.get_xticks().tolist()
155
+ for k, v in enumerate(labels):
156
+ labels[k] = str(int(v / 1000)) + 'K'
157
+ ax.set_xticklabels(labels)
158
+ ax.yaxis.set_major_formatter(mtick.FormatStrFormatter('%.1e'))
159
+
160
+ ax.set_ylabel('Learning rate')
161
+ ax.set_xlabel('Iteration')
162
+ fig = plt.gcf()
163
+ plt.show()
models/SRFlow/code/models/modules/FlowActNorms.py ADDED
@@ -0,0 +1,142 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) 2020 Huawei Technologies Co., Ltd.
2
+ # Licensed under CC BY-NC-SA 4.0 (Attribution-NonCommercial-ShareAlike 4.0 International) (the "License");
3
+ # you may not use this file except in compliance with the License.
4
+ # You may obtain a copy of the License at
5
+ #
6
+ # https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode
7
+ #
8
+ # The code is released for academic research use only. For commercial use, please contact Huawei Technologies Co., Ltd.
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
+ # This file contains content licensed by https://github.com/chaiyujin/glow-pytorch/blob/master/LICENSE
16
+
17
+ import torch
18
+ from torch import nn as nn
19
+ import sys
20
+ sys.path.append('../../../..')
21
+ from SRFlow.code.models.modules import thops
22
+
23
+
24
+ class _ActNorm(nn.Module):
25
+ """
26
+ Activation Normalization
27
+ Initialize the bias and scale with a given minibatch,
28
+ so that the output per-channel have zero mean and unit variance for that.
29
+
30
+ After initialization, `bias` and `logs` will be trained as parameters.
31
+ """
32
+
33
+ def __init__(self, num_features, scale=1.):
34
+ super().__init__()
35
+ # register mean and scale
36
+ size = [1, num_features, 1, 1]
37
+ self.register_parameter("bias", nn.Parameter(torch.zeros(*size)))
38
+ self.register_parameter("logs", nn.Parameter(torch.zeros(*size)))
39
+ self.num_features = num_features
40
+ self.scale = float(scale)
41
+ self.inited = False
42
+
43
+ def _check_input_dim(self, input):
44
+ return NotImplemented
45
+
46
+ def initialize_parameters(self, input):
47
+ self._check_input_dim(input)
48
+ if not self.training:
49
+ return
50
+ if (self.bias != 0).any():
51
+ self.inited = True
52
+ return
53
+ assert input.device == self.bias.device, (input.device, self.bias.device)
54
+ with torch.no_grad():
55
+ bias = thops.mean(input.clone(), dim=[0, 2, 3], keepdim=True) * -1.0
56
+ vars = thops.mean((input.clone() + bias) ** 2, dim=[0, 2, 3], keepdim=True)
57
+ logs = torch.log(self.scale / (torch.sqrt(vars) + 1e-6))
58
+ self.bias.data.copy_(bias.data)
59
+ self.logs.data.copy_(logs.data)
60
+ self.inited = True
61
+
62
+ def _center(self, input, reverse=False, offset=None):
63
+ bias = self.bias
64
+
65
+ if offset is not None:
66
+ bias = bias + offset
67
+
68
+ if not reverse:
69
+ return input + bias
70
+ else:
71
+ return input - bias
72
+
73
+ def _scale(self, input, logdet=None, reverse=False, offset=None):
74
+ logs = self.logs
75
+
76
+ if offset is not None:
77
+ logs = logs + offset
78
+
79
+ if not reverse:
80
+ input = input * torch.exp(logs) # should have shape batchsize, n_channels, 1, 1
81
+ # input = input * torch.exp(logs+logs_offset)
82
+ else:
83
+ input = input * torch.exp(-logs)
84
+ if logdet is not None:
85
+ """
86
+ logs is log_std of `mean of channels`
87
+ so we need to multiply pixels
88
+ """
89
+ dlogdet = thops.sum(logs) * thops.pixels(input)
90
+ if reverse:
91
+ dlogdet *= -1
92
+ logdet = logdet + dlogdet
93
+ return input, logdet
94
+
95
+ def forward(self, input, logdet=None, reverse=False, offset_mask=None, logs_offset=None, bias_offset=None):
96
+ if not self.inited:
97
+ self.initialize_parameters(input)
98
+ self._check_input_dim(input)
99
+
100
+ if offset_mask is not None:
101
+ logs_offset *= offset_mask
102
+ bias_offset *= offset_mask
103
+ # no need to permute dims as old version
104
+ if not reverse:
105
+ # center and scale
106
+
107
+ # self.input = input
108
+ input = self._center(input, reverse, bias_offset)
109
+ input, logdet = self._scale(input, logdet, reverse, logs_offset)
110
+ else:
111
+ # scale and center
112
+ input, logdet = self._scale(input, logdet, reverse, logs_offset)
113
+ input = self._center(input, reverse, bias_offset)
114
+ return input, logdet
115
+
116
+
117
+ class ActNorm2d(_ActNorm):
118
+ def __init__(self, num_features, scale=1.):
119
+ super().__init__(num_features, scale)
120
+
121
+ def _check_input_dim(self, input):
122
+ assert len(input.size()) == 4
123
+ assert input.size(1) == self.num_features, (
124
+ "[ActNorm]: input should be in shape as `BCHW`,"
125
+ " channels should be {} rather than {}".format(
126
+ self.num_features, input.size()))
127
+
128
+
129
+ class MaskedActNorm2d(ActNorm2d):
130
+ def __init__(self, num_features, scale=1.):
131
+ super().__init__(num_features, scale)
132
+
133
+ def forward(self, input, mask, logdet=None, reverse=False):
134
+
135
+ assert mask.dtype == torch.bool
136
+ output, logdet_out = super().forward(input, logdet, reverse)
137
+
138
+ input[mask] = output[mask]
139
+ logdet[mask] = logdet_out[mask]
140
+
141
+ return input, logdet
142
+
models/SRFlow/code/models/modules/FlowAffineCouplingsAblation.py ADDED
@@ -0,0 +1,136 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) 2020 Huawei Technologies Co., Ltd.
2
+ # Licensed under CC BY-NC-SA 4.0 (Attribution-NonCommercial-ShareAlike 4.0 International) (the "License");
3
+ # you may not use this file except in compliance with the License.
4
+ # You may obtain a copy of the License at
5
+ #
6
+ # https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode
7
+ #
8
+ # The code is released for academic research use only. For commercial use, please contact Huawei Technologies Co., Ltd.
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
+ # This file contains content licensed by https://github.com/chaiyujin/glow-pytorch/blob/master/LICENSE
16
+
17
+ import torch
18
+ from torch import nn as nn
19
+ import sys
20
+ sys.path.append('../../../..')
21
+ from SRFlow.code.models.modules import thops
22
+ from SRFlow.code.models.modules.flow import Conv2d, Conv2dZeros
23
+ from SRFlow.code.utils.util import opt_get
24
+
25
+
26
+ class CondAffineSeparatedAndCond(nn.Module):
27
+ def __init__(self, in_channels, opt):
28
+ super().__init__()
29
+ self.need_features = True
30
+ self.in_channels = in_channels
31
+ self.in_channels_rrdb = 320
32
+ self.kernel_hidden = 1
33
+ self.affine_eps = 0.0001
34
+ self.n_hidden_layers = 1
35
+ hidden_channels = opt_get(opt, ['network_G', 'flow', 'CondAffineSeparatedAndCond', 'hidden_channels'])
36
+ self.hidden_channels = 64 if hidden_channels is None else hidden_channels
37
+
38
+ self.affine_eps = opt_get(opt, ['network_G', 'flow', 'CondAffineSeparatedAndCond', 'eps'], 0.0001)
39
+
40
+ self.channels_for_nn = self.in_channels // 2
41
+ self.channels_for_co = self.in_channels - self.channels_for_nn
42
+
43
+ if self.channels_for_nn is None:
44
+ self.channels_for_nn = self.in_channels // 2
45
+
46
+ self.fAffine = self.F(in_channels=self.channels_for_nn + self.in_channels_rrdb,
47
+ out_channels=self.channels_for_co * 2,
48
+ hidden_channels=self.hidden_channels,
49
+ kernel_hidden=self.kernel_hidden,
50
+ n_hidden_layers=self.n_hidden_layers)
51
+
52
+ self.fFeatures = self.F(in_channels=self.in_channels_rrdb,
53
+ out_channels=self.in_channels * 2,
54
+ hidden_channels=self.hidden_channels,
55
+ kernel_hidden=self.kernel_hidden,
56
+ n_hidden_layers=self.n_hidden_layers)
57
+
58
+ def forward(self, input: torch.Tensor, logdet=None, reverse=False, ft=None):
59
+ if not reverse:
60
+ z = input
61
+ assert z.shape[1] == self.in_channels, (z.shape[1], self.in_channels)
62
+
63
+ # Feature Conditional
64
+ scaleFt, shiftFt = self.feature_extract(ft, self.fFeatures)
65
+ z = z + shiftFt
66
+ z = z * scaleFt
67
+ logdet = logdet + self.get_logdet(scaleFt)
68
+
69
+ # Self Conditional
70
+ z1, z2 = self.split(z)
71
+ scale, shift = self.feature_extract_aff(z1, ft, self.fAffine)
72
+ self.asserts(scale, shift, z1, z2)
73
+ z2 = z2 + shift
74
+ z2 = z2 * scale
75
+
76
+ logdet = logdet + self.get_logdet(scale)
77
+ z = thops.cat_feature(z1, z2)
78
+ output = z
79
+ else:
80
+ z = input
81
+
82
+ # Self Conditional
83
+ z1, z2 = self.split(z)
84
+ scale, shift = self.feature_extract_aff(z1, ft, self.fAffine)
85
+ self.asserts(scale, shift, z1, z2)
86
+ z2 = z2 / scale
87
+ z2 = z2 - shift
88
+ z = thops.cat_feature(z1, z2)
89
+ logdet = logdet - self.get_logdet(scale)
90
+
91
+ # Feature Conditional
92
+ scaleFt, shiftFt = self.feature_extract(ft, self.fFeatures)
93
+ z = z / scaleFt
94
+ z = z - shiftFt
95
+ logdet = logdet - self.get_logdet(scaleFt)
96
+
97
+ output = z
98
+ return output, logdet
99
+
100
+ def asserts(self, scale, shift, z1, z2):
101
+ assert z1.shape[1] == self.channels_for_nn, (z1.shape[1], self.channels_for_nn)
102
+ assert z2.shape[1] == self.channels_for_co, (z2.shape[1], self.channels_for_co)
103
+ assert scale.shape[1] == shift.shape[1], (scale.shape[1], shift.shape[1])
104
+ assert scale.shape[1] == z2.shape[1], (scale.shape[1], z1.shape[1], z2.shape[1])
105
+
106
+ def get_logdet(self, scale):
107
+ return thops.sum(torch.log(scale), dim=[1, 2, 3])
108
+
109
+ def feature_extract(self, z, f):
110
+ h = f(z)
111
+ shift, scale = thops.split_feature(h, "cross")
112
+ scale = (torch.sigmoid(scale + 2.) + self.affine_eps)
113
+ return scale, shift
114
+
115
+ def feature_extract_aff(self, z1, ft, f):
116
+ z = torch.cat([z1, ft], dim=1)
117
+ h = f(z)
118
+ shift, scale = thops.split_feature(h, "cross")
119
+ scale = (torch.sigmoid(scale + 2.) + self.affine_eps)
120
+ return scale, shift
121
+
122
+ def split(self, z):
123
+ z1 = z[:, :self.channels_for_nn]
124
+ z2 = z[:, self.channels_for_nn:]
125
+ assert z1.shape[1] + z2.shape[1] == z.shape[1], (z1.shape[1], z2.shape[1], z.shape[1])
126
+ return z1, z2
127
+
128
+ def F(self, in_channels, out_channels, hidden_channels, kernel_hidden=1, n_hidden_layers=1):
129
+ layers = [Conv2d(in_channels, hidden_channels), nn.ReLU(inplace=False)]
130
+
131
+ for _ in range(n_hidden_layers):
132
+ layers.append(Conv2d(hidden_channels, hidden_channels, kernel_size=[kernel_hidden, kernel_hidden]))
133
+ layers.append(nn.ReLU(inplace=False))
134
+ layers.append(Conv2dZeros(hidden_channels, out_channels))
135
+
136
+ return nn.Sequential(*layers)
models/SRFlow/code/models/modules/FlowStep.py ADDED
@@ -0,0 +1,139 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) 2020 Huawei Technologies Co., Ltd.
2
+ # Licensed under CC BY-NC-SA 4.0 (Attribution-NonCommercial-ShareAlike 4.0 International) (the "License");
3
+ # you may not use this file except in compliance with the License.
4
+ # You may obtain a copy of the License at
5
+ #
6
+ # https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode
7
+ #
8
+ # The code is released for academic research use only. For commercial use, please contact Huawei Technologies Co., Ltd.
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
+ # This file contains content licensed by https://github.com/chaiyujin/glow-pytorch/blob/master/LICENSE
16
+
17
+ import torch
18
+ from torch import nn as nn
19
+ import sys
20
+ sys.path.append('../../../..')
21
+ import SRFlow.code.models.modules
22
+ from SRFlow.code.models.modules.Permutations import InvertibleConv1x1
23
+ from SRFlow.code.models.modules.FlowActNorms import ActNorm2d
24
+ from SRFlow.code.models.modules import flow, thops, FlowAffineCouplingsAblation
25
+ from SRFlow.code.utils.util import opt_get
26
+
27
+
28
+ def getConditional(rrdbResults, position):
29
+ img_ft = rrdbResults if isinstance(rrdbResults, torch.Tensor) else rrdbResults[position]
30
+ return img_ft
31
+
32
+
33
+ class FlowStep(nn.Module):
34
+ FlowPermutation = {
35
+ "reverse": lambda obj, z, logdet, rev: (obj.reverse(z, rev), logdet),
36
+ "shuffle": lambda obj, z, logdet, rev: (obj.shuffle(z, rev), logdet),
37
+ "invconv": lambda obj, z, logdet, rev: obj.invconv(z, logdet, rev),
38
+ "squeeze_invconv": lambda obj, z, logdet, rev: obj.invconv(z, logdet, rev),
39
+ "resqueeze_invconv_alternating_2_3": lambda obj, z, logdet, rev: obj.invconv(z, logdet, rev),
40
+ "resqueeze_invconv_3": lambda obj, z, logdet, rev: obj.invconv(z, logdet, rev),
41
+ "InvertibleConv1x1GridAlign": lambda obj, z, logdet, rev: obj.invconv(z, logdet, rev),
42
+ "InvertibleConv1x1SubblocksShuf": lambda obj, z, logdet, rev: obj.invconv(z, logdet, rev),
43
+ "InvertibleConv1x1GridAlignIndepBorder": lambda obj, z, logdet, rev: obj.invconv(z, logdet, rev),
44
+ "InvertibleConv1x1GridAlignIndepBorder4": lambda obj, z, logdet, rev: obj.invconv(z, logdet, rev),
45
+ }
46
+
47
+ def __init__(self, in_channels, hidden_channels,
48
+ actnorm_scale=1.0, flow_permutation="invconv", flow_coupling="additive",
49
+ LU_decomposed=False, opt=None, image_injector=None, idx=None, acOpt=None, normOpt=None, in_shape=None,
50
+ position=None):
51
+ # check configures
52
+ assert flow_permutation in FlowStep.FlowPermutation, \
53
+ "float_permutation should be in `{}`".format(
54
+ FlowStep.FlowPermutation.keys())
55
+ super().__init__()
56
+ self.flow_permutation = flow_permutation
57
+ self.flow_coupling = flow_coupling
58
+ self.image_injector = image_injector
59
+
60
+ self.norm_type = normOpt['type'] if normOpt else 'ActNorm2d'
61
+ self.position = normOpt['position'] if normOpt else None
62
+
63
+ self.in_shape = in_shape
64
+ self.position = position
65
+ self.acOpt = acOpt
66
+
67
+ # 1. actnorm
68
+ self.actnorm = ActNorm2d(in_channels, actnorm_scale)
69
+
70
+ # 2. permute
71
+ if flow_permutation == "invconv":
72
+ self.invconv = InvertibleConv1x1(
73
+ in_channels, LU_decomposed=LU_decomposed)
74
+
75
+ # 3. coupling
76
+ if flow_coupling == "CondAffineSeparatedAndCond":
77
+ self.affine = FlowAffineCouplingsAblation.CondAffineSeparatedAndCond(in_channels=in_channels,
78
+ opt=opt)
79
+ elif flow_coupling == "noCoupling":
80
+ pass
81
+ else:
82
+ raise RuntimeError("coupling not Found:", flow_coupling)
83
+
84
+ def forward(self, input, logdet=None, reverse=False, rrdbResults=None):
85
+ if not reverse:
86
+ return self.normal_flow(input, logdet, rrdbResults)
87
+ else:
88
+ return self.reverse_flow(input, logdet, rrdbResults)
89
+
90
+ def normal_flow(self, z, logdet, rrdbResults=None):
91
+ if self.flow_coupling == "bentIdentityPreAct":
92
+ z, logdet = self.bentIdentPar(z, logdet, reverse=False)
93
+
94
+ # 1. actnorm
95
+ if self.norm_type == "ConditionalActNormImageInjector":
96
+ img_ft = getConditional(rrdbResults, self.position)
97
+ z, logdet = self.actnorm(z, img_ft=img_ft, logdet=logdet, reverse=False)
98
+ elif self.norm_type == "noNorm":
99
+ pass
100
+ else:
101
+ z, logdet = self.actnorm(z, logdet=logdet, reverse=False)
102
+
103
+ # 2. permute
104
+ z, logdet = FlowStep.FlowPermutation[self.flow_permutation](
105
+ self, z, logdet, False)
106
+
107
+ need_features = self.affine_need_features()
108
+
109
+ # 3. coupling
110
+ if need_features or self.flow_coupling in ["condAffine", "condFtAffine", "condNormAffine"]:
111
+ img_ft = getConditional(rrdbResults, self.position)
112
+ z, logdet = self.affine(input=z, logdet=logdet, reverse=False, ft=img_ft)
113
+ return z, logdet
114
+
115
+ def reverse_flow(self, z, logdet, rrdbResults=None):
116
+
117
+ need_features = self.affine_need_features()
118
+
119
+ # 1.coupling
120
+ if need_features or self.flow_coupling in ["condAffine", "condFtAffine", "condNormAffine"]:
121
+ img_ft = getConditional(rrdbResults, self.position)
122
+ z, logdet = self.affine(input=z, logdet=logdet, reverse=True, ft=img_ft)
123
+
124
+ # 2. permute
125
+ z, logdet = FlowStep.FlowPermutation[self.flow_permutation](
126
+ self, z, logdet, True)
127
+
128
+ # 3. actnorm
129
+ z, logdet = self.actnorm(z, logdet=logdet, reverse=True)
130
+
131
+ return z, logdet
132
+
133
+ def affine_need_features(self):
134
+ need_features = False
135
+ try:
136
+ need_features = self.affine.need_features
137
+ except:
138
+ pass
139
+ return need_features
models/SRFlow/code/models/modules/FlowUpsamplerNet.py ADDED
@@ -0,0 +1,310 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) 2020 Huawei Technologies Co., Ltd.
2
+ # Licensed under CC BY-NC-SA 4.0 (Attribution-NonCommercial-ShareAlike 4.0 International) (the "License");
3
+ # you may not use this file except in compliance with the License.
4
+ # You may obtain a copy of the License at
5
+ #
6
+ # https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode
7
+ #
8
+ # The code is released for academic research use only. For commercial use, please contact Huawei Technologies Co., Ltd.
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
+ # This file contains content licensed by https://github.com/chaiyujin/glow-pytorch/blob/master/LICENSE
16
+
17
+ import numpy as np
18
+ import torch
19
+ from torch import nn as nn
20
+ import sys
21
+ sys.path.append('../../../..')
22
+ import SRFlow.code.models.modules.Split
23
+ from SRFlow.code.models.modules import flow, thops
24
+ from SRFlow.code.models.modules.Split import Split2d
25
+ from SRFlow.code.models.modules.glow_arch import f_conv2d_bias
26
+ from SRFlow.code.models.modules.FlowStep import FlowStep
27
+ from SRFlow.code.utils.util import opt_get
28
+
29
+
30
+ class FlowUpsamplerNet(nn.Module):
31
+ def __init__(self, image_shape, hidden_channels, K, L=None,
32
+ actnorm_scale=1.0,
33
+ flow_permutation=None,
34
+ flow_coupling="affine",
35
+ LU_decomposed=False, opt=None):
36
+
37
+ super().__init__()
38
+
39
+ self.layers = nn.ModuleList()
40
+ self.output_shapes = []
41
+ self.L = opt_get(opt, ['network_G', 'flow', 'L'])
42
+ self.K = opt_get(opt, ['network_G', 'flow', 'K'])
43
+ if isinstance(self.K, int):
44
+ self.K = [K for K in [K, ] * (self.L + 1)]
45
+
46
+ self.opt = opt
47
+ H, W, self.C = image_shape
48
+ self.check_image_shape()
49
+
50
+ if opt['scale'] == 16:
51
+ self.levelToName = {
52
+ 0: 'fea_up16',
53
+ 1: 'fea_up8',
54
+ 2: 'fea_up4',
55
+ 3: 'fea_up2',
56
+ 4: 'fea_up1',
57
+ }
58
+
59
+ if opt['scale'] == 8:
60
+ self.levelToName = {
61
+ 0: 'fea_up8',
62
+ 1: 'fea_up4',
63
+ 2: 'fea_up2',
64
+ 3: 'fea_up1',
65
+ 4: 'fea_up0'
66
+ }
67
+
68
+ elif opt['scale'] == 4:
69
+ self.levelToName = {
70
+ 0: 'fea_up4',
71
+ 1: 'fea_up2',
72
+ 2: 'fea_up1',
73
+ 3: 'fea_up0',
74
+ 4: 'fea_up-1'
75
+ }
76
+
77
+ affineInCh = self.get_affineInCh(opt_get)
78
+ flow_permutation = self.get_flow_permutation(flow_permutation, opt)
79
+
80
+ normOpt = opt_get(opt, ['network_G', 'flow', 'norm'])
81
+
82
+ conditional_channels = {}
83
+ n_rrdb = self.get_n_rrdb_channels(opt, opt_get)
84
+ n_bypass_channels = opt_get(opt, ['network_G', 'flow', 'levelConditional', 'n_channels'])
85
+ conditional_channels[0] = n_rrdb
86
+ for level in range(1, self.L + 1):
87
+ # Level 1 gets conditionals from 2, 3, 4 => L - level
88
+ # Level 2 gets conditionals from 3, 4
89
+ # Level 3 gets conditionals from 4
90
+ # Level 4 gets conditionals from None
91
+ n_bypass = 0 if n_bypass_channels is None else (self.L - level) * n_bypass_channels
92
+ conditional_channels[level] = n_rrdb + n_bypass
93
+
94
+ # Upsampler
95
+ for level in range(1, self.L + 1):
96
+ # 1. Squeeze
97
+ H, W = self.arch_squeeze(H, W)
98
+
99
+ # 2. K FlowStep
100
+ self.arch_additionalFlowAffine(H, LU_decomposed, W, actnorm_scale, hidden_channels, opt)
101
+ self.arch_FlowStep(H, self.K[level], LU_decomposed, W, actnorm_scale, affineInCh, flow_coupling,
102
+ flow_permutation,
103
+ hidden_channels, normOpt, opt, opt_get,
104
+ n_conditinal_channels=conditional_channels[level])
105
+ # Split
106
+ self.arch_split(H, W, level, self.L, opt, opt_get)
107
+
108
+ if opt_get(opt, ['network_G', 'flow', 'split', 'enable']):
109
+ self.f = f_conv2d_bias(affineInCh, 2 * 3 * 64 // 2 // 2)
110
+ else:
111
+ self.f = f_conv2d_bias(affineInCh, 2 * 3 * 64)
112
+
113
+ self.H = H
114
+ self.W = W
115
+ self.scaleH = 160 / H
116
+ self.scaleW = 160 / W
117
+
118
+ def get_n_rrdb_channels(self, opt, opt_get):
119
+ blocks = opt_get(opt, ['network_G', 'flow', 'stackRRDB', 'blocks'])
120
+ n_rrdb = 64 if blocks is None else (len(blocks) + 1) * 64
121
+ return n_rrdb
122
+
123
+ def arch_FlowStep(self, H, K, LU_decomposed, W, actnorm_scale, affineInCh, flow_coupling, flow_permutation,
124
+ hidden_channels, normOpt, opt, opt_get, n_conditinal_channels=None):
125
+ condAff = self.get_condAffSetting(opt, opt_get)
126
+ if condAff is not None:
127
+ condAff['in_channels_rrdb'] = n_conditinal_channels
128
+
129
+ for k in range(K):
130
+ position_name = get_position_name(H, self.opt['scale'])
131
+ if normOpt: normOpt['position'] = position_name
132
+
133
+ self.layers.append(
134
+ FlowStep(in_channels=self.C,
135
+ hidden_channels=hidden_channels,
136
+ actnorm_scale=actnorm_scale,
137
+ flow_permutation=flow_permutation,
138
+ flow_coupling=flow_coupling,
139
+ acOpt=condAff,
140
+ position=position_name,
141
+ LU_decomposed=LU_decomposed, opt=opt, idx=k, normOpt=normOpt))
142
+ self.output_shapes.append(
143
+ [-1, self.C, H, W])
144
+
145
+ def get_condAffSetting(self, opt, opt_get):
146
+ condAff = opt_get(opt, ['network_G', 'flow', 'condAff']) or None
147
+ condAff = opt_get(opt, ['network_G', 'flow', 'condFtAffine']) or condAff
148
+ return condAff
149
+
150
+ def arch_split(self, H, W, L, levels, opt, opt_get):
151
+ correct_splits = opt_get(opt, ['network_G', 'flow', 'split', 'correct_splits'], False)
152
+ correction = 0 if correct_splits else 1
153
+ if opt_get(opt, ['network_G', 'flow', 'split', 'enable']) and L < levels - correction:
154
+ logs_eps = opt_get(opt, ['network_G', 'flow', 'split', 'logs_eps']) or 0
155
+ consume_ratio = opt_get(opt, ['network_G', 'flow', 'split', 'consume_ratio']) or 0.5
156
+ position_name = get_position_name(H, self.opt['scale'])
157
+ position = position_name if opt_get(opt, ['network_G', 'flow', 'split', 'conditional']) else None
158
+ cond_channels = opt_get(opt, ['network_G', 'flow', 'split', 'cond_channels'])
159
+ cond_channels = 0 if cond_channels is None else cond_channels
160
+
161
+ t = opt_get(opt, ['network_G', 'flow', 'split', 'type'], 'Split2d')
162
+
163
+ if t == 'Split2d':
164
+ split = Split2d(num_channels=self.C, logs_eps=logs_eps, position=position,
165
+ cond_channels=cond_channels, consume_ratio=consume_ratio, opt=opt)
166
+ self.layers.append(split)
167
+ self.output_shapes.append([-1, split.num_channels_pass, H, W])
168
+ self.C = split.num_channels_pass
169
+
170
+ def arch_additionalFlowAffine(self, H, LU_decomposed, W, actnorm_scale, hidden_channels, opt):
171
+ if 'additionalFlowNoAffine' in opt['network_G']['flow']:
172
+ n_additionalFlowNoAffine = int(opt['network_G']['flow']['additionalFlowNoAffine'])
173
+ for _ in range(n_additionalFlowNoAffine):
174
+ self.layers.append(
175
+ FlowStep(in_channels=self.C,
176
+ hidden_channels=hidden_channels,
177
+ actnorm_scale=actnorm_scale,
178
+ flow_permutation='invconv',
179
+ flow_coupling='noCoupling',
180
+ LU_decomposed=LU_decomposed, opt=opt))
181
+ self.output_shapes.append(
182
+ [-1, self.C, H, W])
183
+
184
+ def arch_squeeze(self, H, W):
185
+ self.C, H, W = self.C * 4, H // 2, W // 2
186
+ self.layers.append(flow.SqueezeLayer(factor=2))
187
+ self.output_shapes.append([-1, self.C, H, W])
188
+ return H, W
189
+
190
+ def get_flow_permutation(self, flow_permutation, opt):
191
+ flow_permutation = opt['network_G']['flow'].get('flow_permutation', 'invconv')
192
+ return flow_permutation
193
+
194
+ def get_affineInCh(self, opt_get):
195
+ affineInCh = opt_get(self.opt, ['network_G', 'flow', 'stackRRDB', 'blocks']) or []
196
+ affineInCh = (len(affineInCh) + 1) * 64
197
+ return affineInCh
198
+
199
+ def check_image_shape(self):
200
+ assert self.C == 1 or self.C == 3, ("image_shape should be HWC, like (64, 64, 3)"
201
+ "self.C == 1 or self.C == 3")
202
+
203
+ def forward(self, gt=None, rrdbResults=None, z=None, epses=None, logdet=0., reverse=False, eps_std=None,
204
+ y_onehot=None):
205
+
206
+ if reverse:
207
+ epses_copy = [eps for eps in epses] if isinstance(epses, list) else epses
208
+
209
+ sr, logdet = self.decode(rrdbResults, z, eps_std, epses=epses_copy, logdet=logdet, y_onehot=y_onehot)
210
+ return sr, logdet
211
+ else:
212
+ assert gt is not None
213
+ assert rrdbResults is not None
214
+ z, logdet = self.encode(gt, rrdbResults, logdet=logdet, epses=epses, y_onehot=y_onehot)
215
+
216
+ return z, logdet
217
+
218
+ def encode(self, gt, rrdbResults, logdet=0.0, epses=None, y_onehot=None):
219
+ fl_fea = gt
220
+ reverse = False
221
+ level_conditionals = {}
222
+ bypasses = {}
223
+
224
+ L = opt_get(self.opt, ['network_G', 'flow', 'L'])
225
+
226
+ for level in range(1, L + 1):
227
+ bypasses[level] = torch.nn.functional.interpolate(gt, scale_factor=2 ** -level, mode='bilinear', align_corners=False)
228
+
229
+ for layer, shape in zip(self.layers, self.output_shapes):
230
+ size = shape[2]
231
+ level = int(np.log(160 / size) / np.log(2))
232
+
233
+ if level > 0 and level not in level_conditionals.keys():
234
+ level_conditionals[level] = rrdbResults[self.levelToName[level]]
235
+
236
+ level_conditionals[level] = rrdbResults[self.levelToName[level]]
237
+
238
+ if isinstance(layer, FlowStep):
239
+ fl_fea, logdet = layer(fl_fea, logdet, reverse=reverse, rrdbResults=level_conditionals[level])
240
+ elif isinstance(layer, Split2d):
241
+ fl_fea, logdet = self.forward_split2d(epses, fl_fea, layer, logdet, reverse, level_conditionals[level],
242
+ y_onehot=y_onehot)
243
+ else:
244
+ fl_fea, logdet = layer(fl_fea, logdet, reverse=reverse)
245
+
246
+ z = fl_fea
247
+
248
+ if not isinstance(epses, list):
249
+ return z, logdet
250
+
251
+ epses.append(z)
252
+ return epses, logdet
253
+
254
+ def forward_preFlow(self, fl_fea, logdet, reverse):
255
+ if hasattr(self, 'preFlow'):
256
+ for l in self.preFlow:
257
+ fl_fea, logdet = l(fl_fea, logdet, reverse=reverse)
258
+ return fl_fea, logdet
259
+
260
+ def forward_split2d(self, epses, fl_fea, layer, logdet, reverse, rrdbResults, y_onehot=None):
261
+ ft = None if layer.position is None else rrdbResults[layer.position]
262
+ fl_fea, logdet, eps = layer(fl_fea, logdet, reverse=reverse, eps=epses, ft=ft, y_onehot=y_onehot)
263
+
264
+ if isinstance(epses, list):
265
+ epses.append(eps)
266
+ return fl_fea, logdet
267
+
268
+ def decode(self, rrdbResults, z, eps_std=None, epses=None, logdet=0.0, y_onehot=None):
269
+ z = epses.pop() if isinstance(epses, list) else z
270
+
271
+ fl_fea = z
272
+ # debug.imwrite("fl_fea", fl_fea)
273
+ bypasses = {}
274
+ level_conditionals = {}
275
+ if not opt_get(self.opt, ['network_G', 'flow', 'levelConditional', 'conditional']) == True:
276
+ for level in range(self.L + 1):
277
+ level_conditionals[level] = rrdbResults[self.levelToName[level]]
278
+
279
+ for layer, shape in zip(reversed(self.layers), reversed(self.output_shapes)):
280
+ size = shape[2]
281
+ level = int(np.log(160 / size) / np.log(2))
282
+ # size = fl_fea.shape[2]
283
+ # level = int(np.log(160 / size) / np.log(2))
284
+
285
+ if isinstance(layer, Split2d):
286
+ fl_fea, logdet = self.forward_split2d_reverse(eps_std, epses, fl_fea, layer,
287
+ rrdbResults[self.levelToName[level]], logdet=logdet,
288
+ y_onehot=y_onehot)
289
+ elif isinstance(layer, FlowStep):
290
+ fl_fea, logdet = layer(fl_fea, logdet=logdet, reverse=True, rrdbResults=level_conditionals[level])
291
+ else:
292
+ fl_fea, logdet = layer(fl_fea, logdet=logdet, reverse=True)
293
+
294
+ sr = fl_fea
295
+
296
+ assert sr.shape[1] == 3
297
+ return sr, logdet
298
+
299
+ def forward_split2d_reverse(self, eps_std, epses, fl_fea, layer, rrdbResults, logdet, y_onehot=None):
300
+ ft = None if layer.position is None else rrdbResults[layer.position]
301
+ fl_fea, logdet = layer(fl_fea, logdet=logdet, reverse=True,
302
+ eps=epses.pop() if isinstance(epses, list) else None,
303
+ eps_std=eps_std, ft=ft, y_onehot=y_onehot)
304
+ return fl_fea, logdet
305
+
306
+
307
+ def get_position_name(H, scale):
308
+ downscale_factor = 160 // H
309
+ position_name = 'fea_up{}'.format(scale / downscale_factor)
310
+ return position_name
models/SRFlow/code/models/modules/Permutations.py ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) 2020 Huawei Technologies Co., Ltd.
2
+ # Licensed under CC BY-NC-SA 4.0 (Attribution-NonCommercial-ShareAlike 4.0 International) (the "License");
3
+ # you may not use this file except in compliance with the License.
4
+ # You may obtain a copy of the License at
5
+ #
6
+ # https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode
7
+ #
8
+ # The code is released for academic research use only. For commercial use, please contact Huawei Technologies Co., Ltd.
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
+ # This file contains content licensed by https://github.com/chaiyujin/glow-pytorch/blob/master/LICENSE
16
+
17
+ import numpy as np
18
+ import torch
19
+ from torch import nn as nn
20
+ from torch.nn import functional as F
21
+ import sys
22
+ sys.path.append('../../../..')
23
+ from SRFlow.code.models.modules import thops
24
+
25
+
26
+ class InvertibleConv1x1(nn.Module):
27
+ def __init__(self, num_channels, LU_decomposed=False):
28
+ super().__init__()
29
+ w_shape = [num_channels, num_channels]
30
+ w_init = np.linalg.qr(np.random.randn(*w_shape))[0].astype(np.float32)
31
+ self.register_parameter("weight", nn.Parameter(torch.Tensor(w_init)))
32
+ self.w_shape = w_shape
33
+ self.LU = LU_decomposed
34
+
35
+ def get_weight(self, input, reverse):
36
+ w_shape = self.w_shape
37
+ pixels = thops.pixels(input)
38
+ dlogdet = torch.slogdet(self.weight)[1] * pixels
39
+ if not reverse:
40
+ weight = self.weight.view(w_shape[0], w_shape[1], 1, 1)
41
+ else:
42
+ weight = torch.inverse(self.weight.double()).float() \
43
+ .view(w_shape[0], w_shape[1], 1, 1)
44
+ return weight, dlogdet
45
+ def forward(self, input, logdet=None, reverse=False):
46
+ """
47
+ log-det = log|abs(|W|)| * pixels
48
+ """
49
+ weight, dlogdet = self.get_weight(input, reverse)
50
+ if not reverse:
51
+ z = F.conv2d(input, weight)
52
+ if logdet is not None:
53
+ logdet = logdet + dlogdet
54
+ return z, logdet
55
+ else:
56
+ z = F.conv2d(input, weight)
57
+ if logdet is not None:
58
+ logdet = logdet - dlogdet
59
+ return z, logdet
models/SRFlow/code/models/modules/RRDBNet_arch.py ADDED
@@ -0,0 +1,150 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) 2020 Huawei Technologies Co., Ltd.
2
+ # Licensed under CC BY-NC-SA 4.0 (Attribution-NonCommercial-ShareAlike 4.0 International) (the "License");
3
+ # you may not use this file except in compliance with the License.
4
+ # You may obtain a copy of the License at
5
+ #
6
+ # https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode
7
+ #
8
+ # The code is released for academic research use only. For commercial use, please contact Huawei Technologies Co., Ltd.
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
+ # This file contains content licensed by https://github.com/chaiyujin/glow-pytorch/blob/master/LICENSE
16
+
17
+ import functools
18
+ import torch
19
+ import torch.nn as nn
20
+ import torch.nn.functional as F
21
+ import sys
22
+ sys.path.append('../..')
23
+ import SRFlow.code.models.modules.module_util as mutil
24
+ from SRFlow.code.utils.util import opt_get
25
+
26
+
27
+ class ResidualDenseBlock_5C(nn.Module):
28
+ def __init__(self, nf=64, gc=32, bias=True):
29
+ super(ResidualDenseBlock_5C, self).__init__()
30
+ # gc: growth channel, i.e. intermediate channels
31
+ self.conv1 = nn.Conv2d(nf, gc, 3, 1, 1, bias=bias)
32
+ self.conv2 = nn.Conv2d(nf + gc, gc, 3, 1, 1, bias=bias)
33
+ self.conv3 = nn.Conv2d(nf + 2 * gc, gc, 3, 1, 1, bias=bias)
34
+ self.conv4 = nn.Conv2d(nf + 3 * gc, gc, 3, 1, 1, bias=bias)
35
+ self.conv5 = nn.Conv2d(nf + 4 * gc, nf, 3, 1, 1, bias=bias)
36
+ self.lrelu = nn.LeakyReLU(negative_slope=0.2, inplace=True)
37
+
38
+ # initialization
39
+ mutil.initialize_weights([self.conv1, self.conv2, self.conv3, self.conv4, self.conv5], 0.1)
40
+
41
+ def forward(self, x):
42
+ x1 = self.lrelu(self.conv1(x))
43
+ x2 = self.lrelu(self.conv2(torch.cat((x, x1), 1)))
44
+ x3 = self.lrelu(self.conv3(torch.cat((x, x1, x2), 1)))
45
+ x4 = self.lrelu(self.conv4(torch.cat((x, x1, x2, x3), 1)))
46
+ x5 = self.conv5(torch.cat((x, x1, x2, x3, x4), 1))
47
+ return x5 * 0.2 + x
48
+
49
+
50
+ class RRDB(nn.Module):
51
+ '''Residual in Residual Dense Block'''
52
+
53
+ def __init__(self, nf, gc=32):
54
+ super(RRDB, self).__init__()
55
+ self.RDB1 = ResidualDenseBlock_5C(nf, gc)
56
+ self.RDB2 = ResidualDenseBlock_5C(nf, gc)
57
+ self.RDB3 = ResidualDenseBlock_5C(nf, gc)
58
+
59
+ def forward(self, x):
60
+ out = self.RDB1(x)
61
+ out = self.RDB2(out)
62
+ out = self.RDB3(out)
63
+ return out * 0.2 + x
64
+
65
+
66
+ class RRDBNet(nn.Module):
67
+ def __init__(self, in_nc, out_nc, nf, nb, gc=32, scale=4, opt=None):
68
+ self.opt = opt
69
+ super(RRDBNet, self).__init__()
70
+ RRDB_block_f = functools.partial(RRDB, nf=nf, gc=gc)
71
+ self.scale = scale
72
+
73
+ self.conv_first = nn.Conv2d(in_nc, nf, 3, 1, 1, bias=True)
74
+ self.RRDB_trunk = mutil.make_layer(RRDB_block_f, nb)
75
+ self.trunk_conv = nn.Conv2d(nf, nf, 3, 1, 1, bias=True)
76
+ #### upsampling
77
+ self.upconv1 = nn.Conv2d(nf, nf, 3, 1, 1, bias=True)
78
+ self.upconv2 = nn.Conv2d(nf, nf, 3, 1, 1, bias=True)
79
+ if self.scale >= 8:
80
+ self.upconv3 = nn.Conv2d(nf, nf, 3, 1, 1, bias=True)
81
+ if self.scale >= 16:
82
+ self.upconv4 = nn.Conv2d(nf, nf, 3, 1, 1, bias=True)
83
+ if self.scale >= 32:
84
+ self.upconv5 = nn.Conv2d(nf, nf, 3, 1, 1, bias=True)
85
+
86
+ self.HRconv = nn.Conv2d(nf, nf, 3, 1, 1, bias=True)
87
+ self.conv_last = nn.Conv2d(nf, out_nc, 3, 1, 1, bias=True)
88
+
89
+ self.lrelu = nn.LeakyReLU(negative_slope=0.2, inplace=True)
90
+
91
+ def forward(self, x, get_steps=False):
92
+ fea = self.conv_first(x)
93
+
94
+ block_idxs = opt_get(self.opt, ['network_G', 'flow', 'stackRRDB', 'blocks']) or []
95
+ block_results = {}
96
+
97
+ for idx, m in enumerate(self.RRDB_trunk.children()):
98
+ fea = m(fea)
99
+ for b in block_idxs:
100
+ if b == idx:
101
+ block_results["block_{}".format(idx)] = fea
102
+
103
+ trunk = self.trunk_conv(fea)
104
+
105
+ last_lr_fea = fea + trunk
106
+
107
+ fea_up2 = self.upconv1(F.interpolate(last_lr_fea, scale_factor=2, mode='nearest'))
108
+ fea = self.lrelu(fea_up2)
109
+
110
+ fea_up4 = self.upconv2(F.interpolate(fea, scale_factor=2, mode='nearest'))
111
+ fea = self.lrelu(fea_up4)
112
+
113
+ fea_up8 = None
114
+ fea_up16 = None
115
+ fea_up32 = None
116
+
117
+ if self.scale >= 8:
118
+ fea_up8 = self.upconv3(F.interpolate(fea, scale_factor=2, mode='nearest'))
119
+ fea = self.lrelu(fea_up8)
120
+ if self.scale >= 16:
121
+ fea_up16 = self.upconv4(F.interpolate(fea, scale_factor=2, mode='nearest'))
122
+ fea = self.lrelu(fea_up16)
123
+ if self.scale >= 32:
124
+ fea_up32 = self.upconv5(F.interpolate(fea, scale_factor=2, mode='nearest'))
125
+ fea = self.lrelu(fea_up32)
126
+
127
+ out = self.conv_last(self.lrelu(self.HRconv(fea)))
128
+
129
+ results = {'last_lr_fea': last_lr_fea,
130
+ 'fea_up1': last_lr_fea,
131
+ 'fea_up2': fea_up2,
132
+ 'fea_up4': fea_up4,
133
+ 'fea_up8': fea_up8,
134
+ 'fea_up16': fea_up16,
135
+ 'fea_up32': fea_up32,
136
+ 'out': out}
137
+
138
+ fea_up0_en = opt_get(self.opt, ['network_G', 'flow', 'fea_up0']) or False
139
+ if fea_up0_en:
140
+ results['fea_up0'] = F.interpolate(last_lr_fea, scale_factor=1/2, mode='bilinear', align_corners=False, recompute_scale_factor=True)
141
+ fea_upn1_en = opt_get(self.opt, ['network_G', 'flow', 'fea_up-1']) or False
142
+ if fea_upn1_en:
143
+ results['fea_up-1'] = F.interpolate(last_lr_fea, scale_factor=1/4, mode='bilinear', align_corners=False, recompute_scale_factor=True)
144
+
145
+ if get_steps:
146
+ for k, v in block_results.items():
147
+ results[k] = v
148
+ return results
149
+ else:
150
+ return out
models/SRFlow/code/models/modules/SRFlowNet_arch.py ADDED
@@ -0,0 +1,160 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) 2020 Huawei Technologies Co., Ltd.
2
+ # Licensed under CC BY-NC-SA 4.0 (Attribution-NonCommercial-ShareAlike 4.0 International) (the "License");
3
+ # you may not use this file except in compliance with the License.
4
+ # You may obtain a copy of the License at
5
+ #
6
+ # https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode
7
+ #
8
+ # The code is released for academic research use only. For commercial use, please contact Huawei Technologies Co., Ltd.
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
+ # This file contains content licensed by https://github.com/chaiyujin/glow-pytorch/blob/master/LICENSE
16
+
17
+ import math
18
+
19
+ import torch
20
+ import torch.nn as nn
21
+ import torch.nn.functional as F
22
+ import numpy as np
23
+ import sys
24
+ sys.path.append('../../../..')
25
+ from SRFlow.code.models.modules.RRDBNet_arch import RRDBNet
26
+ from SRFlow.code.models.modules.FlowUpsamplerNet import FlowUpsamplerNet
27
+ import SRFlow.code.models.modules.thops as thops
28
+ import SRFlow.code.models.modules.flow as flow
29
+ from SRFlow.code.utils.util import opt_get
30
+
31
+
32
+ class SRFlowNet(nn.Module):
33
+ def __init__(self, in_nc, out_nc, nf, nb, gc=32, scale=4, K=None, opt=None, step=None):
34
+ super(SRFlowNet, self).__init__()
35
+
36
+ self.opt = opt
37
+ self.quant = 255 if opt_get(opt, ['datasets', 'train', 'quant']) is \
38
+ None else opt_get(opt, ['datasets', 'train', 'quant'])
39
+ self.RRDB = RRDBNet(in_nc, out_nc, nf, nb, gc, scale, opt)
40
+ hidden_channels = opt_get(opt, ['network_G', 'flow', 'hidden_channels'])
41
+ hidden_channels = hidden_channels or 64
42
+ self.RRDB_training = True # Default is true
43
+
44
+ train_RRDB_delay = opt_get(self.opt, ['network_G', 'train_RRDB_delay'])
45
+ set_RRDB_to_train = False
46
+ if set_RRDB_to_train:
47
+ self.set_rrdb_training(True)
48
+
49
+ self.flowUpsamplerNet = \
50
+ FlowUpsamplerNet((160, 160, 3), hidden_channels, K,
51
+ flow_coupling=opt['network_G']['flow']['coupling'], opt=opt)
52
+ self.i = 0
53
+
54
+ def set_rrdb_training(self, trainable):
55
+ if self.RRDB_training != trainable:
56
+ for p in self.RRDB.parameters():
57
+ p.requires_grad = trainable
58
+ self.RRDB_training = trainable
59
+ return True
60
+ return False
61
+
62
+ def forward(self, gt=None, lr=None, z=None, eps_std=None, reverse=False, epses=None, reverse_with_grad=False,
63
+ lr_enc=None,
64
+ add_gt_noise=False, step=None, y_label=None):
65
+ if not reverse:
66
+ return self.normal_flow(gt, lr, epses=epses, lr_enc=lr_enc, add_gt_noise=add_gt_noise, step=step,
67
+ y_onehot=y_label)
68
+ else:
69
+ # assert lr.shape[0] == 1
70
+ assert lr.shape[1] == 3
71
+ # assert lr.shape[2] == 20
72
+ # assert lr.shape[3] == 20
73
+ # assert z.shape[0] == 1
74
+ # assert z.shape[1] == 3 * 8 * 8
75
+ # assert z.shape[2] == 20
76
+ # assert z.shape[3] == 20
77
+ if reverse_with_grad:
78
+ return self.reverse_flow(lr, z, y_onehot=y_label, eps_std=eps_std, epses=epses, lr_enc=lr_enc,
79
+ add_gt_noise=add_gt_noise)
80
+ else:
81
+ with torch.no_grad():
82
+ return self.reverse_flow(lr, z, y_onehot=y_label, eps_std=eps_std, epses=epses, lr_enc=lr_enc,
83
+ add_gt_noise=add_gt_noise)
84
+
85
+ def normal_flow(self, gt, lr, y_onehot=None, epses=None, lr_enc=None, add_gt_noise=True, step=None):
86
+ if lr_enc is None:
87
+ lr_enc = self.rrdbPreprocessing(lr)
88
+
89
+ logdet = torch.zeros_like(gt[:, 0, 0, 0])
90
+ pixels = thops.pixels(gt)
91
+
92
+ z = gt
93
+
94
+ if add_gt_noise:
95
+ # Setup
96
+ noiseQuant = opt_get(self.opt, ['network_G', 'flow', 'augmentation', 'noiseQuant'], True)
97
+ if noiseQuant:
98
+ z = z + ((torch.rand(z.shape, device=z.device) - 0.5) / self.quant)
99
+ logdet = logdet + float(-np.log(self.quant) * pixels)
100
+
101
+ # Encode
102
+ epses, logdet = self.flowUpsamplerNet(rrdbResults=lr_enc, gt=z, logdet=logdet, reverse=False, epses=epses,
103
+ y_onehot=y_onehot)
104
+
105
+ objective = logdet.clone()
106
+
107
+ if isinstance(epses, (list, tuple)):
108
+ z = epses[-1]
109
+ else:
110
+ z = epses
111
+
112
+ objective = objective + flow.GaussianDiag.logp(None, None, z)
113
+
114
+ nll = (-objective) / float(np.log(2.) * pixels)
115
+
116
+ if isinstance(epses, list):
117
+ return epses, nll, logdet
118
+ return z, nll, logdet
119
+
120
+ def rrdbPreprocessing(self, lr):
121
+ rrdbResults = self.RRDB(lr, get_steps=True)
122
+ block_idxs = opt_get(self.opt, ['network_G', 'flow', 'stackRRDB', 'blocks']) or []
123
+ if len(block_idxs) > 0:
124
+ concat = torch.cat([rrdbResults["block_{}".format(idx)] for idx in block_idxs], dim=1)
125
+
126
+ if opt_get(self.opt, ['network_G', 'flow', 'stackRRDB', 'concat']) or False:
127
+ keys = ['last_lr_fea', 'fea_up1', 'fea_up2', 'fea_up4']
128
+ if 'fea_up0' in rrdbResults.keys():
129
+ keys.append('fea_up0')
130
+ if 'fea_up-1' in rrdbResults.keys():
131
+ keys.append('fea_up-1')
132
+ if self.opt['scale'] >= 8:
133
+ keys.append('fea_up8')
134
+ if self.opt['scale'] == 16:
135
+ keys.append('fea_up16')
136
+ for k in keys:
137
+ h = rrdbResults[k].shape[2]
138
+ w = rrdbResults[k].shape[3]
139
+ rrdbResults[k] = torch.cat([rrdbResults[k], F.interpolate(concat, (h, w))], dim=1)
140
+ return rrdbResults
141
+
142
+ def get_score(self, disc_loss_sigma, z):
143
+ score_real = 0.5 * (1 - 1 / (disc_loss_sigma ** 2)) * thops.sum(z ** 2, dim=[1, 2, 3]) - \
144
+ z.shape[1] * z.shape[2] * z.shape[3] * math.log(disc_loss_sigma)
145
+ return -score_real
146
+
147
+ def reverse_flow(self, lr, z, y_onehot, eps_std, epses=None, lr_enc=None, add_gt_noise=True):
148
+ logdet = torch.zeros_like(lr[:, 0, 0, 0])
149
+ pixels = thops.pixels(lr) * self.opt['scale'] ** 2
150
+
151
+ if add_gt_noise:
152
+ logdet = logdet - float(-np.log(self.quant) * pixels)
153
+
154
+ if lr_enc is None:
155
+ lr_enc = self.rrdbPreprocessing(lr)
156
+
157
+ x, logdet = self.flowUpsamplerNet(rrdbResults=lr_enc, z=z, eps_std=eps_std, reverse=True, epses=epses,
158
+ logdet=logdet)
159
+
160
+ return x, logdet
models/SRFlow/code/models/modules/Split.py ADDED
@@ -0,0 +1,87 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) 2020 Huawei Technologies Co., Ltd.
2
+ # Licensed under CC BY-NC-SA 4.0 (Attribution-NonCommercial-ShareAlike 4.0 International) (the "License");
3
+ # you may not use this file except in compliance with the License.
4
+ # You may obtain a copy of the License at
5
+ #
6
+ # https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode
7
+ #
8
+ # The code is released for academic research use only. For commercial use, please contact Huawei Technologies Co., Ltd.
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
+ # This file contains content licensed by https://github.com/chaiyujin/glow-pytorch/blob/master/LICENSE
16
+
17
+ import torch
18
+ from torch import nn as nn
19
+ import sys
20
+ sys.path.append('../../../..')
21
+ from SRFlow.code.models.modules import thops
22
+ from SRFlow.code.models.modules.FlowStep import FlowStep
23
+ from SRFlow.code.models.modules.flow import Conv2dZeros, GaussianDiag
24
+ from SRFlow.code.utils.util import opt_get
25
+
26
+
27
+ class Split2d(nn.Module):
28
+ def __init__(self, num_channels, logs_eps=0, cond_channels=0, position=None, consume_ratio=0.5, opt=None):
29
+ super().__init__()
30
+
31
+ self.num_channels_consume = int(round(num_channels * consume_ratio))
32
+ self.num_channels_pass = num_channels - self.num_channels_consume
33
+
34
+ self.conv = Conv2dZeros(in_channels=self.num_channels_pass + cond_channels,
35
+ out_channels=self.num_channels_consume * 2)
36
+ self.logs_eps = logs_eps
37
+ self.position = position
38
+ self.opt = opt
39
+
40
+ def split2d_prior(self, z, ft):
41
+ if ft is not None:
42
+ z = torch.cat([z, ft], dim=1)
43
+ h = self.conv(z)
44
+ return thops.split_feature(h, "cross")
45
+
46
+ def exp_eps(self, logs):
47
+ return torch.exp(logs) + self.logs_eps
48
+
49
+ def forward(self, input, logdet=0., reverse=False, eps_std=None, eps=None, ft=None, y_onehot=None):
50
+ if not reverse:
51
+ # self.input = input
52
+ z1, z2 = self.split_ratio(input)
53
+ mean, logs = self.split2d_prior(z1, ft)
54
+
55
+ eps = (z2 - mean) / self.exp_eps(logs)
56
+
57
+ logdet = logdet + self.get_logdet(logs, mean, z2)
58
+
59
+ # print(logs.shape, mean.shape, z2.shape)
60
+ # self.eps = eps
61
+ # print('split, enc eps:', eps)
62
+ return z1, logdet, eps
63
+ else:
64
+ z1 = input
65
+ mean, logs = self.split2d_prior(z1, ft)
66
+
67
+ if eps is None:
68
+ #print("WARNING: eps is None, generating eps untested functionality!")
69
+ eps = GaussianDiag.sample_eps(mean.shape, eps_std)
70
+
71
+ eps = eps.to(mean.device)
72
+ z2 = mean + self.exp_eps(logs) * eps
73
+
74
+ z = thops.cat_feature(z1, z2)
75
+ logdet = logdet - self.get_logdet(logs, mean, z2)
76
+
77
+ return z, logdet
78
+ # return z, logdet, eps
79
+
80
+ def get_logdet(self, logs, mean, z2):
81
+ logdet_diff = GaussianDiag.logp(mean, logs, z2)
82
+ # print("Split2D: logdet diff", logdet_diff.item())
83
+ return logdet_diff
84
+
85
+ def split_ratio(self, input):
86
+ z1, z2 = input[:, :self.num_channels_pass, ...], input[:, self.num_channels_pass:, ...]
87
+ return z1, z2
models/SRFlow/code/models/modules/__init__.py ADDED
File without changes
models/SRFlow/code/models/modules/__pycache__/FlowActNorms.cpython-311.pyc ADDED
Binary file (7.28 kB). View file
 
models/SRFlow/code/models/modules/__pycache__/FlowAffineCouplingsAblation.cpython-311.pyc ADDED
Binary file (7.73 kB). View file
 
models/SRFlow/code/models/modules/__pycache__/FlowStep.cpython-311.pyc ADDED
Binary file (7.48 kB). View file
 
models/SRFlow/code/models/modules/__pycache__/FlowUpsamplerNet.cpython-311.pyc ADDED
Binary file (16.3 kB). View file
 
models/SRFlow/code/models/modules/__pycache__/Permutations.cpython-311.pyc ADDED
Binary file (3.12 kB). View file
 
models/SRFlow/code/models/modules/__pycache__/RRDBNet_arch.cpython-311.pyc ADDED
Binary file (9.43 kB). View file
 
models/SRFlow/code/models/modules/__pycache__/SRFlowNet_arch.cpython-311.pyc ADDED
Binary file (9.03 kB). View file
 
models/SRFlow/code/models/modules/__pycache__/Split.cpython-311.pyc ADDED
Binary file (4.12 kB). View file
 
models/SRFlow/code/models/modules/__pycache__/__init__.cpython-311.pyc ADDED
Binary file (205 Bytes). View file
 
models/SRFlow/code/models/modules/__pycache__/flow.cpython-311.pyc ADDED
Binary file (10.4 kB). View file
 
models/SRFlow/code/models/modules/__pycache__/glow_arch.cpython-311.pyc ADDED
Binary file (1.25 kB). View file
 
models/SRFlow/code/models/modules/__pycache__/module_util.cpython-311.pyc ADDED
Binary file (5.42 kB). View file
 
models/SRFlow/code/models/modules/__pycache__/thops.cpython-311.pyc ADDED
Binary file (2.53 kB). View file
 
models/SRFlow/code/models/modules/flow.py ADDED
@@ -0,0 +1,167 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) 2020 Huawei Technologies Co., Ltd.
2
+ # Licensed under CC BY-NC-SA 4.0 (Attribution-NonCommercial-ShareAlike 4.0 International) (the "License");
3
+ # you may not use this file except in compliance with the License.
4
+ # You may obtain a copy of the License at
5
+ #
6
+ # https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode
7
+ #
8
+ # The code is released for academic research use only. For commercial use, please contact Huawei Technologies Co., Ltd.
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
+ # This file contains content licensed by https://github.com/chaiyujin/glow-pytorch/blob/master/LICENSE
16
+
17
+ import torch
18
+ import torch.nn as nn
19
+ import torch.nn.functional as F
20
+ import numpy as np
21
+ import sys
22
+ sys.path.append('../../../..')
23
+ from SRFlow.code.models.modules.FlowActNorms import ActNorm2d
24
+ from . import thops
25
+
26
+
27
+ class Conv2d(nn.Conv2d):
28
+ pad_dict = {
29
+ "same": lambda kernel, stride: [((k - 1) * s + 1) // 2 for k, s in zip(kernel, stride)],
30
+ "valid": lambda kernel, stride: [0 for _ in kernel]
31
+ }
32
+
33
+ @staticmethod
34
+ def get_padding(padding, kernel_size, stride):
35
+ # make paddding
36
+ if isinstance(padding, str):
37
+ if isinstance(kernel_size, int):
38
+ kernel_size = [kernel_size, kernel_size]
39
+ if isinstance(stride, int):
40
+ stride = [stride, stride]
41
+ padding = padding.lower()
42
+ try:
43
+ padding = Conv2d.pad_dict[padding](kernel_size, stride)
44
+ except KeyError:
45
+ raise ValueError("{} is not supported".format(padding))
46
+ return padding
47
+
48
+ def __init__(self, in_channels, out_channels,
49
+ kernel_size=[3, 3], stride=[1, 1],
50
+ padding="same", do_actnorm=True, weight_std=0.05):
51
+ padding = Conv2d.get_padding(padding, kernel_size, stride)
52
+ super().__init__(in_channels, out_channels, kernel_size, stride,
53
+ padding, bias=(not do_actnorm))
54
+ # init weight with std
55
+ self.weight.data.normal_(mean=0.0, std=weight_std)
56
+ if not do_actnorm:
57
+ self.bias.data.zero_()
58
+ else:
59
+ self.actnorm = ActNorm2d(out_channels)
60
+ self.do_actnorm = do_actnorm
61
+
62
+ def forward(self, input):
63
+ x = super().forward(input)
64
+ if self.do_actnorm:
65
+ x, _ = self.actnorm(x)
66
+ return x
67
+
68
+
69
+ class Conv2dZeros(nn.Conv2d):
70
+ def __init__(self, in_channels, out_channels,
71
+ kernel_size=[3, 3], stride=[1, 1],
72
+ padding="same", logscale_factor=3):
73
+ padding = Conv2d.get_padding(padding, kernel_size, stride)
74
+ super().__init__(in_channels, out_channels, kernel_size, stride, padding)
75
+ # logscale_factor
76
+ self.logscale_factor = logscale_factor
77
+ self.register_parameter("logs", nn.Parameter(torch.zeros(out_channels, 1, 1)))
78
+ # init
79
+ self.weight.data.zero_()
80
+ self.bias.data.zero_()
81
+
82
+ def forward(self, input):
83
+ output = super().forward(input)
84
+ return output * torch.exp(self.logs * self.logscale_factor)
85
+
86
+
87
+ class GaussianDiag:
88
+ Log2PI = float(np.log(2 * np.pi))
89
+
90
+ @staticmethod
91
+ def likelihood(mean, logs, x):
92
+ """
93
+ lnL = -1/2 * { ln|Var| + ((X - Mu)^T)(Var^-1)(X - Mu) + kln(2*PI) }
94
+ k = 1 (Independent)
95
+ Var = logs ** 2
96
+ """
97
+ if mean is None and logs is None:
98
+ return -0.5 * (x ** 2 + GaussianDiag.Log2PI)
99
+ else:
100
+ return -0.5 * (logs * 2. + ((x - mean) ** 2) / torch.exp(logs * 2.) + GaussianDiag.Log2PI)
101
+
102
+ @staticmethod
103
+ def logp(mean, logs, x):
104
+ likelihood = GaussianDiag.likelihood(mean, logs, x)
105
+ return thops.sum(likelihood, dim=[1, 2, 3])
106
+
107
+ @staticmethod
108
+ def sample(mean, logs, eps_std=None):
109
+ eps_std = eps_std or 1
110
+ eps = torch.normal(mean=torch.zeros_like(mean),
111
+ std=torch.ones_like(logs) * eps_std)
112
+ return mean + torch.exp(logs) * eps
113
+
114
+ @staticmethod
115
+ def sample_eps(shape, eps_std, seed=None):
116
+ if seed is not None:
117
+ torch.manual_seed(seed)
118
+ eps = torch.normal(mean=torch.zeros(shape),
119
+ std=torch.ones(shape) * eps_std)
120
+ return eps
121
+
122
+
123
+ def squeeze2d(input, factor=2):
124
+ assert factor >= 1 and isinstance(factor, int)
125
+ if factor == 1:
126
+ return input
127
+ size = input.size()
128
+ B = size[0]
129
+ C = size[1]
130
+ H = size[2]
131
+ W = size[3]
132
+ assert H % factor == 0 and W % factor == 0, "{}".format((H, W, factor))
133
+ x = input.view(B, C, H // factor, factor, W // factor, factor)
134
+ x = x.permute(0, 1, 3, 5, 2, 4).contiguous()
135
+ x = x.view(B, C * factor * factor, H // factor, W // factor)
136
+ return x
137
+
138
+
139
+ def unsqueeze2d(input, factor=2):
140
+ assert factor >= 1 and isinstance(factor, int)
141
+ factor2 = factor ** 2
142
+ if factor == 1:
143
+ return input
144
+ size = input.size()
145
+ B = size[0]
146
+ C = size[1]
147
+ H = size[2]
148
+ W = size[3]
149
+ assert C % (factor2) == 0, "{}".format(C)
150
+ x = input.view(B, C // factor2, factor, factor, H, W)
151
+ x = x.permute(0, 1, 4, 2, 5, 3).contiguous()
152
+ x = x.view(B, C // (factor2), H * factor, W * factor)
153
+ return x
154
+
155
+
156
+ class SqueezeLayer(nn.Module):
157
+ def __init__(self, factor):
158
+ super().__init__()
159
+ self.factor = factor
160
+
161
+ def forward(self, input, logdet=None, reverse=False):
162
+ if not reverse:
163
+ output = squeeze2d(input, self.factor) # Squeeze in forward
164
+ return output, logdet
165
+ else:
166
+ output = unsqueeze2d(input, self.factor)
167
+ return output, logdet
models/SRFlow/code/models/modules/glow_arch.py ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) 2020 Huawei Technologies Co., Ltd.
2
+ # Licensed under CC BY-NC-SA 4.0 (Attribution-NonCommercial-ShareAlike 4.0 International) (the "License");
3
+ # you may not use this file except in compliance with the License.
4
+ # You may obtain a copy of the License at
5
+ #
6
+ # https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode
7
+ #
8
+ # The code is released for academic research use only. For commercial use, please contact Huawei Technologies Co., Ltd.
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
+ # This file contains content licensed by https://github.com/chaiyujin/glow-pytorch/blob/master/LICENSE
16
+
17
+ import torch.nn as nn
18
+
19
+
20
+ def f_conv2d_bias(in_channels, out_channels):
21
+ def padding_same(kernel, stride):
22
+ return [((k - 1) * s + 1) // 2 for k, s in zip(kernel, stride)]
23
+
24
+ padding = padding_same([3, 3], [1, 1])
25
+ assert padding == [1, 1], padding
26
+ return nn.Sequential(
27
+ nn.Conv2d(in_channels=in_channels, out_channels=out_channels, kernel_size=[3, 3], stride=1, padding=1,
28
+ bias=True))