Yi Xie
commited on
Commit
·
aa5fd42
1
Parent(s):
b770ee6
Add 2xLexicaRRDBNet and 2xLexicaRRDBNet_Sharp
Browse files- app.py +2 -0
- converter.py +48 -7
- known_models.yaml +24 -0
app.py
CHANGED
@@ -84,6 +84,8 @@ def convert(input_model):
|
|
84 |
command += ['--num-blocks', str(model['blocks'])]
|
85 |
if 'convs' in model:
|
86 |
command += ['--num-convs', str(model['convs'])]
|
|
|
|
|
87 |
command += [file]
|
88 |
logger.debug('Command: %s', command)
|
89 |
process = subprocess.Popen(command, stdout=subprocess.PIPE)
|
|
|
84 |
command += ['--num-blocks', str(model['blocks'])]
|
85 |
if 'convs' in model:
|
86 |
command += ['--num-convs', str(model['convs'])]
|
87 |
+
if 'shuffle-factor' in model:
|
88 |
+
command += ['--shuffle-factor', str(model['shuffle-factor'])]
|
89 |
command += [file]
|
90 |
logger.debug('Command: %s', command)
|
91 |
process = subprocess.Popen(command, stdout=subprocess.PIPE)
|
converter.py
CHANGED
@@ -38,6 +38,7 @@ optional_args.add_argument('--has-cuda', action='store_true', help='Input model
|
|
38 |
optional_args.add_argument('--num-features', type=int, help='Override number of features for (Real-)ESRGAN model')
|
39 |
optional_args.add_argument('--num-blocks', type=int, help='Override number of blocks for (Real-)ESRGAN model')
|
40 |
optional_args.add_argument('--num-convs', type=int, help='Override number of conv layers for Real-ESRGAN Compact model')
|
|
|
41 |
optional_args.add_argument('--input-size', type=int, default=256, help='Input size (both width and height), default to 256')
|
42 |
optional_args.add_argument('--shrink-size', type=int, default=20, help='Shrink size (applied to all 4 sides on input), default to 20')
|
43 |
optional_args.add_argument('--description', type=str, required=False, help='Description of the model, supports Markdown')
|
@@ -88,13 +89,20 @@ else:
|
|
88 |
logger.info('Using torch device cpu, please be patient')
|
89 |
|
90 |
logger.info('Creating model architecture')
|
91 |
-
|
|
|
|
|
92 |
if args.monochrome:
|
93 |
-
|
|
|
|
|
|
|
|
|
94 |
|
95 |
num_features = 64
|
96 |
num_blocks = 23
|
97 |
num_convs = 16
|
|
|
98 |
|
99 |
if args.type == 'esrgan_old_lite':
|
100 |
num_features = 32
|
@@ -110,17 +118,17 @@ if args.num_convs is not None:
|
|
110 |
if args.type == 'esrgan_old' or args.type == 'esrgan_old_lite':
|
111 |
from esrgan_old import architecture
|
112 |
torch_model = architecture.RRDB_Net(
|
113 |
-
|
114 |
act_type='leakyrelu', mode='CNA', res_scale=1, upsample_mode='upconv')
|
115 |
elif args.type == 'real_esrgan':
|
116 |
from basicsr.archs.rrdbnet_arch import RRDBNet
|
117 |
-
torch_model = RRDBNet(num_in_ch=
|
118 |
elif args.type == 'real_esrgan_compact':
|
119 |
from basicsr.archs.srvgg_arch import SRVGGNetCompact
|
120 |
-
torch_model = SRVGGNetCompact(num_in_ch=
|
121 |
elif args.type == 'esrgan_plus':
|
122 |
from esrgan_plus.codes.models.modules.architecture import RRDBNet
|
123 |
-
torch_model = RRDBNet(in_nc=
|
124 |
else:
|
125 |
logger.fatal('Unknown model type: %s', args.type)
|
126 |
sys.exit(-1)
|
@@ -151,6 +159,35 @@ if args.monochrome:
|
|
151 |
return x
|
152 |
torch_model = MonochromeWrapper(torch_model)
|
153 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
154 |
logger.info('Tracing model, will take a long time and a lot of RAM')
|
155 |
torch_model.eval()
|
156 |
torch_model = torch_model.to(device)
|
@@ -170,10 +207,14 @@ logger.info('Converting to Core ML')
|
|
170 |
input_shape = [1, 3, args.input_size, args.input_size]
|
171 |
output_size = args.input_size * args.scale
|
172 |
output_shape = [1, 3, output_size, output_size]
|
|
|
|
|
|
|
173 |
model = ct.convert(
|
174 |
traced_model,
|
175 |
convert_to="mlprogram",
|
176 |
-
inputs=[ct.TensorType(shape=input_shape)]
|
|
|
177 |
)
|
178 |
model_name = args.filename.split('/')[-1].split('.')[0]
|
179 |
mlmodel_file = args.out_dir + '/' + model_name + '.mlpackage'
|
|
|
38 |
optional_args.add_argument('--num-features', type=int, help='Override number of features for (Real-)ESRGAN model')
|
39 |
optional_args.add_argument('--num-blocks', type=int, help='Override number of blocks for (Real-)ESRGAN model')
|
40 |
optional_args.add_argument('--num-convs', type=int, help='Override number of conv layers for Real-ESRGAN Compact model')
|
41 |
+
optional_args.add_argument('--shuffle-factor', type=int, help='Shuffle input channels in ESRGAN model')
|
42 |
optional_args.add_argument('--input-size', type=int, default=256, help='Input size (both width and height), default to 256')
|
43 |
optional_args.add_argument('--shrink-size', type=int, default=20, help='Shrink size (applied to all 4 sides on input), default to 20')
|
44 |
optional_args.add_argument('--description', type=str, required=False, help='Description of the model, supports Markdown')
|
|
|
89 |
logger.info('Using torch device cpu, please be patient')
|
90 |
|
91 |
logger.info('Creating model architecture')
|
92 |
+
in_channels = 3
|
93 |
+
out_channels = 3
|
94 |
+
model_scale = args.scale
|
95 |
if args.monochrome:
|
96 |
+
in_channels = 1
|
97 |
+
out_channels = 1
|
98 |
+
if args.shuffle_factor:
|
99 |
+
in_channels *= args.shuffle_factor * args.shuffle_factor
|
100 |
+
model_scale *= args.shuffle_factor
|
101 |
|
102 |
num_features = 64
|
103 |
num_blocks = 23
|
104 |
num_convs = 16
|
105 |
+
shuffle_factor = None
|
106 |
|
107 |
if args.type == 'esrgan_old_lite':
|
108 |
num_features = 32
|
|
|
118 |
if args.type == 'esrgan_old' or args.type == 'esrgan_old_lite':
|
119 |
from esrgan_old import architecture
|
120 |
torch_model = architecture.RRDB_Net(
|
121 |
+
in_channels, out_channels, num_features, num_blocks, gc=32, upscale=model_scale, norm_type=None,
|
122 |
act_type='leakyrelu', mode='CNA', res_scale=1, upsample_mode='upconv')
|
123 |
elif args.type == 'real_esrgan':
|
124 |
from basicsr.archs.rrdbnet_arch import RRDBNet
|
125 |
+
torch_model = RRDBNet(num_in_ch=in_channels, num_out_ch=out_channels, num_feat=num_features, num_block=num_blocks, num_grow_ch=32, scale=args.scale)
|
126 |
elif args.type == 'real_esrgan_compact':
|
127 |
from basicsr.archs.srvgg_arch import SRVGGNetCompact
|
128 |
+
torch_model = SRVGGNetCompact(num_in_ch=in_channels, num_out_ch=out_channels, num_feat=num_features, num_conv=num_convs, upscale=args.scale, act_type='prelu')
|
129 |
elif args.type == 'esrgan_plus':
|
130 |
from esrgan_plus.codes.models.modules.architecture import RRDBNet
|
131 |
+
torch_model = RRDBNet(in_nc=in_channels, out_nc=out_channels, nf=num_features, nb=num_blocks, gc=32, upscale=args.scale)
|
132 |
else:
|
133 |
logger.fatal('Unknown model type: %s', args.type)
|
134 |
sys.exit(-1)
|
|
|
159 |
return x
|
160 |
torch_model = MonochromeWrapper(torch_model)
|
161 |
|
162 |
+
if args.shuffle_factor:
|
163 |
+
from torch import nn
|
164 |
+
# Source: https://github.com/chaiNNer-org/spandrel/blob/cb2f03459819ce114c52e328b7ac9bb2812f205a/libs/spandrel/spandrel/architectures/__arch_helpers/padding.py
|
165 |
+
def pad_to_multiple(
|
166 |
+
tensor: torch.Tensor,
|
167 |
+
multiple: int,
|
168 |
+
*,
|
169 |
+
mode: str,
|
170 |
+
value: float = 0.0,
|
171 |
+
) -> torch.Tensor:
|
172 |
+
_, _, h, w = tensor.size()
|
173 |
+
pad_h = (multiple - h % multiple) % multiple
|
174 |
+
pad_w = (multiple - w % multiple) % multiple
|
175 |
+
if pad_h or pad_w:
|
176 |
+
return nn.pad(tensor, (0, pad_w, 0, pad_h), mode, value)
|
177 |
+
return tensor
|
178 |
+
|
179 |
+
class ShuffleWrapper(nn.Module):
|
180 |
+
def __init__(self, model: nn.Module):
|
181 |
+
super(ShuffleWrapper, self).__init__()
|
182 |
+
self.model = model
|
183 |
+
def forward(self, x: torch.Tensor):
|
184 |
+
_, _, h, w = x.size()
|
185 |
+
x = pad_to_multiple(x, args.shuffle_factor, mode="reflect")
|
186 |
+
x = torch.pixel_unshuffle(x, downscale_factor=args.shuffle_factor)
|
187 |
+
x = self.model(x)
|
188 |
+
return x[:, :, : h * model_scale, : w * model_scale]
|
189 |
+
torch_model = ShuffleWrapper(torch_model)
|
190 |
+
|
191 |
logger.info('Tracing model, will take a long time and a lot of RAM')
|
192 |
torch_model.eval()
|
193 |
torch_model = torch_model.to(device)
|
|
|
207 |
input_shape = [1, 3, args.input_size, args.input_size]
|
208 |
output_size = args.input_size * args.scale
|
209 |
output_shape = [1, 3, output_size, output_size]
|
210 |
+
minimum_deployment_target = None
|
211 |
+
if args.shuffle_factor:
|
212 |
+
minimum_deployment_target = ct.target.iOS16
|
213 |
model = ct.convert(
|
214 |
traced_model,
|
215 |
convert_to="mlprogram",
|
216 |
+
inputs=[ct.TensorType(shape=input_shape)],
|
217 |
+
minimum_deployment_target=minimum_deployment_target
|
218 |
)
|
219 |
model_name = args.filename.split('/')[-1].split('.')[0]
|
220 |
mlmodel_file = args.out_dir + '/' + model_name + '.mlpackage'
|
known_models.yaml
CHANGED
@@ -340,4 +340,28 @@ models:
|
|
340 |
description: "Category: Oversharpening Purpose: Denoise Pretrained: 1st attempt on random sharpening with the same dataset at 200000 iterations, which was trained on non-random desharp model, total ~600000 iterations on 3 models.\n\n\n\nMade for rare particular cases when the image was destroyed by applying noise, i.e. game textures or any badly exported photos. If your image does not have any oversharpening, it won't hurt them, leaving as is. In theory, this model knows when to activate and when to skip, also can successfully remove artifacts if only some parts of the image are oversharpened, for example in image consisting of several combined images, 1 of them with sharpen noise."
|
341 |
author: "Loinne"
|
342 |
source: "[OpenModelDB](https://openmodeldb.info/models/1x-DeSharpen)"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
343 |
license: "[CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/)"
|
|
|
340 |
description: "Category: Oversharpening Purpose: Denoise Pretrained: 1st attempt on random sharpening with the same dataset at 200000 iterations, which was trained on non-random desharp model, total ~600000 iterations on 3 models.\n\n\n\nMade for rare particular cases when the image was destroyed by applying noise, i.e. game textures or any badly exported photos. If your image does not have any oversharpening, it won't hurt them, leaving as is. In theory, this model knows when to activate and when to skip, also can successfully remove artifacts if only some parts of the image are oversharpened, for example in image consisting of several combined images, 1 of them with sharpen noise."
|
341 |
author: "Loinne"
|
342 |
source: "[OpenModelDB](https://openmodeldb.info/models/1x-DeSharpen)"
|
343 |
+
license: "[CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/)"
|
344 |
+
- name: "2xLexicaRRDBNet"
|
345 |
+
type: esrgan_old
|
346 |
+
file: "./torch_models/2xLexicaRRDBNet.pth"
|
347 |
+
sourceLink: https://github.com/Phhofm/models/raw/main/2xLexicaRRDBNet/2xLexicaRRDBNet.pth
|
348 |
+
sha256: 47c4ecdb06717b13e16da3000485cce72e378e18b7b7ee2e1020562283f7ac31
|
349 |
+
scale: 2
|
350 |
+
shuffle-factor: 2
|
351 |
+
cuda: true
|
352 |
+
description: "Upscaling AI generated images"
|
353 |
+
author: "[Philip Hofmann](https://github.com/Phhofm)"
|
354 |
+
source: "[GitHub Phhofm/models](https://github.com/Phhofm/models)"
|
355 |
+
license: "[CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/)"
|
356 |
+
- name: "2xLexicaRRDBNet Sharp"
|
357 |
+
type: esrgan_old
|
358 |
+
file: "./torch_models/2xLexicaRRDBNet_Sharp.pth"
|
359 |
+
sourceLink: https://github.com/Phhofm/models/raw/main/2xLexicaRRDBNet/2xLexicaRRDBNet_Sharp.pth
|
360 |
+
sha256: 11e7bec714d8d15e686e336fe7095bd952e21ee8308551a00ea4df2caa374ac7
|
361 |
+
scale: 2
|
362 |
+
shuffle-factor: 2
|
363 |
+
cuda: true
|
364 |
+
description: "Upscaling AI generated images - a bit sharper then 2xLexicaRRDBNet"
|
365 |
+
author: "[Philip Hofmann](https://github.com/Phhofm)"
|
366 |
+
source: "[GitHub Phhofm/models](https://github.com/Phhofm/models)"
|
367 |
license: "[CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/)"
|