InvokeAI 2.2.4.5__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (169) hide show
  1. backend/__init__.py +0 -0
  2. backend/invoke_ai_web_server.py +1724 -0
  3. backend/modules/__init__.py +0 -0
  4. backend/modules/create_cmd_parser.py +55 -0
  5. backend/modules/get_canvas_generation_mode.py +117 -0
  6. backend/modules/parameters.py +71 -0
  7. backend/modules/parse_seed_weights.py +47 -0
  8. configs/INITIAL_MODELS.yaml +80 -0
  9. configs/models.yaml.example +29 -0
  10. configs/sd-concepts.txt +803 -0
  11. configs/stable-diffusion/v1-finetune.yaml +110 -0
  12. configs/stable-diffusion/v1-finetune_style.yaml +103 -0
  13. configs/stable-diffusion/v1-inference.yaml +79 -0
  14. configs/stable-diffusion/v1-inpainting-inference.yaml +79 -0
  15. configs/stable-diffusion/v1-m1-finetune.yaml +110 -0
  16. docs/assets/invoke-web-server-1.png +0 -0
  17. docs/assets/invoke_ai_banner.png +0 -0
  18. invokeai-2.2.4.5.data/data/assets/caution.png +0 -0
  19. invokeai-2.2.4.5.data/data/configs/INITIAL_MODELS.yaml +80 -0
  20. invokeai-2.2.4.5.data/data/configs/models.yaml.example +29 -0
  21. invokeai-2.2.4.5.data/data/configs/sd-concepts.txt +803 -0
  22. invokeai-2.2.4.5.data/data/configs/stable-diffusion/v1-finetune.yaml +110 -0
  23. invokeai-2.2.4.5.data/data/configs/stable-diffusion/v1-finetune_style.yaml +103 -0
  24. invokeai-2.2.4.5.data/data/configs/stable-diffusion/v1-inference.yaml +79 -0
  25. invokeai-2.2.4.5.data/data/configs/stable-diffusion/v1-inpainting-inference.yaml +79 -0
  26. invokeai-2.2.4.5.data/data/configs/stable-diffusion/v1-m1-finetune.yaml +110 -0
  27. invokeai-2.2.4.5.data/data/frontend/dist/assets/Inter-Bold.790c108b.ttf +0 -0
  28. invokeai-2.2.4.5.data/data/frontend/dist/assets/Inter.b9a8e5e2.ttf +0 -0
  29. invokeai-2.2.4.5.data/data/frontend/dist/assets/favicon.0d253ced.ico +0 -0
  30. invokeai-2.2.4.5.data/data/frontend/dist/assets/index-legacy-b741077f.js +48 -0
  31. invokeai-2.2.4.5.data/data/frontend/dist/assets/index.0dadf5d0.css +1 -0
  32. invokeai-2.2.4.5.data/data/frontend/dist/assets/index.21ff81eb.js +625 -0
  33. invokeai-2.2.4.5.data/data/frontend/dist/assets/logo.13003d72.png +0 -0
  34. invokeai-2.2.4.5.data/data/frontend/dist/assets/polyfills-legacy-dde3a68a.js +4 -0
  35. invokeai-2.2.4.5.data/data/frontend/dist/assets/polyfills.1ff60148.js +1 -0
  36. invokeai-2.2.4.5.data/data/frontend/dist/index.html +23 -0
  37. invokeai-2.2.4.5.data/data/scripts/configure_invokeai.py +797 -0
  38. invokeai-2.2.4.5.data/data/scripts/create_root.py +43 -0
  39. invokeai-2.2.4.5.data/data/scripts/dream.py +10 -0
  40. invokeai-2.2.4.5.data/data/scripts/images2prompt.py +30 -0
  41. invokeai-2.2.4.5.data/data/scripts/invoke.py +5 -0
  42. invokeai-2.2.4.5.data/data/scripts/legacy_api.py +681 -0
  43. invokeai-2.2.4.5.data/data/scripts/load_models.py +12 -0
  44. invokeai-2.2.4.5.data/data/scripts/merge_embeddings.py +124 -0
  45. invokeai-2.2.4.5.data/data/scripts/preload_models.py +12 -0
  46. invokeai-2.2.4.5.data/data/scripts/sd-metadata.py +22 -0
  47. invokeai-2.2.4.5.dist-info/LICENSE +21 -0
  48. invokeai-2.2.4.5.dist-info/LICENSE-ModelWeights.txt +294 -0
  49. invokeai-2.2.4.5.dist-info/METADATA +288 -0
  50. invokeai-2.2.4.5.dist-info/RECORD +169 -0
  51. invokeai-2.2.4.5.dist-info/WHEEL +5 -0
  52. invokeai-2.2.4.5.dist-info/entry_points.txt +4 -0
  53. invokeai-2.2.4.5.dist-info/top_level.txt +6 -0
  54. invokeai-2.2.4.5.dist-info/zip-safe +1 -0
  55. ldm/__init__.py +0 -0
  56. ldm/data/__init__.py +0 -0
  57. ldm/data/base.py +31 -0
  58. ldm/data/imagenet.py +466 -0
  59. ldm/data/lsun.py +126 -0
  60. ldm/data/personalized.py +202 -0
  61. ldm/data/personalized_style.py +169 -0
  62. ldm/generate.py +1159 -0
  63. ldm/invoke/CLI.py +960 -0
  64. ldm/invoke/__init__.py +3 -0
  65. ldm/invoke/args.py +1257 -0
  66. ldm/invoke/concepts_lib.py +169 -0
  67. ldm/invoke/conditioning.py +289 -0
  68. ldm/invoke/devices.py +27 -0
  69. ldm/invoke/generator/__init__.py +4 -0
  70. ldm/invoke/generator/base.py +335 -0
  71. ldm/invoke/generator/embiggen.py +501 -0
  72. ldm/invoke/generator/img2img.py +97 -0
  73. ldm/invoke/generator/inpaint.py +358 -0
  74. ldm/invoke/generator/omnibus.py +175 -0
  75. ldm/invoke/generator/txt2img.py +88 -0
  76. ldm/invoke/generator/txt2img2img.py +182 -0
  77. ldm/invoke/globals.py +31 -0
  78. ldm/invoke/image_util.py +70 -0
  79. ldm/invoke/log.py +66 -0
  80. ldm/invoke/model_cache.py +449 -0
  81. ldm/invoke/patchmatch.py +44 -0
  82. ldm/invoke/pngwriter.py +113 -0
  83. ldm/invoke/prompt_parser.py +655 -0
  84. ldm/invoke/readline.py +442 -0
  85. ldm/invoke/restoration/__init__.py +4 -0
  86. ldm/invoke/restoration/base.py +38 -0
  87. ldm/invoke/restoration/codeformer.py +103 -0
  88. ldm/invoke/restoration/codeformer_arch.py +276 -0
  89. ldm/invoke/restoration/gfpgan.py +84 -0
  90. ldm/invoke/restoration/outcrop.py +108 -0
  91. ldm/invoke/restoration/outpaint.py +92 -0
  92. ldm/invoke/restoration/realesrgan.py +90 -0
  93. ldm/invoke/restoration/vqgan_arch.py +435 -0
  94. ldm/invoke/seamless.py +30 -0
  95. ldm/invoke/server.py +282 -0
  96. ldm/invoke/server_legacy.py +246 -0
  97. ldm/invoke/txt2mask.py +136 -0
  98. ldm/lr_scheduler.py +143 -0
  99. ldm/models/__init__.py +0 -0
  100. ldm/models/autoencoder.py +596 -0
  101. ldm/models/diffusion/__init__.py +0 -0
  102. ldm/models/diffusion/classifier.py +355 -0
  103. ldm/models/diffusion/cross_attention_control.py +443 -0
  104. ldm/models/diffusion/cross_attention_map_saving.py +95 -0
  105. ldm/models/diffusion/ddim.py +111 -0
  106. ldm/models/diffusion/ddpm.py +2263 -0
  107. ldm/models/diffusion/ksampler.py +312 -0
  108. ldm/models/diffusion/plms.py +146 -0
  109. ldm/models/diffusion/sampler.py +450 -0
  110. ldm/models/diffusion/shared_invokeai_diffusion.py +244 -0
  111. ldm/modules/__init__.py +0 -0
  112. ldm/modules/attention.py +274 -0
  113. ldm/modules/diffusionmodules/__init__.py +0 -0
  114. ldm/modules/diffusionmodules/model.py +894 -0
  115. ldm/modules/diffusionmodules/openaimodel.py +1036 -0
  116. ldm/modules/diffusionmodules/util.py +314 -0
  117. ldm/modules/distributions/__init__.py +0 -0
  118. ldm/modules/distributions/distributions.py +104 -0
  119. ldm/modules/ema.py +88 -0
  120. ldm/modules/embedding_manager.py +413 -0
  121. ldm/modules/encoders/__init__.py +0 -0
  122. ldm/modules/encoders/modules.py +772 -0
  123. ldm/modules/image_degradation/__init__.py +6 -0
  124. ldm/modules/image_degradation/bsrgan.py +846 -0
  125. ldm/modules/image_degradation/bsrgan_light.py +751 -0
  126. ldm/modules/image_degradation/utils_image.py +1024 -0
  127. ldm/modules/losses/__init__.py +1 -0
  128. ldm/modules/losses/contperceptual.py +175 -0
  129. ldm/modules/losses/vqperceptual.py +240 -0
  130. ldm/modules/x_transformer.py +752 -0
  131. ldm/simplet2i.py +13 -0
  132. ldm/util.py +264 -0
  133. scripts/configure_invokeai.py +797 -0
  134. scripts/create_root.py +43 -0
  135. scripts/dream.py +10 -0
  136. scripts/images2prompt.py +30 -0
  137. scripts/invoke.py +5 -0
  138. scripts/legacy_api.py +681 -0
  139. scripts/load_models.py +12 -0
  140. scripts/merge_embeddings.py +124 -0
  141. scripts/orig_scripts/img2img.py +296 -0
  142. scripts/orig_scripts/inpaint.py +98 -0
  143. scripts/orig_scripts/knn2img.py +397 -0
  144. scripts/orig_scripts/sample_diffusion.py +313 -0
  145. scripts/orig_scripts/train_searcher.py +147 -0
  146. scripts/orig_scripts/txt2img.py +324 -0
  147. scripts/preload_models.py +12 -0
  148. scripts/sd-metadata.py +22 -0
  149. vendored/clip/clip/__init__.py +1 -0
  150. vendored/clip/clip/bpe_simple_vocab_16e6.txt.gz +0 -0
  151. vendored/clip/clip/clip.py +237 -0
  152. vendored/clip/clip/model.py +436 -0
  153. vendored/clip/clip/simple_tokenizer.py +132 -0
  154. vendored/clip/hubconf.py +42 -0
  155. vendored/clip/setup.py +21 -0
  156. vendored/clip/tests/test_consistency.py +25 -0
  157. vendored/clipseg/datasets/coco_wrapper.py +99 -0
  158. vendored/clipseg/datasets/pascal_zeroshot.py +60 -0
  159. vendored/clipseg/datasets/pfe_dataset.py +129 -0
  160. vendored/clipseg/datasets/phrasecut.py +380 -0
  161. vendored/clipseg/datasets/utils.py +68 -0
  162. vendored/clipseg/evaluation_utils.py +292 -0
  163. vendored/clipseg/general_utils.py +272 -0
  164. vendored/clipseg/metrics.py +271 -0
  165. vendored/clipseg/models/clipseg.py +538 -0
  166. vendored/clipseg/models/vitseg.py +286 -0
  167. vendored/clipseg/score.py +453 -0
  168. vendored/clipseg/setup.py +30 -0
  169. vendored/clipseg/training.py +266 -0
@@ -0,0 +1,276 @@
1
+ import math
2
+ import numpy as np
3
+ import torch
4
+ from torch import nn, Tensor
5
+ import torch.nn.functional as F
6
+ from typing import Optional, List
7
+
8
+ from ldm.invoke.restoration.vqgan_arch import *
9
+ from basicsr.utils import get_root_logger
10
+ from basicsr.utils.registry import ARCH_REGISTRY
11
+
12
+ def calc_mean_std(feat, eps=1e-5):
13
+ """Calculate mean and std for adaptive_instance_normalization.
14
+
15
+ Args:
16
+ feat (Tensor): 4D tensor.
17
+ eps (float): A small value added to the variance to avoid
18
+ divide-by-zero. Default: 1e-5.
19
+ """
20
+ size = feat.size()
21
+ assert len(size) == 4, 'The input feature should be 4D tensor.'
22
+ b, c = size[:2]
23
+ feat_var = feat.view(b, c, -1).var(dim=2) + eps
24
+ feat_std = feat_var.sqrt().view(b, c, 1, 1)
25
+ feat_mean = feat.view(b, c, -1).mean(dim=2).view(b, c, 1, 1)
26
+ return feat_mean, feat_std
27
+
28
+
29
+ def adaptive_instance_normalization(content_feat, style_feat):
30
+ """Adaptive instance normalization.
31
+
32
+ Adjust the reference features to have the similar color and illuminations
33
+ as those in the degradate features.
34
+
35
+ Args:
36
+ content_feat (Tensor): The reference feature.
37
+ style_feat (Tensor): The degradate features.
38
+ """
39
+ size = content_feat.size()
40
+ style_mean, style_std = calc_mean_std(style_feat)
41
+ content_mean, content_std = calc_mean_std(content_feat)
42
+ normalized_feat = (content_feat - content_mean.expand(size)) / content_std.expand(size)
43
+ return normalized_feat * style_std.expand(size) + style_mean.expand(size)
44
+
45
+
46
+ class PositionEmbeddingSine(nn.Module):
47
+ """
48
+ This is a more standard version of the position embedding, very similar to the one
49
+ used by the Attention is all you need paper, generalized to work on images.
50
+ """
51
+
52
+ def __init__(self, num_pos_feats=64, temperature=10000, normalize=False, scale=None):
53
+ super().__init__()
54
+ self.num_pos_feats = num_pos_feats
55
+ self.temperature = temperature
56
+ self.normalize = normalize
57
+ if scale is not None and normalize is False:
58
+ raise ValueError("normalize should be True if scale is passed")
59
+ if scale is None:
60
+ scale = 2 * math.pi
61
+ self.scale = scale
62
+
63
+ def forward(self, x, mask=None):
64
+ if mask is None:
65
+ mask = torch.zeros((x.size(0), x.size(2), x.size(3)), device=x.device, dtype=torch.bool)
66
+ not_mask = ~mask
67
+ y_embed = not_mask.cumsum(1, dtype=torch.float32)
68
+ x_embed = not_mask.cumsum(2, dtype=torch.float32)
69
+ if self.normalize:
70
+ eps = 1e-6
71
+ y_embed = y_embed / (y_embed[:, -1:, :] + eps) * self.scale
72
+ x_embed = x_embed / (x_embed[:, :, -1:] + eps) * self.scale
73
+
74
+ dim_t = torch.arange(self.num_pos_feats, dtype=torch.float32, device=x.device)
75
+ dim_t = self.temperature ** (2 * (dim_t // 2) / self.num_pos_feats)
76
+
77
+ pos_x = x_embed[:, :, :, None] / dim_t
78
+ pos_y = y_embed[:, :, :, None] / dim_t
79
+ pos_x = torch.stack(
80
+ (pos_x[:, :, :, 0::2].sin(), pos_x[:, :, :, 1::2].cos()), dim=4
81
+ ).flatten(3)
82
+ pos_y = torch.stack(
83
+ (pos_y[:, :, :, 0::2].sin(), pos_y[:, :, :, 1::2].cos()), dim=4
84
+ ).flatten(3)
85
+ pos = torch.cat((pos_y, pos_x), dim=3).permute(0, 3, 1, 2)
86
+ return pos
87
+
88
+ def _get_activation_fn(activation):
89
+ """Return an activation function given a string"""
90
+ if activation == "relu":
91
+ return F.relu
92
+ if activation == "gelu":
93
+ return F.gelu
94
+ if activation == "glu":
95
+ return F.glu
96
+ raise RuntimeError(F"activation should be relu/gelu, not {activation}.")
97
+
98
+
99
+ class TransformerSALayer(nn.Module):
100
+ def __init__(self, embed_dim, nhead=8, dim_mlp=2048, dropout=0.0, activation="gelu"):
101
+ super().__init__()
102
+ self.self_attn = nn.MultiheadAttention(embed_dim, nhead, dropout=dropout)
103
+ # Implementation of Feedforward model - MLP
104
+ self.linear1 = nn.Linear(embed_dim, dim_mlp)
105
+ self.dropout = nn.Dropout(dropout)
106
+ self.linear2 = nn.Linear(dim_mlp, embed_dim)
107
+
108
+ self.norm1 = nn.LayerNorm(embed_dim)
109
+ self.norm2 = nn.LayerNorm(embed_dim)
110
+ self.dropout1 = nn.Dropout(dropout)
111
+ self.dropout2 = nn.Dropout(dropout)
112
+
113
+ self.activation = _get_activation_fn(activation)
114
+
115
+ def with_pos_embed(self, tensor, pos: Optional[Tensor]):
116
+ return tensor if pos is None else tensor + pos
117
+
118
+ def forward(self, tgt,
119
+ tgt_mask: Optional[Tensor] = None,
120
+ tgt_key_padding_mask: Optional[Tensor] = None,
121
+ query_pos: Optional[Tensor] = None):
122
+
123
+ # self attention
124
+ tgt2 = self.norm1(tgt)
125
+ q = k = self.with_pos_embed(tgt2, query_pos)
126
+ tgt2 = self.self_attn(q, k, value=tgt2, attn_mask=tgt_mask,
127
+ key_padding_mask=tgt_key_padding_mask)[0]
128
+ tgt = tgt + self.dropout1(tgt2)
129
+
130
+ # ffn
131
+ tgt2 = self.norm2(tgt)
132
+ tgt2 = self.linear2(self.dropout(self.activation(self.linear1(tgt2))))
133
+ tgt = tgt + self.dropout2(tgt2)
134
+ return tgt
135
+
136
+ class Fuse_sft_block(nn.Module):
137
+ def __init__(self, in_ch, out_ch):
138
+ super().__init__()
139
+ self.encode_enc = ResBlock(2*in_ch, out_ch)
140
+
141
+ self.scale = nn.Sequential(
142
+ nn.Conv2d(in_ch, out_ch, kernel_size=3, padding=1),
143
+ nn.LeakyReLU(0.2, True),
144
+ nn.Conv2d(out_ch, out_ch, kernel_size=3, padding=1))
145
+
146
+ self.shift = nn.Sequential(
147
+ nn.Conv2d(in_ch, out_ch, kernel_size=3, padding=1),
148
+ nn.LeakyReLU(0.2, True),
149
+ nn.Conv2d(out_ch, out_ch, kernel_size=3, padding=1))
150
+
151
+ def forward(self, enc_feat, dec_feat, w=1):
152
+ enc_feat = self.encode_enc(torch.cat([enc_feat, dec_feat], dim=1))
153
+ scale = self.scale(enc_feat)
154
+ shift = self.shift(enc_feat)
155
+ residual = w * (dec_feat * scale + shift)
156
+ out = dec_feat + residual
157
+ return out
158
+
159
+
160
+ @ARCH_REGISTRY.register()
161
+ class CodeFormer(VQAutoEncoder):
162
+ def __init__(self, dim_embd=512, n_head=8, n_layers=9,
163
+ codebook_size=1024, latent_size=256,
164
+ connect_list=['32', '64', '128', '256'],
165
+ fix_modules=['quantize','generator']):
166
+ super(CodeFormer, self).__init__(512, 64, [1, 2, 2, 4, 4, 8], 'nearest',2, [16], codebook_size)
167
+
168
+ if fix_modules is not None:
169
+ for module in fix_modules:
170
+ for param in getattr(self, module).parameters():
171
+ param.requires_grad = False
172
+
173
+ self.connect_list = connect_list
174
+ self.n_layers = n_layers
175
+ self.dim_embd = dim_embd
176
+ self.dim_mlp = dim_embd*2
177
+
178
+ self.position_emb = nn.Parameter(torch.zeros(latent_size, self.dim_embd))
179
+ self.feat_emb = nn.Linear(256, self.dim_embd)
180
+
181
+ # transformer
182
+ self.ft_layers = nn.Sequential(*[TransformerSALayer(embed_dim=dim_embd, nhead=n_head, dim_mlp=self.dim_mlp, dropout=0.0)
183
+ for _ in range(self.n_layers)])
184
+
185
+ # logits_predict head
186
+ self.idx_pred_layer = nn.Sequential(
187
+ nn.LayerNorm(dim_embd),
188
+ nn.Linear(dim_embd, codebook_size, bias=False))
189
+
190
+ self.channels = {
191
+ '16': 512,
192
+ '32': 256,
193
+ '64': 256,
194
+ '128': 128,
195
+ '256': 128,
196
+ '512': 64,
197
+ }
198
+
199
+ # after second residual block for > 16, before attn layer for ==16
200
+ self.fuse_encoder_block = {'512':2, '256':5, '128':8, '64':11, '32':14, '16':18}
201
+ # after first residual block for > 16, before attn layer for ==16
202
+ self.fuse_generator_block = {'16':6, '32': 9, '64':12, '128':15, '256':18, '512':21}
203
+
204
+ # fuse_convs_dict
205
+ self.fuse_convs_dict = nn.ModuleDict()
206
+ for f_size in self.connect_list:
207
+ in_ch = self.channels[f_size]
208
+ self.fuse_convs_dict[f_size] = Fuse_sft_block(in_ch, in_ch)
209
+
210
+ def _init_weights(self, module):
211
+ if isinstance(module, (nn.Linear, nn.Embedding)):
212
+ module.weight.data.normal_(mean=0.0, std=0.02)
213
+ if isinstance(module, nn.Linear) and module.bias is not None:
214
+ module.bias.data.zero_()
215
+ elif isinstance(module, nn.LayerNorm):
216
+ module.bias.data.zero_()
217
+ module.weight.data.fill_(1.0)
218
+
219
+ def forward(self, x, w=0, detach_16=True, code_only=False, adain=False):
220
+ # ################### Encoder #####################
221
+ enc_feat_dict = {}
222
+ out_list = [self.fuse_encoder_block[f_size] for f_size in self.connect_list]
223
+ for i, block in enumerate(self.encoder.blocks):
224
+ x = block(x)
225
+ if i in out_list:
226
+ enc_feat_dict[str(x.shape[-1])] = x.clone()
227
+
228
+ lq_feat = x
229
+ # ################# Transformer ###################
230
+ # quant_feat, codebook_loss, quant_stats = self.quantize(lq_feat)
231
+ pos_emb = self.position_emb.unsqueeze(1).repeat(1,x.shape[0],1)
232
+ # BCHW -> BC(HW) -> (HW)BC
233
+ feat_emb = self.feat_emb(lq_feat.flatten(2).permute(2,0,1))
234
+ query_emb = feat_emb
235
+ # Transformer encoder
236
+ for layer in self.ft_layers:
237
+ query_emb = layer(query_emb, query_pos=pos_emb)
238
+
239
+ # output logits
240
+ logits = self.idx_pred_layer(query_emb) # (hw)bn
241
+ logits = logits.permute(1,0,2) # (hw)bn -> b(hw)n
242
+
243
+ if code_only: # for training stage II
244
+ # logits doesn't need softmax before cross_entropy loss
245
+ return logits, lq_feat
246
+
247
+ # ################# Quantization ###################
248
+ # if self.training:
249
+ # quant_feat = torch.einsum('btn,nc->btc', [soft_one_hot, self.quantize.embedding.weight])
250
+ # # b(hw)c -> bc(hw) -> bchw
251
+ # quant_feat = quant_feat.permute(0,2,1).view(lq_feat.shape)
252
+ # ------------
253
+ soft_one_hot = F.softmax(logits, dim=2)
254
+ _, top_idx = torch.topk(soft_one_hot, 1, dim=2)
255
+ quant_feat = self.quantize.get_codebook_feat(top_idx, shape=[x.shape[0],16,16,256])
256
+ # preserve gradients
257
+ # quant_feat = lq_feat + (quant_feat - lq_feat).detach()
258
+
259
+ if detach_16:
260
+ quant_feat = quant_feat.detach() # for training stage III
261
+ if adain:
262
+ quant_feat = adaptive_instance_normalization(quant_feat, lq_feat)
263
+
264
+ # ################## Generator ####################
265
+ x = quant_feat
266
+ fuse_list = [self.fuse_generator_block[f_size] for f_size in self.connect_list]
267
+
268
+ for i, block in enumerate(self.generator.blocks):
269
+ x = block(x)
270
+ if i in fuse_list: # fuse after i-th block
271
+ f_size = str(x.shape[-1])
272
+ if w>0:
273
+ x = self.fuse_convs_dict[f_size](enc_feat_dict[f_size].detach(), x, w)
274
+ out = x
275
+ # logits doesn't need softmax before cross_entropy loss
276
+ return out, logits, lq_feat
@@ -0,0 +1,84 @@
1
+ import torch
2
+ import warnings
3
+ import os
4
+ import sys
5
+ import numpy as np
6
+ from ldm.invoke.globals import Globals
7
+
8
+ from PIL import Image
9
+
10
+
11
+ class GFPGAN():
12
+ def __init__(
13
+ self,
14
+ gfpgan_model_path='models/gfpgan/GFPGANv1.4.pth'
15
+ ) -> None:
16
+
17
+ if not os.path.isabs(gfpgan_model_path):
18
+ gfpgan_model_path=os.path.abspath(os.path.join(Globals.root,gfpgan_model_path))
19
+ self.model_path = gfpgan_model_path
20
+ self.gfpgan_model_exists = os.path.isfile(self.model_path)
21
+
22
+ if not self.gfpgan_model_exists:
23
+ print('## NOT FOUND: GFPGAN model not found at ' + self.model_path)
24
+ return None
25
+
26
+ def model_exists(self):
27
+ return os.path.isfile(self.model_path)
28
+
29
+ def process(self, image, strength: float, seed: str = None):
30
+ if seed is not None:
31
+ print(f'>> GFPGAN - Restoring Faces for image seed:{seed}')
32
+
33
+ with warnings.catch_warnings():
34
+ warnings.filterwarnings('ignore', category=DeprecationWarning)
35
+ warnings.filterwarnings('ignore', category=UserWarning)
36
+ try:
37
+ from gfpgan import GFPGANer
38
+ self.gfpgan = GFPGANer(
39
+ model_path=self.model_path,
40
+ upscale=1,
41
+ arch='clean',
42
+ channel_multiplier=2,
43
+ bg_upsampler=None,
44
+ )
45
+ except Exception:
46
+ import traceback
47
+ print('>> Error loading GFPGAN:', file=sys.stderr)
48
+ print(traceback.format_exc(), file=sys.stderr)
49
+
50
+ if self.gfpgan is None:
51
+ print(
52
+ f'>> WARNING: GFPGAN not initialized.'
53
+ )
54
+ print(
55
+ f'>> Download https://github.com/TencentARC/GFPGAN/releases/download/v1.3.0/GFPGANv1.4.pth to {self.model_path}'
56
+ )
57
+
58
+ image = image.convert('RGB')
59
+
60
+ # GFPGAN expects a BGR np array; make array and flip channels
61
+ bgr_image_array = np.array(image, dtype=np.uint8)[...,::-1]
62
+
63
+ _, _, restored_img = self.gfpgan.enhance(
64
+ bgr_image_array,
65
+ has_aligned=False,
66
+ only_center_face=False,
67
+ paste_back=True,
68
+ )
69
+
70
+ # Flip the channels back to RGB
71
+ res = Image.fromarray(restored_img[...,::-1])
72
+
73
+ if strength < 1.0:
74
+ # Resize the image to the new image if the sizes have changed
75
+ if restored_img.size != image.size:
76
+ image = image.resize(res.size)
77
+ res = Image.blend(image, res, strength)
78
+
79
+
80
+ if torch.cuda.is_available():
81
+ torch.cuda.empty_cache()
82
+ self.gfpgan = None
83
+
84
+ return res
@@ -0,0 +1,108 @@
1
+ import warnings
2
+ import math
3
+ from PIL import Image, ImageFilter
4
+
5
+ class Outcrop(object):
6
+ def __init__(
7
+ self,
8
+ image,
9
+ generate, # current generate object
10
+ ):
11
+ self.image = image
12
+ self.generate = generate
13
+
14
+ def process (
15
+ self,
16
+ extents:dict,
17
+ opt, # current options
18
+ orig_opt, # ones originally used to generate the image
19
+ image_callback = None,
20
+ prefix = None
21
+ ):
22
+ # grow and mask the image
23
+ extended_image = self._extend_all(extents)
24
+
25
+ # switch samplers temporarily
26
+ curr_sampler = self.generate.sampler
27
+ self.generate.sampler_name = opt.sampler_name
28
+ self.generate._set_sampler()
29
+
30
+ def wrapped_callback(img,seed,**kwargs):
31
+ preferred_seed = orig_opt.seed if orig_opt.seed is not None and orig_opt.seed >= 0 else seed
32
+ image_callback(img,preferred_seed,use_prefix=prefix,**kwargs)
33
+
34
+ result= self.generate.prompt2image(
35
+ opt.prompt,
36
+ seed = opt.seed or orig_opt.seed,
37
+ sampler = self.generate.sampler,
38
+ steps = opt.steps,
39
+ cfg_scale = opt.cfg_scale,
40
+ ddim_eta = self.generate.ddim_eta,
41
+ width = extended_image.width,
42
+ height = extended_image.height,
43
+ init_img = extended_image,
44
+ strength = 0.90,
45
+ image_callback = wrapped_callback if image_callback else None,
46
+ seam_size = opt.seam_size or 96,
47
+ seam_blur = opt.seam_blur or 16,
48
+ seam_strength = opt.seam_strength or 0.7,
49
+ seam_steps = 20,
50
+ tile_size = 32,
51
+ color_match = True,
52
+ force_outpaint = True, # this just stops the warning about erased regions
53
+ )
54
+
55
+ # swap sampler back
56
+ self.generate.sampler = curr_sampler
57
+ return result
58
+
59
+ def _extend_all(
60
+ self,
61
+ extents:dict,
62
+ ) -> Image:
63
+ '''
64
+ Extend the image in direction ('top','bottom','left','right') by
65
+ the indicated value. The image canvas is extended, and the empty
66
+ rectangular section will be filled with a blurred copy of the
67
+ adjacent image.
68
+ '''
69
+ image = self.image
70
+ for direction in extents:
71
+ assert direction in ['top', 'left', 'bottom', 'right'],'Direction must be one of "top", "left", "bottom", "right"'
72
+ pixels = extents[direction]
73
+ # round pixels up to the nearest 64
74
+ pixels = math.ceil(pixels/64) * 64
75
+ print(f'>> extending image {direction}ward by {pixels} pixels')
76
+ image = self._rotate(image,direction)
77
+ image = self._extend(image,pixels)
78
+ image = self._rotate(image,direction,reverse=True)
79
+ return image
80
+
81
+ def _rotate(self,image:Image,direction:str,reverse=False) -> Image:
82
+ '''
83
+ Rotates image so that the area to extend is always at the top top.
84
+ Simplifies logic later. The reverse argument, if true, will undo the
85
+ previous transpose.
86
+ '''
87
+ transposes = {
88
+ 'right': ['ROTATE_90','ROTATE_270'],
89
+ 'bottom': ['ROTATE_180','ROTATE_180'],
90
+ 'left': ['ROTATE_270','ROTATE_90']
91
+ }
92
+ if direction not in transposes:
93
+ return image
94
+ transpose = transposes[direction][1 if reverse else 0]
95
+ return image.transpose(Image.Transpose.__dict__[transpose])
96
+
97
+ def _extend(self,image:Image,pixels:int)-> Image:
98
+ extended_img = Image.new('RGBA',(image.width,image.height+pixels))
99
+
100
+ extended_img.paste((0,0,0),[0,0,image.width,image.height+pixels])
101
+ extended_img.paste(image,box=(0,pixels))
102
+
103
+ # now make the top part transparent to use as a mask
104
+ alpha = extended_img.getchannel('A')
105
+ alpha.paste(0,(0,0,extended_img.width,pixels))
106
+ extended_img.putalpha(alpha)
107
+
108
+ return extended_img
@@ -0,0 +1,92 @@
1
+ import warnings
2
+ import math
3
+ from PIL import Image, ImageFilter
4
+
5
+ class Outpaint(object):
6
+ def __init__(self, image, generate):
7
+ self.image = image
8
+ self.generate = generate
9
+
10
+ def process(self, opt, old_opt, image_callback = None, prefix = None):
11
+ image = self._create_outpaint_image(self.image, opt.out_direction)
12
+
13
+ seed = old_opt.seed
14
+ prompt = old_opt.prompt
15
+
16
+ def wrapped_callback(img,seed,**kwargs):
17
+ image_callback(img,seed,use_prefix=prefix,**kwargs)
18
+
19
+
20
+ return self.generate.prompt2image(
21
+ prompt,
22
+ seed = seed,
23
+ sampler = self.generate.sampler,
24
+ steps = opt.steps,
25
+ cfg_scale = opt.cfg_scale,
26
+ ddim_eta = self.generate.ddim_eta,
27
+ width = opt.width,
28
+ height = opt.height,
29
+ init_img = image,
30
+ strength = 0.83,
31
+ image_callback = wrapped_callback,
32
+ prefix = prefix,
33
+ )
34
+
35
+ def _create_outpaint_image(self, image, direction_args):
36
+ assert len(direction_args) in [1, 2], 'Direction (-D) must have exactly one or two arguments.'
37
+
38
+ if len(direction_args) == 1:
39
+ direction = direction_args[0]
40
+ pixels = None
41
+ elif len(direction_args) == 2:
42
+ direction = direction_args[0]
43
+ pixels = int(direction_args[1])
44
+
45
+ assert direction in ['top', 'left', 'bottom', 'right'], 'Direction (-D) must be one of "top", "left", "bottom", "right"'
46
+
47
+ image = image.convert("RGBA")
48
+ # we always extend top, but rotate to extend along the requested side
49
+ if direction == 'left':
50
+ image = image.transpose(Image.Transpose.ROTATE_270)
51
+ elif direction == 'bottom':
52
+ image = image.transpose(Image.Transpose.ROTATE_180)
53
+ elif direction == 'right':
54
+ image = image.transpose(Image.Transpose.ROTATE_90)
55
+
56
+ pixels = image.height//2 if pixels is None else int(pixels)
57
+ assert 0 < pixels < image.height, 'Direction (-D) pixels length must be in the range 0 - image.size'
58
+
59
+ # the top part of the image is taken from the source image mirrored
60
+ # coordinates (0,0) are the upper left corner of an image
61
+ top = image.transpose(Image.Transpose.FLIP_TOP_BOTTOM).convert("RGBA")
62
+ top = top.crop((0, top.height - pixels, top.width, top.height))
63
+
64
+ # setting all alpha of the top part to 0
65
+ alpha = top.getchannel("A")
66
+ alpha.paste(0, (0, 0, top.width, top.height))
67
+ top.putalpha(alpha)
68
+
69
+ # taking the bottom from the original image
70
+ bottom = image.crop((0, 0, image.width, image.height - pixels))
71
+
72
+ new_img = image.copy()
73
+ new_img.paste(top, (0, 0))
74
+ new_img.paste(bottom, (0, pixels))
75
+
76
+ # create a 10% dither in the middle
77
+ dither = min(image.height//10, pixels)
78
+ for x in range(0, image.width, 2):
79
+ for y in range(pixels - dither, pixels + dither):
80
+ (r, g, b, a) = new_img.getpixel((x, y))
81
+ new_img.putpixel((x, y), (r, g, b, 0))
82
+
83
+ # let's rotate back again
84
+ if direction == 'left':
85
+ new_img = new_img.transpose(Image.Transpose.ROTATE_90)
86
+ elif direction == 'bottom':
87
+ new_img = new_img.transpose(Image.Transpose.ROTATE_180)
88
+ elif direction == 'right':
89
+ new_img = new_img.transpose(Image.Transpose.ROTATE_270)
90
+
91
+ return new_img
92
+
@@ -0,0 +1,90 @@
1
+ import torch
2
+ import warnings
3
+ import numpy as np
4
+ import os
5
+
6
+ from ldm.invoke.globals import Globals
7
+ from PIL import Image
8
+ from PIL.Image import Image as ImageType
9
+
10
+ class ESRGAN():
11
+ def __init__(self, bg_tile_size=400) -> None:
12
+ self.bg_tile_size = bg_tile_size
13
+
14
+ if not torch.cuda.is_available(): # CPU or MPS on M1
15
+ use_half_precision = False
16
+ else:
17
+ use_half_precision = True
18
+
19
+ def load_esrgan_bg_upsampler(self):
20
+ if not torch.cuda.is_available(): # CPU or MPS on M1
21
+ use_half_precision = False
22
+ else:
23
+ use_half_precision = True
24
+
25
+ from realesrgan.archs.srvgg_arch import SRVGGNetCompact
26
+ from realesrgan import RealESRGANer
27
+
28
+ model = SRVGGNetCompact(num_in_ch=3, num_out_ch=3, num_feat=64, num_conv=32, upscale=4, act_type='prelu')
29
+ model_path = os.path.join(Globals.root,'models/realesrgan/realesr-general-x4v3.pth')
30
+ scale = 4
31
+
32
+ bg_upsampler = RealESRGANer(
33
+ scale=scale,
34
+ model_path=model_path,
35
+ model=model,
36
+ tile=self.bg_tile_size,
37
+ tile_pad=10,
38
+ pre_pad=0,
39
+ half=use_half_precision,
40
+ )
41
+
42
+ return bg_upsampler
43
+
44
+ def process(self, image: ImageType, strength: float, seed: str = None, upsampler_scale: int = 2):
45
+ with warnings.catch_warnings():
46
+ warnings.filterwarnings('ignore', category=DeprecationWarning)
47
+ warnings.filterwarnings('ignore', category=UserWarning)
48
+
49
+ try:
50
+ upsampler = self.load_esrgan_bg_upsampler()
51
+ except Exception:
52
+ import traceback
53
+ import sys
54
+ print('>> Error loading Real-ESRGAN:', file=sys.stderr)
55
+ print(traceback.format_exc(), file=sys.stderr)
56
+
57
+ if upsampler_scale == 0:
58
+ print('>> Real-ESRGAN: Invalid scaling option. Image not upscaled.')
59
+ return image
60
+
61
+ if seed is not None:
62
+ print(
63
+ f'>> Real-ESRGAN Upscaling seed:{seed} : scale:{upsampler_scale}x'
64
+ )
65
+ # ESRGAN outputs images with partial transparency if given RGBA images; convert to RGB
66
+ image = image.convert("RGB")
67
+
68
+ # REALSRGAN expects a BGR np array; make array and flip channels
69
+ bgr_image_array = np.array(image, dtype=np.uint8)[...,::-1]
70
+
71
+ output, _ = upsampler.enhance(
72
+ bgr_image_array,
73
+ outscale=upsampler_scale,
74
+ alpha_upsampler='realesrgan',
75
+ )
76
+
77
+ # Flip the channels back to RGB
78
+ res = Image.fromarray(output[...,::-1])
79
+
80
+ if strength < 1.0:
81
+ # Resize the image to the new image if the sizes have changed
82
+ if output.size != image.size:
83
+ image = image.resize(res.size)
84
+ res = Image.blend(image, res, strength)
85
+
86
+ if torch.cuda.is_available():
87
+ torch.cuda.empty_cache()
88
+ upsampler = None
89
+
90
+ return res