wolverinn commited on
Commit
99a5bb3
1 Parent(s): 09714d5

init with model

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .gitignore +35 -0
  2. .pylintrc +3 -0
  3. LICENSE.txt +663 -0
  4. configs/alt-diffusion-inference.yaml +72 -0
  5. configs/instruct-pix2pix.yaml +98 -0
  6. configs/v1-inference.yaml +70 -0
  7. configs/v1-inpainting-inference.yaml +70 -0
  8. extensions-builtin/LDSR/ldsr_model_arch.py +253 -0
  9. extensions-builtin/LDSR/preload.py +6 -0
  10. extensions-builtin/LDSR/scripts/ldsr_model.py +69 -0
  11. extensions-builtin/LDSR/sd_hijack_autoencoder.py +286 -0
  12. extensions-builtin/LDSR/sd_hijack_ddpm_v1.py +1449 -0
  13. extensions-builtin/Lora/extra_networks_lora.py +26 -0
  14. extensions-builtin/Lora/lora.py +207 -0
  15. extensions-builtin/Lora/preload.py +6 -0
  16. extensions-builtin/Lora/scripts/lora_script.py +38 -0
  17. extensions-builtin/Lora/ui_extra_networks_lora.py +37 -0
  18. extensions-builtin/ScuNET/preload.py +6 -0
  19. extensions-builtin/ScuNET/scripts/scunet_model.py +87 -0
  20. extensions-builtin/ScuNET/scunet_model_arch.py +265 -0
  21. extensions-builtin/SwinIR/preload.py +6 -0
  22. extensions-builtin/SwinIR/scripts/swinir_model.py +178 -0
  23. extensions-builtin/SwinIR/swinir_model_arch.py +867 -0
  24. extensions-builtin/SwinIR/swinir_model_arch_v2.py +1017 -0
  25. extensions-builtin/prompt-bracket-checker/javascript/prompt-bracket-checker.js +110 -0
  26. handler.py +226 -0
  27. modules/api/api.py +551 -0
  28. modules/api/models.py +269 -0
  29. modules/call_queue.py +109 -0
  30. modules/codeformer/codeformer_arch.py +278 -0
  31. modules/codeformer/vqgan_arch.py +437 -0
  32. modules/codeformer_model.py +143 -0
  33. modules/deepbooru.py +99 -0
  34. modules/deepbooru_model.py +678 -0
  35. modules/devices.py +152 -0
  36. modules/errors.py +43 -0
  37. modules/esrgan_model.py +233 -0
  38. modules/esrgan_model_arch.py +464 -0
  39. modules/extensions.py +107 -0
  40. modules/extra_networks.py +147 -0
  41. modules/extra_networks_hypernet.py +27 -0
  42. modules/extras.py +258 -0
  43. modules/face_restoration.py +19 -0
  44. modules/generation_parameters_copypaste.py +402 -0
  45. modules/gfpgan_model.py +116 -0
  46. modules/hashes.py +91 -0
  47. modules/hypernetworks/hypernetwork.py +811 -0
  48. modules/hypernetworks/ui.py +40 -0
  49. modules/images.py +669 -0
  50. modules/img2img.py +184 -0
.gitignore ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ __pycache__
2
+ *.ckpt
3
+ *.safetensors
4
+ *.pth
5
+ /ESRGAN/*
6
+ /SwinIR/*
7
+ /repositories
8
+ /venv
9
+ /tmp
10
+ /model.ckpt
11
+ /models/**/*
12
+ /GFPGANv1.3.pth
13
+ /gfpgan/weights/*.pth
14
+ /ui-config.json
15
+ /outputs
16
+ /config.json
17
+ /log
18
+ /webui.settings.bat
19
+ /embeddings
20
+ /styles.csv
21
+ /params.txt
22
+ /styles.csv.bak
23
+ /webui-user.bat
24
+ /webui-user.sh
25
+ /interrogate
26
+ /user.css
27
+ /.idea
28
+ notification.mp3
29
+ /SwinIR
30
+ /textual_inversion
31
+ .vscode
32
+ /extensions
33
+ /test/stdout.txt
34
+ /test/stderr.txt
35
+ /cache.json
.pylintrc ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ # See https://pylint.pycqa.org/en/latest/user_guide/messages/message_control.html
2
+ [MESSAGES CONTROL]
3
+ disable=C,R,W,E,I
LICENSE.txt ADDED
@@ -0,0 +1,663 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ GNU AFFERO GENERAL PUBLIC LICENSE
2
+ Version 3, 19 November 2007
3
+
4
+ Copyright (c) 2023 AUTOMATIC1111
5
+
6
+ Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
7
+ Everyone is permitted to copy and distribute verbatim copies
8
+ of this license document, but changing it is not allowed.
9
+
10
+ Preamble
11
+
12
+ The GNU Affero General Public License is a free, copyleft license for
13
+ software and other kinds of works, specifically designed to ensure
14
+ cooperation with the community in the case of network server software.
15
+
16
+ The licenses for most software and other practical works are designed
17
+ to take away your freedom to share and change the works. By contrast,
18
+ our General Public Licenses are intended to guarantee your freedom to
19
+ share and change all versions of a program--to make sure it remains free
20
+ software for all its users.
21
+
22
+ When we speak of free software, we are referring to freedom, not
23
+ price. Our General Public Licenses are designed to make sure that you
24
+ have the freedom to distribute copies of free software (and charge for
25
+ them if you wish), that you receive source code or can get it if you
26
+ want it, that you can change the software or use pieces of it in new
27
+ free programs, and that you know you can do these things.
28
+
29
+ Developers that use our General Public Licenses protect your rights
30
+ with two steps: (1) assert copyright on the software, and (2) offer
31
+ you this License which gives you legal permission to copy, distribute
32
+ and/or modify the software.
33
+
34
+ A secondary benefit of defending all users' freedom is that
35
+ improvements made in alternate versions of the program, if they
36
+ receive widespread use, become available for other developers to
37
+ incorporate. Many developers of free software are heartened and
38
+ encouraged by the resulting cooperation. However, in the case of
39
+ software used on network servers, this result may fail to come about.
40
+ The GNU General Public License permits making a modified version and
41
+ letting the public access it on a server without ever releasing its
42
+ source code to the public.
43
+
44
+ The GNU Affero General Public License is designed specifically to
45
+ ensure that, in such cases, the modified source code becomes available
46
+ to the community. It requires the operator of a network server to
47
+ provide the source code of the modified version running there to the
48
+ users of that server. Therefore, public use of a modified version, on
49
+ a publicly accessible server, gives the public access to the source
50
+ code of the modified version.
51
+
52
+ An older license, called the Affero General Public License and
53
+ published by Affero, was designed to accomplish similar goals. This is
54
+ a different license, not a version of the Affero GPL, but Affero has
55
+ released a new version of the Affero GPL which permits relicensing under
56
+ this license.
57
+
58
+ The precise terms and conditions for copying, distribution and
59
+ modification follow.
60
+
61
+ TERMS AND CONDITIONS
62
+
63
+ 0. Definitions.
64
+
65
+ "This License" refers to version 3 of the GNU Affero General Public License.
66
+
67
+ "Copyright" also means copyright-like laws that apply to other kinds of
68
+ works, such as semiconductor masks.
69
+
70
+ "The Program" refers to any copyrightable work licensed under this
71
+ License. Each licensee is addressed as "you". "Licensees" and
72
+ "recipients" may be individuals or organizations.
73
+
74
+ To "modify" a work means to copy from or adapt all or part of the work
75
+ in a fashion requiring copyright permission, other than the making of an
76
+ exact copy. The resulting work is called a "modified version" of the
77
+ earlier work or a work "based on" the earlier work.
78
+
79
+ A "covered work" means either the unmodified Program or a work based
80
+ on the Program.
81
+
82
+ To "propagate" a work means to do anything with it that, without
83
+ permission, would make you directly or secondarily liable for
84
+ infringement under applicable copyright law, except executing it on a
85
+ computer or modifying a private copy. Propagation includes copying,
86
+ distribution (with or without modification), making available to the
87
+ public, and in some countries other activities as well.
88
+
89
+ To "convey" a work means any kind of propagation that enables other
90
+ parties to make or receive copies. Mere interaction with a user through
91
+ a computer network, with no transfer of a copy, is not conveying.
92
+
93
+ An interactive user interface displays "Appropriate Legal Notices"
94
+ to the extent that it includes a convenient and prominently visible
95
+ feature that (1) displays an appropriate copyright notice, and (2)
96
+ tells the user that there is no warranty for the work (except to the
97
+ extent that warranties are provided), that licensees may convey the
98
+ work under this License, and how to view a copy of this License. If
99
+ the interface presents a list of user commands or options, such as a
100
+ menu, a prominent item in the list meets this criterion.
101
+
102
+ 1. Source Code.
103
+
104
+ The "source code" for a work means the preferred form of the work
105
+ for making modifications to it. "Object code" means any non-source
106
+ form of a work.
107
+
108
+ A "Standard Interface" means an interface that either is an official
109
+ standard defined by a recognized standards body, or, in the case of
110
+ interfaces specified for a particular programming language, one that
111
+ is widely used among developers working in that language.
112
+
113
+ The "System Libraries" of an executable work include anything, other
114
+ than the work as a whole, that (a) is included in the normal form of
115
+ packaging a Major Component, but which is not part of that Major
116
+ Component, and (b) serves only to enable use of the work with that
117
+ Major Component, or to implement a Standard Interface for which an
118
+ implementation is available to the public in source code form. A
119
+ "Major Component", in this context, means a major essential component
120
+ (kernel, window system, and so on) of the specific operating system
121
+ (if any) on which the executable work runs, or a compiler used to
122
+ produce the work, or an object code interpreter used to run it.
123
+
124
+ The "Corresponding Source" for a work in object code form means all
125
+ the source code needed to generate, install, and (for an executable
126
+ work) run the object code and to modify the work, including scripts to
127
+ control those activities. However, it does not include the work's
128
+ System Libraries, or general-purpose tools or generally available free
129
+ programs which are used unmodified in performing those activities but
130
+ which are not part of the work. For example, Corresponding Source
131
+ includes interface definition files associated with source files for
132
+ the work, and the source code for shared libraries and dynamically
133
+ linked subprograms that the work is specifically designed to require,
134
+ such as by intimate data communication or control flow between those
135
+ subprograms and other parts of the work.
136
+
137
+ The Corresponding Source need not include anything that users
138
+ can regenerate automatically from other parts of the Corresponding
139
+ Source.
140
+
141
+ The Corresponding Source for a work in source code form is that
142
+ same work.
143
+
144
+ 2. Basic Permissions.
145
+
146
+ All rights granted under this License are granted for the term of
147
+ copyright on the Program, and are irrevocable provided the stated
148
+ conditions are met. This License explicitly affirms your unlimited
149
+ permission to run the unmodified Program. The output from running a
150
+ covered work is covered by this License only if the output, given its
151
+ content, constitutes a covered work. This License acknowledges your
152
+ rights of fair use or other equivalent, as provided by copyright law.
153
+
154
+ You may make, run and propagate covered works that you do not
155
+ convey, without conditions so long as your license otherwise remains
156
+ in force. You may convey covered works to others for the sole purpose
157
+ of having them make modifications exclusively for you, or provide you
158
+ with facilities for running those works, provided that you comply with
159
+ the terms of this License in conveying all material for which you do
160
+ not control copyright. Those thus making or running the covered works
161
+ for you must do so exclusively on your behalf, under your direction
162
+ and control, on terms that prohibit them from making any copies of
163
+ your copyrighted material outside their relationship with you.
164
+
165
+ Conveying under any other circumstances is permitted solely under
166
+ the conditions stated below. Sublicensing is not allowed; section 10
167
+ makes it unnecessary.
168
+
169
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
170
+
171
+ No covered work shall be deemed part of an effective technological
172
+ measure under any applicable law fulfilling obligations under article
173
+ 11 of the WIPO copyright treaty adopted on 20 December 1996, or
174
+ similar laws prohibiting or restricting circumvention of such
175
+ measures.
176
+
177
+ When you convey a covered work, you waive any legal power to forbid
178
+ circumvention of technological measures to the extent such circumvention
179
+ is effected by exercising rights under this License with respect to
180
+ the covered work, and you disclaim any intention to limit operation or
181
+ modification of the work as a means of enforcing, against the work's
182
+ users, your or third parties' legal rights to forbid circumvention of
183
+ technological measures.
184
+
185
+ 4. Conveying Verbatim Copies.
186
+
187
+ You may convey verbatim copies of the Program's source code as you
188
+ receive it, in any medium, provided that you conspicuously and
189
+ appropriately publish on each copy an appropriate copyright notice;
190
+ keep intact all notices stating that this License and any
191
+ non-permissive terms added in accord with section 7 apply to the code;
192
+ keep intact all notices of the absence of any warranty; and give all
193
+ recipients a copy of this License along with the Program.
194
+
195
+ You may charge any price or no price for each copy that you convey,
196
+ and you may offer support or warranty protection for a fee.
197
+
198
+ 5. Conveying Modified Source Versions.
199
+
200
+ You may convey a work based on the Program, or the modifications to
201
+ produce it from the Program, in the form of source code under the
202
+ terms of section 4, provided that you also meet all of these conditions:
203
+
204
+ a) The work must carry prominent notices stating that you modified
205
+ it, and giving a relevant date.
206
+
207
+ b) The work must carry prominent notices stating that it is
208
+ released under this License and any conditions added under section
209
+ 7. This requirement modifies the requirement in section 4 to
210
+ "keep intact all notices".
211
+
212
+ c) You must license the entire work, as a whole, under this
213
+ License to anyone who comes into possession of a copy. This
214
+ License will therefore apply, along with any applicable section 7
215
+ additional terms, to the whole of the work, and all its parts,
216
+ regardless of how they are packaged. This License gives no
217
+ permission to license the work in any other way, but it does not
218
+ invalidate such permission if you have separately received it.
219
+
220
+ d) If the work has interactive user interfaces, each must display
221
+ Appropriate Legal Notices; however, if the Program has interactive
222
+ interfaces that do not display Appropriate Legal Notices, your
223
+ work need not make them do so.
224
+
225
+ A compilation of a covered work with other separate and independent
226
+ works, which are not by their nature extensions of the covered work,
227
+ and which are not combined with it such as to form a larger program,
228
+ in or on a volume of a storage or distribution medium, is called an
229
+ "aggregate" if the compilation and its resulting copyright are not
230
+ used to limit the access or legal rights of the compilation's users
231
+ beyond what the individual works permit. Inclusion of a covered work
232
+ in an aggregate does not cause this License to apply to the other
233
+ parts of the aggregate.
234
+
235
+ 6. Conveying Non-Source Forms.
236
+
237
+ You may convey a covered work in object code form under the terms
238
+ of sections 4 and 5, provided that you also convey the
239
+ machine-readable Corresponding Source under the terms of this License,
240
+ in one of these ways:
241
+
242
+ a) Convey the object code in, or embodied in, a physical product
243
+ (including a physical distribution medium), accompanied by the
244
+ Corresponding Source fixed on a durable physical medium
245
+ customarily used for software interchange.
246
+
247
+ b) Convey the object code in, or embodied in, a physical product
248
+ (including a physical distribution medium), accompanied by a
249
+ written offer, valid for at least three years and valid for as
250
+ long as you offer spare parts or customer support for that product
251
+ model, to give anyone who possesses the object code either (1) a
252
+ copy of the Corresponding Source for all the software in the
253
+ product that is covered by this License, on a durable physical
254
+ medium customarily used for software interchange, for a price no
255
+ more than your reasonable cost of physically performing this
256
+ conveying of source, or (2) access to copy the
257
+ Corresponding Source from a network server at no charge.
258
+
259
+ c) Convey individual copies of the object code with a copy of the
260
+ written offer to provide the Corresponding Source. This
261
+ alternative is allowed only occasionally and noncommercially, and
262
+ only if you received the object code with such an offer, in accord
263
+ with subsection 6b.
264
+
265
+ d) Convey the object code by offering access from a designated
266
+ place (gratis or for a charge), and offer equivalent access to the
267
+ Corresponding Source in the same way through the same place at no
268
+ further charge. You need not require recipients to copy the
269
+ Corresponding Source along with the object code. If the place to
270
+ copy the object code is a network server, the Corresponding Source
271
+ may be on a different server (operated by you or a third party)
272
+ that supports equivalent copying facilities, provided you maintain
273
+ clear directions next to the object code saying where to find the
274
+ Corresponding Source. Regardless of what server hosts the
275
+ Corresponding Source, you remain obligated to ensure that it is
276
+ available for as long as needed to satisfy these requirements.
277
+
278
+ e) Convey the object code using peer-to-peer transmission, provided
279
+ you inform other peers where the object code and Corresponding
280
+ Source of the work are being offered to the general public at no
281
+ charge under subsection 6d.
282
+
283
+ A separable portion of the object code, whose source code is excluded
284
+ from the Corresponding Source as a System Library, need not be
285
+ included in conveying the object code work.
286
+
287
+ A "User Product" is either (1) a "consumer product", which means any
288
+ tangible personal property which is normally used for personal, family,
289
+ or household purposes, or (2) anything designed or sold for incorporation
290
+ into a dwelling. In determining whether a product is a consumer product,
291
+ doubtful cases shall be resolved in favor of coverage. For a particular
292
+ product received by a particular user, "normally used" refers to a
293
+ typical or common use of that class of product, regardless of the status
294
+ of the particular user or of the way in which the particular user
295
+ actually uses, or expects or is expected to use, the product. A product
296
+ is a consumer product regardless of whether the product has substantial
297
+ commercial, industrial or non-consumer uses, unless such uses represent
298
+ the only significant mode of use of the product.
299
+
300
+ "Installation Information" for a User Product means any methods,
301
+ procedures, authorization keys, or other information required to install
302
+ and execute modified versions of a covered work in that User Product from
303
+ a modified version of its Corresponding Source. The information must
304
+ suffice to ensure that the continued functioning of the modified object
305
+ code is in no case prevented or interfered with solely because
306
+ modification has been made.
307
+
308
+ If you convey an object code work under this section in, or with, or
309
+ specifically for use in, a User Product, and the conveying occurs as
310
+ part of a transaction in which the right of possession and use of the
311
+ User Product is transferred to the recipient in perpetuity or for a
312
+ fixed term (regardless of how the transaction is characterized), the
313
+ Corresponding Source conveyed under this section must be accompanied
314
+ by the Installation Information. But this requirement does not apply
315
+ if neither you nor any third party retains the ability to install
316
+ modified object code on the User Product (for example, the work has
317
+ been installed in ROM).
318
+
319
+ The requirement to provide Installation Information does not include a
320
+ requirement to continue to provide support service, warranty, or updates
321
+ for a work that has been modified or installed by the recipient, or for
322
+ the User Product in which it has been modified or installed. Access to a
323
+ network may be denied when the modification itself materially and
324
+ adversely affects the operation of the network or violates the rules and
325
+ protocols for communication across the network.
326
+
327
+ Corresponding Source conveyed, and Installation Information provided,
328
+ in accord with this section must be in a format that is publicly
329
+ documented (and with an implementation available to the public in
330
+ source code form), and must require no special password or key for
331
+ unpacking, reading or copying.
332
+
333
+ 7. Additional Terms.
334
+
335
+ "Additional permissions" are terms that supplement the terms of this
336
+ License by making exceptions from one or more of its conditions.
337
+ Additional permissions that are applicable to the entire Program shall
338
+ be treated as though they were included in this License, to the extent
339
+ that they are valid under applicable law. If additional permissions
340
+ apply only to part of the Program, that part may be used separately
341
+ under those permissions, but the entire Program remains governed by
342
+ this License without regard to the additional permissions.
343
+
344
+ When you convey a copy of a covered work, you may at your option
345
+ remove any additional permissions from that copy, or from any part of
346
+ it. (Additional permissions may be written to require their own
347
+ removal in certain cases when you modify the work.) You may place
348
+ additional permissions on material, added by you to a covered work,
349
+ for which you have or can give appropriate copyright permission.
350
+
351
+ Notwithstanding any other provision of this License, for material you
352
+ add to a covered work, you may (if authorized by the copyright holders of
353
+ that material) supplement the terms of this License with terms:
354
+
355
+ a) Disclaiming warranty or limiting liability differently from the
356
+ terms of sections 15 and 16 of this License; or
357
+
358
+ b) Requiring preservation of specified reasonable legal notices or
359
+ author attributions in that material or in the Appropriate Legal
360
+ Notices displayed by works containing it; or
361
+
362
+ c) Prohibiting misrepresentation of the origin of that material, or
363
+ requiring that modified versions of such material be marked in
364
+ reasonable ways as different from the original version; or
365
+
366
+ d) Limiting the use for publicity purposes of names of licensors or
367
+ authors of the material; or
368
+
369
+ e) Declining to grant rights under trademark law for use of some
370
+ trade names, trademarks, or service marks; or
371
+
372
+ f) Requiring indemnification of licensors and authors of that
373
+ material by anyone who conveys the material (or modified versions of
374
+ it) with contractual assumptions of liability to the recipient, for
375
+ any liability that these contractual assumptions directly impose on
376
+ those licensors and authors.
377
+
378
+ All other non-permissive additional terms are considered "further
379
+ restrictions" within the meaning of section 10. If the Program as you
380
+ received it, or any part of it, contains a notice stating that it is
381
+ governed by this License along with a term that is a further
382
+ restriction, you may remove that term. If a license document contains
383
+ a further restriction but permits relicensing or conveying under this
384
+ License, you may add to a covered work material governed by the terms
385
+ of that license document, provided that the further restriction does
386
+ not survive such relicensing or conveying.
387
+
388
+ If you add terms to a covered work in accord with this section, you
389
+ must place, in the relevant source files, a statement of the
390
+ additional terms that apply to those files, or a notice indicating
391
+ where to find the applicable terms.
392
+
393
+ Additional terms, permissive or non-permissive, may be stated in the
394
+ form of a separately written license, or stated as exceptions;
395
+ the above requirements apply either way.
396
+
397
+ 8. Termination.
398
+
399
+ You may not propagate or modify a covered work except as expressly
400
+ provided under this License. Any attempt otherwise to propagate or
401
+ modify it is void, and will automatically terminate your rights under
402
+ this License (including any patent licenses granted under the third
403
+ paragraph of section 11).
404
+
405
+ However, if you cease all violation of this License, then your
406
+ license from a particular copyright holder is reinstated (a)
407
+ provisionally, unless and until the copyright holder explicitly and
408
+ finally terminates your license, and (b) permanently, if the copyright
409
+ holder fails to notify you of the violation by some reasonable means
410
+ prior to 60 days after the cessation.
411
+
412
+ Moreover, your license from a particular copyright holder is
413
+ reinstated permanently if the copyright holder notifies you of the
414
+ violation by some reasonable means, this is the first time you have
415
+ received notice of violation of this License (for any work) from that
416
+ copyright holder, and you cure the violation prior to 30 days after
417
+ your receipt of the notice.
418
+
419
+ Termination of your rights under this section does not terminate the
420
+ licenses of parties who have received copies or rights from you under
421
+ this License. If your rights have been terminated and not permanently
422
+ reinstated, you do not qualify to receive new licenses for the same
423
+ material under section 10.
424
+
425
+ 9. Acceptance Not Required for Having Copies.
426
+
427
+ You are not required to accept this License in order to receive or
428
+ run a copy of the Program. Ancillary propagation of a covered work
429
+ occurring solely as a consequence of using peer-to-peer transmission
430
+ to receive a copy likewise does not require acceptance. However,
431
+ nothing other than this License grants you permission to propagate or
432
+ modify any covered work. These actions infringe copyright if you do
433
+ not accept this License. Therefore, by modifying or propagating a
434
+ covered work, you indicate your acceptance of this License to do so.
435
+
436
+ 10. Automatic Licensing of Downstream Recipients.
437
+
438
+ Each time you convey a covered work, the recipient automatically
439
+ receives a license from the original licensors, to run, modify and
440
+ propagate that work, subject to this License. You are not responsible
441
+ for enforcing compliance by third parties with this License.
442
+
443
+ An "entity transaction" is a transaction transferring control of an
444
+ organization, or substantially all assets of one, or subdividing an
445
+ organization, or merging organizations. If propagation of a covered
446
+ work results from an entity transaction, each party to that
447
+ transaction who receives a copy of the work also receives whatever
448
+ licenses to the work the party's predecessor in interest had or could
449
+ give under the previous paragraph, plus a right to possession of the
450
+ Corresponding Source of the work from the predecessor in interest, if
451
+ the predecessor has it or can get it with reasonable efforts.
452
+
453
+ You may not impose any further restrictions on the exercise of the
454
+ rights granted or affirmed under this License. For example, you may
455
+ not impose a license fee, royalty, or other charge for exercise of
456
+ rights granted under this License, and you may not initiate litigation
457
+ (including a cross-claim or counterclaim in a lawsuit) alleging that
458
+ any patent claim is infringed by making, using, selling, offering for
459
+ sale, or importing the Program or any portion of it.
460
+
461
+ 11. Patents.
462
+
463
+ A "contributor" is a copyright holder who authorizes use under this
464
+ License of the Program or a work on which the Program is based. The
465
+ work thus licensed is called the contributor's "contributor version".
466
+
467
+ A contributor's "essential patent claims" are all patent claims
468
+ owned or controlled by the contributor, whether already acquired or
469
+ hereafter acquired, that would be infringed by some manner, permitted
470
+ by this License, of making, using, or selling its contributor version,
471
+ but do not include claims that would be infringed only as a
472
+ consequence of further modification of the contributor version. For
473
+ purposes of this definition, "control" includes the right to grant
474
+ patent sublicenses in a manner consistent with the requirements of
475
+ this License.
476
+
477
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
478
+ patent license under the contributor's essential patent claims, to
479
+ make, use, sell, offer for sale, import and otherwise run, modify and
480
+ propagate the contents of its contributor version.
481
+
482
+ In the following three paragraphs, a "patent license" is any express
483
+ agreement or commitment, however denominated, not to enforce a patent
484
+ (such as an express permission to practice a patent or covenant not to
485
+ sue for patent infringement). To "grant" such a patent license to a
486
+ party means to make such an agreement or commitment not to enforce a
487
+ patent against the party.
488
+
489
+ If you convey a covered work, knowingly relying on a patent license,
490
+ and the Corresponding Source of the work is not available for anyone
491
+ to copy, free of charge and under the terms of this License, through a
492
+ publicly available network server or other readily accessible means,
493
+ then you must either (1) cause the Corresponding Source to be so
494
+ available, or (2) arrange to deprive yourself of the benefit of the
495
+ patent license for this particular work, or (3) arrange, in a manner
496
+ consistent with the requirements of this License, to extend the patent
497
+ license to downstream recipients. "Knowingly relying" means you have
498
+ actual knowledge that, but for the patent license, your conveying the
499
+ covered work in a country, or your recipient's use of the covered work
500
+ in a country, would infringe one or more identifiable patents in that
501
+ country that you have reason to believe are valid.
502
+
503
+ If, pursuant to or in connection with a single transaction or
504
+ arrangement, you convey, or propagate by procuring conveyance of, a
505
+ covered work, and grant a patent license to some of the parties
506
+ receiving the covered work authorizing them to use, propagate, modify
507
+ or convey a specific copy of the covered work, then the patent license
508
+ you grant is automatically extended to all recipients of the covered
509
+ work and works based on it.
510
+
511
+ A patent license is "discriminatory" if it does not include within
512
+ the scope of its coverage, prohibits the exercise of, or is
513
+ conditioned on the non-exercise of one or more of the rights that are
514
+ specifically granted under this License. You may not convey a covered
515
+ work if you are a party to an arrangement with a third party that is
516
+ in the business of distributing software, under which you make payment
517
+ to the third party based on the extent of your activity of conveying
518
+ the work, and under which the third party grants, to any of the
519
+ parties who would receive the covered work from you, a discriminatory
520
+ patent license (a) in connection with copies of the covered work
521
+ conveyed by you (or copies made from those copies), or (b) primarily
522
+ for and in connection with specific products or compilations that
523
+ contain the covered work, unless you entered into that arrangement,
524
+ or that patent license was granted, prior to 28 March 2007.
525
+
526
+ Nothing in this License shall be construed as excluding or limiting
527
+ any implied license or other defenses to infringement that may
528
+ otherwise be available to you under applicable patent law.
529
+
530
+ 12. No Surrender of Others' Freedom.
531
+
532
+ If conditions are imposed on you (whether by court order, agreement or
533
+ otherwise) that contradict the conditions of this License, they do not
534
+ excuse you from the conditions of this License. If you cannot convey a
535
+ covered work so as to satisfy simultaneously your obligations under this
536
+ License and any other pertinent obligations, then as a consequence you may
537
+ not convey it at all. For example, if you agree to terms that obligate you
538
+ to collect a royalty for further conveying from those to whom you convey
539
+ the Program, the only way you could satisfy both those terms and this
540
+ License would be to refrain entirely from conveying the Program.
541
+
542
+ 13. Remote Network Interaction; Use with the GNU General Public License.
543
+
544
+ Notwithstanding any other provision of this License, if you modify the
545
+ Program, your modified version must prominently offer all users
546
+ interacting with it remotely through a computer network (if your version
547
+ supports such interaction) an opportunity to receive the Corresponding
548
+ Source of your version by providing access to the Corresponding Source
549
+ from a network server at no charge, through some standard or customary
550
+ means of facilitating copying of software. This Corresponding Source
551
+ shall include the Corresponding Source for any work covered by version 3
552
+ of the GNU General Public License that is incorporated pursuant to the
553
+ following paragraph.
554
+
555
+ Notwithstanding any other provision of this License, you have
556
+ permission to link or combine any covered work with a work licensed
557
+ under version 3 of the GNU General Public License into a single
558
+ combined work, and to convey the resulting work. The terms of this
559
+ License will continue to apply to the part which is the covered work,
560
+ but the work with which it is combined will remain governed by version
561
+ 3 of the GNU General Public License.
562
+
563
+ 14. Revised Versions of this License.
564
+
565
+ The Free Software Foundation may publish revised and/or new versions of
566
+ the GNU Affero General Public License from time to time. Such new versions
567
+ will be similar in spirit to the present version, but may differ in detail to
568
+ address new problems or concerns.
569
+
570
+ Each version is given a distinguishing version number. If the
571
+ Program specifies that a certain numbered version of the GNU Affero General
572
+ Public License "or any later version" applies to it, you have the
573
+ option of following the terms and conditions either of that numbered
574
+ version or of any later version published by the Free Software
575
+ Foundation. If the Program does not specify a version number of the
576
+ GNU Affero General Public License, you may choose any version ever published
577
+ by the Free Software Foundation.
578
+
579
+ If the Program specifies that a proxy can decide which future
580
+ versions of the GNU Affero General Public License can be used, that proxy's
581
+ public statement of acceptance of a version permanently authorizes you
582
+ to choose that version for the Program.
583
+
584
+ Later license versions may give you additional or different
585
+ permissions. However, no additional obligations are imposed on any
586
+ author or copyright holder as a result of your choosing to follow a
587
+ later version.
588
+
589
+ 15. Disclaimer of Warranty.
590
+
591
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
592
+ APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
593
+ HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
594
+ OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
595
+ THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
596
+ PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
597
+ IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
598
+ ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
599
+
600
+ 16. Limitation of Liability.
601
+
602
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
603
+ WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
604
+ THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
605
+ GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
606
+ USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
607
+ DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
608
+ PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
609
+ EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
610
+ SUCH DAMAGES.
611
+
612
+ 17. Interpretation of Sections 15 and 16.
613
+
614
+ If the disclaimer of warranty and limitation of liability provided
615
+ above cannot be given local legal effect according to their terms,
616
+ reviewing courts shall apply local law that most closely approximates
617
+ an absolute waiver of all civil liability in connection with the
618
+ Program, unless a warranty or assumption of liability accompanies a
619
+ copy of the Program in return for a fee.
620
+
621
+ END OF TERMS AND CONDITIONS
622
+
623
+ How to Apply These Terms to Your New Programs
624
+
625
+ If you develop a new program, and you want it to be of the greatest
626
+ possible use to the public, the best way to achieve this is to make it
627
+ free software which everyone can redistribute and change under these terms.
628
+
629
+ To do so, attach the following notices to the program. It is safest
630
+ to attach them to the start of each source file to most effectively
631
+ state the exclusion of warranty; and each file should have at least
632
+ the "copyright" line and a pointer to where the full notice is found.
633
+
634
+ <one line to give the program's name and a brief idea of what it does.>
635
+ Copyright (C) <year> <name of author>
636
+
637
+ This program is free software: you can redistribute it and/or modify
638
+ it under the terms of the GNU Affero General Public License as published by
639
+ the Free Software Foundation, either version 3 of the License, or
640
+ (at your option) any later version.
641
+
642
+ This program is distributed in the hope that it will be useful,
643
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
644
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
645
+ GNU Affero General Public License for more details.
646
+
647
+ You should have received a copy of the GNU Affero General Public License
648
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
649
+
650
+ Also add information on how to contact you by electronic and paper mail.
651
+
652
+ If your software can interact with users remotely through a computer
653
+ network, you should also make sure that it provides a way for users to
654
+ get its source. For example, if your program is a web application, its
655
+ interface could display a "Source" link that leads users to an archive
656
+ of the code. There are many ways you could offer source, and different
657
+ solutions will be better for different programs; see section 13 for the
658
+ specific requirements.
659
+
660
+ You should also get your employer (if you work as a programmer) or school,
661
+ if any, to sign a "copyright disclaimer" for the program, if necessary.
662
+ For more information on this, and how to apply and follow the GNU AGPL, see
663
+ <https://www.gnu.org/licenses/>.
configs/alt-diffusion-inference.yaml ADDED
@@ -0,0 +1,72 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ model:
2
+ base_learning_rate: 1.0e-04
3
+ target: ldm.models.diffusion.ddpm.LatentDiffusion
4
+ params:
5
+ linear_start: 0.00085
6
+ linear_end: 0.0120
7
+ num_timesteps_cond: 1
8
+ log_every_t: 200
9
+ timesteps: 1000
10
+ first_stage_key: "jpg"
11
+ cond_stage_key: "txt"
12
+ image_size: 64
13
+ channels: 4
14
+ cond_stage_trainable: false # Note: different from the one we trained before
15
+ conditioning_key: crossattn
16
+ monitor: val/loss_simple_ema
17
+ scale_factor: 0.18215
18
+ use_ema: False
19
+
20
+ scheduler_config: # 10000 warmup steps
21
+ target: ldm.lr_scheduler.LambdaLinearScheduler
22
+ params:
23
+ warm_up_steps: [ 10000 ]
24
+ cycle_lengths: [ 10000000000000 ] # incredibly large number to prevent corner cases
25
+ f_start: [ 1.e-6 ]
26
+ f_max: [ 1. ]
27
+ f_min: [ 1. ]
28
+
29
+ unet_config:
30
+ target: ldm.modules.diffusionmodules.openaimodel.UNetModel
31
+ params:
32
+ image_size: 32 # unused
33
+ in_channels: 4
34
+ out_channels: 4
35
+ model_channels: 320
36
+ attention_resolutions: [ 4, 2, 1 ]
37
+ num_res_blocks: 2
38
+ channel_mult: [ 1, 2, 4, 4 ]
39
+ num_heads: 8
40
+ use_spatial_transformer: True
41
+ transformer_depth: 1
42
+ context_dim: 768
43
+ use_checkpoint: True
44
+ legacy: False
45
+
46
+ first_stage_config:
47
+ target: ldm.models.autoencoder.AutoencoderKL
48
+ params:
49
+ embed_dim: 4
50
+ monitor: val/rec_loss
51
+ ddconfig:
52
+ double_z: true
53
+ z_channels: 4
54
+ resolution: 256
55
+ in_channels: 3
56
+ out_ch: 3
57
+ ch: 128
58
+ ch_mult:
59
+ - 1
60
+ - 2
61
+ - 4
62
+ - 4
63
+ num_res_blocks: 2
64
+ attn_resolutions: []
65
+ dropout: 0.0
66
+ lossconfig:
67
+ target: torch.nn.Identity
68
+
69
+ cond_stage_config:
70
+ target: modules.xlmr.BertSeriesModelWithTransformation
71
+ params:
72
+ name: "XLMR-Large"
configs/instruct-pix2pix.yaml ADDED
@@ -0,0 +1,98 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # File modified by authors of InstructPix2Pix from original (https://github.com/CompVis/stable-diffusion).
2
+ # See more details in LICENSE.
3
+
4
+ model:
5
+ base_learning_rate: 1.0e-04
6
+ target: modules.models.diffusion.ddpm_edit.LatentDiffusion
7
+ params:
8
+ linear_start: 0.00085
9
+ linear_end: 0.0120
10
+ num_timesteps_cond: 1
11
+ log_every_t: 200
12
+ timesteps: 1000
13
+ first_stage_key: edited
14
+ cond_stage_key: edit
15
+ # image_size: 64
16
+ # image_size: 32
17
+ image_size: 16
18
+ channels: 4
19
+ cond_stage_trainable: false # Note: different from the one we trained before
20
+ conditioning_key: hybrid
21
+ monitor: val/loss_simple_ema
22
+ scale_factor: 0.18215
23
+ use_ema: false
24
+
25
+ scheduler_config: # 10000 warmup steps
26
+ target: ldm.lr_scheduler.LambdaLinearScheduler
27
+ params:
28
+ warm_up_steps: [ 0 ]
29
+ cycle_lengths: [ 10000000000000 ] # incredibly large number to prevent corner cases
30
+ f_start: [ 1.e-6 ]
31
+ f_max: [ 1. ]
32
+ f_min: [ 1. ]
33
+
34
+ unet_config:
35
+ target: ldm.modules.diffusionmodules.openaimodel.UNetModel
36
+ params:
37
+ image_size: 32 # unused
38
+ in_channels: 8
39
+ out_channels: 4
40
+ model_channels: 320
41
+ attention_resolutions: [ 4, 2, 1 ]
42
+ num_res_blocks: 2
43
+ channel_mult: [ 1, 2, 4, 4 ]
44
+ num_heads: 8
45
+ use_spatial_transformer: True
46
+ transformer_depth: 1
47
+ context_dim: 768
48
+ use_checkpoint: True
49
+ legacy: False
50
+
51
+ first_stage_config:
52
+ target: ldm.models.autoencoder.AutoencoderKL
53
+ params:
54
+ embed_dim: 4
55
+ monitor: val/rec_loss
56
+ ddconfig:
57
+ double_z: true
58
+ z_channels: 4
59
+ resolution: 256
60
+ in_channels: 3
61
+ out_ch: 3
62
+ ch: 128
63
+ ch_mult:
64
+ - 1
65
+ - 2
66
+ - 4
67
+ - 4
68
+ num_res_blocks: 2
69
+ attn_resolutions: []
70
+ dropout: 0.0
71
+ lossconfig:
72
+ target: torch.nn.Identity
73
+
74
+ cond_stage_config:
75
+ target: ldm.modules.encoders.modules.FrozenCLIPEmbedder
76
+
77
+ data:
78
+ target: main.DataModuleFromConfig
79
+ params:
80
+ batch_size: 128
81
+ num_workers: 1
82
+ wrap: false
83
+ validation:
84
+ target: edit_dataset.EditDataset
85
+ params:
86
+ path: data/clip-filtered-dataset
87
+ cache_dir: data/
88
+ cache_name: data_10k
89
+ split: val
90
+ min_text_sim: 0.2
91
+ min_image_sim: 0.75
92
+ min_direction_sim: 0.2
93
+ max_samples_per_prompt: 1
94
+ min_resize_res: 512
95
+ max_resize_res: 512
96
+ crop_res: 512
97
+ output_as_edit: False
98
+ real_input: True
configs/v1-inference.yaml ADDED
@@ -0,0 +1,70 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ model:
2
+ base_learning_rate: 1.0e-04
3
+ target: ldm.models.diffusion.ddpm.LatentDiffusion
4
+ params:
5
+ linear_start: 0.00085
6
+ linear_end: 0.0120
7
+ num_timesteps_cond: 1
8
+ log_every_t: 200
9
+ timesteps: 1000
10
+ first_stage_key: "jpg"
11
+ cond_stage_key: "txt"
12
+ image_size: 64
13
+ channels: 4
14
+ cond_stage_trainable: false # Note: different from the one we trained before
15
+ conditioning_key: crossattn
16
+ monitor: val/loss_simple_ema
17
+ scale_factor: 0.18215
18
+ use_ema: False
19
+
20
+ scheduler_config: # 10000 warmup steps
21
+ target: ldm.lr_scheduler.LambdaLinearScheduler
22
+ params:
23
+ warm_up_steps: [ 10000 ]
24
+ cycle_lengths: [ 10000000000000 ] # incredibly large number to prevent corner cases
25
+ f_start: [ 1.e-6 ]
26
+ f_max: [ 1. ]
27
+ f_min: [ 1. ]
28
+
29
+ unet_config:
30
+ target: ldm.modules.diffusionmodules.openaimodel.UNetModel
31
+ params:
32
+ image_size: 32 # unused
33
+ in_channels: 4
34
+ out_channels: 4
35
+ model_channels: 320
36
+ attention_resolutions: [ 4, 2, 1 ]
37
+ num_res_blocks: 2
38
+ channel_mult: [ 1, 2, 4, 4 ]
39
+ num_heads: 8
40
+ use_spatial_transformer: True
41
+ transformer_depth: 1
42
+ context_dim: 768
43
+ use_checkpoint: True
44
+ legacy: False
45
+
46
+ first_stage_config:
47
+ target: ldm.models.autoencoder.AutoencoderKL
48
+ params:
49
+ embed_dim: 4
50
+ monitor: val/rec_loss
51
+ ddconfig:
52
+ double_z: true
53
+ z_channels: 4
54
+ resolution: 256
55
+ in_channels: 3
56
+ out_ch: 3
57
+ ch: 128
58
+ ch_mult:
59
+ - 1
60
+ - 2
61
+ - 4
62
+ - 4
63
+ num_res_blocks: 2
64
+ attn_resolutions: []
65
+ dropout: 0.0
66
+ lossconfig:
67
+ target: torch.nn.Identity
68
+
69
+ cond_stage_config:
70
+ target: ldm.modules.encoders.modules.FrozenCLIPEmbedder
configs/v1-inpainting-inference.yaml ADDED
@@ -0,0 +1,70 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ model:
2
+ base_learning_rate: 7.5e-05
3
+ target: ldm.models.diffusion.ddpm.LatentInpaintDiffusion
4
+ params:
5
+ linear_start: 0.00085
6
+ linear_end: 0.0120
7
+ num_timesteps_cond: 1
8
+ log_every_t: 200
9
+ timesteps: 1000
10
+ first_stage_key: "jpg"
11
+ cond_stage_key: "txt"
12
+ image_size: 64
13
+ channels: 4
14
+ cond_stage_trainable: false # Note: different from the one we trained before
15
+ conditioning_key: hybrid # important
16
+ monitor: val/loss_simple_ema
17
+ scale_factor: 0.18215
18
+ finetune_keys: null
19
+
20
+ scheduler_config: # 10000 warmup steps
21
+ target: ldm.lr_scheduler.LambdaLinearScheduler
22
+ params:
23
+ warm_up_steps: [ 2500 ] # NOTE for resuming. use 10000 if starting from scratch
24
+ cycle_lengths: [ 10000000000000 ] # incredibly large number to prevent corner cases
25
+ f_start: [ 1.e-6 ]
26
+ f_max: [ 1. ]
27
+ f_min: [ 1. ]
28
+
29
+ unet_config:
30
+ target: ldm.modules.diffusionmodules.openaimodel.UNetModel
31
+ params:
32
+ image_size: 32 # unused
33
+ in_channels: 9 # 4 data + 4 downscaled image + 1 mask
34
+ out_channels: 4
35
+ model_channels: 320
36
+ attention_resolutions: [ 4, 2, 1 ]
37
+ num_res_blocks: 2
38
+ channel_mult: [ 1, 2, 4, 4 ]
39
+ num_heads: 8
40
+ use_spatial_transformer: True
41
+ transformer_depth: 1
42
+ context_dim: 768
43
+ use_checkpoint: True
44
+ legacy: False
45
+
46
+ first_stage_config:
47
+ target: ldm.models.autoencoder.AutoencoderKL
48
+ params:
49
+ embed_dim: 4
50
+ monitor: val/rec_loss
51
+ ddconfig:
52
+ double_z: true
53
+ z_channels: 4
54
+ resolution: 256
55
+ in_channels: 3
56
+ out_ch: 3
57
+ ch: 128
58
+ ch_mult:
59
+ - 1
60
+ - 2
61
+ - 4
62
+ - 4
63
+ num_res_blocks: 2
64
+ attn_resolutions: []
65
+ dropout: 0.0
66
+ lossconfig:
67
+ target: torch.nn.Identity
68
+
69
+ cond_stage_config:
70
+ target: ldm.modules.encoders.modules.FrozenCLIPEmbedder
extensions-builtin/LDSR/ldsr_model_arch.py ADDED
@@ -0,0 +1,253 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import gc
3
+ import time
4
+
5
+ import numpy as np
6
+ import torch
7
+ import torchvision
8
+ from PIL import Image
9
+ from einops import rearrange, repeat
10
+ from omegaconf import OmegaConf
11
+ import safetensors.torch
12
+
13
+ from ldm.models.diffusion.ddim import DDIMSampler
14
+ from ldm.util import instantiate_from_config, ismap
15
+ from modules import shared, sd_hijack
16
+
17
+ cached_ldsr_model: torch.nn.Module = None
18
+
19
+
20
+ # Create LDSR Class
21
+ class LDSR:
22
+ def load_model_from_config(self, half_attention):
23
+ global cached_ldsr_model
24
+
25
+ if shared.opts.ldsr_cached and cached_ldsr_model is not None:
26
+ print("Loading model from cache")
27
+ model: torch.nn.Module = cached_ldsr_model
28
+ else:
29
+ print(f"Loading model from {self.modelPath}")
30
+ _, extension = os.path.splitext(self.modelPath)
31
+ if extension.lower() == ".safetensors":
32
+ pl_sd = safetensors.torch.load_file(self.modelPath, device="cpu")
33
+ else:
34
+ pl_sd = torch.load(self.modelPath, map_location="cpu")
35
+ sd = pl_sd["state_dict"] if "state_dict" in pl_sd else pl_sd
36
+ config = OmegaConf.load(self.yamlPath)
37
+ config.model.target = "ldm.models.diffusion.ddpm.LatentDiffusionV1"
38
+ model: torch.nn.Module = instantiate_from_config(config.model)
39
+ model.load_state_dict(sd, strict=False)
40
+ model = model.to(shared.device)
41
+ if half_attention:
42
+ model = model.half()
43
+ if shared.cmd_opts.opt_channelslast:
44
+ model = model.to(memory_format=torch.channels_last)
45
+
46
+ sd_hijack.model_hijack.hijack(model) # apply optimization
47
+ model.eval()
48
+
49
+ if shared.opts.ldsr_cached:
50
+ cached_ldsr_model = model
51
+
52
+ return {"model": model}
53
+
54
+ def __init__(self, model_path, yaml_path):
55
+ self.modelPath = model_path
56
+ self.yamlPath = yaml_path
57
+
58
+ @staticmethod
59
+ def run(model, selected_path, custom_steps, eta):
60
+ example = get_cond(selected_path)
61
+
62
+ n_runs = 1
63
+ guider = None
64
+ ckwargs = None
65
+ ddim_use_x0_pred = False
66
+ temperature = 1.
67
+ eta = eta
68
+ custom_shape = None
69
+
70
+ height, width = example["image"].shape[1:3]
71
+ split_input = height >= 128 and width >= 128
72
+
73
+ if split_input:
74
+ ks = 128
75
+ stride = 64
76
+ vqf = 4 #
77
+ model.split_input_params = {"ks": (ks, ks), "stride": (stride, stride),
78
+ "vqf": vqf,
79
+ "patch_distributed_vq": True,
80
+ "tie_braker": False,
81
+ "clip_max_weight": 0.5,
82
+ "clip_min_weight": 0.01,
83
+ "clip_max_tie_weight": 0.5,
84
+ "clip_min_tie_weight": 0.01}
85
+ else:
86
+ if hasattr(model, "split_input_params"):
87
+ delattr(model, "split_input_params")
88
+
89
+ x_t = None
90
+ logs = None
91
+ for n in range(n_runs):
92
+ if custom_shape is not None:
93
+ x_t = torch.randn(1, custom_shape[1], custom_shape[2], custom_shape[3]).to(model.device)
94
+ x_t = repeat(x_t, '1 c h w -> b c h w', b=custom_shape[0])
95
+
96
+ logs = make_convolutional_sample(example, model,
97
+ custom_steps=custom_steps,
98
+ eta=eta, quantize_x0=False,
99
+ custom_shape=custom_shape,
100
+ temperature=temperature, noise_dropout=0.,
101
+ corrector=guider, corrector_kwargs=ckwargs, x_T=x_t,
102
+ ddim_use_x0_pred=ddim_use_x0_pred
103
+ )
104
+ return logs
105
+
106
+ def super_resolution(self, image, steps=100, target_scale=2, half_attention=False):
107
+ model = self.load_model_from_config(half_attention)
108
+
109
+ # Run settings
110
+ diffusion_steps = int(steps)
111
+ eta = 1.0
112
+
113
+ down_sample_method = 'Lanczos'
114
+
115
+ gc.collect()
116
+ if torch.cuda.is_available:
117
+ torch.cuda.empty_cache()
118
+
119
+ im_og = image
120
+ width_og, height_og = im_og.size
121
+ # If we can adjust the max upscale size, then the 4 below should be our variable
122
+ down_sample_rate = target_scale / 4
123
+ wd = width_og * down_sample_rate
124
+ hd = height_og * down_sample_rate
125
+ width_downsampled_pre = int(np.ceil(wd))
126
+ height_downsampled_pre = int(np.ceil(hd))
127
+
128
+ if down_sample_rate != 1:
129
+ print(
130
+ f'Downsampling from [{width_og}, {height_og}] to [{width_downsampled_pre}, {height_downsampled_pre}]')
131
+ im_og = im_og.resize((width_downsampled_pre, height_downsampled_pre), Image.LANCZOS)
132
+ else:
133
+ print(f"Down sample rate is 1 from {target_scale} / 4 (Not downsampling)")
134
+
135
+ # pad width and height to multiples of 64, pads with the edge values of image to avoid artifacts
136
+ pad_w, pad_h = np.max(((2, 2), np.ceil(np.array(im_og.size) / 64).astype(int)), axis=0) * 64 - im_og.size
137
+ im_padded = Image.fromarray(np.pad(np.array(im_og), ((0, pad_h), (0, pad_w), (0, 0)), mode='edge'))
138
+
139
+ logs = self.run(model["model"], im_padded, diffusion_steps, eta)
140
+
141
+ sample = logs["sample"]
142
+ sample = sample.detach().cpu()
143
+ sample = torch.clamp(sample, -1., 1.)
144
+ sample = (sample + 1.) / 2. * 255
145
+ sample = sample.numpy().astype(np.uint8)
146
+ sample = np.transpose(sample, (0, 2, 3, 1))
147
+ a = Image.fromarray(sample[0])
148
+
149
+ # remove padding
150
+ a = a.crop((0, 0) + tuple(np.array(im_og.size) * 4))
151
+
152
+ del model
153
+ gc.collect()
154
+ if torch.cuda.is_available:
155
+ torch.cuda.empty_cache()
156
+
157
+ return a
158
+
159
+
160
+ def get_cond(selected_path):
161
+ example = dict()
162
+ up_f = 4
163
+ c = selected_path.convert('RGB')
164
+ c = torch.unsqueeze(torchvision.transforms.ToTensor()(c), 0)
165
+ c_up = torchvision.transforms.functional.resize(c, size=[up_f * c.shape[2], up_f * c.shape[3]],
166
+ antialias=True)
167
+ c_up = rearrange(c_up, '1 c h w -> 1 h w c')
168
+ c = rearrange(c, '1 c h w -> 1 h w c')
169
+ c = 2. * c - 1.
170
+
171
+ c = c.to(shared.device)
172
+ example["LR_image"] = c
173
+ example["image"] = c_up
174
+
175
+ return example
176
+
177
+
178
+ @torch.no_grad()
179
+ def convsample_ddim(model, cond, steps, shape, eta=1.0, callback=None, normals_sequence=None,
180
+ mask=None, x0=None, quantize_x0=False, temperature=1., score_corrector=None,
181
+ corrector_kwargs=None, x_t=None
182
+ ):
183
+ ddim = DDIMSampler(model)
184
+ bs = shape[0]
185
+ shape = shape[1:]
186
+ print(f"Sampling with eta = {eta}; steps: {steps}")
187
+ samples, intermediates = ddim.sample(steps, batch_size=bs, shape=shape, conditioning=cond, callback=callback,
188
+ normals_sequence=normals_sequence, quantize_x0=quantize_x0, eta=eta,
189
+ mask=mask, x0=x0, temperature=temperature, verbose=False,
190
+ score_corrector=score_corrector,
191
+ corrector_kwargs=corrector_kwargs, x_t=x_t)
192
+
193
+ return samples, intermediates
194
+
195
+
196
+ @torch.no_grad()
197
+ def make_convolutional_sample(batch, model, custom_steps=None, eta=1.0, quantize_x0=False, custom_shape=None, temperature=1., noise_dropout=0., corrector=None,
198
+ corrector_kwargs=None, x_T=None, ddim_use_x0_pred=False):
199
+ log = dict()
200
+
201
+ z, c, x, xrec, xc = model.get_input(batch, model.first_stage_key,
202
+ return_first_stage_outputs=True,
203
+ force_c_encode=not (hasattr(model, 'split_input_params')
204
+ and model.cond_stage_key == 'coordinates_bbox'),
205
+ return_original_cond=True)
206
+
207
+ if custom_shape is not None:
208
+ z = torch.randn(custom_shape)
209
+ print(f"Generating {custom_shape[0]} samples of shape {custom_shape[1:]}")
210
+
211
+ z0 = None
212
+
213
+ log["input"] = x
214
+ log["reconstruction"] = xrec
215
+
216
+ if ismap(xc):
217
+ log["original_conditioning"] = model.to_rgb(xc)
218
+ if hasattr(model, 'cond_stage_key'):
219
+ log[model.cond_stage_key] = model.to_rgb(xc)
220
+
221
+ else:
222
+ log["original_conditioning"] = xc if xc is not None else torch.zeros_like(x)
223
+ if model.cond_stage_model:
224
+ log[model.cond_stage_key] = xc if xc is not None else torch.zeros_like(x)
225
+ if model.cond_stage_key == 'class_label':
226
+ log[model.cond_stage_key] = xc[model.cond_stage_key]
227
+
228
+ with model.ema_scope("Plotting"):
229
+ t0 = time.time()
230
+
231
+ sample, intermediates = convsample_ddim(model, c, steps=custom_steps, shape=z.shape,
232
+ eta=eta,
233
+ quantize_x0=quantize_x0, mask=None, x0=z0,
234
+ temperature=temperature, score_corrector=corrector, corrector_kwargs=corrector_kwargs,
235
+ x_t=x_T)
236
+ t1 = time.time()
237
+
238
+ if ddim_use_x0_pred:
239
+ sample = intermediates['pred_x0'][-1]
240
+
241
+ x_sample = model.decode_first_stage(sample)
242
+
243
+ try:
244
+ x_sample_noquant = model.decode_first_stage(sample, force_not_quantize=True)
245
+ log["sample_noquant"] = x_sample_noquant
246
+ log["sample_diff"] = torch.abs(x_sample_noquant - x_sample)
247
+ except:
248
+ pass
249
+
250
+ log["sample"] = x_sample
251
+ log["time"] = t1 - t0
252
+
253
+ return log
extensions-builtin/LDSR/preload.py ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ import os
2
+ from modules import paths
3
+
4
+
5
+ def preload(parser):
6
+ parser.add_argument("--ldsr-models-path", type=str, help="Path to directory with LDSR model file(s).", default=os.path.join(paths.models_path, 'LDSR'))
extensions-builtin/LDSR/scripts/ldsr_model.py ADDED
@@ -0,0 +1,69 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import sys
3
+ import traceback
4
+
5
+ from basicsr.utils.download_util import load_file_from_url
6
+
7
+ from modules.upscaler import Upscaler, UpscalerData
8
+ from ldsr_model_arch import LDSR
9
+ from modules import shared, script_callbacks
10
+ import sd_hijack_autoencoder, sd_hijack_ddpm_v1
11
+
12
+
13
+ class UpscalerLDSR(Upscaler):
14
+ def __init__(self, user_path):
15
+ self.name = "LDSR"
16
+ self.user_path = user_path
17
+ self.model_url = "https://heibox.uni-heidelberg.de/f/578df07c8fc04ffbadf3/?dl=1"
18
+ self.yaml_url = "https://heibox.uni-heidelberg.de/f/31a76b13ea27482981b4/?dl=1"
19
+ super().__init__()
20
+ scaler_data = UpscalerData("LDSR", None, self)
21
+ self.scalers = [scaler_data]
22
+
23
+ def load_model(self, path: str):
24
+ # Remove incorrect project.yaml file if too big
25
+ yaml_path = os.path.join(self.model_path, "project.yaml")
26
+ old_model_path = os.path.join(self.model_path, "model.pth")
27
+ new_model_path = os.path.join(self.model_path, "model.ckpt")
28
+ safetensors_model_path = os.path.join(self.model_path, "model.safetensors")
29
+ if os.path.exists(yaml_path):
30
+ statinfo = os.stat(yaml_path)
31
+ if statinfo.st_size >= 10485760:
32
+ print("Removing invalid LDSR YAML file.")
33
+ os.remove(yaml_path)
34
+ if os.path.exists(old_model_path):
35
+ print("Renaming model from model.pth to model.ckpt")
36
+ os.rename(old_model_path, new_model_path)
37
+ if os.path.exists(safetensors_model_path):
38
+ model = safetensors_model_path
39
+ else:
40
+ model = load_file_from_url(url=self.model_url, model_dir=self.model_path,
41
+ file_name="model.ckpt", progress=True)
42
+ yaml = load_file_from_url(url=self.yaml_url, model_dir=self.model_path,
43
+ file_name="project.yaml", progress=True)
44
+
45
+ try:
46
+ return LDSR(model, yaml)
47
+
48
+ except Exception:
49
+ print("Error importing LDSR:", file=sys.stderr)
50
+ print(traceback.format_exc(), file=sys.stderr)
51
+ return None
52
+
53
+ def do_upscale(self, img, path):
54
+ ldsr = self.load_model(path)
55
+ if ldsr is None:
56
+ print("NO LDSR!")
57
+ return img
58
+ ddim_steps = shared.opts.ldsr_steps
59
+ return ldsr.super_resolution(img, ddim_steps, self.scale)
60
+
61
+
62
+ def on_ui_settings():
63
+ import gradio as gr
64
+
65
+ shared.opts.add_option("ldsr_steps", shared.OptionInfo(100, "LDSR processing steps. Lower = faster", gr.Slider, {"minimum": 1, "maximum": 200, "step": 1}, section=('upscaling', "Upscaling")))
66
+ shared.opts.add_option("ldsr_cached", shared.OptionInfo(False, "Cache LDSR model in memory", gr.Checkbox, {"interactive": True}, section=('upscaling', "Upscaling")))
67
+
68
+
69
+ script_callbacks.on_ui_settings(on_ui_settings)
extensions-builtin/LDSR/sd_hijack_autoencoder.py ADDED
@@ -0,0 +1,286 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # The content of this file comes from the ldm/models/autoencoder.py file of the compvis/stable-diffusion repo
2
+ # The VQModel & VQModelInterface were subsequently removed from ldm/models/autoencoder.py when we moved to the stability-ai/stablediffusion repo
3
+ # As the LDSR upscaler relies on VQModel & VQModelInterface, the hijack aims to put them back into the ldm.models.autoencoder
4
+
5
+ import torch
6
+ import pytorch_lightning as pl
7
+ import torch.nn.functional as F
8
+ from contextlib import contextmanager
9
+ from taming.modules.vqvae.quantize import VectorQuantizer2 as VectorQuantizer
10
+ from ldm.modules.diffusionmodules.model import Encoder, Decoder
11
+ from ldm.util import instantiate_from_config
12
+
13
+ import ldm.models.autoencoder
14
+
15
+ class VQModel(pl.LightningModule):
16
+ def __init__(self,
17
+ ddconfig,
18
+ lossconfig,
19
+ n_embed,
20
+ embed_dim,
21
+ ckpt_path=None,
22
+ ignore_keys=[],
23
+ image_key="image",
24
+ colorize_nlabels=None,
25
+ monitor=None,
26
+ batch_resize_range=None,
27
+ scheduler_config=None,
28
+ lr_g_factor=1.0,
29
+ remap=None,
30
+ sane_index_shape=False, # tell vector quantizer to return indices as bhw
31
+ use_ema=False
32
+ ):
33
+ super().__init__()
34
+ self.embed_dim = embed_dim
35
+ self.n_embed = n_embed
36
+ self.image_key = image_key
37
+ self.encoder = Encoder(**ddconfig)
38
+ self.decoder = Decoder(**ddconfig)
39
+ self.loss = instantiate_from_config(lossconfig)
40
+ self.quantize = VectorQuantizer(n_embed, embed_dim, beta=0.25,
41
+ remap=remap,
42
+ sane_index_shape=sane_index_shape)
43
+ self.quant_conv = torch.nn.Conv2d(ddconfig["z_channels"], embed_dim, 1)
44
+ self.post_quant_conv = torch.nn.Conv2d(embed_dim, ddconfig["z_channels"], 1)
45
+ if colorize_nlabels is not None:
46
+ assert type(colorize_nlabels)==int
47
+ self.register_buffer("colorize", torch.randn(3, colorize_nlabels, 1, 1))
48
+ if monitor is not None:
49
+ self.monitor = monitor
50
+ self.batch_resize_range = batch_resize_range
51
+ if self.batch_resize_range is not None:
52
+ print(f"{self.__class__.__name__}: Using per-batch resizing in range {batch_resize_range}.")
53
+
54
+ self.use_ema = use_ema
55
+ if self.use_ema:
56
+ self.model_ema = LitEma(self)
57
+ print(f"Keeping EMAs of {len(list(self.model_ema.buffers()))}.")
58
+
59
+ if ckpt_path is not None:
60
+ self.init_from_ckpt(ckpt_path, ignore_keys=ignore_keys)
61
+ self.scheduler_config = scheduler_config
62
+ self.lr_g_factor = lr_g_factor
63
+
64
+ @contextmanager
65
+ def ema_scope(self, context=None):
66
+ if self.use_ema:
67
+ self.model_ema.store(self.parameters())
68
+ self.model_ema.copy_to(self)
69
+ if context is not None:
70
+ print(f"{context}: Switched to EMA weights")
71
+ try:
72
+ yield None
73
+ finally:
74
+ if self.use_ema:
75
+ self.model_ema.restore(self.parameters())
76
+ if context is not None:
77
+ print(f"{context}: Restored training weights")
78
+
79
+ def init_from_ckpt(self, path, ignore_keys=list()):
80
+ sd = torch.load(path, map_location="cpu")["state_dict"]
81
+ keys = list(sd.keys())
82
+ for k in keys:
83
+ for ik in ignore_keys:
84
+ if k.startswith(ik):
85
+ print("Deleting key {} from state_dict.".format(k))
86
+ del sd[k]
87
+ missing, unexpected = self.load_state_dict(sd, strict=False)
88
+ print(f"Restored from {path} with {len(missing)} missing and {len(unexpected)} unexpected keys")
89
+ if len(missing) > 0:
90
+ print(f"Missing Keys: {missing}")
91
+ print(f"Unexpected Keys: {unexpected}")
92
+
93
+ def on_train_batch_end(self, *args, **kwargs):
94
+ if self.use_ema:
95
+ self.model_ema(self)
96
+
97
+ def encode(self, x):
98
+ h = self.encoder(x)
99
+ h = self.quant_conv(h)
100
+ quant, emb_loss, info = self.quantize(h)
101
+ return quant, emb_loss, info
102
+
103
+ def encode_to_prequant(self, x):
104
+ h = self.encoder(x)
105
+ h = self.quant_conv(h)
106
+ return h
107
+
108
+ def decode(self, quant):
109
+ quant = self.post_quant_conv(quant)
110
+ dec = self.decoder(quant)
111
+ return dec
112
+
113
+ def decode_code(self, code_b):
114
+ quant_b = self.quantize.embed_code(code_b)
115
+ dec = self.decode(quant_b)
116
+ return dec
117
+
118
+ def forward(self, input, return_pred_indices=False):
119
+ quant, diff, (_,_,ind) = self.encode(input)
120
+ dec = self.decode(quant)
121
+ if return_pred_indices:
122
+ return dec, diff, ind
123
+ return dec, diff
124
+
125
+ def get_input(self, batch, k):
126
+ x = batch[k]
127
+ if len(x.shape) == 3:
128
+ x = x[..., None]
129
+ x = x.permute(0, 3, 1, 2).to(memory_format=torch.contiguous_format).float()
130
+ if self.batch_resize_range is not None:
131
+ lower_size = self.batch_resize_range[0]
132
+ upper_size = self.batch_resize_range[1]
133
+ if self.global_step <= 4:
134
+ # do the first few batches with max size to avoid later oom
135
+ new_resize = upper_size
136
+ else:
137
+ new_resize = np.random.choice(np.arange(lower_size, upper_size+16, 16))
138
+ if new_resize != x.shape[2]:
139
+ x = F.interpolate(x, size=new_resize, mode="bicubic")
140
+ x = x.detach()
141
+ return x
142
+
143
+ def training_step(self, batch, batch_idx, optimizer_idx):
144
+ # https://github.com/pytorch/pytorch/issues/37142
145
+ # try not to fool the heuristics
146
+ x = self.get_input(batch, self.image_key)
147
+ xrec, qloss, ind = self(x, return_pred_indices=True)
148
+
149
+ if optimizer_idx == 0:
150
+ # autoencode
151
+ aeloss, log_dict_ae = self.loss(qloss, x, xrec, optimizer_idx, self.global_step,
152
+ last_layer=self.get_last_layer(), split="train",
153
+ predicted_indices=ind)
154
+
155
+ self.log_dict(log_dict_ae, prog_bar=False, logger=True, on_step=True, on_epoch=True)
156
+ return aeloss
157
+
158
+ if optimizer_idx == 1:
159
+ # discriminator
160
+ discloss, log_dict_disc = self.loss(qloss, x, xrec, optimizer_idx, self.global_step,
161
+ last_layer=self.get_last_layer(), split="train")
162
+ self.log_dict(log_dict_disc, prog_bar=False, logger=True, on_step=True, on_epoch=True)
163
+ return discloss
164
+
165
+ def validation_step(self, batch, batch_idx):
166
+ log_dict = self._validation_step(batch, batch_idx)
167
+ with self.ema_scope():
168
+ log_dict_ema = self._validation_step(batch, batch_idx, suffix="_ema")
169
+ return log_dict
170
+
171
+ def _validation_step(self, batch, batch_idx, suffix=""):
172
+ x = self.get_input(batch, self.image_key)
173
+ xrec, qloss, ind = self(x, return_pred_indices=True)
174
+ aeloss, log_dict_ae = self.loss(qloss, x, xrec, 0,
175
+ self.global_step,
176
+ last_layer=self.get_last_layer(),
177
+ split="val"+suffix,
178
+ predicted_indices=ind
179
+ )
180
+
181
+ discloss, log_dict_disc = self.loss(qloss, x, xrec, 1,
182
+ self.global_step,
183
+ last_layer=self.get_last_layer(),
184
+ split="val"+suffix,
185
+ predicted_indices=ind
186
+ )
187
+ rec_loss = log_dict_ae[f"val{suffix}/rec_loss"]
188
+ self.log(f"val{suffix}/rec_loss", rec_loss,
189
+ prog_bar=True, logger=True, on_step=False, on_epoch=True, sync_dist=True)
190
+ self.log(f"val{suffix}/aeloss", aeloss,
191
+ prog_bar=True, logger=True, on_step=False, on_epoch=True, sync_dist=True)
192
+ if version.parse(pl.__version__) >= version.parse('1.4.0'):
193
+ del log_dict_ae[f"val{suffix}/rec_loss"]
194
+ self.log_dict(log_dict_ae)
195
+ self.log_dict(log_dict_disc)
196
+ return self.log_dict
197
+
198
+ def configure_optimizers(self):
199
+ lr_d = self.learning_rate
200
+ lr_g = self.lr_g_factor*self.learning_rate
201
+ print("lr_d", lr_d)
202
+ print("lr_g", lr_g)
203
+ opt_ae = torch.optim.Adam(list(self.encoder.parameters())+
204
+ list(self.decoder.parameters())+
205
+ list(self.quantize.parameters())+
206
+ list(self.quant_conv.parameters())+
207
+ list(self.post_quant_conv.parameters()),
208
+ lr=lr_g, betas=(0.5, 0.9))
209
+ opt_disc = torch.optim.Adam(self.loss.discriminator.parameters(),
210
+ lr=lr_d, betas=(0.5, 0.9))
211
+
212
+ if self.scheduler_config is not None:
213
+ scheduler = instantiate_from_config(self.scheduler_config)
214
+
215
+ print("Setting up LambdaLR scheduler...")
216
+ scheduler = [
217
+ {
218
+ 'scheduler': LambdaLR(opt_ae, lr_lambda=scheduler.schedule),
219
+ 'interval': 'step',
220
+ 'frequency': 1
221
+ },
222
+ {
223
+ 'scheduler': LambdaLR(opt_disc, lr_lambda=scheduler.schedule),
224
+ 'interval': 'step',
225
+ 'frequency': 1
226
+ },
227
+ ]
228
+ return [opt_ae, opt_disc], scheduler
229
+ return [opt_ae, opt_disc], []
230
+
231
+ def get_last_layer(self):
232
+ return self.decoder.conv_out.weight
233
+
234
+ def log_images(self, batch, only_inputs=False, plot_ema=False, **kwargs):
235
+ log = dict()
236
+ x = self.get_input(batch, self.image_key)
237
+ x = x.to(self.device)
238
+ if only_inputs:
239
+ log["inputs"] = x
240
+ return log
241
+ xrec, _ = self(x)
242
+ if x.shape[1] > 3:
243
+ # colorize with random projection
244
+ assert xrec.shape[1] > 3
245
+ x = self.to_rgb(x)
246
+ xrec = self.to_rgb(xrec)
247
+ log["inputs"] = x
248
+ log["reconstructions"] = xrec
249
+ if plot_ema:
250
+ with self.ema_scope():
251
+ xrec_ema, _ = self(x)
252
+ if x.shape[1] > 3: xrec_ema = self.to_rgb(xrec_ema)
253
+ log["reconstructions_ema"] = xrec_ema
254
+ return log
255
+
256
+ def to_rgb(self, x):
257
+ assert self.image_key == "segmentation"
258
+ if not hasattr(self, "colorize"):
259
+ self.register_buffer("colorize", torch.randn(3, x.shape[1], 1, 1).to(x))
260
+ x = F.conv2d(x, weight=self.colorize)
261
+ x = 2.*(x-x.min())/(x.max()-x.min()) - 1.
262
+ return x
263
+
264
+
265
+ class VQModelInterface(VQModel):
266
+ def __init__(self, embed_dim, *args, **kwargs):
267
+ super().__init__(embed_dim=embed_dim, *args, **kwargs)
268
+ self.embed_dim = embed_dim
269
+
270
+ def encode(self, x):
271
+ h = self.encoder(x)
272
+ h = self.quant_conv(h)
273
+ return h
274
+
275
+ def decode(self, h, force_not_quantize=False):
276
+ # also go through quantization layer
277
+ if not force_not_quantize:
278
+ quant, emb_loss, info = self.quantize(h)
279
+ else:
280
+ quant = h
281
+ quant = self.post_quant_conv(quant)
282
+ dec = self.decoder(quant)
283
+ return dec
284
+
285
+ setattr(ldm.models.autoencoder, "VQModel", VQModel)
286
+ setattr(ldm.models.autoencoder, "VQModelInterface", VQModelInterface)
extensions-builtin/LDSR/sd_hijack_ddpm_v1.py ADDED
@@ -0,0 +1,1449 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # This script is copied from the compvis/stable-diffusion repo (aka the SD V1 repo)
2
+ # Original filename: ldm/models/diffusion/ddpm.py
3
+ # The purpose to reinstate the old DDPM logic which works with VQ, whereas the V2 one doesn't
4
+ # Some models such as LDSR require VQ to work correctly
5
+ # The classes are suffixed with "V1" and added back to the "ldm.models.diffusion.ddpm" module
6
+
7
+ import torch
8
+ import torch.nn as nn
9
+ import numpy as np
10
+ import pytorch_lightning as pl
11
+ from torch.optim.lr_scheduler import LambdaLR
12
+ from einops import rearrange, repeat
13
+ from contextlib import contextmanager
14
+ from functools import partial
15
+ from tqdm import tqdm
16
+ from torchvision.utils import make_grid
17
+ from pytorch_lightning.utilities.distributed import rank_zero_only
18
+
19
+ from ldm.util import log_txt_as_img, exists, default, ismap, isimage, mean_flat, count_params, instantiate_from_config
20
+ from ldm.modules.ema import LitEma
21
+ from ldm.modules.distributions.distributions import normal_kl, DiagonalGaussianDistribution
22
+ from ldm.models.autoencoder import VQModelInterface, IdentityFirstStage, AutoencoderKL
23
+ from ldm.modules.diffusionmodules.util import make_beta_schedule, extract_into_tensor, noise_like
24
+ from ldm.models.diffusion.ddim import DDIMSampler
25
+
26
+ import ldm.models.diffusion.ddpm
27
+
28
+ __conditioning_keys__ = {'concat': 'c_concat',
29
+ 'crossattn': 'c_crossattn',
30
+ 'adm': 'y'}
31
+
32
+
33
+ def disabled_train(self, mode=True):
34
+ """Overwrite model.train with this function to make sure train/eval mode
35
+ does not change anymore."""
36
+ return self
37
+
38
+
39
+ def uniform_on_device(r1, r2, shape, device):
40
+ return (r1 - r2) * torch.rand(*shape, device=device) + r2
41
+
42
+
43
+ class DDPMV1(pl.LightningModule):
44
+ # classic DDPM with Gaussian diffusion, in image space
45
+ def __init__(self,
46
+ unet_config,
47
+ timesteps=1000,
48
+ beta_schedule="linear",
49
+ loss_type="l2",
50
+ ckpt_path=None,
51
+ ignore_keys=[],
52
+ load_only_unet=False,
53
+ monitor="val/loss",
54
+ use_ema=True,
55
+ first_stage_key="image",
56
+ image_size=256,
57
+ channels=3,
58
+ log_every_t=100,
59
+ clip_denoised=True,
60
+ linear_start=1e-4,
61
+ linear_end=2e-2,
62
+ cosine_s=8e-3,
63
+ given_betas=None,
64
+ original_elbo_weight=0.,
65
+ v_posterior=0., # weight for choosing posterior variance as sigma = (1-v) * beta_tilde + v * beta
66
+ l_simple_weight=1.,
67
+ conditioning_key=None,
68
+ parameterization="eps", # all assuming fixed variance schedules
69
+ scheduler_config=None,
70
+ use_positional_encodings=False,
71
+ learn_logvar=False,
72
+ logvar_init=0.,
73
+ ):
74
+ super().__init__()
75
+ assert parameterization in ["eps", "x0"], 'currently only supporting "eps" and "x0"'
76
+ self.parameterization = parameterization
77
+ print(f"{self.__class__.__name__}: Running in {self.parameterization}-prediction mode")
78
+ self.cond_stage_model = None
79
+ self.clip_denoised = clip_denoised
80
+ self.log_every_t = log_every_t
81
+ self.first_stage_key = first_stage_key
82
+ self.image_size = image_size # try conv?
83
+ self.channels = channels
84
+ self.use_positional_encodings = use_positional_encodings
85
+ self.model = DiffusionWrapperV1(unet_config, conditioning_key)
86
+ count_params(self.model, verbose=True)
87
+ self.use_ema = use_ema
88
+ if self.use_ema:
89
+ self.model_ema = LitEma(self.model)
90
+ print(f"Keeping EMAs of {len(list(self.model_ema.buffers()))}.")
91
+
92
+ self.use_scheduler = scheduler_config is not None
93
+ if self.use_scheduler:
94
+ self.scheduler_config = scheduler_config
95
+
96
+ self.v_posterior = v_posterior
97
+ self.original_elbo_weight = original_elbo_weight
98
+ self.l_simple_weight = l_simple_weight
99
+
100
+ if monitor is not None:
101
+ self.monitor = monitor
102
+ if ckpt_path is not None:
103
+ self.init_from_ckpt(ckpt_path, ignore_keys=ignore_keys, only_model=load_only_unet)
104
+
105
+ self.register_schedule(given_betas=given_betas, beta_schedule=beta_schedule, timesteps=timesteps,
106
+ linear_start=linear_start, linear_end=linear_end, cosine_s=cosine_s)
107
+
108
+ self.loss_type = loss_type
109
+
110
+ self.learn_logvar = learn_logvar
111
+ self.logvar = torch.full(fill_value=logvar_init, size=(self.num_timesteps,))
112
+ if self.learn_logvar:
113
+ self.logvar = nn.Parameter(self.logvar, requires_grad=True)
114
+
115
+
116
+ def register_schedule(self, given_betas=None, beta_schedule="linear", timesteps=1000,
117
+ linear_start=1e-4, linear_end=2e-2, cosine_s=8e-3):
118
+ if exists(given_betas):
119
+ betas = given_betas
120
+ else:
121
+ betas = make_beta_schedule(beta_schedule, timesteps, linear_start=linear_start, linear_end=linear_end,
122
+ cosine_s=cosine_s)
123
+ alphas = 1. - betas
124
+ alphas_cumprod = np.cumprod(alphas, axis=0)
125
+ alphas_cumprod_prev = np.append(1., alphas_cumprod[:-1])
126
+
127
+ timesteps, = betas.shape
128
+ self.num_timesteps = int(timesteps)
129
+ self.linear_start = linear_start
130
+ self.linear_end = linear_end
131
+ assert alphas_cumprod.shape[0] == self.num_timesteps, 'alphas have to be defined for each timestep'
132
+
133
+ to_torch = partial(torch.tensor, dtype=torch.float32)
134
+
135
+ self.register_buffer('betas', to_torch(betas))
136
+ self.register_buffer('alphas_cumprod', to_torch(alphas_cumprod))
137
+ self.register_buffer('alphas_cumprod_prev', to_torch(alphas_cumprod_prev))
138
+
139
+ # calculations for diffusion q(x_t | x_{t-1}) and others
140
+ self.register_buffer('sqrt_alphas_cumprod', to_torch(np.sqrt(alphas_cumprod)))
141
+ self.register_buffer('sqrt_one_minus_alphas_cumprod', to_torch(np.sqrt(1. - alphas_cumprod)))
142
+ self.register_buffer('log_one_minus_alphas_cumprod', to_torch(np.log(1. - alphas_cumprod)))
143
+ self.register_buffer('sqrt_recip_alphas_cumprod', to_torch(np.sqrt(1. / alphas_cumprod)))
144
+ self.register_buffer('sqrt_recipm1_alphas_cumprod', to_torch(np.sqrt(1. / alphas_cumprod - 1)))
145
+
146
+ # calculations for posterior q(x_{t-1} | x_t, x_0)
147
+ posterior_variance = (1 - self.v_posterior) * betas * (1. - alphas_cumprod_prev) / (
148
+ 1. - alphas_cumprod) + self.v_posterior * betas
149
+ # above: equal to 1. / (1. / (1. - alpha_cumprod_tm1) + alpha_t / beta_t)
150
+ self.register_buffer('posterior_variance', to_torch(posterior_variance))
151
+ # below: log calculation clipped because the posterior variance is 0 at the beginning of the diffusion chain
152
+ self.register_buffer('posterior_log_variance_clipped', to_torch(np.log(np.maximum(posterior_variance, 1e-20))))
153
+ self.register_buffer('posterior_mean_coef1', to_torch(
154
+ betas * np.sqrt(alphas_cumprod_prev) / (1. - alphas_cumprod)))
155
+ self.register_buffer('posterior_mean_coef2', to_torch(
156
+ (1. - alphas_cumprod_prev) * np.sqrt(alphas) / (1. - alphas_cumprod)))
157
+
158
+ if self.parameterization == "eps":
159
+ lvlb_weights = self.betas ** 2 / (
160
+ 2 * self.posterior_variance * to_torch(alphas) * (1 - self.alphas_cumprod))
161
+ elif self.parameterization == "x0":
162
+ lvlb_weights = 0.5 * np.sqrt(torch.Tensor(alphas_cumprod)) / (2. * 1 - torch.Tensor(alphas_cumprod))
163
+ else:
164
+ raise NotImplementedError("mu not supported")
165
+ # TODO how to choose this term
166
+ lvlb_weights[0] = lvlb_weights[1]
167
+ self.register_buffer('lvlb_weights', lvlb_weights, persistent=False)
168
+ assert not torch.isnan(self.lvlb_weights).all()
169
+
170
+ @contextmanager
171
+ def ema_scope(self, context=None):
172
+ if self.use_ema:
173
+ self.model_ema.store(self.model.parameters())
174
+ self.model_ema.copy_to(self.model)
175
+ if context is not None:
176
+ print(f"{context}: Switched to EMA weights")
177
+ try:
178
+ yield None
179
+ finally:
180
+ if self.use_ema:
181
+ self.model_ema.restore(self.model.parameters())
182
+ if context is not None:
183
+ print(f"{context}: Restored training weights")
184
+
185
+ def init_from_ckpt(self, path, ignore_keys=list(), only_model=False):
186
+ sd = torch.load(path, map_location="cpu")
187
+ if "state_dict" in list(sd.keys()):
188
+ sd = sd["state_dict"]
189
+ keys = list(sd.keys())
190
+ for k in keys:
191
+ for ik in ignore_keys:
192
+ if k.startswith(ik):
193
+ print("Deleting key {} from state_dict.".format(k))
194
+ del sd[k]
195
+ missing, unexpected = self.load_state_dict(sd, strict=False) if not only_model else self.model.load_state_dict(
196
+ sd, strict=False)
197
+ print(f"Restored from {path} with {len(missing)} missing and {len(unexpected)} unexpected keys")
198
+ if len(missing) > 0:
199
+ print(f"Missing Keys: {missing}")
200
+ if len(unexpected) > 0:
201
+ print(f"Unexpected Keys: {unexpected}")
202
+
203
+ def q_mean_variance(self, x_start, t):
204
+ """
205
+ Get the distribution q(x_t | x_0).
206
+ :param x_start: the [N x C x ...] tensor of noiseless inputs.
207
+ :param t: the number of diffusion steps (minus 1). Here, 0 means one step.
208
+ :return: A tuple (mean, variance, log_variance), all of x_start's shape.
209
+ """
210
+ mean = (extract_into_tensor(self.sqrt_alphas_cumprod, t, x_start.shape) * x_start)
211
+ variance = extract_into_tensor(1.0 - self.alphas_cumprod, t, x_start.shape)
212
+ log_variance = extract_into_tensor(self.log_one_minus_alphas_cumprod, t, x_start.shape)
213
+ return mean, variance, log_variance
214
+
215
+ def predict_start_from_noise(self, x_t, t, noise):
216
+ return (
217
+ extract_into_tensor(self.sqrt_recip_alphas_cumprod, t, x_t.shape) * x_t -
218
+ extract_into_tensor(self.sqrt_recipm1_alphas_cumprod, t, x_t.shape) * noise
219
+ )
220
+
221
+ def q_posterior(self, x_start, x_t, t):
222
+ posterior_mean = (
223
+ extract_into_tensor(self.posterior_mean_coef1, t, x_t.shape) * x_start +
224
+ extract_into_tensor(self.posterior_mean_coef2, t, x_t.shape) * x_t
225
+ )
226
+ posterior_variance = extract_into_tensor(self.posterior_variance, t, x_t.shape)
227
+ posterior_log_variance_clipped = extract_into_tensor(self.posterior_log_variance_clipped, t, x_t.shape)
228
+ return posterior_mean, posterior_variance, posterior_log_variance_clipped
229
+
230
+ def p_mean_variance(self, x, t, clip_denoised: bool):
231
+ model_out = self.model(x, t)
232
+ if self.parameterization == "eps":
233
+ x_recon = self.predict_start_from_noise(x, t=t, noise=model_out)
234
+ elif self.parameterization == "x0":
235
+ x_recon = model_out
236
+ if clip_denoised:
237
+ x_recon.clamp_(-1., 1.)
238
+
239
+ model_mean, posterior_variance, posterior_log_variance = self.q_posterior(x_start=x_recon, x_t=x, t=t)
240
+ return model_mean, posterior_variance, posterior_log_variance
241
+
242
+ @torch.no_grad()
243
+ def p_sample(self, x, t, clip_denoised=True, repeat_noise=False):
244
+ b, *_, device = *x.shape, x.device
245
+ model_mean, _, model_log_variance = self.p_mean_variance(x=x, t=t, clip_denoised=clip_denoised)
246
+ noise = noise_like(x.shape, device, repeat_noise)
247
+ # no noise when t == 0
248
+ nonzero_mask = (1 - (t == 0).float()).reshape(b, *((1,) * (len(x.shape) - 1)))
249
+ return model_mean + nonzero_mask * (0.5 * model_log_variance).exp() * noise
250
+
251
+ @torch.no_grad()
252
+ def p_sample_loop(self, shape, return_intermediates=False):
253
+ device = self.betas.device
254
+ b = shape[0]
255
+ img = torch.randn(shape, device=device)
256
+ intermediates = [img]
257
+ for i in tqdm(reversed(range(0, self.num_timesteps)), desc='Sampling t', total=self.num_timesteps):
258
+ img = self.p_sample(img, torch.full((b,), i, device=device, dtype=torch.long),
259
+ clip_denoised=self.clip_denoised)
260
+ if i % self.log_every_t == 0 or i == self.num_timesteps - 1:
261
+ intermediates.append(img)
262
+ if return_intermediates:
263
+ return img, intermediates
264
+ return img
265
+
266
+ @torch.no_grad()
267
+ def sample(self, batch_size=16, return_intermediates=False):
268
+ image_size = self.image_size
269
+ channels = self.channels
270
+ return self.p_sample_loop((batch_size, channels, image_size, image_size),
271
+ return_intermediates=return_intermediates)
272
+
273
+ def q_sample(self, x_start, t, noise=None):
274
+ noise = default(noise, lambda: torch.randn_like(x_start))
275
+ return (extract_into_tensor(self.sqrt_alphas_cumprod, t, x_start.shape) * x_start +
276
+ extract_into_tensor(self.sqrt_one_minus_alphas_cumprod, t, x_start.shape) * noise)
277
+
278
+ def get_loss(self, pred, target, mean=True):
279
+ if self.loss_type == 'l1':
280
+ loss = (target - pred).abs()
281
+ if mean:
282
+ loss = loss.mean()
283
+ elif self.loss_type == 'l2':
284
+ if mean:
285
+ loss = torch.nn.functional.mse_loss(target, pred)
286
+ else:
287
+ loss = torch.nn.functional.mse_loss(target, pred, reduction='none')
288
+ else:
289
+ raise NotImplementedError("unknown loss type '{loss_type}'")
290
+
291
+ return loss
292
+
293
+ def p_losses(self, x_start, t, noise=None):
294
+ noise = default(noise, lambda: torch.randn_like(x_start))
295
+ x_noisy = self.q_sample(x_start=x_start, t=t, noise=noise)
296
+ model_out = self.model(x_noisy, t)
297
+
298
+ loss_dict = {}
299
+ if self.parameterization == "eps":
300
+ target = noise
301
+ elif self.parameterization == "x0":
302
+ target = x_start
303
+ else:
304
+ raise NotImplementedError(f"Paramterization {self.parameterization} not yet supported")
305
+
306
+ loss = self.get_loss(model_out, target, mean=False).mean(dim=[1, 2, 3])
307
+
308
+ log_prefix = 'train' if self.training else 'val'
309
+
310
+ loss_dict.update({f'{log_prefix}/loss_simple': loss.mean()})
311
+ loss_simple = loss.mean() * self.l_simple_weight
312
+
313
+ loss_vlb = (self.lvlb_weights[t] * loss).mean()
314
+ loss_dict.update({f'{log_prefix}/loss_vlb': loss_vlb})
315
+
316
+ loss = loss_simple + self.original_elbo_weight * loss_vlb
317
+
318
+ loss_dict.update({f'{log_prefix}/loss': loss})
319
+
320
+ return loss, loss_dict
321
+
322
+ def forward(self, x, *args, **kwargs):
323
+ # b, c, h, w, device, img_size, = *x.shape, x.device, self.image_size
324
+ # assert h == img_size and w == img_size, f'height and width of image must be {img_size}'
325
+ t = torch.randint(0, self.num_timesteps, (x.shape[0],), device=self.device).long()
326
+ return self.p_losses(x, t, *args, **kwargs)
327
+
328
+ def get_input(self, batch, k):
329
+ x = batch[k]
330
+ if len(x.shape) == 3:
331
+ x = x[..., None]
332
+ x = rearrange(x, 'b h w c -> b c h w')
333
+ x = x.to(memory_format=torch.contiguous_format).float()
334
+ return x
335
+
336
+ def shared_step(self, batch):
337
+ x = self.get_input(batch, self.first_stage_key)
338
+ loss, loss_dict = self(x)
339
+ return loss, loss_dict
340
+
341
+ def training_step(self, batch, batch_idx):
342
+ loss, loss_dict = self.shared_step(batch)
343
+
344
+ self.log_dict(loss_dict, prog_bar=True,
345
+ logger=True, on_step=True, on_epoch=True)
346
+
347
+ self.log("global_step", self.global_step,
348
+ prog_bar=True, logger=True, on_step=True, on_epoch=False)
349
+
350
+ if self.use_scheduler:
351
+ lr = self.optimizers().param_groups[0]['lr']
352
+ self.log('lr_abs', lr, prog_bar=True, logger=True, on_step=True, on_epoch=False)
353
+
354
+ return loss
355
+
356
+ @torch.no_grad()
357
+ def validation_step(self, batch, batch_idx):
358
+ _, loss_dict_no_ema = self.shared_step(batch)
359
+ with self.ema_scope():
360
+ _, loss_dict_ema = self.shared_step(batch)
361
+ loss_dict_ema = {key + '_ema': loss_dict_ema[key] for key in loss_dict_ema}
362
+ self.log_dict(loss_dict_no_ema, prog_bar=False, logger=True, on_step=False, on_epoch=True)
363
+ self.log_dict(loss_dict_ema, prog_bar=False, logger=True, on_step=False, on_epoch=True)
364
+
365
+ def on_train_batch_end(self, *args, **kwargs):
366
+ if self.use_ema:
367
+ self.model_ema(self.model)
368
+
369
+ def _get_rows_from_list(self, samples):
370
+ n_imgs_per_row = len(samples)
371
+ denoise_grid = rearrange(samples, 'n b c h w -> b n c h w')
372
+ denoise_grid = rearrange(denoise_grid, 'b n c h w -> (b n) c h w')
373
+ denoise_grid = make_grid(denoise_grid, nrow=n_imgs_per_row)
374
+ return denoise_grid
375
+
376
+ @torch.no_grad()
377
+ def log_images(self, batch, N=8, n_row=2, sample=True, return_keys=None, **kwargs):
378
+ log = dict()
379
+ x = self.get_input(batch, self.first_stage_key)
380
+ N = min(x.shape[0], N)
381
+ n_row = min(x.shape[0], n_row)
382
+ x = x.to(self.device)[:N]
383
+ log["inputs"] = x
384
+
385
+ # get diffusion row
386
+ diffusion_row = list()
387
+ x_start = x[:n_row]
388
+
389
+ for t in range(self.num_timesteps):
390
+ if t % self.log_every_t == 0 or t == self.num_timesteps - 1:
391
+ t = repeat(torch.tensor([t]), '1 -> b', b=n_row)
392
+ t = t.to(self.device).long()
393
+ noise = torch.randn_like(x_start)
394
+ x_noisy = self.q_sample(x_start=x_start, t=t, noise=noise)
395
+ diffusion_row.append(x_noisy)
396
+
397
+ log["diffusion_row"] = self._get_rows_from_list(diffusion_row)
398
+
399
+ if sample:
400
+ # get denoise row
401
+ with self.ema_scope("Plotting"):
402
+ samples, denoise_row = self.sample(batch_size=N, return_intermediates=True)
403
+
404
+ log["samples"] = samples
405
+ log["denoise_row"] = self._get_rows_from_list(denoise_row)
406
+
407
+ if return_keys:
408
+ if np.intersect1d(list(log.keys()), return_keys).shape[0] == 0:
409
+ return log
410
+ else:
411
+ return {key: log[key] for key in return_keys}
412
+ return log
413
+
414
+ def configure_optimizers(self):
415
+ lr = self.learning_rate
416
+ params = list(self.model.parameters())
417
+ if self.learn_logvar:
418
+ params = params + [self.logvar]
419
+ opt = torch.optim.AdamW(params, lr=lr)
420
+ return opt
421
+
422
+
423
+ class LatentDiffusionV1(DDPMV1):
424
+ """main class"""
425
+ def __init__(self,
426
+ first_stage_config,
427
+ cond_stage_config,
428
+ num_timesteps_cond=None,
429
+ cond_stage_key="image",
430
+ cond_stage_trainable=False,
431
+ concat_mode=True,
432
+ cond_stage_forward=None,
433
+ conditioning_key=None,
434
+ scale_factor=1.0,
435
+ scale_by_std=False,
436
+ *args, **kwargs):
437
+ self.num_timesteps_cond = default(num_timesteps_cond, 1)
438
+ self.scale_by_std = scale_by_std
439
+ assert self.num_timesteps_cond <= kwargs['timesteps']
440
+ # for backwards compatibility after implementation of DiffusionWrapper
441
+ if conditioning_key is None:
442
+ conditioning_key = 'concat' if concat_mode else 'crossattn'
443
+ if cond_stage_config == '__is_unconditional__':
444
+ conditioning_key = None
445
+ ckpt_path = kwargs.pop("ckpt_path", None)
446
+ ignore_keys = kwargs.pop("ignore_keys", [])
447
+ super().__init__(conditioning_key=conditioning_key, *args, **kwargs)
448
+ self.concat_mode = concat_mode
449
+ self.cond_stage_trainable = cond_stage_trainable
450
+ self.cond_stage_key = cond_stage_key
451
+ try:
452
+ self.num_downs = len(first_stage_config.params.ddconfig.ch_mult) - 1
453
+ except:
454
+ self.num_downs = 0
455
+ if not scale_by_std:
456
+ self.scale_factor = scale_factor
457
+ else:
458
+ self.register_buffer('scale_factor', torch.tensor(scale_factor))
459
+ self.instantiate_first_stage(first_stage_config)
460
+ self.instantiate_cond_stage(cond_stage_config)
461
+ self.cond_stage_forward = cond_stage_forward
462
+ self.clip_denoised = False
463
+ self.bbox_tokenizer = None
464
+
465
+ self.restarted_from_ckpt = False
466
+ if ckpt_path is not None:
467
+ self.init_from_ckpt(ckpt_path, ignore_keys)
468
+ self.restarted_from_ckpt = True
469
+
470
+ def make_cond_schedule(self, ):
471
+ self.cond_ids = torch.full(size=(self.num_timesteps,), fill_value=self.num_timesteps - 1, dtype=torch.long)
472
+ ids = torch.round(torch.linspace(0, self.num_timesteps - 1, self.num_timesteps_cond)).long()
473
+ self.cond_ids[:self.num_timesteps_cond] = ids
474
+
475
+ @rank_zero_only
476
+ @torch.no_grad()
477
+ def on_train_batch_start(self, batch, batch_idx, dataloader_idx):
478
+ # only for very first batch
479
+ if self.scale_by_std and self.current_epoch == 0 and self.global_step == 0 and batch_idx == 0 and not self.restarted_from_ckpt:
480
+ assert self.scale_factor == 1., 'rather not use custom rescaling and std-rescaling simultaneously'
481
+ # set rescale weight to 1./std of encodings
482
+ print("### USING STD-RESCALING ###")
483
+ x = super().get_input(batch, self.first_stage_key)
484
+ x = x.to(self.device)
485
+ encoder_posterior = self.encode_first_stage(x)
486
+ z = self.get_first_stage_encoding(encoder_posterior).detach()
487
+ del self.scale_factor
488
+ self.register_buffer('scale_factor', 1. / z.flatten().std())
489
+ print(f"setting self.scale_factor to {self.scale_factor}")
490
+ print("### USING STD-RESCALING ###")
491
+
492
+ def register_schedule(self,
493
+ given_betas=None, beta_schedule="linear", timesteps=1000,
494
+ linear_start=1e-4, linear_end=2e-2, cosine_s=8e-3):
495
+ super().register_schedule(given_betas, beta_schedule, timesteps, linear_start, linear_end, cosine_s)
496
+
497
+ self.shorten_cond_schedule = self.num_timesteps_cond > 1
498
+ if self.shorten_cond_schedule:
499
+ self.make_cond_schedule()
500
+
501
+ def instantiate_first_stage(self, config):
502
+ model = instantiate_from_config(config)
503
+ self.first_stage_model = model.eval()
504
+ self.first_stage_model.train = disabled_train
505
+ for param in self.first_stage_model.parameters():
506
+ param.requires_grad = False
507
+
508
+ def instantiate_cond_stage(self, config):
509
+ if not self.cond_stage_trainable:
510
+ if config == "__is_first_stage__":
511
+ print("Using first stage also as cond stage.")
512
+ self.cond_stage_model = self.first_stage_model
513
+ elif config == "__is_unconditional__":
514
+ print(f"Training {self.__class__.__name__} as an unconditional model.")
515
+ self.cond_stage_model = None
516
+ # self.be_unconditional = True
517
+ else:
518
+ model = instantiate_from_config(config)
519
+ self.cond_stage_model = model.eval()
520
+ self.cond_stage_model.train = disabled_train
521
+ for param in self.cond_stage_model.parameters():
522
+ param.requires_grad = False
523
+ else:
524
+ assert config != '__is_first_stage__'
525
+ assert config != '__is_unconditional__'
526
+ model = instantiate_from_config(config)
527
+ self.cond_stage_model = model
528
+
529
+ def _get_denoise_row_from_list(self, samples, desc='', force_no_decoder_quantization=False):
530
+ denoise_row = []
531
+ for zd in tqdm(samples, desc=desc):
532
+ denoise_row.append(self.decode_first_stage(zd.to(self.device),
533
+ force_not_quantize=force_no_decoder_quantization))
534
+ n_imgs_per_row = len(denoise_row)
535
+ denoise_row = torch.stack(denoise_row) # n_log_step, n_row, C, H, W
536
+ denoise_grid = rearrange(denoise_row, 'n b c h w -> b n c h w')
537
+ denoise_grid = rearrange(denoise_grid, 'b n c h w -> (b n) c h w')
538
+ denoise_grid = make_grid(denoise_grid, nrow=n_imgs_per_row)
539
+ return denoise_grid
540
+
541
+ def get_first_stage_encoding(self, encoder_posterior):
542
+ if isinstance(encoder_posterior, DiagonalGaussianDistribution):
543
+ z = encoder_posterior.sample()
544
+ elif isinstance(encoder_posterior, torch.Tensor):
545
+ z = encoder_posterior
546
+ else:
547
+ raise NotImplementedError(f"encoder_posterior of type '{type(encoder_posterior)}' not yet implemented")
548
+ return self.scale_factor * z
549
+
550
+ def get_learned_conditioning(self, c):
551
+ if self.cond_stage_forward is None:
552
+ if hasattr(self.cond_stage_model, 'encode') and callable(self.cond_stage_model.encode):
553
+ c = self.cond_stage_model.encode(c)
554
+ if isinstance(c, DiagonalGaussianDistribution):
555
+ c = c.mode()
556
+ else:
557
+ c = self.cond_stage_model(c)
558
+ else:
559
+ assert hasattr(self.cond_stage_model, self.cond_stage_forward)
560
+ c = getattr(self.cond_stage_model, self.cond_stage_forward)(c)
561
+ return c
562
+
563
+ def meshgrid(self, h, w):
564
+ y = torch.arange(0, h).view(h, 1, 1).repeat(1, w, 1)
565
+ x = torch.arange(0, w).view(1, w, 1).repeat(h, 1, 1)
566
+
567
+ arr = torch.cat([y, x], dim=-1)
568
+ return arr
569
+
570
+ def delta_border(self, h, w):
571
+ """
572
+ :param h: height
573
+ :param w: width
574
+ :return: normalized distance to image border,
575
+ wtith min distance = 0 at border and max dist = 0.5 at image center
576
+ """
577
+ lower_right_corner = torch.tensor([h - 1, w - 1]).view(1, 1, 2)
578
+ arr = self.meshgrid(h, w) / lower_right_corner
579
+ dist_left_up = torch.min(arr, dim=-1, keepdims=True)[0]
580
+ dist_right_down = torch.min(1 - arr, dim=-1, keepdims=True)[0]
581
+ edge_dist = torch.min(torch.cat([dist_left_up, dist_right_down], dim=-1), dim=-1)[0]
582
+ return edge_dist
583
+
584
+ def get_weighting(self, h, w, Ly, Lx, device):
585
+ weighting = self.delta_border(h, w)
586
+ weighting = torch.clip(weighting, self.split_input_params["clip_min_weight"],
587
+ self.split_input_params["clip_max_weight"], )
588
+ weighting = weighting.view(1, h * w, 1).repeat(1, 1, Ly * Lx).to(device)
589
+
590
+ if self.split_input_params["tie_braker"]:
591
+ L_weighting = self.delta_border(Ly, Lx)
592
+ L_weighting = torch.clip(L_weighting,
593
+ self.split_input_params["clip_min_tie_weight"],
594
+ self.split_input_params["clip_max_tie_weight"])
595
+
596
+ L_weighting = L_weighting.view(1, 1, Ly * Lx).to(device)
597
+ weighting = weighting * L_weighting
598
+ return weighting
599
+
600
+ def get_fold_unfold(self, x, kernel_size, stride, uf=1, df=1): # todo load once not every time, shorten code
601
+ """
602
+ :param x: img of size (bs, c, h, w)
603
+ :return: n img crops of size (n, bs, c, kernel_size[0], kernel_size[1])
604
+ """
605
+ bs, nc, h, w = x.shape
606
+
607
+ # number of crops in image
608
+ Ly = (h - kernel_size[0]) // stride[0] + 1
609
+ Lx = (w - kernel_size[1]) // stride[1] + 1
610
+
611
+ if uf == 1 and df == 1:
612
+ fold_params = dict(kernel_size=kernel_size, dilation=1, padding=0, stride=stride)
613
+ unfold = torch.nn.Unfold(**fold_params)
614
+
615
+ fold = torch.nn.Fold(output_size=x.shape[2:], **fold_params)
616
+
617
+ weighting = self.get_weighting(kernel_size[0], kernel_size[1], Ly, Lx, x.device).to(x.dtype)
618
+ normalization = fold(weighting).view(1, 1, h, w) # normalizes the overlap
619
+ weighting = weighting.view((1, 1, kernel_size[0], kernel_size[1], Ly * Lx))
620
+
621
+ elif uf > 1 and df == 1:
622
+ fold_params = dict(kernel_size=kernel_size, dilation=1, padding=0, stride=stride)
623
+ unfold = torch.nn.Unfold(**fold_params)
624
+
625
+ fold_params2 = dict(kernel_size=(kernel_size[0] * uf, kernel_size[0] * uf),
626
+ dilation=1, padding=0,
627
+ stride=(stride[0] * uf, stride[1] * uf))
628
+ fold = torch.nn.Fold(output_size=(x.shape[2] * uf, x.shape[3] * uf), **fold_params2)
629
+
630
+ weighting = self.get_weighting(kernel_size[0] * uf, kernel_size[1] * uf, Ly, Lx, x.device).to(x.dtype)
631
+ normalization = fold(weighting).view(1, 1, h * uf, w * uf) # normalizes the overlap
632
+ weighting = weighting.view((1, 1, kernel_size[0] * uf, kernel_size[1] * uf, Ly * Lx))
633
+
634
+ elif df > 1 and uf == 1:
635
+ fold_params = dict(kernel_size=kernel_size, dilation=1, padding=0, stride=stride)
636
+ unfold = torch.nn.Unfold(**fold_params)
637
+
638
+ fold_params2 = dict(kernel_size=(kernel_size[0] // df, kernel_size[0] // df),
639
+ dilation=1, padding=0,
640
+ stride=(stride[0] // df, stride[1] // df))
641
+ fold = torch.nn.Fold(output_size=(x.shape[2] // df, x.shape[3] // df), **fold_params2)
642
+
643
+ weighting = self.get_weighting(kernel_size[0] // df, kernel_size[1] // df, Ly, Lx, x.device).to(x.dtype)
644
+ normalization = fold(weighting).view(1, 1, h // df, w // df) # normalizes the overlap
645
+ weighting = weighting.view((1, 1, kernel_size[0] // df, kernel_size[1] // df, Ly * Lx))
646
+
647
+ else:
648
+ raise NotImplementedError
649
+
650
+ return fold, unfold, normalization, weighting
651
+
652
+ @torch.no_grad()
653
+ def get_input(self, batch, k, return_first_stage_outputs=False, force_c_encode=False,
654
+ cond_key=None, return_original_cond=False, bs=None):
655
+ x = super().get_input(batch, k)
656
+ if bs is not None:
657
+ x = x[:bs]
658
+ x = x.to(self.device)
659
+ encoder_posterior = self.encode_first_stage(x)
660
+ z = self.get_first_stage_encoding(encoder_posterior).detach()
661
+
662
+ if self.model.conditioning_key is not None:
663
+ if cond_key is None:
664
+ cond_key = self.cond_stage_key
665
+ if cond_key != self.first_stage_key:
666
+ if cond_key in ['caption', 'coordinates_bbox']:
667
+ xc = batch[cond_key]
668
+ elif cond_key == 'class_label':
669
+ xc = batch
670
+ else:
671
+ xc = super().get_input(batch, cond_key).to(self.device)
672
+ else:
673
+ xc = x
674
+ if not self.cond_stage_trainable or force_c_encode:
675
+ if isinstance(xc, dict) or isinstance(xc, list):
676
+ # import pudb; pudb.set_trace()
677
+ c = self.get_learned_conditioning(xc)
678
+ else:
679
+ c = self.get_learned_conditioning(xc.to(self.device))
680
+ else:
681
+ c = xc
682
+ if bs is not None:
683
+ c = c[:bs]
684
+
685
+ if self.use_positional_encodings:
686
+ pos_x, pos_y = self.compute_latent_shifts(batch)
687
+ ckey = __conditioning_keys__[self.model.conditioning_key]
688
+ c = {ckey: c, 'pos_x': pos_x, 'pos_y': pos_y}
689
+
690
+ else:
691
+ c = None
692
+ xc = None
693
+ if self.use_positional_encodings:
694
+ pos_x, pos_y = self.compute_latent_shifts(batch)
695
+ c = {'pos_x': pos_x, 'pos_y': pos_y}
696
+ out = [z, c]
697
+ if return_first_stage_outputs:
698
+ xrec = self.decode_first_stage(z)
699
+ out.extend([x, xrec])
700
+ if return_original_cond:
701
+ out.append(xc)
702
+ return out
703
+
704
+ @torch.no_grad()
705
+ def decode_first_stage(self, z, predict_cids=False, force_not_quantize=False):
706
+ if predict_cids:
707
+ if z.dim() == 4:
708
+ z = torch.argmax(z.exp(), dim=1).long()
709
+ z = self.first_stage_model.quantize.get_codebook_entry(z, shape=None)
710
+ z = rearrange(z, 'b h w c -> b c h w').contiguous()
711
+
712
+ z = 1. / self.scale_factor * z
713
+
714
+ if hasattr(self, "split_input_params"):
715
+ if self.split_input_params["patch_distributed_vq"]:
716
+ ks = self.split_input_params["ks"] # eg. (128, 128)
717
+ stride = self.split_input_params["stride"] # eg. (64, 64)
718
+ uf = self.split_input_params["vqf"]
719
+ bs, nc, h, w = z.shape
720
+ if ks[0] > h or ks[1] > w:
721
+ ks = (min(ks[0], h), min(ks[1], w))
722
+ print("reducing Kernel")
723
+
724
+ if stride[0] > h or stride[1] > w:
725
+ stride = (min(stride[0], h), min(stride[1], w))
726
+ print("reducing stride")
727
+
728
+ fold, unfold, normalization, weighting = self.get_fold_unfold(z, ks, stride, uf=uf)
729
+
730
+ z = unfold(z) # (bn, nc * prod(**ks), L)
731
+ # 1. Reshape to img shape
732
+ z = z.view((z.shape[0], -1, ks[0], ks[1], z.shape[-1])) # (bn, nc, ks[0], ks[1], L )
733
+
734
+ # 2. apply model loop over last dim
735
+ if isinstance(self.first_stage_model, VQModelInterface):
736
+ output_list = [self.first_stage_model.decode(z[:, :, :, :, i],
737
+ force_not_quantize=predict_cids or force_not_quantize)
738
+ for i in range(z.shape[-1])]
739
+ else:
740
+
741
+ output_list = [self.first_stage_model.decode(z[:, :, :, :, i])
742
+ for i in range(z.shape[-1])]
743
+
744
+ o = torch.stack(output_list, axis=-1) # # (bn, nc, ks[0], ks[1], L)
745
+ o = o * weighting
746
+ # Reverse 1. reshape to img shape
747
+ o = o.view((o.shape[0], -1, o.shape[-1])) # (bn, nc * ks[0] * ks[1], L)
748
+ # stitch crops together
749
+ decoded = fold(o)
750
+ decoded = decoded / normalization # norm is shape (1, 1, h, w)
751
+ return decoded
752
+ else:
753
+ if isinstance(self.first_stage_model, VQModelInterface):
754
+ return self.first_stage_model.decode(z, force_not_quantize=predict_cids or force_not_quantize)
755
+ else:
756
+ return self.first_stage_model.decode(z)
757
+
758
+ else:
759
+ if isinstance(self.first_stage_model, VQModelInterface):
760
+ return self.first_stage_model.decode(z, force_not_quantize=predict_cids or force_not_quantize)
761
+ else:
762
+ return self.first_stage_model.decode(z)
763
+
764
+ # same as above but without decorator
765
+ def differentiable_decode_first_stage(self, z, predict_cids=False, force_not_quantize=False):
766
+ if predict_cids:
767
+ if z.dim() == 4:
768
+ z = torch.argmax(z.exp(), dim=1).long()
769
+ z = self.first_stage_model.quantize.get_codebook_entry(z, shape=None)
770
+ z = rearrange(z, 'b h w c -> b c h w').contiguous()
771
+
772
+ z = 1. / self.scale_factor * z
773
+
774
+ if hasattr(self, "split_input_params"):
775
+ if self.split_input_params["patch_distributed_vq"]:
776
+ ks = self.split_input_params["ks"] # eg. (128, 128)
777
+ stride = self.split_input_params["stride"] # eg. (64, 64)
778
+ uf = self.split_input_params["vqf"]
779
+ bs, nc, h, w = z.shape
780
+ if ks[0] > h or ks[1] > w:
781
+ ks = (min(ks[0], h), min(ks[1], w))
782
+ print("reducing Kernel")
783
+
784
+ if stride[0] > h or stride[1] > w:
785
+ stride = (min(stride[0], h), min(stride[1], w))
786
+ print("reducing stride")
787
+
788
+ fold, unfold, normalization, weighting = self.get_fold_unfold(z, ks, stride, uf=uf)
789
+
790
+ z = unfold(z) # (bn, nc * prod(**ks), L)
791
+ # 1. Reshape to img shape
792
+ z = z.view((z.shape[0], -1, ks[0], ks[1], z.shape[-1])) # (bn, nc, ks[0], ks[1], L )
793
+
794
+ # 2. apply model loop over last dim
795
+ if isinstance(self.first_stage_model, VQModelInterface):
796
+ output_list = [self.first_stage_model.decode(z[:, :, :, :, i],
797
+ force_not_quantize=predict_cids or force_not_quantize)
798
+ for i in range(z.shape[-1])]
799
+ else:
800
+
801
+ output_list = [self.first_stage_model.decode(z[:, :, :, :, i])
802
+ for i in range(z.shape[-1])]
803
+
804
+ o = torch.stack(output_list, axis=-1) # # (bn, nc, ks[0], ks[1], L)
805
+ o = o * weighting
806
+ # Reverse 1. reshape to img shape
807
+ o = o.view((o.shape[0], -1, o.shape[-1])) # (bn, nc * ks[0] * ks[1], L)
808
+ # stitch crops together
809
+ decoded = fold(o)
810
+ decoded = decoded / normalization # norm is shape (1, 1, h, w)
811
+ return decoded
812
+ else:
813
+ if isinstance(self.first_stage_model, VQModelInterface):
814
+ return self.first_stage_model.decode(z, force_not_quantize=predict_cids or force_not_quantize)
815
+ else:
816
+ return self.first_stage_model.decode(z)
817
+
818
+ else:
819
+ if isinstance(self.first_stage_model, VQModelInterface):
820
+ return self.first_stage_model.decode(z, force_not_quantize=predict_cids or force_not_quantize)
821
+ else:
822
+ return self.first_stage_model.decode(z)
823
+
824
+ @torch.no_grad()
825
+ def encode_first_stage(self, x):
826
+ if hasattr(self, "split_input_params"):
827
+ if self.split_input_params["patch_distributed_vq"]:
828
+ ks = self.split_input_params["ks"] # eg. (128, 128)
829
+ stride = self.split_input_params["stride"] # eg. (64, 64)
830
+ df = self.split_input_params["vqf"]
831
+ self.split_input_params['original_image_size'] = x.shape[-2:]
832
+ bs, nc, h, w = x.shape
833
+ if ks[0] > h or ks[1] > w:
834
+ ks = (min(ks[0], h), min(ks[1], w))
835
+ print("reducing Kernel")
836
+
837
+ if stride[0] > h or stride[1] > w:
838
+ stride = (min(stride[0], h), min(stride[1], w))
839
+ print("reducing stride")
840
+
841
+ fold, unfold, normalization, weighting = self.get_fold_unfold(x, ks, stride, df=df)
842
+ z = unfold(x) # (bn, nc * prod(**ks), L)
843
+ # Reshape to img shape
844
+ z = z.view((z.shape[0], -1, ks[0], ks[1], z.shape[-1])) # (bn, nc, ks[0], ks[1], L )
845
+
846
+ output_list = [self.first_stage_model.encode(z[:, :, :, :, i])
847
+ for i in range(z.shape[-1])]
848
+
849
+ o = torch.stack(output_list, axis=-1)
850
+ o = o * weighting
851
+
852
+ # Reverse reshape to img shape
853
+ o = o.view((o.shape[0], -1, o.shape[-1])) # (bn, nc * ks[0] * ks[1], L)
854
+ # stitch crops together
855
+ decoded = fold(o)
856
+ decoded = decoded / normalization
857
+ return decoded
858
+
859
+ else:
860
+ return self.first_stage_model.encode(x)
861
+ else:
862
+ return self.first_stage_model.encode(x)
863
+
864
+ def shared_step(self, batch, **kwargs):
865
+ x, c = self.get_input(batch, self.first_stage_key)
866
+ loss = self(x, c)
867
+ return loss
868
+
869
+ def forward(self, x, c, *args, **kwargs):
870
+ t = torch.randint(0, self.num_timesteps, (x.shape[0],), device=self.device).long()
871
+ if self.model.conditioning_key is not None:
872
+ assert c is not None
873
+ if self.cond_stage_trainable:
874
+ c = self.get_learned_conditioning(c)
875
+ if self.shorten_cond_schedule: # TODO: drop this option
876
+ tc = self.cond_ids[t].to(self.device)
877
+ c = self.q_sample(x_start=c, t=tc, noise=torch.randn_like(c.float()))
878
+ return self.p_losses(x, c, t, *args, **kwargs)
879
+
880
+ def _rescale_annotations(self, bboxes, crop_coordinates): # TODO: move to dataset
881
+ def rescale_bbox(bbox):
882
+ x0 = clamp((bbox[0] - crop_coordinates[0]) / crop_coordinates[2])
883
+ y0 = clamp((bbox[1] - crop_coordinates[1]) / crop_coordinates[3])
884
+ w = min(bbox[2] / crop_coordinates[2], 1 - x0)
885
+ h = min(bbox[3] / crop_coordinates[3], 1 - y0)
886
+ return x0, y0, w, h
887
+
888
+ return [rescale_bbox(b) for b in bboxes]
889
+
890
+ def apply_model(self, x_noisy, t, cond, return_ids=False):
891
+
892
+ if isinstance(cond, dict):
893
+ # hybrid case, cond is exptected to be a dict
894
+ pass
895
+ else:
896
+ if not isinstance(cond, list):
897
+ cond = [cond]
898
+ key = 'c_concat' if self.model.conditioning_key == 'concat' else 'c_crossattn'
899
+ cond = {key: cond}
900
+
901
+ if hasattr(self, "split_input_params"):
902
+ assert len(cond) == 1 # todo can only deal with one conditioning atm
903
+ assert not return_ids
904
+ ks = self.split_input_params["ks"] # eg. (128, 128)
905
+ stride = self.split_input_params["stride"] # eg. (64, 64)
906
+
907
+ h, w = x_noisy.shape[-2:]
908
+
909
+ fold, unfold, normalization, weighting = self.get_fold_unfold(x_noisy, ks, stride)
910
+
911
+ z = unfold(x_noisy) # (bn, nc * prod(**ks), L)
912
+ # Reshape to img shape
913
+ z = z.view((z.shape[0], -1, ks[0], ks[1], z.shape[-1])) # (bn, nc, ks[0], ks[1], L )
914
+ z_list = [z[:, :, :, :, i] for i in range(z.shape[-1])]
915
+
916
+ if self.cond_stage_key in ["image", "LR_image", "segmentation",
917
+ 'bbox_img'] and self.model.conditioning_key: # todo check for completeness
918
+ c_key = next(iter(cond.keys())) # get key
919
+ c = next(iter(cond.values())) # get value
920
+ assert (len(c) == 1) # todo extend to list with more than one elem
921
+ c = c[0] # get element
922
+
923
+ c = unfold(c)
924
+ c = c.view((c.shape[0], -1, ks[0], ks[1], c.shape[-1])) # (bn, nc, ks[0], ks[1], L )
925
+
926
+ cond_list = [{c_key: [c[:, :, :, :, i]]} for i in range(c.shape[-1])]
927
+
928
+ elif self.cond_stage_key == 'coordinates_bbox':
929
+ assert 'original_image_size' in self.split_input_params, 'BoudingBoxRescaling is missing original_image_size'
930
+
931
+ # assuming padding of unfold is always 0 and its dilation is always 1
932
+ n_patches_per_row = int((w - ks[0]) / stride[0] + 1)
933
+ full_img_h, full_img_w = self.split_input_params['original_image_size']
934
+ # as we are operating on latents, we need the factor from the original image size to the
935
+ # spatial latent size to properly rescale the crops for regenerating the bbox annotations
936
+ num_downs = self.first_stage_model.encoder.num_resolutions - 1
937
+ rescale_latent = 2 ** (num_downs)
938
+
939
+ # get top left postions of patches as conforming for the bbbox tokenizer, therefore we
940
+ # need to rescale the tl patch coordinates to be in between (0,1)
941
+ tl_patch_coordinates = [(rescale_latent * stride[0] * (patch_nr % n_patches_per_row) / full_img_w,
942
+ rescale_latent * stride[1] * (patch_nr // n_patches_per_row) / full_img_h)
943
+ for patch_nr in range(z.shape[-1])]
944
+
945
+ # patch_limits are tl_coord, width and height coordinates as (x_tl, y_tl, h, w)
946
+ patch_limits = [(x_tl, y_tl,
947
+ rescale_latent * ks[0] / full_img_w,
948
+ rescale_latent * ks[1] / full_img_h) for x_tl, y_tl in tl_patch_coordinates]
949
+ # patch_values = [(np.arange(x_tl,min(x_tl+ks, 1.)),np.arange(y_tl,min(y_tl+ks, 1.))) for x_tl, y_tl in tl_patch_coordinates]
950
+
951
+ # tokenize crop coordinates for the bounding boxes of the respective patches
952
+ patch_limits_tknzd = [torch.LongTensor(self.bbox_tokenizer._crop_encoder(bbox))[None].to(self.device)
953
+ for bbox in patch_limits] # list of length l with tensors of shape (1, 2)
954
+ print(patch_limits_tknzd[0].shape)
955
+ # cut tknzd crop position from conditioning
956
+ assert isinstance(cond, dict), 'cond must be dict to be fed into model'
957
+ cut_cond = cond['c_crossattn'][0][..., :-2].to(self.device)
958
+ print(cut_cond.shape)
959
+
960
+ adapted_cond = torch.stack([torch.cat([cut_cond, p], dim=1) for p in patch_limits_tknzd])
961
+ adapted_cond = rearrange(adapted_cond, 'l b n -> (l b) n')
962
+ print(adapted_cond.shape)
963
+ adapted_cond = self.get_learned_conditioning(adapted_cond)
964
+ print(adapted_cond.shape)
965
+ adapted_cond = rearrange(adapted_cond, '(l b) n d -> l b n d', l=z.shape[-1])
966
+ print(adapted_cond.shape)
967
+
968
+ cond_list = [{'c_crossattn': [e]} for e in adapted_cond]
969
+
970
+ else:
971
+ cond_list = [cond for i in range(z.shape[-1])] # Todo make this more efficient
972
+
973
+ # apply model by loop over crops
974
+ output_list = [self.model(z_list[i], t, **cond_list[i]) for i in range(z.shape[-1])]
975
+ assert not isinstance(output_list[0],
976
+ tuple) # todo cant deal with multiple model outputs check this never happens
977
+
978
+ o = torch.stack(output_list, axis=-1)
979
+ o = o * weighting
980
+ # Reverse reshape to img shape
981
+ o = o.view((o.shape[0], -1, o.shape[-1])) # (bn, nc * ks[0] * ks[1], L)
982
+ # stitch crops together
983
+ x_recon = fold(o) / normalization
984
+
985
+ else:
986
+ x_recon = self.model(x_noisy, t, **cond)
987
+
988
+ if isinstance(x_recon, tuple) and not return_ids:
989
+ return x_recon[0]
990
+ else:
991
+ return x_recon
992
+
993
+ def _predict_eps_from_xstart(self, x_t, t, pred_xstart):
994
+ return (extract_into_tensor(self.sqrt_recip_alphas_cumprod, t, x_t.shape) * x_t - pred_xstart) / \
995
+ extract_into_tensor(self.sqrt_recipm1_alphas_cumprod, t, x_t.shape)
996
+
997
+ def _prior_bpd(self, x_start):
998
+ """
999
+ Get the prior KL term for the variational lower-bound, measured in
1000
+ bits-per-dim.
1001
+ This term can't be optimized, as it only depends on the encoder.
1002
+ :param x_start: the [N x C x ...] tensor of inputs.
1003
+ :return: a batch of [N] KL values (in bits), one per batch element.
1004
+ """
1005
+ batch_size = x_start.shape[0]
1006
+ t = torch.tensor([self.num_timesteps - 1] * batch_size, device=x_start.device)
1007
+ qt_mean, _, qt_log_variance = self.q_mean_variance(x_start, t)
1008
+ kl_prior = normal_kl(mean1=qt_mean, logvar1=qt_log_variance, mean2=0.0, logvar2=0.0)
1009
+ return mean_flat(kl_prior) / np.log(2.0)
1010
+
1011
+ def p_losses(self, x_start, cond, t, noise=None):
1012
+ noise = default(noise, lambda: torch.randn_like(x_start))
1013
+ x_noisy = self.q_sample(x_start=x_start, t=t, noise=noise)
1014
+ model_output = self.apply_model(x_noisy, t, cond)
1015
+
1016
+ loss_dict = {}
1017
+ prefix = 'train' if self.training else 'val'
1018
+
1019
+ if self.parameterization == "x0":
1020
+ target = x_start
1021
+ elif self.parameterization == "eps":
1022
+ target = noise
1023
+ else:
1024
+ raise NotImplementedError()
1025
+
1026
+ loss_simple = self.get_loss(model_output, target, mean=False).mean([1, 2, 3])
1027
+ loss_dict.update({f'{prefix}/loss_simple': loss_simple.mean()})
1028
+
1029
+ logvar_t = self.logvar[t].to(self.device)
1030
+ loss = loss_simple / torch.exp(logvar_t) + logvar_t
1031
+ # loss = loss_simple / torch.exp(self.logvar) + self.logvar
1032
+ if self.learn_logvar:
1033
+ loss_dict.update({f'{prefix}/loss_gamma': loss.mean()})
1034
+ loss_dict.update({'logvar': self.logvar.data.mean()})
1035
+
1036
+ loss = self.l_simple_weight * loss.mean()
1037
+
1038
+ loss_vlb = self.get_loss(model_output, target, mean=False).mean(dim=(1, 2, 3))
1039
+ loss_vlb = (self.lvlb_weights[t] * loss_vlb).mean()
1040
+ loss_dict.update({f'{prefix}/loss_vlb': loss_vlb})
1041
+ loss += (self.original_elbo_weight * loss_vlb)
1042
+ loss_dict.update({f'{prefix}/loss': loss})
1043
+
1044
+ return loss, loss_dict
1045
+
1046
+ def p_mean_variance(self, x, c, t, clip_denoised: bool, return_codebook_ids=False, quantize_denoised=False,
1047
+ return_x0=False, score_corrector=None, corrector_kwargs=None):
1048
+ t_in = t
1049
+ model_out = self.apply_model(x, t_in, c, return_ids=return_codebook_ids)
1050
+
1051
+ if score_corrector is not None:
1052
+ assert self.parameterization == "eps"
1053
+ model_out = score_corrector.modify_score(self, model_out, x, t, c, **corrector_kwargs)
1054
+
1055
+ if return_codebook_ids:
1056
+ model_out, logits = model_out
1057
+
1058
+ if self.parameterization == "eps":
1059
+ x_recon = self.predict_start_from_noise(x, t=t, noise=model_out)
1060
+ elif self.parameterization == "x0":
1061
+ x_recon = model_out
1062
+ else:
1063
+ raise NotImplementedError()
1064
+
1065
+ if clip_denoised:
1066
+ x_recon.clamp_(-1., 1.)
1067
+ if quantize_denoised:
1068
+ x_recon, _, [_, _, indices] = self.first_stage_model.quantize(x_recon)
1069
+ model_mean, posterior_variance, posterior_log_variance = self.q_posterior(x_start=x_recon, x_t=x, t=t)
1070
+ if return_codebook_ids:
1071
+ return model_mean, posterior_variance, posterior_log_variance, logits
1072
+ elif return_x0:
1073
+ return model_mean, posterior_variance, posterior_log_variance, x_recon
1074
+ else:
1075
+ return model_mean, posterior_variance, posterior_log_variance
1076
+
1077
+ @torch.no_grad()
1078
+ def p_sample(self, x, c, t, clip_denoised=False, repeat_noise=False,
1079
+ return_codebook_ids=False, quantize_denoised=False, return_x0=False,
1080
+ temperature=1., noise_dropout=0., score_corrector=None, corrector_kwargs=None):
1081
+ b, *_, device = *x.shape, x.device
1082
+ outputs = self.p_mean_variance(x=x, c=c, t=t, clip_denoised=clip_denoised,
1083
+ return_codebook_ids=return_codebook_ids,
1084
+ quantize_denoised=quantize_denoised,
1085
+ return_x0=return_x0,
1086
+ score_corrector=score_corrector, corrector_kwargs=corrector_kwargs)
1087
+ if return_codebook_ids:
1088
+ raise DeprecationWarning("Support dropped.")
1089
+ model_mean, _, model_log_variance, logits = outputs
1090
+ elif return_x0:
1091
+ model_mean, _, model_log_variance, x0 = outputs
1092
+ else:
1093
+ model_mean, _, model_log_variance = outputs
1094
+
1095
+ noise = noise_like(x.shape, device, repeat_noise) * temperature
1096
+ if noise_dropout > 0.:
1097
+ noise = torch.nn.functional.dropout(noise, p=noise_dropout)
1098
+ # no noise when t == 0
1099
+ nonzero_mask = (1 - (t == 0).float()).reshape(b, *((1,) * (len(x.shape) - 1)))
1100
+
1101
+ if return_codebook_ids:
1102
+ return model_mean + nonzero_mask * (0.5 * model_log_variance).exp() * noise, logits.argmax(dim=1)
1103
+ if return_x0:
1104
+ return model_mean + nonzero_mask * (0.5 * model_log_variance).exp() * noise, x0
1105
+ else:
1106
+ return model_mean + nonzero_mask * (0.5 * model_log_variance).exp() * noise
1107
+
1108
+ @torch.no_grad()
1109
+ def progressive_denoising(self, cond, shape, verbose=True, callback=None, quantize_denoised=False,
1110
+ img_callback=None, mask=None, x0=None, temperature=1., noise_dropout=0.,
1111
+ score_corrector=None, corrector_kwargs=None, batch_size=None, x_T=None, start_T=None,
1112
+ log_every_t=None):
1113
+ if not log_every_t:
1114
+ log_every_t = self.log_every_t
1115
+ timesteps = self.num_timesteps
1116
+ if batch_size is not None:
1117
+ b = batch_size if batch_size is not None else shape[0]
1118
+ shape = [batch_size] + list(shape)
1119
+ else:
1120
+ b = batch_size = shape[0]
1121
+ if x_T is None:
1122
+ img = torch.randn(shape, device=self.device)
1123
+ else:
1124
+ img = x_T
1125
+ intermediates = []
1126
+ if cond is not None:
1127
+ if isinstance(cond, dict):
1128
+ cond = {key: cond[key][:batch_size] if not isinstance(cond[key], list) else
1129
+ list(map(lambda x: x[:batch_size], cond[key])) for key in cond}
1130
+ else:
1131
+ cond = [c[:batch_size] for c in cond] if isinstance(cond, list) else cond[:batch_size]
1132
+
1133
+ if start_T is not None:
1134
+ timesteps = min(timesteps, start_T)
1135
+ iterator = tqdm(reversed(range(0, timesteps)), desc='Progressive Generation',
1136
+ total=timesteps) if verbose else reversed(
1137
+ range(0, timesteps))
1138
+ if type(temperature) == float:
1139
+ temperature = [temperature] * timesteps
1140
+
1141
+ for i in iterator:
1142
+ ts = torch.full((b,), i, device=self.device, dtype=torch.long)
1143
+ if self.shorten_cond_schedule:
1144
+ assert self.model.conditioning_key != 'hybrid'
1145
+ tc = self.cond_ids[ts].to(cond.device)
1146
+ cond = self.q_sample(x_start=cond, t=tc, noise=torch.randn_like(cond))
1147
+
1148
+ img, x0_partial = self.p_sample(img, cond, ts,
1149
+ clip_denoised=self.clip_denoised,
1150
+ quantize_denoised=quantize_denoised, return_x0=True,
1151
+ temperature=temperature[i], noise_dropout=noise_dropout,
1152
+ score_corrector=score_corrector, corrector_kwargs=corrector_kwargs)
1153
+ if mask is not None:
1154
+ assert x0 is not None
1155
+ img_orig = self.q_sample(x0, ts)
1156
+ img = img_orig * mask + (1. - mask) * img
1157
+
1158
+ if i % log_every_t == 0 or i == timesteps - 1:
1159
+ intermediates.append(x0_partial)
1160
+ if callback: callback(i)
1161
+ if img_callback: img_callback(img, i)
1162
+ return img, intermediates
1163
+
1164
+ @torch.no_grad()
1165
+ def p_sample_loop(self, cond, shape, return_intermediates=False,
1166
+ x_T=None, verbose=True, callback=None, timesteps=None, quantize_denoised=False,
1167
+ mask=None, x0=None, img_callback=None, start_T=None,
1168
+ log_every_t=None):
1169
+
1170
+ if not log_every_t:
1171
+ log_every_t = self.log_every_t
1172
+ device = self.betas.device
1173
+ b = shape[0]
1174
+ if x_T is None:
1175
+ img = torch.randn(shape, device=device)
1176
+ else:
1177
+ img = x_T
1178
+
1179
+ intermediates = [img]
1180
+ if timesteps is None:
1181
+ timesteps = self.num_timesteps
1182
+
1183
+ if start_T is not None:
1184
+ timesteps = min(timesteps, start_T)
1185
+ iterator = tqdm(reversed(range(0, timesteps)), desc='Sampling t', total=timesteps) if verbose else reversed(
1186
+ range(0, timesteps))
1187
+
1188
+ if mask is not None:
1189
+ assert x0 is not None
1190
+ assert x0.shape[2:3] == mask.shape[2:3] # spatial size has to match
1191
+
1192
+ for i in iterator:
1193
+ ts = torch.full((b,), i, device=device, dtype=torch.long)
1194
+ if self.shorten_cond_schedule:
1195
+ assert self.model.conditioning_key != 'hybrid'
1196
+ tc = self.cond_ids[ts].to(cond.device)
1197
+ cond = self.q_sample(x_start=cond, t=tc, noise=torch.randn_like(cond))
1198
+
1199
+ img = self.p_sample(img, cond, ts,
1200
+ clip_denoised=self.clip_denoised,
1201
+ quantize_denoised=quantize_denoised)
1202
+ if mask is not None:
1203
+ img_orig = self.q_sample(x0, ts)
1204
+ img = img_orig * mask + (1. - mask) * img
1205
+
1206
+ if i % log_every_t == 0 or i == timesteps - 1:
1207
+ intermediates.append(img)
1208
+ if callback: callback(i)
1209
+ if img_callback: img_callback(img, i)
1210
+
1211
+ if return_intermediates:
1212
+ return img, intermediates
1213
+ return img
1214
+
1215
+ @torch.no_grad()
1216
+ def sample(self, cond, batch_size=16, return_intermediates=False, x_T=None,
1217
+ verbose=True, timesteps=None, quantize_denoised=False,
1218
+ mask=None, x0=None, shape=None,**kwargs):
1219
+ if shape is None:
1220
+ shape = (batch_size, self.channels, self.image_size, self.image_size)
1221
+ if cond is not None:
1222
+ if isinstance(cond, dict):
1223
+ cond = {key: cond[key][:batch_size] if not isinstance(cond[key], list) else
1224
+ list(map(lambda x: x[:batch_size], cond[key])) for key in cond}
1225
+ else:
1226
+ cond = [c[:batch_size] for c in cond] if isinstance(cond, list) else cond[:batch_size]
1227
+ return self.p_sample_loop(cond,
1228
+ shape,
1229
+ return_intermediates=return_intermediates, x_T=x_T,
1230
+ verbose=verbose, timesteps=timesteps, quantize_denoised=quantize_denoised,
1231
+ mask=mask, x0=x0)
1232
+
1233
+ @torch.no_grad()
1234
+ def sample_log(self,cond,batch_size,ddim, ddim_steps,**kwargs):
1235
+
1236
+ if ddim:
1237
+ ddim_sampler = DDIMSampler(self)
1238
+ shape = (self.channels, self.image_size, self.image_size)
1239
+ samples, intermediates =ddim_sampler.sample(ddim_steps,batch_size,
1240
+ shape,cond,verbose=False,**kwargs)
1241
+
1242
+ else:
1243
+ samples, intermediates = self.sample(cond=cond, batch_size=batch_size,
1244
+ return_intermediates=True,**kwargs)
1245
+
1246
+ return samples, intermediates
1247
+
1248
+
1249
+ @torch.no_grad()
1250
+ def log_images(self, batch, N=8, n_row=4, sample=True, ddim_steps=200, ddim_eta=1., return_keys=None,
1251
+ quantize_denoised=True, inpaint=True, plot_denoise_rows=False, plot_progressive_rows=True,
1252
+ plot_diffusion_rows=True, **kwargs):
1253
+
1254
+ use_ddim = ddim_steps is not None
1255
+
1256
+ log = dict()
1257
+ z, c, x, xrec, xc = self.get_input(batch, self.first_stage_key,
1258
+ return_first_stage_outputs=True,
1259
+ force_c_encode=True,
1260
+ return_original_cond=True,
1261
+ bs=N)
1262
+ N = min(x.shape[0], N)
1263
+ n_row = min(x.shape[0], n_row)
1264
+ log["inputs"] = x
1265
+ log["reconstruction"] = xrec
1266
+ if self.model.conditioning_key is not None:
1267
+ if hasattr(self.cond_stage_model, "decode"):
1268
+ xc = self.cond_stage_model.decode(c)
1269
+ log["conditioning"] = xc
1270
+ elif self.cond_stage_key in ["caption"]:
1271
+ xc = log_txt_as_img((x.shape[2], x.shape[3]), batch["caption"])
1272
+ log["conditioning"] = xc
1273
+ elif self.cond_stage_key == 'class_label':
1274
+ xc = log_txt_as_img((x.shape[2], x.shape[3]), batch["human_label"])
1275
+ log['conditioning'] = xc
1276
+ elif isimage(xc):
1277
+ log["conditioning"] = xc
1278
+ if ismap(xc):
1279
+ log["original_conditioning"] = self.to_rgb(xc)
1280
+
1281
+ if plot_diffusion_rows:
1282
+ # get diffusion row
1283
+ diffusion_row = list()
1284
+ z_start = z[:n_row]
1285
+ for t in range(self.num_timesteps):
1286
+ if t % self.log_every_t == 0 or t == self.num_timesteps - 1:
1287
+ t = repeat(torch.tensor([t]), '1 -> b', b=n_row)
1288
+ t = t.to(self.device).long()
1289
+ noise = torch.randn_like(z_start)
1290
+ z_noisy = self.q_sample(x_start=z_start, t=t, noise=noise)
1291
+ diffusion_row.append(self.decode_first_stage(z_noisy))
1292
+
1293
+ diffusion_row = torch.stack(diffusion_row) # n_log_step, n_row, C, H, W
1294
+ diffusion_grid = rearrange(diffusion_row, 'n b c h w -> b n c h w')
1295
+ diffusion_grid = rearrange(diffusion_grid, 'b n c h w -> (b n) c h w')
1296
+ diffusion_grid = make_grid(diffusion_grid, nrow=diffusion_row.shape[0])
1297
+ log["diffusion_row"] = diffusion_grid
1298
+
1299
+ if sample:
1300
+ # get denoise row
1301
+ with self.ema_scope("Plotting"):
1302
+ samples, z_denoise_row = self.sample_log(cond=c,batch_size=N,ddim=use_ddim,
1303
+ ddim_steps=ddim_steps,eta=ddim_eta)
1304
+ # samples, z_denoise_row = self.sample(cond=c, batch_size=N, return_intermediates=True)
1305
+ x_samples = self.decode_first_stage(samples)
1306
+ log["samples"] = x_samples
1307
+ if plot_denoise_rows:
1308
+ denoise_grid = self._get_denoise_row_from_list(z_denoise_row)
1309
+ log["denoise_row"] = denoise_grid
1310
+
1311
+ if quantize_denoised and not isinstance(self.first_stage_model, AutoencoderKL) and not isinstance(
1312
+ self.first_stage_model, IdentityFirstStage):
1313
+ # also display when quantizing x0 while sampling
1314
+ with self.ema_scope("Plotting Quantized Denoised"):
1315
+ samples, z_denoise_row = self.sample_log(cond=c,batch_size=N,ddim=use_ddim,
1316
+ ddim_steps=ddim_steps,eta=ddim_eta,
1317
+ quantize_denoised=True)
1318
+ # samples, z_denoise_row = self.sample(cond=c, batch_size=N, return_intermediates=True,
1319
+ # quantize_denoised=True)
1320
+ x_samples = self.decode_first_stage(samples.to(self.device))
1321
+ log["samples_x0_quantized"] = x_samples
1322
+
1323
+ if inpaint:
1324
+ # make a simple center square
1325
+ b, h, w = z.shape[0], z.shape[2], z.shape[3]
1326
+ mask = torch.ones(N, h, w).to(self.device)
1327
+ # zeros will be filled in
1328
+ mask[:, h // 4:3 * h // 4, w // 4:3 * w // 4] = 0.
1329
+ mask = mask[:, None, ...]
1330
+ with self.ema_scope("Plotting Inpaint"):
1331
+
1332
+ samples, _ = self.sample_log(cond=c,batch_size=N,ddim=use_ddim, eta=ddim_eta,
1333
+ ddim_steps=ddim_steps, x0=z[:N], mask=mask)
1334
+ x_samples = self.decode_first_stage(samples.to(self.device))
1335
+ log["samples_inpainting"] = x_samples
1336
+ log["mask"] = mask
1337
+
1338
+ # outpaint
1339
+ with self.ema_scope("Plotting Outpaint"):
1340
+ samples, _ = self.sample_log(cond=c, batch_size=N, ddim=use_ddim,eta=ddim_eta,
1341
+ ddim_steps=ddim_steps, x0=z[:N], mask=mask)
1342
+ x_samples = self.decode_first_stage(samples.to(self.device))
1343
+ log["samples_outpainting"] = x_samples
1344
+
1345
+ if plot_progressive_rows:
1346
+ with self.ema_scope("Plotting Progressives"):
1347
+ img, progressives = self.progressive_denoising(c,
1348
+ shape=(self.channels, self.image_size, self.image_size),
1349
+ batch_size=N)
1350
+ prog_row = self._get_denoise_row_from_list(progressives, desc="Progressive Generation")
1351
+ log["progressive_row"] = prog_row
1352
+
1353
+ if return_keys:
1354
+ if np.intersect1d(list(log.keys()), return_keys).shape[0] == 0:
1355
+ return log
1356
+ else:
1357
+ return {key: log[key] for key in return_keys}
1358
+ return log
1359
+
1360
+ def configure_optimizers(self):
1361
+ lr = self.learning_rate
1362
+ params = list(self.model.parameters())
1363
+ if self.cond_stage_trainable:
1364
+ print(f"{self.__class__.__name__}: Also optimizing conditioner params!")
1365
+ params = params + list(self.cond_stage_model.parameters())
1366
+ if self.learn_logvar:
1367
+ print('Diffusion model optimizing logvar')
1368
+ params.append(self.logvar)
1369
+ opt = torch.optim.AdamW(params, lr=lr)
1370
+ if self.use_scheduler:
1371
+ assert 'target' in self.scheduler_config
1372
+ scheduler = instantiate_from_config(self.scheduler_config)
1373
+
1374
+ print("Setting up LambdaLR scheduler...")
1375
+ scheduler = [
1376
+ {
1377
+ 'scheduler': LambdaLR(opt, lr_lambda=scheduler.schedule),
1378
+ 'interval': 'step',
1379
+ 'frequency': 1
1380
+ }]
1381
+ return [opt], scheduler
1382
+ return opt
1383
+
1384
+ @torch.no_grad()
1385
+ def to_rgb(self, x):
1386
+ x = x.float()
1387
+ if not hasattr(self, "colorize"):
1388
+ self.colorize = torch.randn(3, x.shape[1], 1, 1).to(x)
1389
+ x = nn.functional.conv2d(x, weight=self.colorize)
1390
+ x = 2. * (x - x.min()) / (x.max() - x.min()) - 1.
1391
+ return x
1392
+
1393
+
1394
+ class DiffusionWrapperV1(pl.LightningModule):
1395
+ def __init__(self, diff_model_config, conditioning_key):
1396
+ super().__init__()
1397
+ self.diffusion_model = instantiate_from_config(diff_model_config)
1398
+ self.conditioning_key = conditioning_key
1399
+ assert self.conditioning_key in [None, 'concat', 'crossattn', 'hybrid', 'adm']
1400
+
1401
+ def forward(self, x, t, c_concat: list = None, c_crossattn: list = None):
1402
+ if self.conditioning_key is None:
1403
+ out = self.diffusion_model(x, t)
1404
+ elif self.conditioning_key == 'concat':
1405
+ xc = torch.cat([x] + c_concat, dim=1)
1406
+ out = self.diffusion_model(xc, t)
1407
+ elif self.conditioning_key == 'crossattn':
1408
+ cc = torch.cat(c_crossattn, 1)
1409
+ out = self.diffusion_model(x, t, context=cc)
1410
+ elif self.conditioning_key == 'hybrid':
1411
+ xc = torch.cat([x] + c_concat, dim=1)
1412
+ cc = torch.cat(c_crossattn, 1)
1413
+ out = self.diffusion_model(xc, t, context=cc)
1414
+ elif self.conditioning_key == 'adm':
1415
+ cc = c_crossattn[0]
1416
+ out = self.diffusion_model(x, t, y=cc)
1417
+ else:
1418
+ raise NotImplementedError()
1419
+
1420
+ return out
1421
+
1422
+
1423
+ class Layout2ImgDiffusionV1(LatentDiffusionV1):
1424
+ # TODO: move all layout-specific hacks to this class
1425
+ def __init__(self, cond_stage_key, *args, **kwargs):
1426
+ assert cond_stage_key == 'coordinates_bbox', 'Layout2ImgDiffusion only for cond_stage_key="coordinates_bbox"'
1427
+ super().__init__(cond_stage_key=cond_stage_key, *args, **kwargs)
1428
+
1429
+ def log_images(self, batch, N=8, *args, **kwargs):
1430
+ logs = super().log_images(batch=batch, N=N, *args, **kwargs)
1431
+
1432
+ key = 'train' if self.training else 'validation'
1433
+ dset = self.trainer.datamodule.datasets[key]
1434
+ mapper = dset.conditional_builders[self.cond_stage_key]
1435
+
1436
+ bbox_imgs = []
1437
+ map_fn = lambda catno: dset.get_textual_label(dset.get_category_id(catno))
1438
+ for tknzd_bbox in batch[self.cond_stage_key][:N]:
1439
+ bboximg = mapper.plot(tknzd_bbox.detach().cpu(), map_fn, (256, 256))
1440
+ bbox_imgs.append(bboximg)
1441
+
1442
+ cond_img = torch.stack(bbox_imgs, dim=0)
1443
+ logs['bbox_image'] = cond_img
1444
+ return logs
1445
+
1446
+ setattr(ldm.models.diffusion.ddpm, "DDPMV1", DDPMV1)
1447
+ setattr(ldm.models.diffusion.ddpm, "LatentDiffusionV1", LatentDiffusionV1)
1448
+ setattr(ldm.models.diffusion.ddpm, "DiffusionWrapperV1", DiffusionWrapperV1)
1449
+ setattr(ldm.models.diffusion.ddpm, "Layout2ImgDiffusionV1", Layout2ImgDiffusionV1)
extensions-builtin/Lora/extra_networks_lora.py ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from modules import extra_networks, shared
2
+ import lora
3
+
4
+ class ExtraNetworkLora(extra_networks.ExtraNetwork):
5
+ def __init__(self):
6
+ super().__init__('lora')
7
+
8
+ def activate(self, p, params_list):
9
+ additional = shared.opts.sd_lora
10
+
11
+ if additional != "" and additional in lora.available_loras and len([x for x in params_list if x.items[0] == additional]) == 0:
12
+ p.all_prompts = [x + f"<lora:{additional}:{shared.opts.extra_networks_default_multiplier}>" for x in p.all_prompts]
13
+ params_list.append(extra_networks.ExtraNetworkParams(items=[additional, shared.opts.extra_networks_default_multiplier]))
14
+
15
+ names = []
16
+ multipliers = []
17
+ for params in params_list:
18
+ assert len(params.items) > 0
19
+
20
+ names.append(params.items[0])
21
+ multipliers.append(float(params.items[1]) if len(params.items) > 1 else 1.0)
22
+
23
+ lora.load_loras(names, multipliers)
24
+
25
+ def deactivate(self, p):
26
+ pass
extensions-builtin/Lora/lora.py ADDED
@@ -0,0 +1,207 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import glob
2
+ import os
3
+ import re
4
+ import torch
5
+
6
+ from modules import shared, devices, sd_models
7
+
8
+ re_digits = re.compile(r"\d+")
9
+ re_unet_down_blocks = re.compile(r"lora_unet_down_blocks_(\d+)_attentions_(\d+)_(.+)")
10
+ re_unet_mid_blocks = re.compile(r"lora_unet_mid_block_attentions_(\d+)_(.+)")
11
+ re_unet_up_blocks = re.compile(r"lora_unet_up_blocks_(\d+)_attentions_(\d+)_(.+)")
12
+ re_text_block = re.compile(r"lora_te_text_model_encoder_layers_(\d+)_(.+)")
13
+
14
+
15
+ def convert_diffusers_name_to_compvis(key):
16
+ def match(match_list, regex):
17
+ r = re.match(regex, key)
18
+ if not r:
19
+ return False
20
+
21
+ match_list.clear()
22
+ match_list.extend([int(x) if re.match(re_digits, x) else x for x in r.groups()])
23
+ return True
24
+
25
+ m = []
26
+
27
+ if match(m, re_unet_down_blocks):
28
+ return f"diffusion_model_input_blocks_{1 + m[0] * 3 + m[1]}_1_{m[2]}"
29
+
30
+ if match(m, re_unet_mid_blocks):
31
+ return f"diffusion_model_middle_block_1_{m[1]}"
32
+
33
+ if match(m, re_unet_up_blocks):
34
+ return f"diffusion_model_output_blocks_{m[0] * 3 + m[1]}_1_{m[2]}"
35
+
36
+ if match(m, re_text_block):
37
+ return f"transformer_text_model_encoder_layers_{m[0]}_{m[1]}"
38
+
39
+ return key
40
+
41
+
42
+ class LoraOnDisk:
43
+ def __init__(self, name, filename):
44
+ self.name = name
45
+ self.filename = filename
46
+
47
+
48
+ class LoraModule:
49
+ def __init__(self, name):
50
+ self.name = name
51
+ self.multiplier = 1.0
52
+ self.modules = {}
53
+ self.mtime = None
54
+
55
+
56
+ class LoraUpDownModule:
57
+ def __init__(self):
58
+ self.up = None
59
+ self.down = None
60
+ self.alpha = None
61
+
62
+
63
+ def assign_lora_names_to_compvis_modules(sd_model):
64
+ lora_layer_mapping = {}
65
+
66
+ for name, module in shared.sd_model.cond_stage_model.wrapped.named_modules():
67
+ lora_name = name.replace(".", "_")
68
+ lora_layer_mapping[lora_name] = module
69
+ module.lora_layer_name = lora_name
70
+
71
+ for name, module in shared.sd_model.model.named_modules():
72
+ lora_name = name.replace(".", "_")
73
+ lora_layer_mapping[lora_name] = module
74
+ module.lora_layer_name = lora_name
75
+
76
+ sd_model.lora_layer_mapping = lora_layer_mapping
77
+
78
+
79
+ def load_lora(name, filename):
80
+ lora = LoraModule(name)
81
+ lora.mtime = os.path.getmtime(filename)
82
+
83
+ sd = sd_models.read_state_dict(filename)
84
+
85
+ keys_failed_to_match = []
86
+
87
+ for key_diffusers, weight in sd.items():
88
+ fullkey = convert_diffusers_name_to_compvis(key_diffusers)
89
+ key, lora_key = fullkey.split(".", 1)
90
+
91
+ sd_module = shared.sd_model.lora_layer_mapping.get(key, None)
92
+ if sd_module is None:
93
+ keys_failed_to_match.append(key_diffusers)
94
+ continue
95
+
96
+ lora_module = lora.modules.get(key, None)
97
+ if lora_module is None:
98
+ lora_module = LoraUpDownModule()
99
+ lora.modules[key] = lora_module
100
+
101
+ if lora_key == "alpha":
102
+ lora_module.alpha = weight.item()
103
+ continue
104
+
105
+ if type(sd_module) == torch.nn.Linear:
106
+ module = torch.nn.Linear(weight.shape[1], weight.shape[0], bias=False)
107
+ elif type(sd_module) == torch.nn.Conv2d:
108
+ module = torch.nn.Conv2d(weight.shape[1], weight.shape[0], (1, 1), bias=False)
109
+ else:
110
+ assert False, f'Lora layer {key_diffusers} matched a layer with unsupported type: {type(sd_module).__name__}'
111
+
112
+ with torch.no_grad():
113
+ module.weight.copy_(weight)
114
+
115
+ module.to(device=devices.device, dtype=devices.dtype)
116
+
117
+ if lora_key == "lora_up.weight":
118
+ lora_module.up = module
119
+ elif lora_key == "lora_down.weight":
120
+ lora_module.down = module
121
+ else:
122
+ assert False, f'Bad Lora layer name: {key_diffusers} - must end in lora_up.weight, lora_down.weight or alpha'
123
+
124
+ if len(keys_failed_to_match) > 0:
125
+ print(f"Failed to match keys when loading Lora {filename}: {keys_failed_to_match}")
126
+
127
+ return lora
128
+
129
+
130
+ def load_loras(names, multipliers=None):
131
+ already_loaded = {}
132
+
133
+ for lora in loaded_loras:
134
+ if lora.name in names:
135
+ already_loaded[lora.name] = lora
136
+
137
+ loaded_loras.clear()
138
+
139
+ loras_on_disk = [available_loras.get(name, None) for name in names]
140
+ if any([x is None for x in loras_on_disk]):
141
+ list_available_loras()
142
+
143
+ loras_on_disk = [available_loras.get(name, None) for name in names]
144
+
145
+ for i, name in enumerate(names):
146
+ lora = already_loaded.get(name, None)
147
+
148
+ lora_on_disk = loras_on_disk[i]
149
+ if lora_on_disk is not None:
150
+ if lora is None or os.path.getmtime(lora_on_disk.filename) > lora.mtime:
151
+ lora = load_lora(name, lora_on_disk.filename)
152
+
153
+ if lora is None:
154
+ print(f"Couldn't find Lora with name {name}")
155
+ continue
156
+
157
+ lora.multiplier = multipliers[i] if multipliers else 1.0
158
+ loaded_loras.append(lora)
159
+
160
+
161
+ def lora_forward(module, input, res):
162
+ if len(loaded_loras) == 0:
163
+ return res
164
+
165
+ lora_layer_name = getattr(module, 'lora_layer_name', None)
166
+ for lora in loaded_loras:
167
+ module = lora.modules.get(lora_layer_name, None)
168
+ if module is not None:
169
+ if shared.opts.lora_apply_to_outputs and res.shape == input.shape:
170
+ res = res + module.up(module.down(res)) * lora.multiplier * (module.alpha / module.up.weight.shape[1] if module.alpha else 1.0)
171
+ else:
172
+ res = res + module.up(module.down(input)) * lora.multiplier * (module.alpha / module.up.weight.shape[1] if module.alpha else 1.0)
173
+
174
+ return res
175
+
176
+
177
+ def lora_Linear_forward(self, input):
178
+ return lora_forward(self, input, torch.nn.Linear_forward_before_lora(self, input))
179
+
180
+
181
+ def lora_Conv2d_forward(self, input):
182
+ return lora_forward(self, input, torch.nn.Conv2d_forward_before_lora(self, input))
183
+
184
+
185
+ def list_available_loras():
186
+ available_loras.clear()
187
+
188
+ os.makedirs(shared.cmd_opts.lora_dir, exist_ok=True)
189
+
190
+ candidates = \
191
+ glob.glob(os.path.join(shared.cmd_opts.lora_dir, '**/*.pt'), recursive=True) + \
192
+ glob.glob(os.path.join(shared.cmd_opts.lora_dir, '**/*.safetensors'), recursive=True) + \
193
+ glob.glob(os.path.join(shared.cmd_opts.lora_dir, '**/*.ckpt'), recursive=True)
194
+
195
+ for filename in sorted(candidates):
196
+ if os.path.isdir(filename):
197
+ continue
198
+
199
+ name = os.path.splitext(os.path.basename(filename))[0]
200
+
201
+ available_loras[name] = LoraOnDisk(name, filename)
202
+
203
+
204
+ available_loras = {}
205
+ loaded_loras = []
206
+
207
+ list_available_loras()
extensions-builtin/Lora/preload.py ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ import os
2
+ from modules import paths
3
+
4
+
5
+ def preload(parser):
6
+ parser.add_argument("--lora-dir", type=str, help="Path to directory with Lora networks.", default=os.path.join(paths.models_path, 'Lora'))
extensions-builtin/Lora/scripts/lora_script.py ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ import gradio as gr
3
+
4
+ import lora
5
+ import extra_networks_lora
6
+ import ui_extra_networks_lora
7
+ from modules import script_callbacks, ui_extra_networks, extra_networks, shared
8
+
9
+
10
+ def unload():
11
+ torch.nn.Linear.forward = torch.nn.Linear_forward_before_lora
12
+ torch.nn.Conv2d.forward = torch.nn.Conv2d_forward_before_lora
13
+
14
+
15
+ def before_ui():
16
+ ui_extra_networks.register_page(ui_extra_networks_lora.ExtraNetworksPageLora())
17
+ extra_networks.register_extra_network(extra_networks_lora.ExtraNetworkLora())
18
+
19
+
20
+ if not hasattr(torch.nn, 'Linear_forward_before_lora'):
21
+ torch.nn.Linear_forward_before_lora = torch.nn.Linear.forward
22
+
23
+ if not hasattr(torch.nn, 'Conv2d_forward_before_lora'):
24
+ torch.nn.Conv2d_forward_before_lora = torch.nn.Conv2d.forward
25
+
26
+ torch.nn.Linear.forward = lora.lora_Linear_forward
27
+ torch.nn.Conv2d.forward = lora.lora_Conv2d_forward
28
+
29
+ script_callbacks.on_model_loaded(lora.assign_lora_names_to_compvis_modules)
30
+ script_callbacks.on_script_unloaded(unload)
31
+ script_callbacks.on_before_ui(before_ui)
32
+
33
+
34
+ shared.options_templates.update(shared.options_section(('extra_networks', "Extra Networks"), {
35
+ "sd_lora": shared.OptionInfo("None", "Add Lora to prompt", gr.Dropdown, lambda: {"choices": [""] + [x for x in lora.available_loras]}, refresh=lora.list_available_loras),
36
+ "lora_apply_to_outputs": shared.OptionInfo(False, "Apply Lora to outputs rather than inputs when possible (experimental)"),
37
+
38
+ }))
extensions-builtin/Lora/ui_extra_networks_lora.py ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json
2
+ import os
3
+ import lora
4
+
5
+ from modules import shared, ui_extra_networks
6
+
7
+
8
+ class ExtraNetworksPageLora(ui_extra_networks.ExtraNetworksPage):
9
+ def __init__(self):
10
+ super().__init__('Lora')
11
+
12
+ def refresh(self):
13
+ lora.list_available_loras()
14
+
15
+ def list_items(self):
16
+ for name, lora_on_disk in lora.available_loras.items():
17
+ path, ext = os.path.splitext(lora_on_disk.filename)
18
+ previews = [path + ".png", path + ".preview.png"]
19
+
20
+ preview = None
21
+ for file in previews:
22
+ if os.path.isfile(file):
23
+ preview = self.link_preview(file)
24
+ break
25
+
26
+ yield {
27
+ "name": name,
28
+ "filename": path,
29
+ "preview": preview,
30
+ "search_term": self.search_terms_from_path(lora_on_disk.filename),
31
+ "prompt": json.dumps(f"<lora:{name}:") + " + opts.extra_networks_default_multiplier + " + json.dumps(">"),
32
+ "local_preview": path + ".png",
33
+ }
34
+
35
+ def allowed_directories_for_previews(self):
36
+ return [shared.cmd_opts.lora_dir]
37
+
extensions-builtin/ScuNET/preload.py ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ import os
2
+ from modules import paths
3
+
4
+
5
+ def preload(parser):
6
+ parser.add_argument("--scunet-models-path", type=str, help="Path to directory with ScuNET model file(s).", default=os.path.join(paths.models_path, 'ScuNET'))
extensions-builtin/ScuNET/scripts/scunet_model.py ADDED
@@ -0,0 +1,87 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os.path
2
+ import sys
3
+ import traceback
4
+
5
+ import PIL.Image
6
+ import numpy as np
7
+ import torch
8
+ from basicsr.utils.download_util import load_file_from_url
9
+
10
+ import modules.upscaler
11
+ from modules import devices, modelloader
12
+ from scunet_model_arch import SCUNet as net
13
+
14
+
15
+ class UpscalerScuNET(modules.upscaler.Upscaler):
16
+ def __init__(self, dirname):
17
+ self.name = "ScuNET"
18
+ self.model_name = "ScuNET GAN"
19
+ self.model_name2 = "ScuNET PSNR"
20
+ self.model_url = "https://github.com/cszn/KAIR/releases/download/v1.0/scunet_color_real_gan.pth"
21
+ self.model_url2 = "https://github.com/cszn/KAIR/releases/download/v1.0/scunet_color_real_psnr.pth"
22
+ self.user_path = dirname
23
+ super().__init__()
24
+ model_paths = self.find_models(ext_filter=[".pth"])
25
+ scalers = []
26
+ add_model2 = True
27
+ for file in model_paths:
28
+ if "http" in file:
29
+ name = self.model_name
30
+ else:
31
+ name = modelloader.friendly_name(file)
32
+ if name == self.model_name2 or file == self.model_url2:
33
+ add_model2 = False
34
+ try:
35
+ scaler_data = modules.upscaler.UpscalerData(name, file, self, 4)
36
+ scalers.append(scaler_data)
37
+ except Exception:
38
+ print(f"Error loading ScuNET model: {file}", file=sys.stderr)
39
+ print(traceback.format_exc(), file=sys.stderr)
40
+ if add_model2:
41
+ scaler_data2 = modules.upscaler.UpscalerData(self.model_name2, self.model_url2, self)
42
+ scalers.append(scaler_data2)
43
+ self.scalers = scalers
44
+
45
+ def do_upscale(self, img: PIL.Image, selected_file):
46
+ torch.cuda.empty_cache()
47
+
48
+ model = self.load_model(selected_file)
49
+ if model is None:
50
+ return img
51
+
52
+ device = devices.get_device_for('scunet')
53
+ img = np.array(img)
54
+ img = img[:, :, ::-1]
55
+ img = np.moveaxis(img, 2, 0) / 255
56
+ img = torch.from_numpy(img).float()
57
+ img = img.unsqueeze(0).to(device)
58
+
59
+ with torch.no_grad():
60
+ output = model(img)
61
+ output = output.squeeze().float().cpu().clamp_(0, 1).numpy()
62
+ output = 255. * np.moveaxis(output, 0, 2)
63
+ output = output.astype(np.uint8)
64
+ output = output[:, :, ::-1]
65
+ torch.cuda.empty_cache()
66
+ return PIL.Image.fromarray(output, 'RGB')
67
+
68
+ def load_model(self, path: str):
69
+ device = devices.get_device_for('scunet')
70
+ if "http" in path:
71
+ filename = load_file_from_url(url=self.model_url, model_dir=self.model_path, file_name="%s.pth" % self.name,
72
+ progress=True)
73
+ else:
74
+ filename = path
75
+ if not os.path.exists(os.path.join(self.model_path, filename)) or filename is None:
76
+ print(f"ScuNET: Unable to load model from {filename}", file=sys.stderr)
77
+ return None
78
+
79
+ model = net(in_nc=3, config=[4, 4, 4, 4, 4, 4, 4], dim=64)
80
+ model.load_state_dict(torch.load(filename), strict=True)
81
+ model.eval()
82
+ for k, v in model.named_parameters():
83
+ v.requires_grad = False
84
+ model = model.to(device)
85
+
86
+ return model
87
+
extensions-builtin/ScuNET/scunet_model_arch.py ADDED
@@ -0,0 +1,265 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ import numpy as np
3
+ import torch
4
+ import torch.nn as nn
5
+ from einops import rearrange
6
+ from einops.layers.torch import Rearrange
7
+ from timm.models.layers import trunc_normal_, DropPath
8
+
9
+
10
+ class WMSA(nn.Module):
11
+ """ Self-attention module in Swin Transformer
12
+ """
13
+
14
+ def __init__(self, input_dim, output_dim, head_dim, window_size, type):
15
+ super(WMSA, self).__init__()
16
+ self.input_dim = input_dim
17
+ self.output_dim = output_dim
18
+ self.head_dim = head_dim
19
+ self.scale = self.head_dim ** -0.5
20
+ self.n_heads = input_dim // head_dim
21
+ self.window_size = window_size
22
+ self.type = type
23
+ self.embedding_layer = nn.Linear(self.input_dim, 3 * self.input_dim, bias=True)
24
+
25
+ self.relative_position_params = nn.Parameter(
26
+ torch.zeros((2 * window_size - 1) * (2 * window_size - 1), self.n_heads))
27
+
28
+ self.linear = nn.Linear(self.input_dim, self.output_dim)
29
+
30
+ trunc_normal_(self.relative_position_params, std=.02)
31
+ self.relative_position_params = torch.nn.Parameter(
32
+ self.relative_position_params.view(2 * window_size - 1, 2 * window_size - 1, self.n_heads).transpose(1,
33
+ 2).transpose(
34
+ 0, 1))
35
+
36
+ def generate_mask(self, h, w, p, shift):
37
+ """ generating the mask of SW-MSA
38
+ Args:
39
+ shift: shift parameters in CyclicShift.
40
+ Returns:
41
+ attn_mask: should be (1 1 w p p),
42
+ """
43
+ # supporting square.
44
+ attn_mask = torch.zeros(h, w, p, p, p, p, dtype=torch.bool, device=self.relative_position_params.device)
45
+ if self.type == 'W':
46
+ return attn_mask
47
+
48
+ s = p - shift
49
+ attn_mask[-1, :, :s, :, s:, :] = True
50
+ attn_mask[-1, :, s:, :, :s, :] = True
51
+ attn_mask[:, -1, :, :s, :, s:] = True
52
+ attn_mask[:, -1, :, s:, :, :s] = True
53
+ attn_mask = rearrange(attn_mask, 'w1 w2 p1 p2 p3 p4 -> 1 1 (w1 w2) (p1 p2) (p3 p4)')
54
+ return attn_mask
55
+
56
+ def forward(self, x):
57
+ """ Forward pass of Window Multi-head Self-attention module.
58
+ Args:
59
+ x: input tensor with shape of [b h w c];
60
+ attn_mask: attention mask, fill -inf where the value is True;
61
+ Returns:
62
+ output: tensor shape [b h w c]
63
+ """
64
+ if self.type != 'W': x = torch.roll(x, shifts=(-(self.window_size // 2), -(self.window_size // 2)), dims=(1, 2))
65
+ x = rearrange(x, 'b (w1 p1) (w2 p2) c -> b w1 w2 p1 p2 c', p1=self.window_size, p2=self.window_size)
66
+ h_windows = x.size(1)
67
+ w_windows = x.size(2)
68
+ # square validation
69
+ # assert h_windows == w_windows
70
+
71
+ x = rearrange(x, 'b w1 w2 p1 p2 c -> b (w1 w2) (p1 p2) c', p1=self.window_size, p2=self.window_size)
72
+ qkv = self.embedding_layer(x)
73
+ q, k, v = rearrange(qkv, 'b nw np (threeh c) -> threeh b nw np c', c=self.head_dim).chunk(3, dim=0)
74
+ sim = torch.einsum('hbwpc,hbwqc->hbwpq', q, k) * self.scale
75
+ # Adding learnable relative embedding
76
+ sim = sim + rearrange(self.relative_embedding(), 'h p q -> h 1 1 p q')
77
+ # Using Attn Mask to distinguish different subwindows.
78
+ if self.type != 'W':
79
+ attn_mask = self.generate_mask(h_windows, w_windows, self.window_size, shift=self.window_size // 2)
80
+ sim = sim.masked_fill_(attn_mask, float("-inf"))
81
+
82
+ probs = nn.functional.softmax(sim, dim=-1)
83
+ output = torch.einsum('hbwij,hbwjc->hbwic', probs, v)
84
+ output = rearrange(output, 'h b w p c -> b w p (h c)')
85
+ output = self.linear(output)
86
+ output = rearrange(output, 'b (w1 w2) (p1 p2) c -> b (w1 p1) (w2 p2) c', w1=h_windows, p1=self.window_size)
87
+
88
+ if self.type != 'W': output = torch.roll(output, shifts=(self.window_size // 2, self.window_size // 2),
89
+ dims=(1, 2))
90
+ return output
91
+
92
+ def relative_embedding(self):
93
+ cord = torch.tensor(np.array([[i, j] for i in range(self.window_size) for j in range(self.window_size)]))
94
+ relation = cord[:, None, :] - cord[None, :, :] + self.window_size - 1
95
+ # negative is allowed
96
+ return self.relative_position_params[:, relation[:, :, 0].long(), relation[:, :, 1].long()]
97
+
98
+
99
+ class Block(nn.Module):
100
+ def __init__(self, input_dim, output_dim, head_dim, window_size, drop_path, type='W', input_resolution=None):
101
+ """ SwinTransformer Block
102
+ """
103
+ super(Block, self).__init__()
104
+ self.input_dim = input_dim
105
+ self.output_dim = output_dim
106
+ assert type in ['W', 'SW']
107
+ self.type = type
108
+ if input_resolution <= window_size:
109
+ self.type = 'W'
110
+
111
+ self.ln1 = nn.LayerNorm(input_dim)
112
+ self.msa = WMSA(input_dim, input_dim, head_dim, window_size, self.type)
113
+ self.drop_path = DropPath(drop_path) if drop_path > 0. else nn.Identity()
114
+ self.ln2 = nn.LayerNorm(input_dim)
115
+ self.mlp = nn.Sequential(
116
+ nn.Linear(input_dim, 4 * input_dim),
117
+ nn.GELU(),
118
+ nn.Linear(4 * input_dim, output_dim),
119
+ )
120
+
121
+ def forward(self, x):
122
+ x = x + self.drop_path(self.msa(self.ln1(x)))
123
+ x = x + self.drop_path(self.mlp(self.ln2(x)))
124
+ return x
125
+
126
+
127
+ class ConvTransBlock(nn.Module):
128
+ def __init__(self, conv_dim, trans_dim, head_dim, window_size, drop_path, type='W', input_resolution=None):
129
+ """ SwinTransformer and Conv Block
130
+ """
131
+ super(ConvTransBlock, self).__init__()
132
+ self.conv_dim = conv_dim
133
+ self.trans_dim = trans_dim
134
+ self.head_dim = head_dim
135
+ self.window_size = window_size
136
+ self.drop_path = drop_path
137
+ self.type = type
138
+ self.input_resolution = input_resolution
139
+
140
+ assert self.type in ['W', 'SW']
141
+ if self.input_resolution <= self.window_size:
142
+ self.type = 'W'
143
+
144
+ self.trans_block = Block(self.trans_dim, self.trans_dim, self.head_dim, self.window_size, self.drop_path,
145
+ self.type, self.input_resolution)
146
+ self.conv1_1 = nn.Conv2d(self.conv_dim + self.trans_dim, self.conv_dim + self.trans_dim, 1, 1, 0, bias=True)
147
+ self.conv1_2 = nn.Conv2d(self.conv_dim + self.trans_dim, self.conv_dim + self.trans_dim, 1, 1, 0, bias=True)
148
+
149
+ self.conv_block = nn.Sequential(
150
+ nn.Conv2d(self.conv_dim, self.conv_dim, 3, 1, 1, bias=False),
151
+ nn.ReLU(True),
152
+ nn.Conv2d(self.conv_dim, self.conv_dim, 3, 1, 1, bias=False)
153
+ )
154
+
155
+ def forward(self, x):
156
+ conv_x, trans_x = torch.split(self.conv1_1(x), (self.conv_dim, self.trans_dim), dim=1)
157
+ conv_x = self.conv_block(conv_x) + conv_x
158
+ trans_x = Rearrange('b c h w -> b h w c')(trans_x)
159
+ trans_x = self.trans_block(trans_x)
160
+ trans_x = Rearrange('b h w c -> b c h w')(trans_x)
161
+ res = self.conv1_2(torch.cat((conv_x, trans_x), dim=1))
162
+ x = x + res
163
+
164
+ return x
165
+
166
+
167
+ class SCUNet(nn.Module):
168
+ # def __init__(self, in_nc=3, config=[2, 2, 2, 2, 2, 2, 2], dim=64, drop_path_rate=0.0, input_resolution=256):
169
+ def __init__(self, in_nc=3, config=None, dim=64, drop_path_rate=0.0, input_resolution=256):
170
+ super(SCUNet, self).__init__()
171
+ if config is None:
172
+ config = [2, 2, 2, 2, 2, 2, 2]
173
+ self.config = config
174
+ self.dim = dim
175
+ self.head_dim = 32
176
+ self.window_size = 8
177
+
178
+ # drop path rate for each layer
179
+ dpr = [x.item() for x in torch.linspace(0, drop_path_rate, sum(config))]
180
+
181
+ self.m_head = [nn.Conv2d(in_nc, dim, 3, 1, 1, bias=False)]
182
+
183
+ begin = 0
184
+ self.m_down1 = [ConvTransBlock(dim // 2, dim // 2, self.head_dim, self.window_size, dpr[i + begin],
185
+ 'W' if not i % 2 else 'SW', input_resolution)
186
+ for i in range(config[0])] + \
187
+ [nn.Conv2d(dim, 2 * dim, 2, 2, 0, bias=False)]
188
+
189
+ begin += config[0]
190
+ self.m_down2 = [ConvTransBlock(dim, dim, self.head_dim, self.window_size, dpr[i + begin],
191
+ 'W' if not i % 2 else 'SW', input_resolution // 2)
192
+ for i in range(config[1])] + \
193
+ [nn.Conv2d(2 * dim, 4 * dim, 2, 2, 0, bias=False)]
194
+
195
+ begin += config[1]
196
+ self.m_down3 = [ConvTransBlock(2 * dim, 2 * dim, self.head_dim, self.window_size, dpr[i + begin],
197
+ 'W' if not i % 2 else 'SW', input_resolution // 4)
198
+ for i in range(config[2])] + \
199
+ [nn.Conv2d(4 * dim, 8 * dim, 2, 2, 0, bias=False)]
200
+
201
+ begin += config[2]
202
+ self.m_body = [ConvTransBlock(4 * dim, 4 * dim, self.head_dim, self.window_size, dpr[i + begin],
203
+ 'W' if not i % 2 else 'SW', input_resolution // 8)
204
+ for i in range(config[3])]
205
+
206
+ begin += config[3]
207
+ self.m_up3 = [nn.ConvTranspose2d(8 * dim, 4 * dim, 2, 2, 0, bias=False), ] + \
208
+ [ConvTransBlock(2 * dim, 2 * dim, self.head_dim, self.window_size, dpr[i + begin],
209
+ 'W' if not i % 2 else 'SW', input_resolution // 4)
210
+ for i in range(config[4])]
211
+
212
+ begin += config[4]
213
+ self.m_up2 = [nn.ConvTranspose2d(4 * dim, 2 * dim, 2, 2, 0, bias=False), ] + \
214
+ [ConvTransBlock(dim, dim, self.head_dim, self.window_size, dpr[i + begin],
215
+ 'W' if not i % 2 else 'SW', input_resolution // 2)
216
+ for i in range(config[5])]
217
+
218
+ begin += config[5]
219
+ self.m_up1 = [nn.ConvTranspose2d(2 * dim, dim, 2, 2, 0, bias=False), ] + \
220
+ [ConvTransBlock(dim // 2, dim // 2, self.head_dim, self.window_size, dpr[i + begin],
221
+ 'W' if not i % 2 else 'SW', input_resolution)
222
+ for i in range(config[6])]
223
+
224
+ self.m_tail = [nn.Conv2d(dim, in_nc, 3, 1, 1, bias=False)]
225
+
226
+ self.m_head = nn.Sequential(*self.m_head)
227
+ self.m_down1 = nn.Sequential(*self.m_down1)
228
+ self.m_down2 = nn.Sequential(*self.m_down2)
229
+ self.m_down3 = nn.Sequential(*self.m_down3)
230
+ self.m_body = nn.Sequential(*self.m_body)
231
+ self.m_up3 = nn.Sequential(*self.m_up3)
232
+ self.m_up2 = nn.Sequential(*self.m_up2)
233
+ self.m_up1 = nn.Sequential(*self.m_up1)
234
+ self.m_tail = nn.Sequential(*self.m_tail)
235
+ # self.apply(self._init_weights)
236
+
237
+ def forward(self, x0):
238
+
239
+ h, w = x0.size()[-2:]
240
+ paddingBottom = int(np.ceil(h / 64) * 64 - h)
241
+ paddingRight = int(np.ceil(w / 64) * 64 - w)
242
+ x0 = nn.ReplicationPad2d((0, paddingRight, 0, paddingBottom))(x0)
243
+
244
+ x1 = self.m_head(x0)
245
+ x2 = self.m_down1(x1)
246
+ x3 = self.m_down2(x2)
247
+ x4 = self.m_down3(x3)
248
+ x = self.m_body(x4)
249
+ x = self.m_up3(x + x4)
250
+ x = self.m_up2(x + x3)
251
+ x = self.m_up1(x + x2)
252
+ x = self.m_tail(x + x1)
253
+
254
+ x = x[..., :h, :w]
255
+
256
+ return x
257
+
258
+ def _init_weights(self, m):
259
+ if isinstance(m, nn.Linear):
260
+ trunc_normal_(m.weight, std=.02)
261
+ if m.bias is not None:
262
+ nn.init.constant_(m.bias, 0)
263
+ elif isinstance(m, nn.LayerNorm):
264
+ nn.init.constant_(m.bias, 0)
265
+ nn.init.constant_(m.weight, 1.0)
extensions-builtin/SwinIR/preload.py ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ import os
2
+ from modules import paths
3
+
4
+
5
+ def preload(parser):
6
+ parser.add_argument("--swinir-models-path", type=str, help="Path to directory with SwinIR model file(s).", default=os.path.join(paths.models_path, 'SwinIR'))
extensions-builtin/SwinIR/scripts/swinir_model.py ADDED
@@ -0,0 +1,178 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import contextlib
2
+ import os
3
+
4
+ import numpy as np
5
+ import torch
6
+ from PIL import Image
7
+ from basicsr.utils.download_util import load_file_from_url
8
+ from tqdm import tqdm
9
+
10
+ from modules import modelloader, devices, script_callbacks, shared
11
+ from modules.shared import cmd_opts, opts, state
12
+ from swinir_model_arch import SwinIR as net
13
+ from swinir_model_arch_v2 import Swin2SR as net2
14
+ from modules.upscaler import Upscaler, UpscalerData
15
+
16
+
17
+ device_swinir = devices.get_device_for('swinir')
18
+
19
+
20
+ class UpscalerSwinIR(Upscaler):
21
+ def __init__(self, dirname):
22
+ self.name = "SwinIR"
23
+ self.model_url = "https://github.com/JingyunLiang/SwinIR/releases/download/v0.0" \
24
+ "/003_realSR_BSRGAN_DFOWMFC_s64w8_SwinIR" \
25
+ "-L_x4_GAN.pth "
26
+ self.model_name = "SwinIR 4x"
27
+ self.user_path = dirname
28
+ super().__init__()
29
+ scalers = []
30
+ model_files = self.find_models(ext_filter=[".pt", ".pth"])
31
+ for model in model_files:
32
+ if "http" in model:
33
+ name = self.model_name
34
+ else:
35
+ name = modelloader.friendly_name(model)
36
+ model_data = UpscalerData(name, model, self)
37
+ scalers.append(model_data)
38
+ self.scalers = scalers
39
+
40
+ def do_upscale(self, img, model_file):
41
+ model = self.load_model(model_file)
42
+ if model is None:
43
+ return img
44
+ model = model.to(device_swinir, dtype=devices.dtype)
45
+ img = upscale(img, model)
46
+ try:
47
+ torch.cuda.empty_cache()
48
+ except:
49
+ pass
50
+ return img
51
+
52
+ def load_model(self, path, scale=4):
53
+ if "http" in path:
54
+ dl_name = "%s%s" % (self.model_name.replace(" ", "_"), ".pth")
55
+ filename = load_file_from_url(url=path, model_dir=self.model_path, file_name=dl_name, progress=True)
56
+ else:
57
+ filename = path
58
+ if filename is None or not os.path.exists(filename):
59
+ return None
60
+ if filename.endswith(".v2.pth"):
61
+ model = net2(
62
+ upscale=scale,
63
+ in_chans=3,
64
+ img_size=64,
65
+ window_size=8,
66
+ img_range=1.0,
67
+ depths=[6, 6, 6, 6, 6, 6],
68
+ embed_dim=180,
69
+ num_heads=[6, 6, 6, 6, 6, 6],
70
+ mlp_ratio=2,
71
+ upsampler="nearest+conv",
72
+ resi_connection="1conv",
73
+ )
74
+ params = None
75
+ else:
76
+ model = net(
77
+ upscale=scale,
78
+ in_chans=3,
79
+ img_size=64,
80
+ window_size=8,
81
+ img_range=1.0,
82
+ depths=[6, 6, 6, 6, 6, 6, 6, 6, 6],
83
+ embed_dim=240,
84
+ num_heads=[8, 8, 8, 8, 8, 8, 8, 8, 8],
85
+ mlp_ratio=2,
86
+ upsampler="nearest+conv",
87
+ resi_connection="3conv",
88
+ )
89
+ params = "params_ema"
90
+
91
+ pretrained_model = torch.load(filename)
92
+ if params is not None:
93
+ model.load_state_dict(pretrained_model[params], strict=True)
94
+ else:
95
+ model.load_state_dict(pretrained_model, strict=True)
96
+ return model
97
+
98
+
99
+ def upscale(
100
+ img,
101
+ model,
102
+ tile=None,
103
+ tile_overlap=None,
104
+ window_size=8,
105
+ scale=4,
106
+ ):
107
+ tile = tile or opts.SWIN_tile
108
+ tile_overlap = tile_overlap or opts.SWIN_tile_overlap
109
+
110
+
111
+ img = np.array(img)
112
+ img = img[:, :, ::-1]
113
+ img = np.moveaxis(img, 2, 0) / 255
114
+ img = torch.from_numpy(img).float()
115
+ img = img.unsqueeze(0).to(device_swinir, dtype=devices.dtype)
116
+ with torch.no_grad(), devices.autocast():
117
+ _, _, h_old, w_old = img.size()
118
+ h_pad = (h_old // window_size + 1) * window_size - h_old
119
+ w_pad = (w_old // window_size + 1) * window_size - w_old
120
+ img = torch.cat([img, torch.flip(img, [2])], 2)[:, :, : h_old + h_pad, :]
121
+ img = torch.cat([img, torch.flip(img, [3])], 3)[:, :, :, : w_old + w_pad]
122
+ output = inference(img, model, tile, tile_overlap, window_size, scale)
123
+ output = output[..., : h_old * scale, : w_old * scale]
124
+ output = output.data.squeeze().float().cpu().clamp_(0, 1).numpy()
125
+ if output.ndim == 3:
126
+ output = np.transpose(
127
+ output[[2, 1, 0], :, :], (1, 2, 0)
128
+ ) # CHW-RGB to HCW-BGR
129
+ output = (output * 255.0).round().astype(np.uint8) # float32 to uint8
130
+ return Image.fromarray(output, "RGB")
131
+
132
+
133
+ def inference(img, model, tile, tile_overlap, window_size, scale):
134
+ # test the image tile by tile
135
+ b, c, h, w = img.size()
136
+ tile = min(tile, h, w)
137
+ assert tile % window_size == 0, "tile size should be a multiple of window_size"
138
+ sf = scale
139
+
140
+ stride = tile - tile_overlap
141
+ h_idx_list = list(range(0, h - tile, stride)) + [h - tile]
142
+ w_idx_list = list(range(0, w - tile, stride)) + [w - tile]
143
+ E = torch.zeros(b, c, h * sf, w * sf, dtype=devices.dtype, device=device_swinir).type_as(img)
144
+ W = torch.zeros_like(E, dtype=devices.dtype, device=device_swinir)
145
+
146
+ with tqdm(total=len(h_idx_list) * len(w_idx_list), desc="SwinIR tiles") as pbar:
147
+ for h_idx in h_idx_list:
148
+ if state.interrupted or state.skipped:
149
+ break
150
+
151
+ for w_idx in w_idx_list:
152
+ if state.interrupted or state.skipped:
153
+ break
154
+
155
+ in_patch = img[..., h_idx: h_idx + tile, w_idx: w_idx + tile]
156
+ out_patch = model(in_patch)
157
+ out_patch_mask = torch.ones_like(out_patch)
158
+
159
+ E[
160
+ ..., h_idx * sf: (h_idx + tile) * sf, w_idx * sf: (w_idx + tile) * sf
161
+ ].add_(out_patch)
162
+ W[
163
+ ..., h_idx * sf: (h_idx + tile) * sf, w_idx * sf: (w_idx + tile) * sf
164
+ ].add_(out_patch_mask)
165
+ pbar.update(1)
166
+ output = E.div_(W)
167
+
168
+ return output
169
+
170
+
171
+ def on_ui_settings():
172
+ import gradio as gr
173
+
174
+ shared.opts.add_option("SWIN_tile", shared.OptionInfo(192, "Tile size for all SwinIR.", gr.Slider, {"minimum": 16, "maximum": 512, "step": 16}, section=('upscaling', "Upscaling")))
175
+ shared.opts.add_option("SWIN_tile_overlap", shared.OptionInfo(8, "Tile overlap, in pixels for SwinIR. Low values = visible seam.", gr.Slider, {"minimum": 0, "maximum": 48, "step": 1}, section=('upscaling', "Upscaling")))
176
+
177
+
178
+ script_callbacks.on_ui_settings(on_ui_settings)
extensions-builtin/SwinIR/swinir_model_arch.py ADDED
@@ -0,0 +1,867 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -----------------------------------------------------------------------------------
2
+ # SwinIR: Image Restoration Using Swin Transformer, https://arxiv.org/abs/2108.10257
3
+ # Originally Written by Ze Liu, Modified by Jingyun Liang.
4
+ # -----------------------------------------------------------------------------------
5
+
6
+ import math
7
+ import torch
8
+ import torch.nn as nn
9
+ import torch.nn.functional as F
10
+ import torch.utils.checkpoint as checkpoint
11
+ from timm.models.layers import DropPath, to_2tuple, trunc_normal_
12
+
13
+
14
+ class Mlp(nn.Module):
15
+ def __init__(self, in_features, hidden_features=None, out_features=None, act_layer=nn.GELU, drop=0.):
16
+ super().__init__()
17
+ out_features = out_features or in_features
18
+ hidden_features = hidden_features or in_features
19
+ self.fc1 = nn.Linear(in_features, hidden_features)
20
+ self.act = act_layer()
21
+ self.fc2 = nn.Linear(hidden_features, out_features)
22
+ self.drop = nn.Dropout(drop)
23
+
24
+ def forward(self, x):
25
+ x = self.fc1(x)
26
+ x = self.act(x)
27
+ x = self.drop(x)
28
+ x = self.fc2(x)
29
+ x = self.drop(x)
30
+ return x
31
+
32
+
33
+ def window_partition(x, window_size):
34
+ """
35
+ Args:
36
+ x: (B, H, W, C)
37
+ window_size (int): window size
38
+
39
+ Returns:
40
+ windows: (num_windows*B, window_size, window_size, C)
41
+ """
42
+ B, H, W, C = x.shape
43
+ x = x.view(B, H // window_size, window_size, W // window_size, window_size, C)
44
+ windows = x.permute(0, 1, 3, 2, 4, 5).contiguous().view(-1, window_size, window_size, C)
45
+ return windows
46
+
47
+
48
+ def window_reverse(windows, window_size, H, W):
49
+ """
50
+ Args:
51
+ windows: (num_windows*B, window_size, window_size, C)
52
+ window_size (int): Window size
53
+ H (int): Height of image
54
+ W (int): Width of image
55
+
56
+ Returns:
57
+ x: (B, H, W, C)
58
+ """
59
+ B = int(windows.shape[0] / (H * W / window_size / window_size))
60
+ x = windows.view(B, H // window_size, W // window_size, window_size, window_size, -1)
61
+ x = x.permute(0, 1, 3, 2, 4, 5).contiguous().view(B, H, W, -1)
62
+ return x
63
+
64
+
65
+ class WindowAttention(nn.Module):
66
+ r""" Window based multi-head self attention (W-MSA) module with relative position bias.
67
+ It supports both of shifted and non-shifted window.
68
+
69
+ Args:
70
+ dim (int): Number of input channels.
71
+ window_size (tuple[int]): The height and width of the window.
72
+ num_heads (int): Number of attention heads.
73
+ qkv_bias (bool, optional): If True, add a learnable bias to query, key, value. Default: True
74
+ qk_scale (float | None, optional): Override default qk scale of head_dim ** -0.5 if set
75
+ attn_drop (float, optional): Dropout ratio of attention weight. Default: 0.0
76
+ proj_drop (float, optional): Dropout ratio of output. Default: 0.0
77
+ """
78
+
79
+ def __init__(self, dim, window_size, num_heads, qkv_bias=True, qk_scale=None, attn_drop=0., proj_drop=0.):
80
+
81
+ super().__init__()
82
+ self.dim = dim
83
+ self.window_size = window_size # Wh, Ww
84
+ self.num_heads = num_heads
85
+ head_dim = dim // num_heads
86
+ self.scale = qk_scale or head_dim ** -0.5
87
+
88
+ # define a parameter table of relative position bias
89
+ self.relative_position_bias_table = nn.Parameter(
90
+ torch.zeros((2 * window_size[0] - 1) * (2 * window_size[1] - 1), num_heads)) # 2*Wh-1 * 2*Ww-1, nH
91
+
92
+ # get pair-wise relative position index for each token inside the window
93
+ coords_h = torch.arange(self.window_size[0])
94
+ coords_w = torch.arange(self.window_size[1])
95
+ coords = torch.stack(torch.meshgrid([coords_h, coords_w])) # 2, Wh, Ww
96
+ coords_flatten = torch.flatten(coords, 1) # 2, Wh*Ww
97
+ relative_coords = coords_flatten[:, :, None] - coords_flatten[:, None, :] # 2, Wh*Ww, Wh*Ww
98
+ relative_coords = relative_coords.permute(1, 2, 0).contiguous() # Wh*Ww, Wh*Ww, 2
99
+ relative_coords[:, :, 0] += self.window_size[0] - 1 # shift to start from 0
100
+ relative_coords[:, :, 1] += self.window_size[1] - 1
101
+ relative_coords[:, :, 0] *= 2 * self.window_size[1] - 1
102
+ relative_position_index = relative_coords.sum(-1) # Wh*Ww, Wh*Ww
103
+ self.register_buffer("relative_position_index", relative_position_index)
104
+
105
+ self.qkv = nn.Linear(dim, dim * 3, bias=qkv_bias)
106
+ self.attn_drop = nn.Dropout(attn_drop)
107
+ self.proj = nn.Linear(dim, dim)
108
+
109
+ self.proj_drop = nn.Dropout(proj_drop)
110
+
111
+ trunc_normal_(self.relative_position_bias_table, std=.02)
112
+ self.softmax = nn.Softmax(dim=-1)
113
+
114
+ def forward(self, x, mask=None):
115
+ """
116
+ Args:
117
+ x: input features with shape of (num_windows*B, N, C)
118
+ mask: (0/-inf) mask with shape of (num_windows, Wh*Ww, Wh*Ww) or None
119
+ """
120
+ B_, N, C = x.shape
121
+ qkv = self.qkv(x).reshape(B_, N, 3, self.num_heads, C // self.num_heads).permute(2, 0, 3, 1, 4)
122
+ q, k, v = qkv[0], qkv[1], qkv[2] # make torchscript happy (cannot use tensor as tuple)
123
+
124
+ q = q * self.scale
125
+ attn = (q @ k.transpose(-2, -1))
126
+
127
+ relative_position_bias = self.relative_position_bias_table[self.relative_position_index.view(-1)].view(
128
+ self.window_size[0] * self.window_size[1], self.window_size[0] * self.window_size[1], -1) # Wh*Ww,Wh*Ww,nH
129
+ relative_position_bias = relative_position_bias.permute(2, 0, 1).contiguous() # nH, Wh*Ww, Wh*Ww
130
+ attn = attn + relative_position_bias.unsqueeze(0)
131
+
132
+ if mask is not None:
133
+ nW = mask.shape[0]
134
+ attn = attn.view(B_ // nW, nW, self.num_heads, N, N) + mask.unsqueeze(1).unsqueeze(0)
135
+ attn = attn.view(-1, self.num_heads, N, N)
136
+ attn = self.softmax(attn)
137
+ else:
138
+ attn = self.softmax(attn)
139
+
140
+ attn = self.attn_drop(attn)
141
+
142
+ x = (attn @ v).transpose(1, 2).reshape(B_, N, C)
143
+ x = self.proj(x)
144
+ x = self.proj_drop(x)
145
+ return x
146
+
147
+ def extra_repr(self) -> str:
148
+ return f'dim={self.dim}, window_size={self.window_size}, num_heads={self.num_heads}'
149
+
150
+ def flops(self, N):
151
+ # calculate flops for 1 window with token length of N
152
+ flops = 0
153
+ # qkv = self.qkv(x)
154
+ flops += N * self.dim * 3 * self.dim
155
+ # attn = (q @ k.transpose(-2, -1))
156
+ flops += self.num_heads * N * (self.dim // self.num_heads) * N
157
+ # x = (attn @ v)
158
+ flops += self.num_heads * N * N * (self.dim // self.num_heads)
159
+ # x = self.proj(x)
160
+ flops += N * self.dim * self.dim
161
+ return flops
162
+
163
+
164
+ class SwinTransformerBlock(nn.Module):
165
+ r""" Swin Transformer Block.
166
+
167
+ Args:
168
+ dim (int): Number of input channels.
169
+ input_resolution (tuple[int]): Input resolution.
170
+ num_heads (int): Number of attention heads.
171
+ window_size (int): Window size.
172
+ shift_size (int): Shift size for SW-MSA.
173
+ mlp_ratio (float): Ratio of mlp hidden dim to embedding dim.
174
+ qkv_bias (bool, optional): If True, add a learnable bias to query, key, value. Default: True
175
+ qk_scale (float | None, optional): Override default qk scale of head_dim ** -0.5 if set.
176
+ drop (float, optional): Dropout rate. Default: 0.0
177
+ attn_drop (float, optional): Attention dropout rate. Default: 0.0
178
+ drop_path (float, optional): Stochastic depth rate. Default: 0.0
179
+ act_layer (nn.Module, optional): Activation layer. Default: nn.GELU
180
+ norm_layer (nn.Module, optional): Normalization layer. Default: nn.LayerNorm
181
+ """
182
+
183
+ def __init__(self, dim, input_resolution, num_heads, window_size=7, shift_size=0,
184
+ mlp_ratio=4., qkv_bias=True, qk_scale=None, drop=0., attn_drop=0., drop_path=0.,
185
+ act_layer=nn.GELU, norm_layer=nn.LayerNorm):
186
+ super().__init__()
187
+ self.dim = dim
188
+ self.input_resolution = input_resolution
189
+ self.num_heads = num_heads
190
+ self.window_size = window_size
191
+ self.shift_size = shift_size
192
+ self.mlp_ratio = mlp_ratio
193
+ if min(self.input_resolution) <= self.window_size:
194
+ # if window size is larger than input resolution, we don't partition windows
195
+ self.shift_size = 0
196
+ self.window_size = min(self.input_resolution)
197
+ assert 0 <= self.shift_size < self.window_size, "shift_size must in 0-window_size"
198
+
199
+ self.norm1 = norm_layer(dim)
200
+ self.attn = WindowAttention(
201
+ dim, window_size=to_2tuple(self.window_size), num_heads=num_heads,
202
+ qkv_bias=qkv_bias, qk_scale=qk_scale, attn_drop=attn_drop, proj_drop=drop)
203
+
204
+ self.drop_path = DropPath(drop_path) if drop_path > 0. else nn.Identity()
205
+ self.norm2 = norm_layer(dim)
206
+ mlp_hidden_dim = int(dim * mlp_ratio)
207
+ self.mlp = Mlp(in_features=dim, hidden_features=mlp_hidden_dim, act_layer=act_layer, drop=drop)
208
+
209
+ if self.shift_size > 0:
210
+ attn_mask = self.calculate_mask(self.input_resolution)
211
+ else:
212
+ attn_mask = None
213
+
214
+ self.register_buffer("attn_mask", attn_mask)
215
+
216
+ def calculate_mask(self, x_size):
217
+ # calculate attention mask for SW-MSA
218
+ H, W = x_size
219
+ img_mask = torch.zeros((1, H, W, 1)) # 1 H W 1
220
+ h_slices = (slice(0, -self.window_size),
221
+ slice(-self.window_size, -self.shift_size),
222
+ slice(-self.shift_size, None))
223
+ w_slices = (slice(0, -self.window_size),
224
+ slice(-self.window_size, -self.shift_size),
225
+ slice(-self.shift_size, None))
226
+ cnt = 0
227
+ for h in h_slices:
228
+ for w in w_slices:
229
+ img_mask[:, h, w, :] = cnt
230
+ cnt += 1
231
+
232
+ mask_windows = window_partition(img_mask, self.window_size) # nW, window_size, window_size, 1
233
+ mask_windows = mask_windows.view(-1, self.window_size * self.window_size)
234
+ attn_mask = mask_windows.unsqueeze(1) - mask_windows.unsqueeze(2)
235
+ attn_mask = attn_mask.masked_fill(attn_mask != 0, float(-100.0)).masked_fill(attn_mask == 0, float(0.0))
236
+
237
+ return attn_mask
238
+
239
+ def forward(self, x, x_size):
240
+ H, W = x_size
241
+ B, L, C = x.shape
242
+ # assert L == H * W, "input feature has wrong size"
243
+
244
+ shortcut = x
245
+ x = self.norm1(x)
246
+ x = x.view(B, H, W, C)
247
+
248
+ # cyclic shift
249
+ if self.shift_size > 0:
250
+ shifted_x = torch.roll(x, shifts=(-self.shift_size, -self.shift_size), dims=(1, 2))
251
+ else:
252
+ shifted_x = x
253
+
254
+ # partition windows
255
+ x_windows = window_partition(shifted_x, self.window_size) # nW*B, window_size, window_size, C
256
+ x_windows = x_windows.view(-1, self.window_size * self.window_size, C) # nW*B, window_size*window_size, C
257
+
258
+ # W-MSA/SW-MSA (to be compatible for testing on images whose shapes are the multiple of window size
259
+ if self.input_resolution == x_size:
260
+ attn_windows = self.attn(x_windows, mask=self.attn_mask) # nW*B, window_size*window_size, C
261
+ else:
262
+ attn_windows = self.attn(x_windows, mask=self.calculate_mask(x_size).to(x.device))
263
+
264
+ # merge windows
265
+ attn_windows = attn_windows.view(-1, self.window_size, self.window_size, C)
266
+ shifted_x = window_reverse(attn_windows, self.window_size, H, W) # B H' W' C
267
+
268
+ # reverse cyclic shift
269
+ if self.shift_size > 0:
270
+ x = torch.roll(shifted_x, shifts=(self.shift_size, self.shift_size), dims=(1, 2))
271
+ else:
272
+ x = shifted_x
273
+ x = x.view(B, H * W, C)
274
+
275
+ # FFN
276
+ x = shortcut + self.drop_path(x)
277
+ x = x + self.drop_path(self.mlp(self.norm2(x)))
278
+
279
+ return x
280
+
281
+ def extra_repr(self) -> str:
282
+ return f"dim={self.dim}, input_resolution={self.input_resolution}, num_heads={self.num_heads}, " \
283
+ f"window_size={self.window_size}, shift_size={self.shift_size}, mlp_ratio={self.mlp_ratio}"
284
+
285
+ def flops(self):
286
+ flops = 0
287
+ H, W = self.input_resolution
288
+ # norm1
289
+ flops += self.dim * H * W
290
+ # W-MSA/SW-MSA
291
+ nW = H * W / self.window_size / self.window_size
292
+ flops += nW * self.attn.flops(self.window_size * self.window_size)
293
+ # mlp
294
+ flops += 2 * H * W * self.dim * self.dim * self.mlp_ratio
295
+ # norm2
296
+ flops += self.dim * H * W
297
+ return flops
298
+
299
+
300
+ class PatchMerging(nn.Module):
301
+ r""" Patch Merging Layer.
302
+
303
+ Args:
304
+ input_resolution (tuple[int]): Resolution of input feature.
305
+ dim (int): Number of input channels.
306
+ norm_layer (nn.Module, optional): Normalization layer. Default: nn.LayerNorm
307
+ """
308
+
309
+ def __init__(self, input_resolution, dim, norm_layer=nn.LayerNorm):
310
+ super().__init__()
311
+ self.input_resolution = input_resolution
312
+ self.dim = dim
313
+ self.reduction = nn.Linear(4 * dim, 2 * dim, bias=False)
314
+ self.norm = norm_layer(4 * dim)
315
+
316
+ def forward(self, x):
317
+ """
318
+ x: B, H*W, C
319
+ """
320
+ H, W = self.input_resolution
321
+ B, L, C = x.shape
322
+ assert L == H * W, "input feature has wrong size"
323
+ assert H % 2 == 0 and W % 2 == 0, f"x size ({H}*{W}) are not even."
324
+
325
+ x = x.view(B, H, W, C)
326
+
327
+ x0 = x[:, 0::2, 0::2, :] # B H/2 W/2 C
328
+ x1 = x[:, 1::2, 0::2, :] # B H/2 W/2 C
329
+ x2 = x[:, 0::2, 1::2, :] # B H/2 W/2 C
330
+ x3 = x[:, 1::2, 1::2, :] # B H/2 W/2 C
331
+ x = torch.cat([x0, x1, x2, x3], -1) # B H/2 W/2 4*C
332
+ x = x.view(B, -1, 4 * C) # B H/2*W/2 4*C
333
+
334
+ x = self.norm(x)
335
+ x = self.reduction(x)
336
+
337
+ return x
338
+
339
+ def extra_repr(self) -> str:
340
+ return f"input_resolution={self.input_resolution}, dim={self.dim}"
341
+
342
+ def flops(self):
343
+ H, W = self.input_resolution
344
+ flops = H * W * self.dim
345
+ flops += (H // 2) * (W // 2) * 4 * self.dim * 2 * self.dim
346
+ return flops
347
+
348
+
349
+ class BasicLayer(nn.Module):
350
+ """ A basic Swin Transformer layer for one stage.
351
+
352
+ Args:
353
+ dim (int): Number of input channels.
354
+ input_resolution (tuple[int]): Input resolution.
355
+ depth (int): Number of blocks.
356
+ num_heads (int): Number of attention heads.
357
+ window_size (int): Local window size.
358
+ mlp_ratio (float): Ratio of mlp hidden dim to embedding dim.
359
+ qkv_bias (bool, optional): If True, add a learnable bias to query, key, value. Default: True
360
+ qk_scale (float | None, optional): Override default qk scale of head_dim ** -0.5 if set.
361
+ drop (float, optional): Dropout rate. Default: 0.0
362
+ attn_drop (float, optional): Attention dropout rate. Default: 0.0
363
+ drop_path (float | tuple[float], optional): Stochastic depth rate. Default: 0.0
364
+ norm_layer (nn.Module, optional): Normalization layer. Default: nn.LayerNorm
365
+ downsample (nn.Module | None, optional): Downsample layer at the end of the layer. Default: None
366
+ use_checkpoint (bool): Whether to use checkpointing to save memory. Default: False.
367
+ """
368
+
369
+ def __init__(self, dim, input_resolution, depth, num_heads, window_size,
370
+ mlp_ratio=4., qkv_bias=True, qk_scale=None, drop=0., attn_drop=0.,
371
+ drop_path=0., norm_layer=nn.LayerNorm, downsample=None, use_checkpoint=False):
372
+
373
+ super().__init__()
374
+ self.dim = dim
375
+ self.input_resolution = input_resolution
376
+ self.depth = depth
377
+ self.use_checkpoint = use_checkpoint
378
+
379
+ # build blocks
380
+ self.blocks = nn.ModuleList([
381
+ SwinTransformerBlock(dim=dim, input_resolution=input_resolution,
382
+ num_heads=num_heads, window_size=window_size,
383
+ shift_size=0 if (i % 2 == 0) else window_size // 2,
384
+ mlp_ratio=mlp_ratio,
385
+ qkv_bias=qkv_bias, qk_scale=qk_scale,
386
+ drop=drop, attn_drop=attn_drop,
387
+ drop_path=drop_path[i] if isinstance(drop_path, list) else drop_path,
388
+ norm_layer=norm_layer)
389
+ for i in range(depth)])
390
+
391
+ # patch merging layer
392
+ if downsample is not None:
393
+ self.downsample = downsample(input_resolution, dim=dim, norm_layer=norm_layer)
394
+ else:
395
+ self.downsample = None
396
+
397
+ def forward(self, x, x_size):
398
+ for blk in self.blocks:
399
+ if self.use_checkpoint:
400
+ x = checkpoint.checkpoint(blk, x, x_size)
401
+ else:
402
+ x = blk(x, x_size)
403
+ if self.downsample is not None:
404
+ x = self.downsample(x)
405
+ return x
406
+
407
+ def extra_repr(self) -> str:
408
+ return f"dim={self.dim}, input_resolution={self.input_resolution}, depth={self.depth}"
409
+
410
+ def flops(self):
411
+ flops = 0
412
+ for blk in self.blocks:
413
+ flops += blk.flops()
414
+ if self.downsample is not None:
415
+ flops += self.downsample.flops()
416
+ return flops
417
+
418
+
419
+ class RSTB(nn.Module):
420
+ """Residual Swin Transformer Block (RSTB).
421
+
422
+ Args:
423
+ dim (int): Number of input channels.
424
+ input_resolution (tuple[int]): Input resolution.
425
+ depth (int): Number of blocks.
426
+ num_heads (int): Number of attention heads.
427
+ window_size (int): Local window size.
428
+ mlp_ratio (float): Ratio of mlp hidden dim to embedding dim.
429
+ qkv_bias (bool, optional): If True, add a learnable bias to query, key, value. Default: True
430
+ qk_scale (float | None, optional): Override default qk scale of head_dim ** -0.5 if set.
431
+ drop (float, optional): Dropout rate. Default: 0.0
432
+ attn_drop (float, optional): Attention dropout rate. Default: 0.0
433
+ drop_path (float | tuple[float], optional): Stochastic depth rate. Default: 0.0
434
+ norm_layer (nn.Module, optional): Normalization layer. Default: nn.LayerNorm
435
+ downsample (nn.Module | None, optional): Downsample layer at the end of the layer. Default: None
436
+ use_checkpoint (bool): Whether to use checkpointing to save memory. Default: False.
437
+ img_size: Input image size.
438
+ patch_size: Patch size.
439
+ resi_connection: The convolutional block before residual connection.
440
+ """
441
+
442
+ def __init__(self, dim, input_resolution, depth, num_heads, window_size,
443
+ mlp_ratio=4., qkv_bias=True, qk_scale=None, drop=0., attn_drop=0.,
444
+ drop_path=0., norm_layer=nn.LayerNorm, downsample=None, use_checkpoint=False,
445
+ img_size=224, patch_size=4, resi_connection='1conv'):
446
+ super(RSTB, self).__init__()
447
+
448
+ self.dim = dim
449
+ self.input_resolution = input_resolution
450
+
451
+ self.residual_group = BasicLayer(dim=dim,
452
+ input_resolution=input_resolution,
453
+ depth=depth,
454
+ num_heads=num_heads,
455
+ window_size=window_size,
456
+ mlp_ratio=mlp_ratio,
457
+ qkv_bias=qkv_bias, qk_scale=qk_scale,
458
+ drop=drop, attn_drop=attn_drop,
459
+ drop_path=drop_path,
460
+ norm_layer=norm_layer,
461
+ downsample=downsample,
462
+ use_checkpoint=use_checkpoint)
463
+
464
+ if resi_connection == '1conv':
465
+ self.conv = nn.Conv2d(dim, dim, 3, 1, 1)
466
+ elif resi_connection == '3conv':
467
+ # to save parameters and memory
468
+ self.conv = nn.Sequential(nn.Conv2d(dim, dim // 4, 3, 1, 1), nn.LeakyReLU(negative_slope=0.2, inplace=True),
469
+ nn.Conv2d(dim // 4, dim // 4, 1, 1, 0),
470
+ nn.LeakyReLU(negative_slope=0.2, inplace=True),
471
+ nn.Conv2d(dim // 4, dim, 3, 1, 1))
472
+
473
+ self.patch_embed = PatchEmbed(
474
+ img_size=img_size, patch_size=patch_size, in_chans=0, embed_dim=dim,
475
+ norm_layer=None)
476
+
477
+ self.patch_unembed = PatchUnEmbed(
478
+ img_size=img_size, patch_size=patch_size, in_chans=0, embed_dim=dim,
479
+ norm_layer=None)
480
+
481
+ def forward(self, x, x_size):
482
+ return self.patch_embed(self.conv(self.patch_unembed(self.residual_group(x, x_size), x_size))) + x
483
+
484
+ def flops(self):
485
+ flops = 0
486
+ flops += self.residual_group.flops()
487
+ H, W = self.input_resolution
488
+ flops += H * W * self.dim * self.dim * 9
489
+ flops += self.patch_embed.flops()
490
+ flops += self.patch_unembed.flops()
491
+
492
+ return flops
493
+
494
+
495
+ class PatchEmbed(nn.Module):
496
+ r""" Image to Patch Embedding
497
+
498
+ Args:
499
+ img_size (int): Image size. Default: 224.
500
+ patch_size (int): Patch token size. Default: 4.
501
+ in_chans (int): Number of input image channels. Default: 3.
502
+ embed_dim (int): Number of linear projection output channels. Default: 96.
503
+ norm_layer (nn.Module, optional): Normalization layer. Default: None
504
+ """
505
+
506
+ def __init__(self, img_size=224, patch_size=4, in_chans=3, embed_dim=96, norm_layer=None):
507
+ super().__init__()
508
+ img_size = to_2tuple(img_size)
509
+ patch_size = to_2tuple(patch_size)
510
+ patches_resolution = [img_size[0] // patch_size[0], img_size[1] // patch_size[1]]
511
+ self.img_size = img_size
512
+ self.patch_size = patch_size
513
+ self.patches_resolution = patches_resolution
514
+ self.num_patches = patches_resolution[0] * patches_resolution[1]
515
+
516
+ self.in_chans = in_chans
517
+ self.embed_dim = embed_dim
518
+
519
+ if norm_layer is not None:
520
+ self.norm = norm_layer(embed_dim)
521
+ else:
522
+ self.norm = None
523
+
524
+ def forward(self, x):
525
+ x = x.flatten(2).transpose(1, 2) # B Ph*Pw C
526
+ if self.norm is not None:
527
+ x = self.norm(x)
528
+ return x
529
+
530
+ def flops(self):
531
+ flops = 0
532
+ H, W = self.img_size
533
+ if self.norm is not None:
534
+ flops += H * W * self.embed_dim
535
+ return flops
536
+
537
+
538
+ class PatchUnEmbed(nn.Module):
539
+ r""" Image to Patch Unembedding
540
+
541
+ Args:
542
+ img_size (int): Image size. Default: 224.
543
+ patch_size (int): Patch token size. Default: 4.
544
+ in_chans (int): Number of input image channels. Default: 3.
545
+ embed_dim (int): Number of linear projection output channels. Default: 96.
546
+ norm_layer (nn.Module, optional): Normalization layer. Default: None
547
+ """
548
+
549
+ def __init__(self, img_size=224, patch_size=4, in_chans=3, embed_dim=96, norm_layer=None):
550
+ super().__init__()
551
+ img_size = to_2tuple(img_size)
552
+ patch_size = to_2tuple(patch_size)
553
+ patches_resolution = [img_size[0] // patch_size[0], img_size[1] // patch_size[1]]
554
+ self.img_size = img_size
555
+ self.patch_size = patch_size
556
+ self.patches_resolution = patches_resolution
557
+ self.num_patches = patches_resolution[0] * patches_resolution[1]
558
+
559
+ self.in_chans = in_chans
560
+ self.embed_dim = embed_dim
561
+
562
+ def forward(self, x, x_size):
563
+ B, HW, C = x.shape
564
+ x = x.transpose(1, 2).view(B, self.embed_dim, x_size[0], x_size[1]) # B Ph*Pw C
565
+ return x
566
+
567
+ def flops(self):
568
+ flops = 0
569
+ return flops
570
+
571
+
572
+ class Upsample(nn.Sequential):
573
+ """Upsample module.
574
+
575
+ Args:
576
+ scale (int): Scale factor. Supported scales: 2^n and 3.
577
+ num_feat (int): Channel number of intermediate features.
578
+ """
579
+
580
+ def __init__(self, scale, num_feat):
581
+ m = []
582
+ if (scale & (scale - 1)) == 0: # scale = 2^n
583
+ for _ in range(int(math.log(scale, 2))):
584
+ m.append(nn.Conv2d(num_feat, 4 * num_feat, 3, 1, 1))
585
+ m.append(nn.PixelShuffle(2))
586
+ elif scale == 3:
587
+ m.append(nn.Conv2d(num_feat, 9 * num_feat, 3, 1, 1))
588
+ m.append(nn.PixelShuffle(3))
589
+ else:
590
+ raise ValueError(f'scale {scale} is not supported. ' 'Supported scales: 2^n and 3.')
591
+ super(Upsample, self).__init__(*m)
592
+
593
+
594
+ class UpsampleOneStep(nn.Sequential):
595
+ """UpsampleOneStep module (the difference with Upsample is that it always only has 1conv + 1pixelshuffle)
596
+ Used in lightweight SR to save parameters.
597
+
598
+ Args:
599
+ scale (int): Scale factor. Supported scales: 2^n and 3.
600
+ num_feat (int): Channel number of intermediate features.
601
+
602
+ """
603
+
604
+ def __init__(self, scale, num_feat, num_out_ch, input_resolution=None):
605
+ self.num_feat = num_feat
606
+ self.input_resolution = input_resolution
607
+ m = []
608
+ m.append(nn.Conv2d(num_feat, (scale ** 2) * num_out_ch, 3, 1, 1))
609
+ m.append(nn.PixelShuffle(scale))
610
+ super(UpsampleOneStep, self).__init__(*m)
611
+
612
+ def flops(self):
613
+ H, W = self.input_resolution
614
+ flops = H * W * self.num_feat * 3 * 9
615
+ return flops
616
+
617
+
618
+ class SwinIR(nn.Module):
619
+ r""" SwinIR
620
+ A PyTorch impl of : `SwinIR: Image Restoration Using Swin Transformer`, based on Swin Transformer.
621
+
622
+ Args:
623
+ img_size (int | tuple(int)): Input image size. Default 64
624
+ patch_size (int | tuple(int)): Patch size. Default: 1
625
+ in_chans (int): Number of input image channels. Default: 3
626
+ embed_dim (int): Patch embedding dimension. Default: 96
627
+ depths (tuple(int)): Depth of each Swin Transformer layer.
628
+ num_heads (tuple(int)): Number of attention heads in different layers.
629
+ window_size (int): Window size. Default: 7
630
+ mlp_ratio (float): Ratio of mlp hidden dim to embedding dim. Default: 4
631
+ qkv_bias (bool): If True, add a learnable bias to query, key, value. Default: True
632
+ qk_scale (float): Override default qk scale of head_dim ** -0.5 if set. Default: None
633
+ drop_rate (float): Dropout rate. Default: 0
634
+ attn_drop_rate (float): Attention dropout rate. Default: 0
635
+ drop_path_rate (float): Stochastic depth rate. Default: 0.1
636
+ norm_layer (nn.Module): Normalization layer. Default: nn.LayerNorm.
637
+ ape (bool): If True, add absolute position embedding to the patch embedding. Default: False
638
+ patch_norm (bool): If True, add normalization after patch embedding. Default: True
639
+ use_checkpoint (bool): Whether to use checkpointing to save memory. Default: False
640
+ upscale: Upscale factor. 2/3/4/8 for image SR, 1 for denoising and compress artifact reduction
641
+ img_range: Image range. 1. or 255.
642
+ upsampler: The reconstruction reconstruction module. 'pixelshuffle'/'pixelshuffledirect'/'nearest+conv'/None
643
+ resi_connection: The convolutional block before residual connection. '1conv'/'3conv'
644
+ """
645
+
646
+ def __init__(self, img_size=64, patch_size=1, in_chans=3,
647
+ embed_dim=96, depths=[6, 6, 6, 6], num_heads=[6, 6, 6, 6],
648
+ window_size=7, mlp_ratio=4., qkv_bias=True, qk_scale=None,
649
+ drop_rate=0., attn_drop_rate=0., drop_path_rate=0.1,
650
+ norm_layer=nn.LayerNorm, ape=False, patch_norm=True,
651
+ use_checkpoint=False, upscale=2, img_range=1., upsampler='', resi_connection='1conv',
652
+ **kwargs):
653
+ super(SwinIR, self).__init__()
654
+ num_in_ch = in_chans
655
+ num_out_ch = in_chans
656
+ num_feat = 64
657
+ self.img_range = img_range
658
+ if in_chans == 3:
659
+ rgb_mean = (0.4488, 0.4371, 0.4040)
660
+ self.mean = torch.Tensor(rgb_mean).view(1, 3, 1, 1)
661
+ else:
662
+ self.mean = torch.zeros(1, 1, 1, 1)
663
+ self.upscale = upscale
664
+ self.upsampler = upsampler
665
+ self.window_size = window_size
666
+
667
+ #####################################################################################################
668
+ ################################### 1, shallow feature extraction ###################################
669
+ self.conv_first = nn.Conv2d(num_in_ch, embed_dim, 3, 1, 1)
670
+
671
+ #####################################################################################################
672
+ ################################### 2, deep feature extraction ######################################
673
+ self.num_layers = len(depths)
674
+ self.embed_dim = embed_dim
675
+ self.ape = ape
676
+ self.patch_norm = patch_norm
677
+ self.num_features = embed_dim
678
+ self.mlp_ratio = mlp_ratio
679
+
680
+ # split image into non-overlapping patches
681
+ self.patch_embed = PatchEmbed(
682
+ img_size=img_size, patch_size=patch_size, in_chans=embed_dim, embed_dim=embed_dim,
683
+ norm_layer=norm_layer if self.patch_norm else None)
684
+ num_patches = self.patch_embed.num_patches
685
+ patches_resolution = self.patch_embed.patches_resolution
686
+ self.patches_resolution = patches_resolution
687
+
688
+ # merge non-overlapping patches into image
689
+ self.patch_unembed = PatchUnEmbed(
690
+ img_size=img_size, patch_size=patch_size, in_chans=embed_dim, embed_dim=embed_dim,
691
+ norm_layer=norm_layer if self.patch_norm else None)
692
+
693
+ # absolute position embedding
694
+ if self.ape:
695
+ self.absolute_pos_embed = nn.Parameter(torch.zeros(1, num_patches, embed_dim))
696
+ trunc_normal_(self.absolute_pos_embed, std=.02)
697
+
698
+ self.pos_drop = nn.Dropout(p=drop_rate)
699
+
700
+ # stochastic depth
701
+ dpr = [x.item() for x in torch.linspace(0, drop_path_rate, sum(depths))] # stochastic depth decay rule
702
+
703
+ # build Residual Swin Transformer blocks (RSTB)
704
+ self.layers = nn.ModuleList()
705
+ for i_layer in range(self.num_layers):
706
+ layer = RSTB(dim=embed_dim,
707
+ input_resolution=(patches_resolution[0],
708
+ patches_resolution[1]),
709
+ depth=depths[i_layer],
710
+ num_heads=num_heads[i_layer],
711
+ window_size=window_size,
712
+ mlp_ratio=self.mlp_ratio,
713
+ qkv_bias=qkv_bias, qk_scale=qk_scale,
714
+ drop=drop_rate, attn_drop=attn_drop_rate,
715
+ drop_path=dpr[sum(depths[:i_layer]):sum(depths[:i_layer + 1])], # no impact on SR results
716
+ norm_layer=norm_layer,
717
+ downsample=None,
718
+ use_checkpoint=use_checkpoint,
719
+ img_size=img_size,
720
+ patch_size=patch_size,
721
+ resi_connection=resi_connection
722
+
723
+ )
724
+ self.layers.append(layer)
725
+ self.norm = norm_layer(self.num_features)
726
+
727
+ # build the last conv layer in deep feature extraction
728
+ if resi_connection == '1conv':
729
+ self.conv_after_body = nn.Conv2d(embed_dim, embed_dim, 3, 1, 1)
730
+ elif resi_connection == '3conv':
731
+ # to save parameters and memory
732
+ self.conv_after_body = nn.Sequential(nn.Conv2d(embed_dim, embed_dim // 4, 3, 1, 1),
733
+ nn.LeakyReLU(negative_slope=0.2, inplace=True),
734
+ nn.Conv2d(embed_dim // 4, embed_dim // 4, 1, 1, 0),
735
+ nn.LeakyReLU(negative_slope=0.2, inplace=True),
736
+ nn.Conv2d(embed_dim // 4, embed_dim, 3, 1, 1))
737
+
738
+ #####################################################################################################
739
+ ################################ 3, high quality image reconstruction ################################
740
+ if self.upsampler == 'pixelshuffle':
741
+ # for classical SR
742
+ self.conv_before_upsample = nn.Sequential(nn.Conv2d(embed_dim, num_feat, 3, 1, 1),
743
+ nn.LeakyReLU(inplace=True))
744
+ self.upsample = Upsample(upscale, num_feat)
745
+ self.conv_last = nn.Conv2d(num_feat, num_out_ch, 3, 1, 1)
746
+ elif self.upsampler == 'pixelshuffledirect':
747
+ # for lightweight SR (to save parameters)
748
+ self.upsample = UpsampleOneStep(upscale, embed_dim, num_out_ch,
749
+ (patches_resolution[0], patches_resolution[1]))
750
+ elif self.upsampler == 'nearest+conv':
751
+ # for real-world SR (less artifacts)
752
+ self.conv_before_upsample = nn.Sequential(nn.Conv2d(embed_dim, num_feat, 3, 1, 1),
753
+ nn.LeakyReLU(inplace=True))
754
+ self.conv_up1 = nn.Conv2d(num_feat, num_feat, 3, 1, 1)
755
+ if self.upscale == 4:
756
+ self.conv_up2 = nn.Conv2d(num_feat, num_feat, 3, 1, 1)
757
+ self.conv_hr = nn.Conv2d(num_feat, num_feat, 3, 1, 1)
758
+ self.conv_last = nn.Conv2d(num_feat, num_out_ch, 3, 1, 1)
759
+ self.lrelu = nn.LeakyReLU(negative_slope=0.2, inplace=True)
760
+ else:
761
+ # for image denoising and JPEG compression artifact reduction
762
+ self.conv_last = nn.Conv2d(embed_dim, num_out_ch, 3, 1, 1)
763
+
764
+ self.apply(self._init_weights)
765
+
766
+ def _init_weights(self, m):
767
+ if isinstance(m, nn.Linear):
768
+ trunc_normal_(m.weight, std=.02)
769
+ if isinstance(m, nn.Linear) and m.bias is not None:
770
+ nn.init.constant_(m.bias, 0)
771
+ elif isinstance(m, nn.LayerNorm):
772
+ nn.init.constant_(m.bias, 0)
773
+ nn.init.constant_(m.weight, 1.0)
774
+
775
+ @torch.jit.ignore
776
+ def no_weight_decay(self):
777
+ return {'absolute_pos_embed'}
778
+
779
+ @torch.jit.ignore
780
+ def no_weight_decay_keywords(self):
781
+ return {'relative_position_bias_table'}
782
+
783
+ def check_image_size(self, x):
784
+ _, _, h, w = x.size()
785
+ mod_pad_h = (self.window_size - h % self.window_size) % self.window_size
786
+ mod_pad_w = (self.window_size - w % self.window_size) % self.window_size
787
+ x = F.pad(x, (0, mod_pad_w, 0, mod_pad_h), 'reflect')
788
+ return x
789
+
790
+ def forward_features(self, x):
791
+ x_size = (x.shape[2], x.shape[3])
792
+ x = self.patch_embed(x)
793
+ if self.ape:
794
+ x = x + self.absolute_pos_embed
795
+ x = self.pos_drop(x)
796
+
797
+ for layer in self.layers:
798
+ x = layer(x, x_size)
799
+
800
+ x = self.norm(x) # B L C
801
+ x = self.patch_unembed(x, x_size)
802
+
803
+ return x
804
+
805
+ def forward(self, x):
806
+ H, W = x.shape[2:]
807
+ x = self.check_image_size(x)
808
+
809
+ self.mean = self.mean.type_as(x)
810
+ x = (x - self.mean) * self.img_range
811
+
812
+ if self.upsampler == 'pixelshuffle':
813
+ # for classical SR
814
+ x = self.conv_first(x)
815
+ x = self.conv_after_body(self.forward_features(x)) + x
816
+ x = self.conv_before_upsample(x)
817
+ x = self.conv_last(self.upsample(x))
818
+ elif self.upsampler == 'pixelshuffledirect':
819
+ # for lightweight SR
820
+ x = self.conv_first(x)
821
+ x = self.conv_after_body(self.forward_features(x)) + x
822
+ x = self.upsample(x)
823
+ elif self.upsampler == 'nearest+conv':
824
+ # for real-world SR
825
+ x = self.conv_first(x)
826
+ x = self.conv_after_body(self.forward_features(x)) + x
827
+ x = self.conv_before_upsample(x)
828
+ x = self.lrelu(self.conv_up1(torch.nn.functional.interpolate(x, scale_factor=2, mode='nearest')))
829
+ if self.upscale == 4:
830
+ x = self.lrelu(self.conv_up2(torch.nn.functional.interpolate(x, scale_factor=2, mode='nearest')))
831
+ x = self.conv_last(self.lrelu(self.conv_hr(x)))
832
+ else:
833
+ # for image denoising and JPEG compression artifact reduction
834
+ x_first = self.conv_first(x)
835
+ res = self.conv_after_body(self.forward_features(x_first)) + x_first
836
+ x = x + self.conv_last(res)
837
+
838
+ x = x / self.img_range + self.mean
839
+
840
+ return x[:, :, :H*self.upscale, :W*self.upscale]
841
+
842
+ def flops(self):
843
+ flops = 0
844
+ H, W = self.patches_resolution
845
+ flops += H * W * 3 * self.embed_dim * 9
846
+ flops += self.patch_embed.flops()
847
+ for i, layer in enumerate(self.layers):
848
+ flops += layer.flops()
849
+ flops += H * W * 3 * self.embed_dim * self.embed_dim
850
+ flops += self.upsample.flops()
851
+ return flops
852
+
853
+
854
+ if __name__ == '__main__':
855
+ upscale = 4
856
+ window_size = 8
857
+ height = (1024 // upscale // window_size + 1) * window_size
858
+ width = (720 // upscale // window_size + 1) * window_size
859
+ model = SwinIR(upscale=2, img_size=(height, width),
860
+ window_size=window_size, img_range=1., depths=[6, 6, 6, 6],
861
+ embed_dim=60, num_heads=[6, 6, 6, 6], mlp_ratio=2, upsampler='pixelshuffledirect')
862
+ print(model)
863
+ print(height, width, model.flops() / 1e9)
864
+
865
+ x = torch.randn((1, 3, height, width))
866
+ x = model(x)
867
+ print(x.shape)
extensions-builtin/SwinIR/swinir_model_arch_v2.py ADDED
@@ -0,0 +1,1017 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -----------------------------------------------------------------------------------
2
+ # Swin2SR: Swin2SR: SwinV2 Transformer for Compressed Image Super-Resolution and Restoration, https://arxiv.org/abs/
3
+ # Written by Conde and Choi et al.
4
+ # -----------------------------------------------------------------------------------
5
+
6
+ import math
7
+ import numpy as np
8
+ import torch
9
+ import torch.nn as nn
10
+ import torch.nn.functional as F
11
+ import torch.utils.checkpoint as checkpoint
12
+ from timm.models.layers import DropPath, to_2tuple, trunc_normal_
13
+
14
+
15
+ class Mlp(nn.Module):
16
+ def __init__(self, in_features, hidden_features=None, out_features=None, act_layer=nn.GELU, drop=0.):
17
+ super().__init__()
18
+ out_features = out_features or in_features
19
+ hidden_features = hidden_features or in_features
20
+ self.fc1 = nn.Linear(in_features, hidden_features)
21
+ self.act = act_layer()
22
+ self.fc2 = nn.Linear(hidden_features, out_features)
23
+ self.drop = nn.Dropout(drop)
24
+
25
+ def forward(self, x):
26
+ x = self.fc1(x)
27
+ x = self.act(x)
28
+ x = self.drop(x)
29
+ x = self.fc2(x)
30
+ x = self.drop(x)
31
+ return x
32
+
33
+
34
+ def window_partition(x, window_size):
35
+ """
36
+ Args:
37
+ x: (B, H, W, C)
38
+ window_size (int): window size
39
+ Returns:
40
+ windows: (num_windows*B, window_size, window_size, C)
41
+ """
42
+ B, H, W, C = x.shape
43
+ x = x.view(B, H // window_size, window_size, W // window_size, window_size, C)
44
+ windows = x.permute(0, 1, 3, 2, 4, 5).contiguous().view(-1, window_size, window_size, C)
45
+ return windows
46
+
47
+
48
+ def window_reverse(windows, window_size, H, W):
49
+ """
50
+ Args:
51
+ windows: (num_windows*B, window_size, window_size, C)
52
+ window_size (int): Window size
53
+ H (int): Height of image
54
+ W (int): Width of image
55
+ Returns:
56
+ x: (B, H, W, C)
57
+ """
58
+ B = int(windows.shape[0] / (H * W / window_size / window_size))
59
+ x = windows.view(B, H // window_size, W // window_size, window_size, window_size, -1)
60
+ x = x.permute(0, 1, 3, 2, 4, 5).contiguous().view(B, H, W, -1)
61
+ return x
62
+
63
+ class WindowAttention(nn.Module):
64
+ r""" Window based multi-head self attention (W-MSA) module with relative position bias.
65
+ It supports both of shifted and non-shifted window.
66
+ Args:
67
+ dim (int): Number of input channels.
68
+ window_size (tuple[int]): The height and width of the window.
69
+ num_heads (int): Number of attention heads.
70
+ qkv_bias (bool, optional): If True, add a learnable bias to query, key, value. Default: True
71
+ attn_drop (float, optional): Dropout ratio of attention weight. Default: 0.0
72
+ proj_drop (float, optional): Dropout ratio of output. Default: 0.0
73
+ pretrained_window_size (tuple[int]): The height and width of the window in pre-training.
74
+ """
75
+
76
+ def __init__(self, dim, window_size, num_heads, qkv_bias=True, attn_drop=0., proj_drop=0.,
77
+ pretrained_window_size=[0, 0]):
78
+
79
+ super().__init__()
80
+ self.dim = dim
81
+ self.window_size = window_size # Wh, Ww
82
+ self.pretrained_window_size = pretrained_window_size
83
+ self.num_heads = num_heads
84
+
85
+ self.logit_scale = nn.Parameter(torch.log(10 * torch.ones((num_heads, 1, 1))), requires_grad=True)
86
+
87
+ # mlp to generate continuous relative position bias
88
+ self.cpb_mlp = nn.Sequential(nn.Linear(2, 512, bias=True),
89
+ nn.ReLU(inplace=True),
90
+ nn.Linear(512, num_heads, bias=False))
91
+
92
+ # get relative_coords_table
93
+ relative_coords_h = torch.arange(-(self.window_size[0] - 1), self.window_size[0], dtype=torch.float32)
94
+ relative_coords_w = torch.arange(-(self.window_size[1] - 1), self.window_size[1], dtype=torch.float32)
95
+ relative_coords_table = torch.stack(
96
+ torch.meshgrid([relative_coords_h,
97
+ relative_coords_w])).permute(1, 2, 0).contiguous().unsqueeze(0) # 1, 2*Wh-1, 2*Ww-1, 2
98
+ if pretrained_window_size[0] > 0:
99
+ relative_coords_table[:, :, :, 0] /= (pretrained_window_size[0] - 1)
100
+ relative_coords_table[:, :, :, 1] /= (pretrained_window_size[1] - 1)
101
+ else:
102
+ relative_coords_table[:, :, :, 0] /= (self.window_size[0] - 1)
103
+ relative_coords_table[:, :, :, 1] /= (self.window_size[1] - 1)
104
+ relative_coords_table *= 8 # normalize to -8, 8
105
+ relative_coords_table = torch.sign(relative_coords_table) * torch.log2(
106
+ torch.abs(relative_coords_table) + 1.0) / np.log2(8)
107
+
108
+ self.register_buffer("relative_coords_table", relative_coords_table)
109
+
110
+ # get pair-wise relative position index for each token inside the window
111
+ coords_h = torch.arange(self.window_size[0])
112
+ coords_w = torch.arange(self.window_size[1])
113
+ coords = torch.stack(torch.meshgrid([coords_h, coords_w])) # 2, Wh, Ww
114
+ coords_flatten = torch.flatten(coords, 1) # 2, Wh*Ww
115
+ relative_coords = coords_flatten[:, :, None] - coords_flatten[:, None, :] # 2, Wh*Ww, Wh*Ww
116
+ relative_coords = relative_coords.permute(1, 2, 0).contiguous() # Wh*Ww, Wh*Ww, 2
117
+ relative_coords[:, :, 0] += self.window_size[0] - 1 # shift to start from 0
118
+ relative_coords[:, :, 1] += self.window_size[1] - 1
119
+ relative_coords[:, :, 0] *= 2 * self.window_size[1] - 1
120
+ relative_position_index = relative_coords.sum(-1) # Wh*Ww, Wh*Ww
121
+ self.register_buffer("relative_position_index", relative_position_index)
122
+
123
+ self.qkv = nn.Linear(dim, dim * 3, bias=False)
124
+ if qkv_bias:
125
+ self.q_bias = nn.Parameter(torch.zeros(dim))
126
+ self.v_bias = nn.Parameter(torch.zeros(dim))
127
+ else:
128
+ self.q_bias = None
129
+ self.v_bias = None
130
+ self.attn_drop = nn.Dropout(attn_drop)
131
+ self.proj = nn.Linear(dim, dim)
132
+ self.proj_drop = nn.Dropout(proj_drop)
133
+ self.softmax = nn.Softmax(dim=-1)
134
+
135
+ def forward(self, x, mask=None):
136
+ """
137
+ Args:
138
+ x: input features with shape of (num_windows*B, N, C)
139
+ mask: (0/-inf) mask with shape of (num_windows, Wh*Ww, Wh*Ww) or None
140
+ """
141
+ B_, N, C = x.shape
142
+ qkv_bias = None
143
+ if self.q_bias is not None:
144
+ qkv_bias = torch.cat((self.q_bias, torch.zeros_like(self.v_bias, requires_grad=False), self.v_bias))
145
+ qkv = F.linear(input=x, weight=self.qkv.weight, bias=qkv_bias)
146
+ qkv = qkv.reshape(B_, N, 3, self.num_heads, -1).permute(2, 0, 3, 1, 4)
147
+ q, k, v = qkv[0], qkv[1], qkv[2] # make torchscript happy (cannot use tensor as tuple)
148
+
149
+ # cosine attention
150
+ attn = (F.normalize(q, dim=-1) @ F.normalize(k, dim=-1).transpose(-2, -1))
151
+ logit_scale = torch.clamp(self.logit_scale, max=torch.log(torch.tensor(1. / 0.01)).to(self.logit_scale.device)).exp()
152
+ attn = attn * logit_scale
153
+
154
+ relative_position_bias_table = self.cpb_mlp(self.relative_coords_table).view(-1, self.num_heads)
155
+ relative_position_bias = relative_position_bias_table[self.relative_position_index.view(-1)].view(
156
+ self.window_size[0] * self.window_size[1], self.window_size[0] * self.window_size[1], -1) # Wh*Ww,Wh*Ww,nH
157
+ relative_position_bias = relative_position_bias.permute(2, 0, 1).contiguous() # nH, Wh*Ww, Wh*Ww
158
+ relative_position_bias = 16 * torch.sigmoid(relative_position_bias)
159
+ attn = attn + relative_position_bias.unsqueeze(0)
160
+
161
+ if mask is not None:
162
+ nW = mask.shape[0]
163
+ attn = attn.view(B_ // nW, nW, self.num_heads, N, N) + mask.unsqueeze(1).unsqueeze(0)
164
+ attn = attn.view(-1, self.num_heads, N, N)
165
+ attn = self.softmax(attn)
166
+ else:
167
+ attn = self.softmax(attn)
168
+
169
+ attn = self.attn_drop(attn)
170
+
171
+ x = (attn @ v).transpose(1, 2).reshape(B_, N, C)
172
+ x = self.proj(x)
173
+ x = self.proj_drop(x)
174
+ return x
175
+
176
+ def extra_repr(self) -> str:
177
+ return f'dim={self.dim}, window_size={self.window_size}, ' \
178
+ f'pretrained_window_size={self.pretrained_window_size}, num_heads={self.num_heads}'
179
+
180
+ def flops(self, N):
181
+ # calculate flops for 1 window with token length of N
182
+ flops = 0
183
+ # qkv = self.qkv(x)
184
+ flops += N * self.dim * 3 * self.dim
185
+ # attn = (q @ k.transpose(-2, -1))
186
+ flops += self.num_heads * N * (self.dim // self.num_heads) * N
187
+ # x = (attn @ v)
188
+ flops += self.num_heads * N * N * (self.dim // self.num_heads)
189
+ # x = self.proj(x)
190
+ flops += N * self.dim * self.dim
191
+ return flops
192
+
193
+ class SwinTransformerBlock(nn.Module):
194
+ r""" Swin Transformer Block.
195
+ Args:
196
+ dim (int): Number of input channels.
197
+ input_resolution (tuple[int]): Input resulotion.
198
+ num_heads (int): Number of attention heads.
199
+ window_size (int): Window size.
200
+ shift_size (int): Shift size for SW-MSA.
201
+ mlp_ratio (float): Ratio of mlp hidden dim to embedding dim.
202
+ qkv_bias (bool, optional): If True, add a learnable bias to query, key, value. Default: True
203
+ drop (float, optional): Dropout rate. Default: 0.0
204
+ attn_drop (float, optional): Attention dropout rate. Default: 0.0
205
+ drop_path (float, optional): Stochastic depth rate. Default: 0.0
206
+ act_layer (nn.Module, optional): Activation layer. Default: nn.GELU
207
+ norm_layer (nn.Module, optional): Normalization layer. Default: nn.LayerNorm
208
+ pretrained_window_size (int): Window size in pre-training.
209
+ """
210
+
211
+ def __init__(self, dim, input_resolution, num_heads, window_size=7, shift_size=0,
212
+ mlp_ratio=4., qkv_bias=True, drop=0., attn_drop=0., drop_path=0.,
213
+ act_layer=nn.GELU, norm_layer=nn.LayerNorm, pretrained_window_size=0):
214
+ super().__init__()
215
+ self.dim = dim
216
+ self.input_resolution = input_resolution
217
+ self.num_heads = num_heads
218
+ self.window_size = window_size
219
+ self.shift_size = shift_size
220
+ self.mlp_ratio = mlp_ratio
221
+ if min(self.input_resolution) <= self.window_size:
222
+ # if window size is larger than input resolution, we don't partition windows
223
+ self.shift_size = 0
224
+ self.window_size = min(self.input_resolution)
225
+ assert 0 <= self.shift_size < self.window_size, "shift_size must in 0-window_size"
226
+
227
+ self.norm1 = norm_layer(dim)
228
+ self.attn = WindowAttention(
229
+ dim, window_size=to_2tuple(self.window_size), num_heads=num_heads,
230
+ qkv_bias=qkv_bias, attn_drop=attn_drop, proj_drop=drop,
231
+ pretrained_window_size=to_2tuple(pretrained_window_size))
232
+
233
+ self.drop_path = DropPath(drop_path) if drop_path > 0. else nn.Identity()
234
+ self.norm2 = norm_layer(dim)
235
+ mlp_hidden_dim = int(dim * mlp_ratio)
236
+ self.mlp = Mlp(in_features=dim, hidden_features=mlp_hidden_dim, act_layer=act_layer, drop=drop)
237
+
238
+ if self.shift_size > 0:
239
+ attn_mask = self.calculate_mask(self.input_resolution)
240
+ else:
241
+ attn_mask = None
242
+
243
+ self.register_buffer("attn_mask", attn_mask)
244
+
245
+ def calculate_mask(self, x_size):
246
+ # calculate attention mask for SW-MSA
247
+ H, W = x_size
248
+ img_mask = torch.zeros((1, H, W, 1)) # 1 H W 1
249
+ h_slices = (slice(0, -self.window_size),
250
+ slice(-self.window_size, -self.shift_size),
251
+ slice(-self.shift_size, None))
252
+ w_slices = (slice(0, -self.window_size),
253
+ slice(-self.window_size, -self.shift_size),
254
+ slice(-self.shift_size, None))
255
+ cnt = 0
256
+ for h in h_slices:
257
+ for w in w_slices:
258
+ img_mask[:, h, w, :] = cnt
259
+ cnt += 1
260
+
261
+ mask_windows = window_partition(img_mask, self.window_size) # nW, window_size, window_size, 1
262
+ mask_windows = mask_windows.view(-1, self.window_size * self.window_size)
263
+ attn_mask = mask_windows.unsqueeze(1) - mask_windows.unsqueeze(2)
264
+ attn_mask = attn_mask.masked_fill(attn_mask != 0, float(-100.0)).masked_fill(attn_mask == 0, float(0.0))
265
+
266
+ return attn_mask
267
+
268
+ def forward(self, x, x_size):
269
+ H, W = x_size
270
+ B, L, C = x.shape
271
+ #assert L == H * W, "input feature has wrong size"
272
+
273
+ shortcut = x
274
+ x = x.view(B, H, W, C)
275
+
276
+ # cyclic shift
277
+ if self.shift_size > 0:
278
+ shifted_x = torch.roll(x, shifts=(-self.shift_size, -self.shift_size), dims=(1, 2))
279
+ else:
280
+ shifted_x = x
281
+
282
+ # partition windows
283
+ x_windows = window_partition(shifted_x, self.window_size) # nW*B, window_size, window_size, C
284
+ x_windows = x_windows.view(-1, self.window_size * self.window_size, C) # nW*B, window_size*window_size, C
285
+
286
+ # W-MSA/SW-MSA (to be compatible for testing on images whose shapes are the multiple of window size
287
+ if self.input_resolution == x_size:
288
+ attn_windows = self.attn(x_windows, mask=self.attn_mask) # nW*B, window_size*window_size, C
289
+ else:
290
+ attn_windows = self.attn(x_windows, mask=self.calculate_mask(x_size).to(x.device))
291
+
292
+ # merge windows
293
+ attn_windows = attn_windows.view(-1, self.window_size, self.window_size, C)
294
+ shifted_x = window_reverse(attn_windows, self.window_size, H, W) # B H' W' C
295
+
296
+ # reverse cyclic shift
297
+ if self.shift_size > 0:
298
+ x = torch.roll(shifted_x, shifts=(self.shift_size, self.shift_size), dims=(1, 2))
299
+ else:
300
+ x = shifted_x
301
+ x = x.view(B, H * W, C)
302
+ x = shortcut + self.drop_path(self.norm1(x))
303
+
304
+ # FFN
305
+ x = x + self.drop_path(self.norm2(self.mlp(x)))
306
+
307
+ return x
308
+
309
+ def extra_repr(self) -> str:
310
+ return f"dim={self.dim}, input_resolution={self.input_resolution}, num_heads={self.num_heads}, " \
311
+ f"window_size={self.window_size}, shift_size={self.shift_size}, mlp_ratio={self.mlp_ratio}"
312
+
313
+ def flops(self):
314
+ flops = 0
315
+ H, W = self.input_resolution
316
+ # norm1
317
+ flops += self.dim * H * W
318
+ # W-MSA/SW-MSA
319
+ nW = H * W / self.window_size / self.window_size
320
+ flops += nW * self.attn.flops(self.window_size * self.window_size)
321
+ # mlp
322
+ flops += 2 * H * W * self.dim * self.dim * self.mlp_ratio
323
+ # norm2
324
+ flops += self.dim * H * W
325
+ return flops
326
+
327
+ class PatchMerging(nn.Module):
328
+ r""" Patch Merging Layer.
329
+ Args:
330
+ input_resolution (tuple[int]): Resolution of input feature.
331
+ dim (int): Number of input channels.
332
+ norm_layer (nn.Module, optional): Normalization layer. Default: nn.LayerNorm
333
+ """
334
+
335
+ def __init__(self, input_resolution, dim, norm_layer=nn.LayerNorm):
336
+ super().__init__()
337
+ self.input_resolution = input_resolution
338
+ self.dim = dim
339
+ self.reduction = nn.Linear(4 * dim, 2 * dim, bias=False)
340
+ self.norm = norm_layer(2 * dim)
341
+
342
+ def forward(self, x):
343
+ """
344
+ x: B, H*W, C
345
+ """
346
+ H, W = self.input_resolution
347
+ B, L, C = x.shape
348
+ assert L == H * W, "input feature has wrong size"
349
+ assert H % 2 == 0 and W % 2 == 0, f"x size ({H}*{W}) are not even."
350
+
351
+ x = x.view(B, H, W, C)
352
+
353
+ x0 = x[:, 0::2, 0::2, :] # B H/2 W/2 C
354
+ x1 = x[:, 1::2, 0::2, :] # B H/2 W/2 C
355
+ x2 = x[:, 0::2, 1::2, :] # B H/2 W/2 C
356
+ x3 = x[:, 1::2, 1::2, :] # B H/2 W/2 C
357
+ x = torch.cat([x0, x1, x2, x3], -1) # B H/2 W/2 4*C
358
+ x = x.view(B, -1, 4 * C) # B H/2*W/2 4*C
359
+
360
+ x = self.reduction(x)
361
+ x = self.norm(x)
362
+
363
+ return x
364
+
365
+ def extra_repr(self) -> str:
366
+ return f"input_resolution={self.input_resolution}, dim={self.dim}"
367
+
368
+ def flops(self):
369
+ H, W = self.input_resolution
370
+ flops = (H // 2) * (W // 2) * 4 * self.dim * 2 * self.dim
371
+ flops += H * W * self.dim // 2
372
+ return flops
373
+
374
+ class BasicLayer(nn.Module):
375
+ """ A basic Swin Transformer layer for one stage.
376
+ Args:
377
+ dim (int): Number of input channels.
378
+ input_resolution (tuple[int]): Input resolution.
379
+ depth (int): Number of blocks.
380
+ num_heads (int): Number of attention heads.
381
+ window_size (int): Local window size.
382
+ mlp_ratio (float): Ratio of mlp hidden dim to embedding dim.
383
+ qkv_bias (bool, optional): If True, add a learnable bias to query, key, value. Default: True
384
+ drop (float, optional): Dropout rate. Default: 0.0
385
+ attn_drop (float, optional): Attention dropout rate. Default: 0.0
386
+ drop_path (float | tuple[float], optional): Stochastic depth rate. Default: 0.0
387
+ norm_layer (nn.Module, optional): Normalization layer. Default: nn.LayerNorm
388
+ downsample (nn.Module | None, optional): Downsample layer at the end of the layer. Default: None
389
+ use_checkpoint (bool): Whether to use checkpointing to save memory. Default: False.
390
+ pretrained_window_size (int): Local window size in pre-training.
391
+ """
392
+
393
+ def __init__(self, dim, input_resolution, depth, num_heads, window_size,
394
+ mlp_ratio=4., qkv_bias=True, drop=0., attn_drop=0.,
395
+ drop_path=0., norm_layer=nn.LayerNorm, downsample=None, use_checkpoint=False,
396
+ pretrained_window_size=0):
397
+
398
+ super().__init__()
399
+ self.dim = dim
400
+ self.input_resolution = input_resolution
401
+ self.depth = depth
402
+ self.use_checkpoint = use_checkpoint
403
+
404
+ # build blocks
405
+ self.blocks = nn.ModuleList([
406
+ SwinTransformerBlock(dim=dim, input_resolution=input_resolution,
407
+ num_heads=num_heads, window_size=window_size,
408
+ shift_size=0 if (i % 2 == 0) else window_size // 2,
409
+ mlp_ratio=mlp_ratio,
410
+ qkv_bias=qkv_bias,
411
+ drop=drop, attn_drop=attn_drop,
412
+ drop_path=drop_path[i] if isinstance(drop_path, list) else drop_path,
413
+ norm_layer=norm_layer,
414
+ pretrained_window_size=pretrained_window_size)
415
+ for i in range(depth)])
416
+
417
+ # patch merging layer
418
+ if downsample is not None:
419
+ self.downsample = downsample(input_resolution, dim=dim, norm_layer=norm_layer)
420
+ else:
421
+ self.downsample = None
422
+
423
+ def forward(self, x, x_size):
424
+ for blk in self.blocks:
425
+ if self.use_checkpoint:
426
+ x = checkpoint.checkpoint(blk, x, x_size)
427
+ else:
428
+ x = blk(x, x_size)
429
+ if self.downsample is not None:
430
+ x = self.downsample(x)
431
+ return x
432
+
433
+ def extra_repr(self) -> str:
434
+ return f"dim={self.dim}, input_resolution={self.input_resolution}, depth={self.depth}"
435
+
436
+ def flops(self):
437
+ flops = 0
438
+ for blk in self.blocks:
439
+ flops += blk.flops()
440
+ if self.downsample is not None:
441
+ flops += self.downsample.flops()
442
+ return flops
443
+
444
+ def _init_respostnorm(self):
445
+ for blk in self.blocks:
446
+ nn.init.constant_(blk.norm1.bias, 0)
447
+ nn.init.constant_(blk.norm1.weight, 0)
448
+ nn.init.constant_(blk.norm2.bias, 0)
449
+ nn.init.constant_(blk.norm2.weight, 0)
450
+
451
+ class PatchEmbed(nn.Module):
452
+ r""" Image to Patch Embedding
453
+ Args:
454
+ img_size (int): Image size. Default: 224.
455
+ patch_size (int): Patch token size. Default: 4.
456
+ in_chans (int): Number of input image channels. Default: 3.
457
+ embed_dim (int): Number of linear projection output channels. Default: 96.
458
+ norm_layer (nn.Module, optional): Normalization layer. Default: None
459
+ """
460
+
461
+ def __init__(self, img_size=224, patch_size=4, in_chans=3, embed_dim=96, norm_layer=None):
462
+ super().__init__()
463
+ img_size = to_2tuple(img_size)
464
+ patch_size = to_2tuple(patch_size)
465
+ patches_resolution = [img_size[0] // patch_size[0], img_size[1] // patch_size[1]]
466
+ self.img_size = img_size
467
+ self.patch_size = patch_size
468
+ self.patches_resolution = patches_resolution
469
+ self.num_patches = patches_resolution[0] * patches_resolution[1]
470
+
471
+ self.in_chans = in_chans
472
+ self.embed_dim = embed_dim
473
+
474
+ self.proj = nn.Conv2d(in_chans, embed_dim, kernel_size=patch_size, stride=patch_size)
475
+ if norm_layer is not None:
476
+ self.norm = norm_layer(embed_dim)
477
+ else:
478
+ self.norm = None
479
+
480
+ def forward(self, x):
481
+ B, C, H, W = x.shape
482
+ # FIXME look at relaxing size constraints
483
+ # assert H == self.img_size[0] and W == self.img_size[1],
484
+ # f"Input image size ({H}*{W}) doesn't match model ({self.img_size[0]}*{self.img_size[1]})."
485
+ x = self.proj(x).flatten(2).transpose(1, 2) # B Ph*Pw C
486
+ if self.norm is not None:
487
+ x = self.norm(x)
488
+ return x
489
+
490
+ def flops(self):
491
+ Ho, Wo = self.patches_resolution
492
+ flops = Ho * Wo * self.embed_dim * self.in_chans * (self.patch_size[0] * self.patch_size[1])
493
+ if self.norm is not None:
494
+ flops += Ho * Wo * self.embed_dim
495
+ return flops
496
+
497
+ class RSTB(nn.Module):
498
+ """Residual Swin Transformer Block (RSTB).
499
+
500
+ Args:
501
+ dim (int): Number of input channels.
502
+ input_resolution (tuple[int]): Input resolution.
503
+ depth (int): Number of blocks.
504
+ num_heads (int): Number of attention heads.
505
+ window_size (int): Local window size.
506
+ mlp_ratio (float): Ratio of mlp hidden dim to embedding dim.
507
+ qkv_bias (bool, optional): If True, add a learnable bias to query, key, value. Default: True
508
+ drop (float, optional): Dropout rate. Default: 0.0
509
+ attn_drop (float, optional): Attention dropout rate. Default: 0.0
510
+ drop_path (float | tuple[float], optional): Stochastic depth rate. Default: 0.0
511
+ norm_layer (nn.Module, optional): Normalization layer. Default: nn.LayerNorm
512
+ downsample (nn.Module | None, optional): Downsample layer at the end of the layer. Default: None
513
+ use_checkpoint (bool): Whether to use checkpointing to save memory. Default: False.
514
+ img_size: Input image size.
515
+ patch_size: Patch size.
516
+ resi_connection: The convolutional block before residual connection.
517
+ """
518
+
519
+ def __init__(self, dim, input_resolution, depth, num_heads, window_size,
520
+ mlp_ratio=4., qkv_bias=True, drop=0., attn_drop=0.,
521
+ drop_path=0., norm_layer=nn.LayerNorm, downsample=None, use_checkpoint=False,
522
+ img_size=224, patch_size=4, resi_connection='1conv'):
523
+ super(RSTB, self).__init__()
524
+
525
+ self.dim = dim
526
+ self.input_resolution = input_resolution
527
+
528
+ self.residual_group = BasicLayer(dim=dim,
529
+ input_resolution=input_resolution,
530
+ depth=depth,
531
+ num_heads=num_heads,
532
+ window_size=window_size,
533
+ mlp_ratio=mlp_ratio,
534
+ qkv_bias=qkv_bias,
535
+ drop=drop, attn_drop=attn_drop,
536
+ drop_path=drop_path,
537
+ norm_layer=norm_layer,
538
+ downsample=downsample,
539
+ use_checkpoint=use_checkpoint)
540
+
541
+ if resi_connection == '1conv':
542
+ self.conv = nn.Conv2d(dim, dim, 3, 1, 1)
543
+ elif resi_connection == '3conv':
544
+ # to save parameters and memory
545
+ self.conv = nn.Sequential(nn.Conv2d(dim, dim // 4, 3, 1, 1), nn.LeakyReLU(negative_slope=0.2, inplace=True),
546
+ nn.Conv2d(dim // 4, dim // 4, 1, 1, 0),
547
+ nn.LeakyReLU(negative_slope=0.2, inplace=True),
548
+ nn.Conv2d(dim // 4, dim, 3, 1, 1))
549
+
550
+ self.patch_embed = PatchEmbed(
551
+ img_size=img_size, patch_size=patch_size, in_chans=dim, embed_dim=dim,
552
+ norm_layer=None)
553
+
554
+ self.patch_unembed = PatchUnEmbed(
555
+ img_size=img_size, patch_size=patch_size, in_chans=dim, embed_dim=dim,
556
+ norm_layer=None)
557
+
558
+ def forward(self, x, x_size):
559
+ return self.patch_embed(self.conv(self.patch_unembed(self.residual_group(x, x_size), x_size))) + x
560
+
561
+ def flops(self):
562
+ flops = 0
563
+ flops += self.residual_group.flops()
564
+ H, W = self.input_resolution
565
+ flops += H * W * self.dim * self.dim * 9
566
+ flops += self.patch_embed.flops()
567
+ flops += self.patch_unembed.flops()
568
+
569
+ return flops
570
+
571
+ class PatchUnEmbed(nn.Module):
572
+ r""" Image to Patch Unembedding
573
+
574
+ Args:
575
+ img_size (int): Image size. Default: 224.
576
+ patch_size (int): Patch token size. Default: 4.
577
+ in_chans (int): Number of input image channels. Default: 3.
578
+ embed_dim (int): Number of linear projection output channels. Default: 96.
579
+ norm_layer (nn.Module, optional): Normalization layer. Default: None
580
+ """
581
+
582
+ def __init__(self, img_size=224, patch_size=4, in_chans=3, embed_dim=96, norm_layer=None):
583
+ super().__init__()
584
+ img_size = to_2tuple(img_size)
585
+ patch_size = to_2tuple(patch_size)
586
+ patches_resolution = [img_size[0] // patch_size[0], img_size[1] // patch_size[1]]
587
+ self.img_size = img_size
588
+ self.patch_size = patch_size
589
+ self.patches_resolution = patches_resolution
590
+ self.num_patches = patches_resolution[0] * patches_resolution[1]
591
+
592
+ self.in_chans = in_chans
593
+ self.embed_dim = embed_dim
594
+
595
+ def forward(self, x, x_size):
596
+ B, HW, C = x.shape
597
+ x = x.transpose(1, 2).view(B, self.embed_dim, x_size[0], x_size[1]) # B Ph*Pw C
598
+ return x
599
+
600
+ def flops(self):
601
+ flops = 0
602
+ return flops
603
+
604
+
605
+ class Upsample(nn.Sequential):
606
+ """Upsample module.
607
+
608
+ Args:
609
+ scale (int): Scale factor. Supported scales: 2^n and 3.
610
+ num_feat (int): Channel number of intermediate features.
611
+ """
612
+
613
+ def __init__(self, scale, num_feat):
614
+ m = []
615
+ if (scale & (scale - 1)) == 0: # scale = 2^n
616
+ for _ in range(int(math.log(scale, 2))):
617
+ m.append(nn.Conv2d(num_feat, 4 * num_feat, 3, 1, 1))
618
+ m.append(nn.PixelShuffle(2))
619
+ elif scale == 3:
620
+ m.append(nn.Conv2d(num_feat, 9 * num_feat, 3, 1, 1))
621
+ m.append(nn.PixelShuffle(3))
622
+ else:
623
+ raise ValueError(f'scale {scale} is not supported. ' 'Supported scales: 2^n and 3.')
624
+ super(Upsample, self).__init__(*m)
625
+
626
+ class Upsample_hf(nn.Sequential):
627
+ """Upsample module.
628
+
629
+ Args:
630
+ scale (int): Scale factor. Supported scales: 2^n and 3.
631
+ num_feat (int): Channel number of intermediate features.
632
+ """
633
+
634
+ def __init__(self, scale, num_feat):
635
+ m = []
636
+ if (scale & (scale - 1)) == 0: # scale = 2^n
637
+ for _ in range(int(math.log(scale, 2))):
638
+ m.append(nn.Conv2d(num_feat, 4 * num_feat, 3, 1, 1))
639
+ m.append(nn.PixelShuffle(2))
640
+ elif scale == 3:
641
+ m.append(nn.Conv2d(num_feat, 9 * num_feat, 3, 1, 1))
642
+ m.append(nn.PixelShuffle(3))
643
+ else:
644
+ raise ValueError(f'scale {scale} is not supported. ' 'Supported scales: 2^n and 3.')
645
+ super(Upsample_hf, self).__init__(*m)
646
+
647
+
648
+ class UpsampleOneStep(nn.Sequential):
649
+ """UpsampleOneStep module (the difference with Upsample is that it always only has 1conv + 1pixelshuffle)
650
+ Used in lightweight SR to save parameters.
651
+
652
+ Args:
653
+ scale (int): Scale factor. Supported scales: 2^n and 3.
654
+ num_feat (int): Channel number of intermediate features.
655
+
656
+ """
657
+
658
+ def __init__(self, scale, num_feat, num_out_ch, input_resolution=None):
659
+ self.num_feat = num_feat
660
+ self.input_resolution = input_resolution
661
+ m = []
662
+ m.append(nn.Conv2d(num_feat, (scale ** 2) * num_out_ch, 3, 1, 1))
663
+ m.append(nn.PixelShuffle(scale))
664
+ super(UpsampleOneStep, self).__init__(*m)
665
+
666
+ def flops(self):
667
+ H, W = self.input_resolution
668
+ flops = H * W * self.num_feat * 3 * 9
669
+ return flops
670
+
671
+
672
+
673
+ class Swin2SR(nn.Module):
674
+ r""" Swin2SR
675
+ A PyTorch impl of : `Swin2SR: SwinV2 Transformer for Compressed Image Super-Resolution and Restoration`.
676
+
677
+ Args:
678
+ img_size (int | tuple(int)): Input image size. Default 64
679
+ patch_size (int | tuple(int)): Patch size. Default: 1
680
+ in_chans (int): Number of input image channels. Default: 3
681
+ embed_dim (int): Patch embedding dimension. Default: 96
682
+ depths (tuple(int)): Depth of each Swin Transformer layer.
683
+ num_heads (tuple(int)): Number of attention heads in different layers.
684
+ window_size (int): Window size. Default: 7
685
+ mlp_ratio (float): Ratio of mlp hidden dim to embedding dim. Default: 4
686
+ qkv_bias (bool): If True, add a learnable bias to query, key, value. Default: True
687
+ drop_rate (float): Dropout rate. Default: 0
688
+ attn_drop_rate (float): Attention dropout rate. Default: 0
689
+ drop_path_rate (float): Stochastic depth rate. Default: 0.1
690
+ norm_layer (nn.Module): Normalization layer. Default: nn.LayerNorm.
691
+ ape (bool): If True, add absolute position embedding to the patch embedding. Default: False
692
+ patch_norm (bool): If True, add normalization after patch embedding. Default: True
693
+ use_checkpoint (bool): Whether to use checkpointing to save memory. Default: False
694
+ upscale: Upscale factor. 2/3/4/8 for image SR, 1 for denoising and compress artifact reduction
695
+ img_range: Image range. 1. or 255.
696
+ upsampler: The reconstruction reconstruction module. 'pixelshuffle'/'pixelshuffledirect'/'nearest+conv'/None
697
+ resi_connection: The convolutional block before residual connection. '1conv'/'3conv'
698
+ """
699
+
700
+ def __init__(self, img_size=64, patch_size=1, in_chans=3,
701
+ embed_dim=96, depths=[6, 6, 6, 6], num_heads=[6, 6, 6, 6],
702
+ window_size=7, mlp_ratio=4., qkv_bias=True,
703
+ drop_rate=0., attn_drop_rate=0., drop_path_rate=0.1,
704
+ norm_layer=nn.LayerNorm, ape=False, patch_norm=True,
705
+ use_checkpoint=False, upscale=2, img_range=1., upsampler='', resi_connection='1conv',
706
+ **kwargs):
707
+ super(Swin2SR, self).__init__()
708
+ num_in_ch = in_chans
709
+ num_out_ch = in_chans
710
+ num_feat = 64
711
+ self.img_range = img_range
712
+ if in_chans == 3:
713
+ rgb_mean = (0.4488, 0.4371, 0.4040)
714
+ self.mean = torch.Tensor(rgb_mean).view(1, 3, 1, 1)
715
+ else:
716
+ self.mean = torch.zeros(1, 1, 1, 1)
717
+ self.upscale = upscale
718
+ self.upsampler = upsampler
719
+ self.window_size = window_size
720
+
721
+ #####################################################################################################
722
+ ################################### 1, shallow feature extraction ###################################
723
+ self.conv_first = nn.Conv2d(num_in_ch, embed_dim, 3, 1, 1)
724
+
725
+ #####################################################################################################
726
+ ################################### 2, deep feature extraction ######################################
727
+ self.num_layers = len(depths)
728
+ self.embed_dim = embed_dim
729
+ self.ape = ape
730
+ self.patch_norm = patch_norm
731
+ self.num_features = embed_dim
732
+ self.mlp_ratio = mlp_ratio
733
+
734
+ # split image into non-overlapping patches
735
+ self.patch_embed = PatchEmbed(
736
+ img_size=img_size, patch_size=patch_size, in_chans=embed_dim, embed_dim=embed_dim,
737
+ norm_layer=norm_layer if self.patch_norm else None)
738
+ num_patches = self.patch_embed.num_patches
739
+ patches_resolution = self.patch_embed.patches_resolution
740
+ self.patches_resolution = patches_resolution
741
+
742
+ # merge non-overlapping patches into image
743
+ self.patch_unembed = PatchUnEmbed(
744
+ img_size=img_size, patch_size=patch_size, in_chans=embed_dim, embed_dim=embed_dim,
745
+ norm_layer=norm_layer if self.patch_norm else None)
746
+
747
+ # absolute position embedding
748
+ if self.ape:
749
+ self.absolute_pos_embed = nn.Parameter(torch.zeros(1, num_patches, embed_dim))
750
+ trunc_normal_(self.absolute_pos_embed, std=.02)
751
+
752
+ self.pos_drop = nn.Dropout(p=drop_rate)
753
+
754
+ # stochastic depth
755
+ dpr = [x.item() for x in torch.linspace(0, drop_path_rate, sum(depths))] # stochastic depth decay rule
756
+
757
+ # build Residual Swin Transformer blocks (RSTB)
758
+ self.layers = nn.ModuleList()
759
+ for i_layer in range(self.num_layers):
760
+ layer = RSTB(dim=embed_dim,
761
+ input_resolution=(patches_resolution[0],
762
+ patches_resolution[1]),
763
+ depth=depths[i_layer],
764
+ num_heads=num_heads[i_layer],
765
+ window_size=window_size,
766
+ mlp_ratio=self.mlp_ratio,
767
+ qkv_bias=qkv_bias,
768
+ drop=drop_rate, attn_drop=attn_drop_rate,
769
+ drop_path=dpr[sum(depths[:i_layer]):sum(depths[:i_layer + 1])], # no impact on SR results
770
+ norm_layer=norm_layer,
771
+ downsample=None,
772
+ use_checkpoint=use_checkpoint,
773
+ img_size=img_size,
774
+ patch_size=patch_size,
775
+ resi_connection=resi_connection
776
+
777
+ )
778
+ self.layers.append(layer)
779
+
780
+ if self.upsampler == 'pixelshuffle_hf':
781
+ self.layers_hf = nn.ModuleList()
782
+ for i_layer in range(self.num_layers):
783
+ layer = RSTB(dim=embed_dim,
784
+ input_resolution=(patches_resolution[0],
785
+ patches_resolution[1]),
786
+ depth=depths[i_layer],
787
+ num_heads=num_heads[i_layer],
788
+ window_size=window_size,
789
+ mlp_ratio=self.mlp_ratio,
790
+ qkv_bias=qkv_bias,
791
+ drop=drop_rate, attn_drop=attn_drop_rate,
792
+ drop_path=dpr[sum(depths[:i_layer]):sum(depths[:i_layer + 1])], # no impact on SR results
793
+ norm_layer=norm_layer,
794
+ downsample=None,
795
+ use_checkpoint=use_checkpoint,
796
+ img_size=img_size,
797
+ patch_size=patch_size,
798
+ resi_connection=resi_connection
799
+
800
+ )
801
+ self.layers_hf.append(layer)
802
+
803
+ self.norm = norm_layer(self.num_features)
804
+
805
+ # build the last conv layer in deep feature extraction
806
+ if resi_connection == '1conv':
807
+ self.conv_after_body = nn.Conv2d(embed_dim, embed_dim, 3, 1, 1)
808
+ elif resi_connection == '3conv':
809
+ # to save parameters and memory
810
+ self.conv_after_body = nn.Sequential(nn.Conv2d(embed_dim, embed_dim // 4, 3, 1, 1),
811
+ nn.LeakyReLU(negative_slope=0.2, inplace=True),
812
+ nn.Conv2d(embed_dim // 4, embed_dim // 4, 1, 1, 0),
813
+ nn.LeakyReLU(negative_slope=0.2, inplace=True),
814
+ nn.Conv2d(embed_dim // 4, embed_dim, 3, 1, 1))
815
+
816
+ #####################################################################################################
817
+ ################################ 3, high quality image reconstruction ################################
818
+ if self.upsampler == 'pixelshuffle':
819
+ # for classical SR
820
+ self.conv_before_upsample = nn.Sequential(nn.Conv2d(embed_dim, num_feat, 3, 1, 1),
821
+ nn.LeakyReLU(inplace=True))
822
+ self.upsample = Upsample(upscale, num_feat)
823
+ self.conv_last = nn.Conv2d(num_feat, num_out_ch, 3, 1, 1)
824
+ elif self.upsampler == 'pixelshuffle_aux':
825
+ self.conv_bicubic = nn.Conv2d(num_in_ch, num_feat, 3, 1, 1)
826
+ self.conv_before_upsample = nn.Sequential(
827
+ nn.Conv2d(embed_dim, num_feat, 3, 1, 1),
828
+ nn.LeakyReLU(inplace=True))
829
+ self.conv_aux = nn.Conv2d(num_feat, num_out_ch, 3, 1, 1)
830
+ self.conv_after_aux = nn.Sequential(
831
+ nn.Conv2d(3, num_feat, 3, 1, 1),
832
+ nn.LeakyReLU(inplace=True))
833
+ self.upsample = Upsample(upscale, num_feat)
834
+ self.conv_last = nn.Conv2d(num_feat, num_out_ch, 3, 1, 1)
835
+
836
+ elif self.upsampler == 'pixelshuffle_hf':
837
+ self.conv_before_upsample = nn.Sequential(nn.Conv2d(embed_dim, num_feat, 3, 1, 1),
838
+ nn.LeakyReLU(inplace=True))
839
+ self.upsample = Upsample(upscale, num_feat)
840
+ self.upsample_hf = Upsample_hf(upscale, num_feat)
841
+ self.conv_last = nn.Conv2d(num_feat, num_out_ch, 3, 1, 1)
842
+ self.conv_first_hf = nn.Sequential(nn.Conv2d(num_feat, embed_dim, 3, 1, 1),
843
+ nn.LeakyReLU(inplace=True))
844
+ self.conv_after_body_hf = nn.Conv2d(embed_dim, embed_dim, 3, 1, 1)
845
+ self.conv_before_upsample_hf = nn.Sequential(
846
+ nn.Conv2d(embed_dim, num_feat, 3, 1, 1),
847
+ nn.LeakyReLU(inplace=True))
848
+ self.conv_last_hf = nn.Conv2d(num_feat, num_out_ch, 3, 1, 1)
849
+
850
+ elif self.upsampler == 'pixelshuffledirect':
851
+ # for lightweight SR (to save parameters)
852
+ self.upsample = UpsampleOneStep(upscale, embed_dim, num_out_ch,
853
+ (patches_resolution[0], patches_resolution[1]))
854
+ elif self.upsampler == 'nearest+conv':
855
+ # for real-world SR (less artifacts)
856
+ assert self.upscale == 4, 'only support x4 now.'
857
+ self.conv_before_upsample = nn.Sequential(nn.Conv2d(embed_dim, num_feat, 3, 1, 1),
858
+ nn.LeakyReLU(inplace=True))
859
+ self.conv_up1 = nn.Conv2d(num_feat, num_feat, 3, 1, 1)
860
+ self.conv_up2 = nn.Conv2d(num_feat, num_feat, 3, 1, 1)
861
+ self.conv_hr = nn.Conv2d(num_feat, num_feat, 3, 1, 1)
862
+ self.conv_last = nn.Conv2d(num_feat, num_out_ch, 3, 1, 1)
863
+ self.lrelu = nn.LeakyReLU(negative_slope=0.2, inplace=True)
864
+ else:
865
+ # for image denoising and JPEG compression artifact reduction
866
+ self.conv_last = nn.Conv2d(embed_dim, num_out_ch, 3, 1, 1)
867
+
868
+ self.apply(self._init_weights)
869
+
870
+ def _init_weights(self, m):
871
+ if isinstance(m, nn.Linear):
872
+ trunc_normal_(m.weight, std=.02)
873
+ if isinstance(m, nn.Linear) and m.bias is not None:
874
+ nn.init.constant_(m.bias, 0)
875
+ elif isinstance(m, nn.LayerNorm):
876
+ nn.init.constant_(m.bias, 0)
877
+ nn.init.constant_(m.weight, 1.0)
878
+
879
+ @torch.jit.ignore
880
+ def no_weight_decay(self):
881
+ return {'absolute_pos_embed'}
882
+
883
+ @torch.jit.ignore
884
+ def no_weight_decay_keywords(self):
885
+ return {'relative_position_bias_table'}
886
+
887
+ def check_image_size(self, x):
888
+ _, _, h, w = x.size()
889
+ mod_pad_h = (self.window_size - h % self.window_size) % self.window_size
890
+ mod_pad_w = (self.window_size - w % self.window_size) % self.window_size
891
+ x = F.pad(x, (0, mod_pad_w, 0, mod_pad_h), 'reflect')
892
+ return x
893
+
894
+ def forward_features(self, x):
895
+ x_size = (x.shape[2], x.shape[3])
896
+ x = self.patch_embed(x)
897
+ if self.ape:
898
+ x = x + self.absolute_pos_embed
899
+ x = self.pos_drop(x)
900
+
901
+ for layer in self.layers:
902
+ x = layer(x, x_size)
903
+
904
+ x = self.norm(x) # B L C
905
+ x = self.patch_unembed(x, x_size)
906
+
907
+ return x
908
+
909
+ def forward_features_hf(self, x):
910
+ x_size = (x.shape[2], x.shape[3])
911
+ x = self.patch_embed(x)
912
+ if self.ape:
913
+ x = x + self.absolute_pos_embed
914
+ x = self.pos_drop(x)
915
+
916
+ for layer in self.layers_hf:
917
+ x = layer(x, x_size)
918
+
919
+ x = self.norm(x) # B L C
920
+ x = self.patch_unembed(x, x_size)
921
+
922
+ return x
923
+
924
+ def forward(self, x):
925
+ H, W = x.shape[2:]
926
+ x = self.check_image_size(x)
927
+
928
+ self.mean = self.mean.type_as(x)
929
+ x = (x - self.mean) * self.img_range
930
+
931
+ if self.upsampler == 'pixelshuffle':
932
+ # for classical SR
933
+ x = self.conv_first(x)
934
+ x = self.conv_after_body(self.forward_features(x)) + x
935
+ x = self.conv_before_upsample(x)
936
+ x = self.conv_last(self.upsample(x))
937
+ elif self.upsampler == 'pixelshuffle_aux':
938
+ bicubic = F.interpolate(x, size=(H * self.upscale, W * self.upscale), mode='bicubic', align_corners=False)
939
+ bicubic = self.conv_bicubic(bicubic)
940
+ x = self.conv_first(x)
941
+ x = self.conv_after_body(self.forward_features(x)) + x
942
+ x = self.conv_before_upsample(x)
943
+ aux = self.conv_aux(x) # b, 3, LR_H, LR_W
944
+ x = self.conv_after_aux(aux)
945
+ x = self.upsample(x)[:, :, :H * self.upscale, :W * self.upscale] + bicubic[:, :, :H * self.upscale, :W * self.upscale]
946
+ x = self.conv_last(x)
947
+ aux = aux / self.img_range + self.mean
948
+ elif self.upsampler == 'pixelshuffle_hf':
949
+ # for classical SR with HF
950
+ x = self.conv_first(x)
951
+ x = self.conv_after_body(self.forward_features(x)) + x
952
+ x_before = self.conv_before_upsample(x)
953
+ x_out = self.conv_last(self.upsample(x_before))
954
+
955
+ x_hf = self.conv_first_hf(x_before)
956
+ x_hf = self.conv_after_body_hf(self.forward_features_hf(x_hf)) + x_hf
957
+ x_hf = self.conv_before_upsample_hf(x_hf)
958
+ x_hf = self.conv_last_hf(self.upsample_hf(x_hf))
959
+ x = x_out + x_hf
960
+ x_hf = x_hf / self.img_range + self.mean
961
+
962
+ elif self.upsampler == 'pixelshuffledirect':
963
+ # for lightweight SR
964
+ x = self.conv_first(x)
965
+ x = self.conv_after_body(self.forward_features(x)) + x
966
+ x = self.upsample(x)
967
+ elif self.upsampler == 'nearest+conv':
968
+ # for real-world SR
969
+ x = self.conv_first(x)
970
+ x = self.conv_after_body(self.forward_features(x)) + x
971
+ x = self.conv_before_upsample(x)
972
+ x = self.lrelu(self.conv_up1(torch.nn.functional.interpolate(x, scale_factor=2, mode='nearest')))
973
+ x = self.lrelu(self.conv_up2(torch.nn.functional.interpolate(x, scale_factor=2, mode='nearest')))
974
+ x = self.conv_last(self.lrelu(self.conv_hr(x)))
975
+ else:
976
+ # for image denoising and JPEG compression artifact reduction
977
+ x_first = self.conv_first(x)
978
+ res = self.conv_after_body(self.forward_features(x_first)) + x_first
979
+ x = x + self.conv_last(res)
980
+
981
+ x = x / self.img_range + self.mean
982
+ if self.upsampler == "pixelshuffle_aux":
983
+ return x[:, :, :H*self.upscale, :W*self.upscale], aux
984
+
985
+ elif self.upsampler == "pixelshuffle_hf":
986
+ x_out = x_out / self.img_range + self.mean
987
+ return x_out[:, :, :H*self.upscale, :W*self.upscale], x[:, :, :H*self.upscale, :W*self.upscale], x_hf[:, :, :H*self.upscale, :W*self.upscale]
988
+
989
+ else:
990
+ return x[:, :, :H*self.upscale, :W*self.upscale]
991
+
992
+ def flops(self):
993
+ flops = 0
994
+ H, W = self.patches_resolution
995
+ flops += H * W * 3 * self.embed_dim * 9
996
+ flops += self.patch_embed.flops()
997
+ for i, layer in enumerate(self.layers):
998
+ flops += layer.flops()
999
+ flops += H * W * 3 * self.embed_dim * self.embed_dim
1000
+ flops += self.upsample.flops()
1001
+ return flops
1002
+
1003
+
1004
+ if __name__ == '__main__':
1005
+ upscale = 4
1006
+ window_size = 8
1007
+ height = (1024 // upscale // window_size + 1) * window_size
1008
+ width = (720 // upscale // window_size + 1) * window_size
1009
+ model = Swin2SR(upscale=2, img_size=(height, width),
1010
+ window_size=window_size, img_range=1., depths=[6, 6, 6, 6],
1011
+ embed_dim=60, num_heads=[6, 6, 6, 6], mlp_ratio=2, upsampler='pixelshuffledirect')
1012
+ print(model)
1013
+ print(height, width, model.flops() / 1e9)
1014
+
1015
+ x = torch.randn((1, 3, height, width))
1016
+ x = model(x)
1017
+ print(x.shape)
extensions-builtin/prompt-bracket-checker/javascript/prompt-bracket-checker.js ADDED
@@ -0,0 +1,110 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Stable Diffusion WebUI - Bracket checker
2
+ // Version 1.0
3
+ // By Hingashi no Florin/Bwin4L
4
+ // Counts open and closed brackets (round, square, curly) in the prompt and negative prompt text boxes in the txt2img and img2img tabs.
5
+ // If there's a mismatch, the keyword counter turns red and if you hover on it, a tooltip tells you what's wrong.
6
+
7
+ function checkBrackets(evt, textArea, counterElt) {
8
+ errorStringParen = '(...) - Different number of opening and closing parentheses detected.\n';
9
+ errorStringSquare = '[...] - Different number of opening and closing square brackets detected.\n';
10
+ errorStringCurly = '{...} - Different number of opening and closing curly brackets detected.\n';
11
+
12
+ openBracketRegExp = /\(/g;
13
+ closeBracketRegExp = /\)/g;
14
+
15
+ openSquareBracketRegExp = /\[/g;
16
+ closeSquareBracketRegExp = /\]/g;
17
+
18
+ openCurlyBracketRegExp = /\{/g;
19
+ closeCurlyBracketRegExp = /\}/g;
20
+
21
+ totalOpenBracketMatches = 0;
22
+ totalCloseBracketMatches = 0;
23
+ totalOpenSquareBracketMatches = 0;
24
+ totalCloseSquareBracketMatches = 0;
25
+ totalOpenCurlyBracketMatches = 0;
26
+ totalCloseCurlyBracketMatches = 0;
27
+
28
+ openBracketMatches = textArea.value.match(openBracketRegExp);
29
+ if(openBracketMatches) {
30
+ totalOpenBracketMatches = openBracketMatches.length;
31
+ }
32
+
33
+ closeBracketMatches = textArea.value.match(closeBracketRegExp);
34
+ if(closeBracketMatches) {
35
+ totalCloseBracketMatches = closeBracketMatches.length;
36
+ }
37
+
38
+ openSquareBracketMatches = textArea.value.match(openSquareBracketRegExp);
39
+ if(openSquareBracketMatches) {
40
+ totalOpenSquareBracketMatches = openSquareBracketMatches.length;
41
+ }
42
+
43
+ closeSquareBracketMatches = textArea.value.match(closeSquareBracketRegExp);
44
+ if(closeSquareBracketMatches) {
45
+ totalCloseSquareBracketMatches = closeSquareBracketMatches.length;
46
+ }
47
+
48
+ openCurlyBracketMatches = textArea.value.match(openCurlyBracketRegExp);
49
+ if(openCurlyBracketMatches) {
50
+ totalOpenCurlyBracketMatches = openCurlyBracketMatches.length;
51
+ }
52
+
53
+ closeCurlyBracketMatches = textArea.value.match(closeCurlyBracketRegExp);
54
+ if(closeCurlyBracketMatches) {
55
+ totalCloseCurlyBracketMatches = closeCurlyBracketMatches.length;
56
+ }
57
+
58
+ if(totalOpenBracketMatches != totalCloseBracketMatches) {
59
+ if(!counterElt.title.includes(errorStringParen)) {
60
+ counterElt.title += errorStringParen;
61
+ }
62
+ } else {
63
+ counterElt.title = counterElt.title.replace(errorStringParen, '');
64
+ }
65
+
66
+ if(totalOpenSquareBracketMatches != totalCloseSquareBracketMatches) {
67
+ if(!counterElt.title.includes(errorStringSquare)) {
68
+ counterElt.title += errorStringSquare;
69
+ }
70
+ } else {
71
+ counterElt.title = counterElt.title.replace(errorStringSquare, '');
72
+ }
73
+
74
+ if(totalOpenCurlyBracketMatches != totalCloseCurlyBracketMatches) {
75
+ if(!counterElt.title.includes(errorStringCurly)) {
76
+ counterElt.title += errorStringCurly;
77
+ }
78
+ } else {
79
+ counterElt.title = counterElt.title.replace(errorStringCurly, '');
80
+ }
81
+
82
+ if(counterElt.title != '') {
83
+ counterElt.classList.add('error');
84
+ } else {
85
+ counterElt.classList.remove('error');
86
+ }
87
+ }
88
+
89
+ function setupBracketChecking(id_prompt, id_counter){
90
+ var textarea = gradioApp().querySelector("#" + id_prompt + " > label > textarea");
91
+ var counter = gradioApp().getElementById(id_counter)
92
+ textarea.addEventListener("input", function(evt){
93
+ checkBrackets(evt, textarea, counter)
94
+ });
95
+ }
96
+
97
+ var shadowRootLoaded = setInterval(function() {
98
+ var shadowRoot = document.querySelector('gradio-app').shadowRoot;
99
+ if(! shadowRoot) return false;
100
+
101
+ var shadowTextArea = shadowRoot.querySelectorAll('#txt2img_prompt > label > textarea');
102
+ if(shadowTextArea.length < 1) return false;
103
+
104
+ clearInterval(shadowRootLoaded);
105
+
106
+ setupBracketChecking('txt2img_prompt', 'txt2img_token_counter')
107
+ setupBracketChecking('txt2img_neg_prompt', 'txt2img_negative_token_counter')
108
+ setupBracketChecking('img2img_prompt', 'imgimg_token_counter')
109
+ setupBracketChecking('img2img_neg_prompt', 'img2img_negative_token_counter')
110
+ }, 1000);
handler.py ADDED
@@ -0,0 +1,226 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import sys
3
+ import time
4
+ import importlib
5
+ import signal
6
+ import re
7
+ from typing import Dict, List, Any
8
+ # from fastapi import FastAPI
9
+ # from fastapi.middleware.cors import CORSMiddleware
10
+ # from fastapi.middleware.gzip import GZipMiddleware
11
+ from packaging import version
12
+
13
+ import logging
14
+ logging.getLogger("xformers").addFilter(lambda record: 'A matching Triton is not available' not in record.getMessage())
15
+
16
+ from modules import import_hook, errors, extra_networks, ui_extra_networks_checkpoints
17
+ from modules import extra_networks_hypernet, ui_extra_networks_hypernets, ui_extra_networks_textual_inversion
18
+ from modules.call_queue import wrap_queued_call, queue_lock, wrap_gradio_gpu_call
19
+
20
+ import torch
21
+
22
+ # Truncate version number of nightly/local build of PyTorch to not cause exceptions with CodeFormer or Safetensors
23
+ if ".dev" in torch.__version__ or "+git" in torch.__version__:
24
+ torch.__long_version__ = torch.__version__
25
+ torch.__version__ = re.search(r'[\d.]+[\d]', torch.__version__).group(0)
26
+
27
+ from modules import shared, devices, sd_samplers, upscaler, extensions, localization, ui_tempdir, ui_extra_networks
28
+ import modules.codeformer_model as codeformer
29
+ import modules.face_restoration
30
+ import modules.gfpgan_model as gfpgan
31
+ import modules.img2img
32
+
33
+ import modules.lowvram
34
+ import modules.paths
35
+ import modules.scripts
36
+ import modules.sd_hijack
37
+ import modules.sd_models
38
+ import modules.sd_vae
39
+ import modules.txt2img
40
+ import modules.script_callbacks
41
+ import modules.textual_inversion.textual_inversion
42
+ import modules.progress
43
+
44
+ import modules.ui
45
+ from modules import modelloader
46
+ from modules.shared import cmd_opts, opts
47
+ import modules.hypernetworks.hypernetwork
48
+
49
+ from modules.processing import StableDiffusionProcessingTxt2Img, StableDiffusionProcessingImg2Img, process_images
50
+ import base64
51
+ import io
52
+ from fastapi import HTTPException
53
+ from io import BytesIO
54
+ import piexif
55
+ import piexif.helper
56
+ from PIL import PngImagePlugin,Image
57
+
58
+
59
+ def initialize():
60
+ # check_versions()
61
+
62
+ # extensions.list_extensions()
63
+ # localization.list_localizations(cmd_opts.localizations_dir)
64
+
65
+ # if cmd_opts.ui_debug_mode:
66
+ # shared.sd_upscalers = upscaler.UpscalerLanczos().scalers
67
+ # modules.scripts.load_scripts()
68
+ # return
69
+
70
+ modelloader.cleanup_models()
71
+ modules.sd_models.setup_model()
72
+ codeformer.setup_model(cmd_opts.codeformer_models_path)
73
+ gfpgan.setup_model(cmd_opts.gfpgan_models_path)
74
+
75
+ modelloader.list_builtin_upscalers()
76
+ # modules.scripts.load_scripts()
77
+ modelloader.load_upscalers()
78
+
79
+ modules.sd_vae.refresh_vae_list()
80
+
81
+ # modules.textual_inversion.textual_inversion.list_textual_inversion_templates()
82
+
83
+ try:
84
+ modules.sd_models.load_model()
85
+ except Exception as e:
86
+ errors.display(e, "loading stable diffusion model")
87
+ print("", file=sys.stderr)
88
+ print("Stable diffusion model failed to load, exiting", file=sys.stderr)
89
+ exit(1)
90
+
91
+ shared.opts.data["sd_model_checkpoint"] = shared.sd_model.sd_checkpoint_info.title
92
+
93
+ shared.opts.onchange("sd_model_checkpoint", wrap_queued_call(lambda: modules.sd_models.reload_model_weights()))
94
+ shared.opts.onchange("sd_vae", wrap_queued_call(lambda: modules.sd_vae.reload_vae_weights()), call=False)
95
+ shared.opts.onchange("sd_vae_as_default", wrap_queued_call(lambda: modules.sd_vae.reload_vae_weights()), call=False)
96
+ shared.opts.onchange("temp_dir", ui_tempdir.on_tmpdir_changed)
97
+
98
+ # shared.reload_hypernetworks()
99
+
100
+ # ui_extra_networks.intialize()
101
+ # ui_extra_networks.register_page(ui_extra_networks_textual_inversion.ExtraNetworksPageTextualInversion())
102
+ # ui_extra_networks.register_page(ui_extra_networks_hypernets.ExtraNetworksPageHypernetworks())
103
+ # ui_extra_networks.register_page(ui_extra_networks_checkpoints.ExtraNetworksPageCheckpoints())
104
+
105
+ # extra_networks.initialize()
106
+ # extra_networks.register_extra_network(extra_networks_hypernet.ExtraNetworkHypernet())
107
+
108
+ # if cmd_opts.tls_keyfile is not None and cmd_opts.tls_keyfile is not None:
109
+
110
+ # try:
111
+ # if not os.path.exists(cmd_opts.tls_keyfile):
112
+ # print("Invalid path to TLS keyfile given")
113
+ # if not os.path.exists(cmd_opts.tls_certfile):
114
+ # print(f"Invalid path to TLS certfile: '{cmd_opts.tls_certfile}'")
115
+ # except TypeError:
116
+ # cmd_opts.tls_keyfile = cmd_opts.tls_certfile = None
117
+ # print("TLS setup invalid, running webui without TLS")
118
+ # else:
119
+ # print("Running with TLS")
120
+
121
+ # make the program just exit at ctrl+c without waiting for anything
122
+ def sigint_handler(sig, frame):
123
+ print(f'Interrupted with signal {sig} in {frame}')
124
+ os._exit(0)
125
+
126
+ signal.signal(signal.SIGINT, sigint_handler)
127
+
128
+
129
+ class EndpointHandler():
130
+ def __init__(self, path=""):
131
+ # Preload all the elements you are going to need at inference.
132
+ # pseudo:
133
+ # self.model= load_model(path)
134
+ initialize()
135
+ self.shared = shared
136
+
137
+ def __call__(self, data: Dict[str, Any]) -> List[Dict[str, Any]]:
138
+ """
139
+ data args:
140
+ inputs (:obj: `str` | `PIL.Image` | `np.array`)
141
+ kwargs
142
+ Return:
143
+ A :obj:`list` | `dict`: will be serialized and returned
144
+ """
145
+ args = {
146
+ "outpath_samples": "C:\\Users\\wolvz\\Desktop",
147
+ "prompt": "lora:koreanDollLikeness_v15:0.66, best quality, ultra high res, (photorealistic:1.4), 1girl, beige sweater, black choker, smile, laughing, bare shoulders, solo focus, ((full body), (brown hair:1), looking at viewer",
148
+ "negative_prompt": "paintings, sketches, (worst quality:2), (low quality:2), (normal quality:2), lowres, normal quality, ((monochrome)), ((grayscale)), skin spots, acnes, skin blemishes, age spot, glans",
149
+ "sampler_name": "DPM++ SDE Karras",
150
+ "steps": 20, # 25
151
+ "cfg_scale": 8,
152
+ "width": 512,
153
+ "height": 768,
154
+ "seed": -1,
155
+ }
156
+ if "prompt" in data.keys():
157
+ args["prompt"] = data["prompt"]
158
+ p = StableDiffusionProcessingTxt2Img(sd_model=self.shared.sd_model, **args)
159
+ processed = process_images(p)
160
+ single_image_b64 = encode_pil_to_base64(processed.images[0])
161
+ return {
162
+ "img_data": single_image_b64,
163
+ }
164
+
165
+
166
+ def manual_hack():
167
+ initialize()
168
+ args = {
169
+ "outpath_samples": "C:\\Users\\wolvz\\Desktop",
170
+ "prompt": "lora:koreanDollLikeness_v15:0.66, best quality, ultra high res, (photorealistic:1.4), 1girl, beige sweater, black choker, smile, laughing, bare shoulders, solo focus, ((full body), (brown hair:1), looking at viewer",
171
+ "negative_prompt": "paintings, sketches, (worst quality:2), (low quality:2), (normal quality:2), lowres, normal quality, ((monochrome)), ((grayscale)), skin spots, acnes, skin blemishes, age spot, glans",
172
+ "sampler_name": "DPM++ SDE Karras",
173
+ "steps": 20, # 25
174
+ "cfg_scale": 8,
175
+ "width": 512,
176
+ "height": 768,
177
+ "seed": -1,
178
+ }
179
+ p = StableDiffusionProcessingTxt2Img(sd_model=shared.sd_model, **args)
180
+ processed = process_images(p)
181
+
182
+
183
+ def decode_base64_to_image(encoding):
184
+ if encoding.startswith("data:image/"):
185
+ encoding = encoding.split(";")[1].split(",")[1]
186
+ try:
187
+ image = Image.open(BytesIO(base64.b64decode(encoding)))
188
+ return image
189
+ except Exception as err:
190
+ raise HTTPException(status_code=500, detail="Invalid encoded image")
191
+
192
+ def encode_pil_to_base64(image):
193
+ with io.BytesIO() as output_bytes:
194
+
195
+ if opts.samples_format.lower() == 'png':
196
+ use_metadata = False
197
+ metadata = PngImagePlugin.PngInfo()
198
+ for key, value in image.info.items():
199
+ if isinstance(key, str) and isinstance(value, str):
200
+ metadata.add_text(key, value)
201
+ use_metadata = True
202
+ image.save(output_bytes, format="PNG", pnginfo=(metadata if use_metadata else None), quality=opts.jpeg_quality)
203
+
204
+ elif opts.samples_format.lower() in ("jpg", "jpeg", "webp"):
205
+ parameters = image.info.get('parameters', None)
206
+ exif_bytes = piexif.dump({
207
+ "Exif": { piexif.ExifIFD.UserComment: piexif.helper.UserComment.dump(parameters or "", encoding="unicode") }
208
+ })
209
+ if opts.samples_format.lower() in ("jpg", "jpeg"):
210
+ image.save(output_bytes, format="JPEG", exif = exif_bytes, quality=opts.jpeg_quality)
211
+ else:
212
+ image.save(output_bytes, format="WEBP", exif = exif_bytes, quality=opts.jpeg_quality)
213
+
214
+ else:
215
+ raise HTTPException(status_code=500, detail="Invalid image format")
216
+
217
+ bytes_data = output_bytes.getvalue()
218
+
219
+ return base64.b64encode(bytes_data)
220
+
221
+
222
+ if __name__ == "__main__":
223
+ # manual_hack()
224
+ handler = EndpointHandler("./")
225
+ res = handler.__call__({})
226
+ # print(res)
modules/api/api.py ADDED
@@ -0,0 +1,551 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import base64
2
+ import io
3
+ import time
4
+ import datetime
5
+ import uvicorn
6
+ from threading import Lock
7
+ from io import BytesIO
8
+ from gradio.processing_utils import decode_base64_to_file
9
+ from fastapi import APIRouter, Depends, FastAPI, HTTPException, Request, Response
10
+ from fastapi.security import HTTPBasic, HTTPBasicCredentials
11
+ from secrets import compare_digest
12
+
13
+ import modules.shared as shared
14
+ from modules import sd_samplers, deepbooru, sd_hijack, images, scripts, ui, postprocessing
15
+ from modules.api.models import *
16
+ from modules.processing import StableDiffusionProcessingTxt2Img, StableDiffusionProcessingImg2Img, process_images
17
+ from modules.textual_inversion.textual_inversion import create_embedding, train_embedding
18
+ from modules.textual_inversion.preprocess import preprocess
19
+ from modules.hypernetworks.hypernetwork import create_hypernetwork, train_hypernetwork
20
+ from PIL import PngImagePlugin,Image
21
+ from modules.sd_models import checkpoints_list
22
+ from modules.sd_models_config import find_checkpoint_config_near_filename
23
+ from modules.realesrgan_model import get_realesrgan_models
24
+ from modules import devices
25
+ from typing import List
26
+ import piexif
27
+ import piexif.helper
28
+
29
+ def upscaler_to_index(name: str):
30
+ try:
31
+ return [x.name.lower() for x in shared.sd_upscalers].index(name.lower())
32
+ except:
33
+ raise HTTPException(status_code=400, detail=f"Invalid upscaler, needs to be one of these: {' , '.join([x.name for x in sd_upscalers])}")
34
+
35
+ def script_name_to_index(name, scripts):
36
+ try:
37
+ return [script.title().lower() for script in scripts].index(name.lower())
38
+ except:
39
+ raise HTTPException(status_code=422, detail=f"Script '{name}' not found")
40
+
41
+ def validate_sampler_name(name):
42
+ config = sd_samplers.all_samplers_map.get(name, None)
43
+ if config is None:
44
+ raise HTTPException(status_code=404, detail="Sampler not found")
45
+
46
+ return name
47
+
48
+ def setUpscalers(req: dict):
49
+ reqDict = vars(req)
50
+ reqDict['extras_upscaler_1'] = reqDict.pop('upscaler_1', None)
51
+ reqDict['extras_upscaler_2'] = reqDict.pop('upscaler_2', None)
52
+ return reqDict
53
+
54
+ def decode_base64_to_image(encoding):
55
+ if encoding.startswith("data:image/"):
56
+ encoding = encoding.split(";")[1].split(",")[1]
57
+ try:
58
+ image = Image.open(BytesIO(base64.b64decode(encoding)))
59
+ return image
60
+ except Exception as err:
61
+ raise HTTPException(status_code=500, detail="Invalid encoded image")
62
+
63
+ def encode_pil_to_base64(image):
64
+ with io.BytesIO() as output_bytes:
65
+
66
+ if opts.samples_format.lower() == 'png':
67
+ use_metadata = False
68
+ metadata = PngImagePlugin.PngInfo()
69
+ for key, value in image.info.items():
70
+ if isinstance(key, str) and isinstance(value, str):
71
+ metadata.add_text(key, value)
72
+ use_metadata = True
73
+ image.save(output_bytes, format="PNG", pnginfo=(metadata if use_metadata else None), quality=opts.jpeg_quality)
74
+
75
+ elif opts.samples_format.lower() in ("jpg", "jpeg", "webp"):
76
+ parameters = image.info.get('parameters', None)
77
+ exif_bytes = piexif.dump({
78
+ "Exif": { piexif.ExifIFD.UserComment: piexif.helper.UserComment.dump(parameters or "", encoding="unicode") }
79
+ })
80
+ if opts.samples_format.lower() in ("jpg", "jpeg"):
81
+ image.save(output_bytes, format="JPEG", exif = exif_bytes, quality=opts.jpeg_quality)
82
+ else:
83
+ image.save(output_bytes, format="WEBP", exif = exif_bytes, quality=opts.jpeg_quality)
84
+
85
+ else:
86
+ raise HTTPException(status_code=500, detail="Invalid image format")
87
+
88
+ bytes_data = output_bytes.getvalue()
89
+
90
+ return base64.b64encode(bytes_data)
91
+
92
+ def api_middleware(app: FastAPI):
93
+ @app.middleware("http")
94
+ async def log_and_time(req: Request, call_next):
95
+ ts = time.time()
96
+ res: Response = await call_next(req)
97
+ duration = str(round(time.time() - ts, 4))
98
+ res.headers["X-Process-Time"] = duration
99
+ endpoint = req.scope.get('path', 'err')
100
+ if shared.cmd_opts.api_log and endpoint.startswith('/sdapi'):
101
+ print('API {t} {code} {prot}/{ver} {method} {endpoint} {cli} {duration}'.format(
102
+ t = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f"),
103
+ code = res.status_code,
104
+ ver = req.scope.get('http_version', '0.0'),
105
+ cli = req.scope.get('client', ('0:0.0.0', 0))[0],
106
+ prot = req.scope.get('scheme', 'err'),
107
+ method = req.scope.get('method', 'err'),
108
+ endpoint = endpoint,
109
+ duration = duration,
110
+ ))
111
+ return res
112
+
113
+
114
+ class Api:
115
+ def __init__(self, app: FastAPI, queue_lock: Lock):
116
+ if shared.cmd_opts.api_auth:
117
+ self.credentials = dict()
118
+ for auth in shared.cmd_opts.api_auth.split(","):
119
+ user, password = auth.split(":")
120
+ self.credentials[user] = password
121
+
122
+ self.router = APIRouter()
123
+ self.app = app
124
+ self.queue_lock = queue_lock
125
+ api_middleware(self.app)
126
+ self.add_api_route("/sdapi/v1/txt2img", self.text2imgapi, methods=["POST"], response_model=TextToImageResponse)
127
+ self.add_api_route("/sdapi/v1/img2img", self.img2imgapi, methods=["POST"], response_model=ImageToImageResponse)
128
+ self.add_api_route("/sdapi/v1/extra-single-image", self.extras_single_image_api, methods=["POST"], response_model=ExtrasSingleImageResponse)
129
+ self.add_api_route("/sdapi/v1/extra-batch-images", self.extras_batch_images_api, methods=["POST"], response_model=ExtrasBatchImagesResponse)
130
+ self.add_api_route("/sdapi/v1/png-info", self.pnginfoapi, methods=["POST"], response_model=PNGInfoResponse)
131
+ self.add_api_route("/sdapi/v1/progress", self.progressapi, methods=["GET"], response_model=ProgressResponse)
132
+ self.add_api_route("/sdapi/v1/interrogate", self.interrogateapi, methods=["POST"])
133
+ self.add_api_route("/sdapi/v1/interrupt", self.interruptapi, methods=["POST"])
134
+ self.add_api_route("/sdapi/v1/skip", self.skip, methods=["POST"])
135
+ self.add_api_route("/sdapi/v1/options", self.get_config, methods=["GET"], response_model=OptionsModel)
136
+ self.add_api_route("/sdapi/v1/options", self.set_config, methods=["POST"])
137
+ self.add_api_route("/sdapi/v1/cmd-flags", self.get_cmd_flags, methods=["GET"], response_model=FlagsModel)
138
+ self.add_api_route("/sdapi/v1/samplers", self.get_samplers, methods=["GET"], response_model=List[SamplerItem])
139
+ self.add_api_route("/sdapi/v1/upscalers", self.get_upscalers, methods=["GET"], response_model=List[UpscalerItem])
140
+ self.add_api_route("/sdapi/v1/sd-models", self.get_sd_models, methods=["GET"], response_model=List[SDModelItem])
141
+ self.add_api_route("/sdapi/v1/hypernetworks", self.get_hypernetworks, methods=["GET"], response_model=List[HypernetworkItem])
142
+ self.add_api_route("/sdapi/v1/face-restorers", self.get_face_restorers, methods=["GET"], response_model=List[FaceRestorerItem])
143
+ self.add_api_route("/sdapi/v1/realesrgan-models", self.get_realesrgan_models, methods=["GET"], response_model=List[RealesrganItem])
144
+ self.add_api_route("/sdapi/v1/prompt-styles", self.get_prompt_styles, methods=["GET"], response_model=List[PromptStyleItem])
145
+ self.add_api_route("/sdapi/v1/embeddings", self.get_embeddings, methods=["GET"], response_model=EmbeddingsResponse)
146
+ self.add_api_route("/sdapi/v1/refresh-checkpoints", self.refresh_checkpoints, methods=["POST"])
147
+ self.add_api_route("/sdapi/v1/create/embedding", self.create_embedding, methods=["POST"], response_model=CreateResponse)
148
+ self.add_api_route("/sdapi/v1/create/hypernetwork", self.create_hypernetwork, methods=["POST"], response_model=CreateResponse)
149
+ self.add_api_route("/sdapi/v1/preprocess", self.preprocess, methods=["POST"], response_model=PreprocessResponse)
150
+ self.add_api_route("/sdapi/v1/train/embedding", self.train_embedding, methods=["POST"], response_model=TrainResponse)
151
+ self.add_api_route("/sdapi/v1/train/hypernetwork", self.train_hypernetwork, methods=["POST"], response_model=TrainResponse)
152
+ self.add_api_route("/sdapi/v1/memory", self.get_memory, methods=["GET"], response_model=MemoryResponse)
153
+
154
+ def add_api_route(self, path: str, endpoint, **kwargs):
155
+ if shared.cmd_opts.api_auth:
156
+ return self.app.add_api_route(path, endpoint, dependencies=[Depends(self.auth)], **kwargs)
157
+ return self.app.add_api_route(path, endpoint, **kwargs)
158
+
159
+ def auth(self, credentials: HTTPBasicCredentials = Depends(HTTPBasic())):
160
+ if credentials.username in self.credentials:
161
+ if compare_digest(credentials.password, self.credentials[credentials.username]):
162
+ return True
163
+
164
+ raise HTTPException(status_code=401, detail="Incorrect username or password", headers={"WWW-Authenticate": "Basic"})
165
+
166
+ def get_script(self, script_name, script_runner):
167
+ if script_name is None:
168
+ return None, None
169
+
170
+ if not script_runner.scripts:
171
+ script_runner.initialize_scripts(False)
172
+ ui.create_ui()
173
+
174
+ script_idx = script_name_to_index(script_name, script_runner.selectable_scripts)
175
+ script = script_runner.selectable_scripts[script_idx]
176
+ return script, script_idx
177
+
178
+ def text2imgapi(self, txt2imgreq: StableDiffusionTxt2ImgProcessingAPI):
179
+ script, script_idx = self.get_script(txt2imgreq.script_name, scripts.scripts_txt2img)
180
+
181
+ populate = txt2imgreq.copy(update={ # Override __init__ params
182
+ "sampler_name": validate_sampler_name(txt2imgreq.sampler_name or txt2imgreq.sampler_index),
183
+ "do_not_save_samples": True,
184
+ "do_not_save_grid": True
185
+ }
186
+ )
187
+ if populate.sampler_name:
188
+ populate.sampler_index = None # prevent a warning later on
189
+
190
+ args = vars(populate)
191
+ args.pop('script_name', None)
192
+
193
+ with self.queue_lock:
194
+ p = StableDiffusionProcessingTxt2Img(sd_model=shared.sd_model, **args)
195
+
196
+ shared.state.begin()
197
+ if script is not None:
198
+ p.outpath_grids = opts.outdir_txt2img_grids
199
+ p.outpath_samples = opts.outdir_txt2img_samples
200
+ p.script_args = [script_idx + 1] + [None] * (script.args_from - 1) + p.script_args
201
+ processed = scripts.scripts_txt2img.run(p, *p.script_args)
202
+ else:
203
+ processed = process_images(p)
204
+ shared.state.end()
205
+
206
+ b64images = list(map(encode_pil_to_base64, processed.images))
207
+
208
+ return TextToImageResponse(images=b64images, parameters=vars(txt2imgreq), info=processed.js())
209
+
210
+ def img2imgapi(self, img2imgreq: StableDiffusionImg2ImgProcessingAPI):
211
+ init_images = img2imgreq.init_images
212
+ if init_images is None:
213
+ raise HTTPException(status_code=404, detail="Init image not found")
214
+
215
+ script, script_idx = self.get_script(img2imgreq.script_name, scripts.scripts_img2img)
216
+
217
+ mask = img2imgreq.mask
218
+ if mask:
219
+ mask = decode_base64_to_image(mask)
220
+
221
+ populate = img2imgreq.copy(update={ # Override __init__ params
222
+ "sampler_name": validate_sampler_name(img2imgreq.sampler_name or img2imgreq.sampler_index),
223
+ "do_not_save_samples": True,
224
+ "do_not_save_grid": True,
225
+ "mask": mask
226
+ }
227
+ )
228
+ if populate.sampler_name:
229
+ populate.sampler_index = None # prevent a warning later on
230
+
231
+ args = vars(populate)
232
+ args.pop('include_init_images', None) # this is meant to be done by "exclude": True in model, but it's for a reason that I cannot determine.
233
+ args.pop('script_name', None)
234
+
235
+ with self.queue_lock:
236
+ p = StableDiffusionProcessingImg2Img(sd_model=shared.sd_model, **args)
237
+ p.init_images = [decode_base64_to_image(x) for x in init_images]
238
+
239
+ shared.state.begin()
240
+ if script is not None:
241
+ p.outpath_grids = opts.outdir_img2img_grids
242
+ p.outpath_samples = opts.outdir_img2img_samples
243
+ p.script_args = [script_idx + 1] + [None] * (script.args_from - 1) + p.script_args
244
+ processed = scripts.scripts_img2img.run(p, *p.script_args)
245
+ else:
246
+ processed = process_images(p)
247
+ shared.state.end()
248
+
249
+ b64images = list(map(encode_pil_to_base64, processed.images))
250
+
251
+ if not img2imgreq.include_init_images:
252
+ img2imgreq.init_images = None
253
+ img2imgreq.mask = None
254
+
255
+ return ImageToImageResponse(images=b64images, parameters=vars(img2imgreq), info=processed.js())
256
+
257
+ def extras_single_image_api(self, req: ExtrasSingleImageRequest):
258
+ reqDict = setUpscalers(req)
259
+
260
+ reqDict['image'] = decode_base64_to_image(reqDict['image'])
261
+
262
+ with self.queue_lock:
263
+ result = postprocessing.run_extras(extras_mode=0, image_folder="", input_dir="", output_dir="", save_output=False, **reqDict)
264
+
265
+ return ExtrasSingleImageResponse(image=encode_pil_to_base64(result[0][0]), html_info=result[1])
266
+
267
+ def extras_batch_images_api(self, req: ExtrasBatchImagesRequest):
268
+ reqDict = setUpscalers(req)
269
+
270
+ def prepareFiles(file):
271
+ file = decode_base64_to_file(file.data, file_path=file.name)
272
+ file.orig_name = file.name
273
+ return file
274
+
275
+ reqDict['image_folder'] = list(map(prepareFiles, reqDict['imageList']))
276
+ reqDict.pop('imageList')
277
+
278
+ with self.queue_lock:
279
+ result = postprocessing.run_extras(extras_mode=1, image="", input_dir="", output_dir="", save_output=False, **reqDict)
280
+
281
+ return ExtrasBatchImagesResponse(images=list(map(encode_pil_to_base64, result[0])), html_info=result[1])
282
+
283
+ def pnginfoapi(self, req: PNGInfoRequest):
284
+ if(not req.image.strip()):
285
+ return PNGInfoResponse(info="")
286
+
287
+ image = decode_base64_to_image(req.image.strip())
288
+ if image is None:
289
+ return PNGInfoResponse(info="")
290
+
291
+ geninfo, items = images.read_info_from_image(image)
292
+ if geninfo is None:
293
+ geninfo = ""
294
+
295
+ items = {**{'parameters': geninfo}, **items}
296
+
297
+ return PNGInfoResponse(info=geninfo, items=items)
298
+
299
+ def progressapi(self, req: ProgressRequest = Depends()):
300
+ # copy from check_progress_call of ui.py
301
+
302
+ if shared.state.job_count == 0:
303
+ return ProgressResponse(progress=0, eta_relative=0, state=shared.state.dict(), textinfo=shared.state.textinfo)
304
+
305
+ # avoid dividing zero
306
+ progress = 0.01
307
+
308
+ if shared.state.job_count > 0:
309
+ progress += shared.state.job_no / shared.state.job_count
310
+ if shared.state.sampling_steps > 0:
311
+ progress += 1 / shared.state.job_count * shared.state.sampling_step / shared.state.sampling_steps
312
+
313
+ time_since_start = time.time() - shared.state.time_start
314
+ eta = (time_since_start/progress)
315
+ eta_relative = eta-time_since_start
316
+
317
+ progress = min(progress, 1)
318
+
319
+ shared.state.set_current_image()
320
+
321
+ current_image = None
322
+ if shared.state.current_image and not req.skip_current_image:
323
+ current_image = encode_pil_to_base64(shared.state.current_image)
324
+
325
+ return ProgressResponse(progress=progress, eta_relative=eta_relative, state=shared.state.dict(), current_image=current_image, textinfo=shared.state.textinfo)
326
+
327
+ def interrogateapi(self, interrogatereq: InterrogateRequest):
328
+ image_b64 = interrogatereq.image
329
+ if image_b64 is None:
330
+ raise HTTPException(status_code=404, detail="Image not found")
331
+
332
+ img = decode_base64_to_image(image_b64)
333
+ img = img.convert('RGB')
334
+
335
+ # Override object param
336
+ with self.queue_lock:
337
+ if interrogatereq.model == "clip":
338
+ processed = shared.interrogator.interrogate(img)
339
+ elif interrogatereq.model == "deepdanbooru":
340
+ processed = deepbooru.model.tag(img)
341
+ else:
342
+ raise HTTPException(status_code=404, detail="Model not found")
343
+
344
+ return InterrogateResponse(caption=processed)
345
+
346
+ def interruptapi(self):
347
+ shared.state.interrupt()
348
+
349
+ return {}
350
+
351
+ def skip(self):
352
+ shared.state.skip()
353
+
354
+ def get_config(self):
355
+ options = {}
356
+ for key in shared.opts.data.keys():
357
+ metadata = shared.opts.data_labels.get(key)
358
+ if(metadata is not None):
359
+ options.update({key: shared.opts.data.get(key, shared.opts.data_labels.get(key).default)})
360
+ else:
361
+ options.update({key: shared.opts.data.get(key, None)})
362
+
363
+ return options
364
+
365
+ def set_config(self, req: Dict[str, Any]):
366
+ for k, v in req.items():
367
+ shared.opts.set(k, v)
368
+
369
+ shared.opts.save(shared.config_filename)
370
+ return
371
+
372
+ def get_cmd_flags(self):
373
+ return vars(shared.cmd_opts)
374
+
375
+ def get_samplers(self):
376
+ return [{"name": sampler[0], "aliases":sampler[2], "options":sampler[3]} for sampler in sd_samplers.all_samplers]
377
+
378
+ def get_upscalers(self):
379
+ return [
380
+ {
381
+ "name": upscaler.name,
382
+ "model_name": upscaler.scaler.model_name,
383
+ "model_path": upscaler.data_path,
384
+ "model_url": None,
385
+ "scale": upscaler.scale,
386
+ }
387
+ for upscaler in shared.sd_upscalers
388
+ ]
389
+
390
+ def get_sd_models(self):
391
+ return [{"title": x.title, "model_name": x.model_name, "hash": x.shorthash, "sha256": x.sha256, "filename": x.filename, "config": find_checkpoint_config_near_filename(x)} for x in checkpoints_list.values()]
392
+
393
+ def get_hypernetworks(self):
394
+ return [{"name": name, "path": shared.hypernetworks[name]} for name in shared.hypernetworks]
395
+
396
+ def get_face_restorers(self):
397
+ return [{"name":x.name(), "cmd_dir": getattr(x, "cmd_dir", None)} for x in shared.face_restorers]
398
+
399
+ def get_realesrgan_models(self):
400
+ return [{"name":x.name,"path":x.data_path, "scale":x.scale} for x in get_realesrgan_models(None)]
401
+
402
+ def get_prompt_styles(self):
403
+ styleList = []
404
+ for k in shared.prompt_styles.styles:
405
+ style = shared.prompt_styles.styles[k]
406
+ styleList.append({"name":style[0], "prompt": style[1], "negative_prompt": style[2]})
407
+
408
+ return styleList
409
+
410
+ def get_embeddings(self):
411
+ db = sd_hijack.model_hijack.embedding_db
412
+
413
+ def convert_embedding(embedding):
414
+ return {
415
+ "step": embedding.step,
416
+ "sd_checkpoint": embedding.sd_checkpoint,
417
+ "sd_checkpoint_name": embedding.sd_checkpoint_name,
418
+ "shape": embedding.shape,
419
+ "vectors": embedding.vectors,
420
+ }
421
+
422
+ def convert_embeddings(embeddings):
423
+ return {embedding.name: convert_embedding(embedding) for embedding in embeddings.values()}
424
+
425
+ return {
426
+ "loaded": convert_embeddings(db.word_embeddings),
427
+ "skipped": convert_embeddings(db.skipped_embeddings),
428
+ }
429
+
430
+ def refresh_checkpoints(self):
431
+ shared.refresh_checkpoints()
432
+
433
+ def create_embedding(self, args: dict):
434
+ try:
435
+ shared.state.begin()
436
+ filename = create_embedding(**args) # create empty embedding
437
+ sd_hijack.model_hijack.embedding_db.load_textual_inversion_embeddings() # reload embeddings so new one can be immediately used
438
+ shared.state.end()
439
+ return CreateResponse(info = "create embedding filename: {filename}".format(filename = filename))
440
+ except AssertionError as e:
441
+ shared.state.end()
442
+ return TrainResponse(info = "create embedding error: {error}".format(error = e))
443
+
444
+ def create_hypernetwork(self, args: dict):
445
+ try:
446
+ shared.state.begin()
447
+ filename = create_hypernetwork(**args) # create empty embedding
448
+ shared.state.end()
449
+ return CreateResponse(info = "create hypernetwork filename: {filename}".format(filename = filename))
450
+ except AssertionError as e:
451
+ shared.state.end()
452
+ return TrainResponse(info = "create hypernetwork error: {error}".format(error = e))
453
+
454
+ def preprocess(self, args: dict):
455
+ try:
456
+ shared.state.begin()
457
+ preprocess(**args) # quick operation unless blip/booru interrogation is enabled
458
+ shared.state.end()
459
+ return PreprocessResponse(info = 'preprocess complete')
460
+ except KeyError as e:
461
+ shared.state.end()
462
+ return PreprocessResponse(info = "preprocess error: invalid token: {error}".format(error = e))
463
+ except AssertionError as e:
464
+ shared.state.end()
465
+ return PreprocessResponse(info = "preprocess error: {error}".format(error = e))
466
+ except FileNotFoundError as e:
467
+ shared.state.end()
468
+ return PreprocessResponse(info = 'preprocess error: {error}'.format(error = e))
469
+
470
+ def train_embedding(self, args: dict):
471
+ try:
472
+ shared.state.begin()
473
+ apply_optimizations = shared.opts.training_xattention_optimizations
474
+ error = None
475
+ filename = ''
476
+ if not apply_optimizations:
477
+ sd_hijack.undo_optimizations()
478
+ try:
479
+ embedding, filename = train_embedding(**args) # can take a long time to complete
480
+ except Exception as e:
481
+ error = e
482
+ finally:
483
+ if not apply_optimizations:
484
+ sd_hijack.apply_optimizations()
485
+ shared.state.end()
486
+ return TrainResponse(info = "train embedding complete: filename: {filename} error: {error}".format(filename = filename, error = error))
487
+ except AssertionError as msg:
488
+ shared.state.end()
489
+ return TrainResponse(info = "train embedding error: {msg}".format(msg = msg))
490
+
491
+ def train_hypernetwork(self, args: dict):
492
+ try:
493
+ shared.state.begin()
494
+ shared.loaded_hypernetworks = []
495
+ apply_optimizations = shared.opts.training_xattention_optimizations
496
+ error = None
497
+ filename = ''
498
+ if not apply_optimizations:
499
+ sd_hijack.undo_optimizations()
500
+ try:
501
+ hypernetwork, filename = train_hypernetwork(**args)
502
+ except Exception as e:
503
+ error = e
504
+ finally:
505
+ shared.sd_model.cond_stage_model.to(devices.device)
506
+ shared.sd_model.first_stage_model.to(devices.device)
507
+ if not apply_optimizations:
508
+ sd_hijack.apply_optimizations()
509
+ shared.state.end()
510
+ return TrainResponse(info="train embedding complete: filename: {filename} error: {error}".format(filename=filename, error=error))
511
+ except AssertionError as msg:
512
+ shared.state.end()
513
+ return TrainResponse(info="train embedding error: {error}".format(error=error))
514
+
515
+ def get_memory(self):
516
+ try:
517
+ import os, psutil
518
+ process = psutil.Process(os.getpid())
519
+ res = process.memory_info() # only rss is cross-platform guaranteed so we dont rely on other values
520
+ ram_total = 100 * res.rss / process.memory_percent() # and total memory is calculated as actual value is not cross-platform safe
521
+ ram = { 'free': ram_total - res.rss, 'used': res.rss, 'total': ram_total }
522
+ except Exception as err:
523
+ ram = { 'error': f'{err}' }
524
+ try:
525
+ import torch
526
+ if torch.cuda.is_available():
527
+ s = torch.cuda.mem_get_info()
528
+ system = { 'free': s[0], 'used': s[1] - s[0], 'total': s[1] }
529
+ s = dict(torch.cuda.memory_stats(shared.device))
530
+ allocated = { 'current': s['allocated_bytes.all.current'], 'peak': s['allocated_bytes.all.peak'] }
531
+ reserved = { 'current': s['reserved_bytes.all.current'], 'peak': s['reserved_bytes.all.peak'] }
532
+ active = { 'current': s['active_bytes.all.current'], 'peak': s['active_bytes.all.peak'] }
533
+ inactive = { 'current': s['inactive_split_bytes.all.current'], 'peak': s['inactive_split_bytes.all.peak'] }
534
+ warnings = { 'retries': s['num_alloc_retries'], 'oom': s['num_ooms'] }
535
+ cuda = {
536
+ 'system': system,
537
+ 'active': active,
538
+ 'allocated': allocated,
539
+ 'reserved': reserved,
540
+ 'inactive': inactive,
541
+ 'events': warnings,
542
+ }
543
+ else:
544
+ cuda = { 'error': 'unavailable' }
545
+ except Exception as err:
546
+ cuda = { 'error': f'{err}' }
547
+ return MemoryResponse(ram = ram, cuda = cuda)
548
+
549
+ def launch(self, server_name, port):
550
+ self.app.include_router(self.router)
551
+ uvicorn.run(self.app, host=server_name, port=port)
modules/api/models.py ADDED
@@ -0,0 +1,269 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import inspect
2
+ from pydantic import BaseModel, Field, create_model
3
+ from typing import Any, Optional
4
+ from typing_extensions import Literal
5
+ from inflection import underscore
6
+ from modules.processing import StableDiffusionProcessingTxt2Img, StableDiffusionProcessingImg2Img
7
+ from modules.shared import sd_upscalers, opts, parser
8
+ from typing import Dict, List
9
+
10
+ API_NOT_ALLOWED = [
11
+ "self",
12
+ "kwargs",
13
+ "sd_model",
14
+ "outpath_samples",
15
+ "outpath_grids",
16
+ "sampler_index",
17
+ "do_not_save_samples",
18
+ "do_not_save_grid",
19
+ "extra_generation_params",
20
+ "overlay_images",
21
+ "do_not_reload_embeddings",
22
+ "seed_enable_extras",
23
+ "prompt_for_display",
24
+ "sampler_noise_scheduler_override",
25
+ "ddim_discretize"
26
+ ]
27
+
28
+ class ModelDef(BaseModel):
29
+ """Assistance Class for Pydantic Dynamic Model Generation"""
30
+
31
+ field: str
32
+ field_alias: str
33
+ field_type: Any
34
+ field_value: Any
35
+ field_exclude: bool = False
36
+
37
+
38
+ class PydanticModelGenerator:
39
+ """
40
+ Takes in created classes and stubs them out in a way FastAPI/Pydantic is happy about:
41
+ source_data is a snapshot of the default values produced by the class
42
+ params are the names of the actual keys required by __init__
43
+ """
44
+
45
+ def __init__(
46
+ self,
47
+ model_name: str = None,
48
+ class_instance = None,
49
+ additional_fields = None,
50
+ ):
51
+ def field_type_generator(k, v):
52
+ # field_type = str if not overrides.get(k) else overrides[k]["type"]
53
+ # print(k, v.annotation, v.default)
54
+ field_type = v.annotation
55
+
56
+ return Optional[field_type]
57
+
58
+ def merge_class_params(class_):
59
+ all_classes = list(filter(lambda x: x is not object, inspect.getmro(class_)))
60
+ parameters = {}
61
+ for classes in all_classes:
62
+ parameters = {**parameters, **inspect.signature(classes.__init__).parameters}
63
+ return parameters
64
+
65
+
66
+ self._model_name = model_name
67
+ self._class_data = merge_class_params(class_instance)
68
+
69
+ self._model_def = [
70
+ ModelDef(
71
+ field=underscore(k),
72
+ field_alias=k,
73
+ field_type=field_type_generator(k, v),
74
+ field_value=v.default
75
+ )
76
+ for (k,v) in self._class_data.items() if k not in API_NOT_ALLOWED
77
+ ]
78
+
79
+ for fields in additional_fields:
80
+ self._model_def.append(ModelDef(
81
+ field=underscore(fields["key"]),
82
+ field_alias=fields["key"],
83
+ field_type=fields["type"],
84
+ field_value=fields["default"],
85
+ field_exclude=fields["exclude"] if "exclude" in fields else False))
86
+
87
+ def generate_model(self):
88
+ """
89
+ Creates a pydantic BaseModel
90
+ from the json and overrides provided at initialization
91
+ """
92
+ fields = {
93
+ d.field: (d.field_type, Field(default=d.field_value, alias=d.field_alias, exclude=d.field_exclude)) for d in self._model_def
94
+ }
95
+ DynamicModel = create_model(self._model_name, **fields)
96
+ DynamicModel.__config__.allow_population_by_field_name = True
97
+ DynamicModel.__config__.allow_mutation = True
98
+ return DynamicModel
99
+
100
+ StableDiffusionTxt2ImgProcessingAPI = PydanticModelGenerator(
101
+ "StableDiffusionProcessingTxt2Img",
102
+ StableDiffusionProcessingTxt2Img,
103
+ [{"key": "sampler_index", "type": str, "default": "Euler"}, {"key": "script_name", "type": str, "default": None}, {"key": "script_args", "type": list, "default": []}]
104
+ ).generate_model()
105
+
106
+ StableDiffusionImg2ImgProcessingAPI = PydanticModelGenerator(
107
+ "StableDiffusionProcessingImg2Img",
108
+ StableDiffusionProcessingImg2Img,
109
+ [{"key": "sampler_index", "type": str, "default": "Euler"}, {"key": "init_images", "type": list, "default": None}, {"key": "denoising_strength", "type": float, "default": 0.75}, {"key": "mask", "type": str, "default": None}, {"key": "include_init_images", "type": bool, "default": False, "exclude" : True}, {"key": "script_name", "type": str, "default": None}, {"key": "script_args", "type": list, "default": []}]
110
+ ).generate_model()
111
+
112
+ class TextToImageResponse(BaseModel):
113
+ images: List[str] = Field(default=None, title="Image", description="The generated image in base64 format.")
114
+ parameters: dict
115
+ info: str
116
+
117
+ class ImageToImageResponse(BaseModel):
118
+ images: List[str] = Field(default=None, title="Image", description="The generated image in base64 format.")
119
+ parameters: dict
120
+ info: str
121
+
122
+ class ExtrasBaseRequest(BaseModel):
123
+ resize_mode: Literal[0, 1] = Field(default=0, title="Resize Mode", description="Sets the resize mode: 0 to upscale by upscaling_resize amount, 1 to upscale up to upscaling_resize_h x upscaling_resize_w.")
124
+ show_extras_results: bool = Field(default=True, title="Show results", description="Should the backend return the generated image?")
125
+ gfpgan_visibility: float = Field(default=0, title="GFPGAN Visibility", ge=0, le=1, allow_inf_nan=False, description="Sets the visibility of GFPGAN, values should be between 0 and 1.")
126
+ codeformer_visibility: float = Field(default=0, title="CodeFormer Visibility", ge=0, le=1, allow_inf_nan=False, description="Sets the visibility of CodeFormer, values should be between 0 and 1.")
127
+ codeformer_weight: float = Field(default=0, title="CodeFormer Weight", ge=0, le=1, allow_inf_nan=False, description="Sets the weight of CodeFormer, values should be between 0 and 1.")
128
+ upscaling_resize: float = Field(default=2, title="Upscaling Factor", ge=1, le=8, description="By how much to upscale the image, only used when resize_mode=0.")
129
+ upscaling_resize_w: int = Field(default=512, title="Target Width", ge=1, description="Target width for the upscaler to hit. Only used when resize_mode=1.")
130
+ upscaling_resize_h: int = Field(default=512, title="Target Height", ge=1, description="Target height for the upscaler to hit. Only used when resize_mode=1.")
131
+ upscaling_crop: bool = Field(default=True, title="Crop to fit", description="Should the upscaler crop the image to fit in the chosen size?")
132
+ upscaler_1: str = Field(default="None", title="Main upscaler", description=f"The name of the main upscaler to use, it has to be one of this list: {' , '.join([x.name for x in sd_upscalers])}")
133
+ upscaler_2: str = Field(default="None", title="Secondary upscaler", description=f"The name of the secondary upscaler to use, it has to be one of this list: {' , '.join([x.name for x in sd_upscalers])}")
134
+ extras_upscaler_2_visibility: float = Field(default=0, title="Secondary upscaler visibility", ge=0, le=1, allow_inf_nan=False, description="Sets the visibility of secondary upscaler, values should be between 0 and 1.")
135
+ upscale_first: bool = Field(default=False, title="Upscale first", description="Should the upscaler run before restoring faces?")
136
+
137
+ class ExtraBaseResponse(BaseModel):
138
+ html_info: str = Field(title="HTML info", description="A series of HTML tags containing the process info.")
139
+
140
+ class ExtrasSingleImageRequest(ExtrasBaseRequest):
141
+ image: str = Field(default="", title="Image", description="Image to work on, must be a Base64 string containing the image's data.")
142
+
143
+ class ExtrasSingleImageResponse(ExtraBaseResponse):
144
+ image: str = Field(default=None, title="Image", description="The generated image in base64 format.")
145
+
146
+ class FileData(BaseModel):
147
+ data: str = Field(title="File data", description="Base64 representation of the file")
148
+ name: str = Field(title="File name")
149
+
150
+ class ExtrasBatchImagesRequest(ExtrasBaseRequest):
151
+ imageList: List[FileData] = Field(title="Images", description="List of images to work on. Must be Base64 strings")
152
+
153
+ class ExtrasBatchImagesResponse(ExtraBaseResponse):
154
+ images: List[str] = Field(title="Images", description="The generated images in base64 format.")
155
+
156
+ class PNGInfoRequest(BaseModel):
157
+ image: str = Field(title="Image", description="The base64 encoded PNG image")
158
+
159
+ class PNGInfoResponse(BaseModel):
160
+ info: str = Field(title="Image info", description="A string with the parameters used to generate the image")
161
+ items: dict = Field(title="Items", description="An object containing all the info the image had")
162
+
163
+ class ProgressRequest(BaseModel):
164
+ skip_current_image: bool = Field(default=False, title="Skip current image", description="Skip current image serialization")
165
+
166
+ class ProgressResponse(BaseModel):
167
+ progress: float = Field(title="Progress", description="The progress with a range of 0 to 1")
168
+ eta_relative: float = Field(title="ETA in secs")
169
+ state: dict = Field(title="State", description="The current state snapshot")
170
+ current_image: str = Field(default=None, title="Current image", description="The current image in base64 format. opts.show_progress_every_n_steps is required for this to work.")
171
+ textinfo: str = Field(default=None, title="Info text", description="Info text used by WebUI.")
172
+
173
+ class InterrogateRequest(BaseModel):
174
+ image: str = Field(default="", title="Image", description="Image to work on, must be a Base64 string containing the image's data.")
175
+ model: str = Field(default="clip", title="Model", description="The interrogate model used.")
176
+
177
+ class InterrogateResponse(BaseModel):
178
+ caption: str = Field(default=None, title="Caption", description="The generated caption for the image.")
179
+
180
+ class TrainResponse(BaseModel):
181
+ info: str = Field(title="Train info", description="Response string from train embedding or hypernetwork task.")
182
+
183
+ class CreateResponse(BaseModel):
184
+ info: str = Field(title="Create info", description="Response string from create embedding or hypernetwork task.")
185
+
186
+ class PreprocessResponse(BaseModel):
187
+ info: str = Field(title="Preprocess info", description="Response string from preprocessing task.")
188
+
189
+ fields = {}
190
+ for key, metadata in opts.data_labels.items():
191
+ value = opts.data.get(key)
192
+ optType = opts.typemap.get(type(metadata.default), type(value))
193
+
194
+ if (metadata is not None):
195
+ fields.update({key: (Optional[optType], Field(
196
+ default=metadata.default ,description=metadata.label))})
197
+ else:
198
+ fields.update({key: (Optional[optType], Field())})
199
+
200
+ OptionsModel = create_model("Options", **fields)
201
+
202
+ flags = {}
203
+ _options = vars(parser)['_option_string_actions']
204
+ for key in _options:
205
+ if(_options[key].dest != 'help'):
206
+ flag = _options[key]
207
+ _type = str
208
+ if _options[key].default is not None: _type = type(_options[key].default)
209
+ flags.update({flag.dest: (_type,Field(default=flag.default, description=flag.help))})
210
+
211
+ FlagsModel = create_model("Flags", **flags)
212
+
213
+ class SamplerItem(BaseModel):
214
+ name: str = Field(title="Name")
215
+ aliases: List[str] = Field(title="Aliases")
216
+ options: Dict[str, str] = Field(title="Options")
217
+
218
+ class UpscalerItem(BaseModel):
219
+ name: str = Field(title="Name")
220
+ model_name: Optional[str] = Field(title="Model Name")
221
+ model_path: Optional[str] = Field(title="Path")
222
+ model_url: Optional[str] = Field(title="URL")
223
+ scale: Optional[float] = Field(title="Scale")
224
+
225
+ class SDModelItem(BaseModel):
226
+ title: str = Field(title="Title")
227
+ model_name: str = Field(title="Model Name")
228
+ hash: Optional[str] = Field(title="Short hash")
229
+ sha256: Optional[str] = Field(title="sha256 hash")
230
+ filename: str = Field(title="Filename")
231
+ config: Optional[str] = Field(title="Config file")
232
+
233
+ class HypernetworkItem(BaseModel):
234
+ name: str = Field(title="Name")
235
+ path: Optional[str] = Field(title="Path")
236
+
237
+ class FaceRestorerItem(BaseModel):
238
+ name: str = Field(title="Name")
239
+ cmd_dir: Optional[str] = Field(title="Path")
240
+
241
+ class RealesrganItem(BaseModel):
242
+ name: str = Field(title="Name")
243
+ path: Optional[str] = Field(title="Path")
244
+ scale: Optional[int] = Field(title="Scale")
245
+
246
+ class PromptStyleItem(BaseModel):
247
+ name: str = Field(title="Name")
248
+ prompt: Optional[str] = Field(title="Prompt")
249
+ negative_prompt: Optional[str] = Field(title="Negative Prompt")
250
+
251
+ class ArtistItem(BaseModel):
252
+ name: str = Field(title="Name")
253
+ score: float = Field(title="Score")
254
+ category: str = Field(title="Category")
255
+
256
+ class EmbeddingItem(BaseModel):
257
+ step: Optional[int] = Field(title="Step", description="The number of steps that were used to train this embedding, if available")
258
+ sd_checkpoint: Optional[str] = Field(title="SD Checkpoint", description="The hash of the checkpoint this embedding was trained on, if available")
259
+ sd_checkpoint_name: Optional[str] = Field(title="SD Checkpoint Name", description="The name of the checkpoint this embedding was trained on, if available. Note that this is the name that was used by the trainer; for a stable identifier, use `sd_checkpoint` instead")
260
+ shape: int = Field(title="Shape", description="The length of each individual vector in the embedding")
261
+ vectors: int = Field(title="Vectors", description="The number of vectors in the embedding")
262
+
263
+ class EmbeddingsResponse(BaseModel):
264
+ loaded: Dict[str, EmbeddingItem] = Field(title="Loaded", description="Embeddings loaded for the current model")
265
+ skipped: Dict[str, EmbeddingItem] = Field(title="Skipped", description="Embeddings skipped for the current model (likely due to architecture incompatibility)")
266
+
267
+ class MemoryResponse(BaseModel):
268
+ ram: dict = Field(title="RAM", description="System memory stats")
269
+ cuda: dict = Field(title="CUDA", description="nVidia CUDA memory stats")
modules/call_queue.py ADDED
@@ -0,0 +1,109 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import html
2
+ import sys
3
+ import threading
4
+ import traceback
5
+ import time
6
+
7
+ from modules import shared, progress
8
+
9
+ queue_lock = threading.Lock()
10
+
11
+
12
+ def wrap_queued_call(func):
13
+ def f(*args, **kwargs):
14
+ with queue_lock:
15
+ res = func(*args, **kwargs)
16
+
17
+ return res
18
+
19
+ return f
20
+
21
+
22
+ def wrap_gradio_gpu_call(func, extra_outputs=None):
23
+ def f(*args, **kwargs):
24
+
25
+ # if the first argument is a string that says "task(...)", it is treated as a job id
26
+ if len(args) > 0 and type(args[0]) == str and args[0][0:5] == "task(" and args[0][-1] == ")":
27
+ id_task = args[0]
28
+ progress.add_task_to_queue(id_task)
29
+ else:
30
+ id_task = None
31
+
32
+ with queue_lock:
33
+ shared.state.begin()
34
+ progress.start_task(id_task)
35
+
36
+ try:
37
+ res = func(*args, **kwargs)
38
+ finally:
39
+ progress.finish_task(id_task)
40
+
41
+ shared.state.end()
42
+
43
+ return res
44
+
45
+ return wrap_gradio_call(f, extra_outputs=extra_outputs, add_stats=True)
46
+
47
+
48
+ def wrap_gradio_call(func, extra_outputs=None, add_stats=False):
49
+ def f(*args, extra_outputs_array=extra_outputs, **kwargs):
50
+ run_memmon = shared.opts.memmon_poll_rate > 0 and not shared.mem_mon.disabled and add_stats
51
+ if run_memmon:
52
+ shared.mem_mon.monitor()
53
+ t = time.perf_counter()
54
+
55
+ try:
56
+ res = list(func(*args, **kwargs))
57
+ except Exception as e:
58
+ # When printing out our debug argument list, do not print out more than a MB of text
59
+ max_debug_str_len = 131072 # (1024*1024)/8
60
+
61
+ print("Error completing request", file=sys.stderr)
62
+ argStr = f"Arguments: {str(args)} {str(kwargs)}"
63
+ print(argStr[:max_debug_str_len], file=sys.stderr)
64
+ if len(argStr) > max_debug_str_len:
65
+ print(f"(Argument list truncated at {max_debug_str_len}/{len(argStr)} characters)", file=sys.stderr)
66
+
67
+ print(traceback.format_exc(), file=sys.stderr)
68
+
69
+ shared.state.job = ""
70
+ shared.state.job_count = 0
71
+
72
+ if extra_outputs_array is None:
73
+ extra_outputs_array = [None, '']
74
+
75
+ res = extra_outputs_array + [f"<div class='error'>{html.escape(type(e).__name__+': '+str(e))}</div>"]
76
+
77
+ shared.state.skipped = False
78
+ shared.state.interrupted = False
79
+ shared.state.job_count = 0
80
+
81
+ if not add_stats:
82
+ return tuple(res)
83
+
84
+ elapsed = time.perf_counter() - t
85
+ elapsed_m = int(elapsed // 60)
86
+ elapsed_s = elapsed % 60
87
+ elapsed_text = f"{elapsed_s:.2f}s"
88
+ if elapsed_m > 0:
89
+ elapsed_text = f"{elapsed_m}m "+elapsed_text
90
+
91
+ if run_memmon:
92
+ mem_stats = {k: -(v//-(1024*1024)) for k, v in shared.mem_mon.stop().items()}
93
+ active_peak = mem_stats['active_peak']
94
+ reserved_peak = mem_stats['reserved_peak']
95
+ sys_peak = mem_stats['system_peak']
96
+ sys_total = mem_stats['total']
97
+ sys_pct = round(sys_peak/max(sys_total, 1) * 100, 2)
98
+
99
+ vram_html = f"<p class='vram'>Torch active/reserved: {active_peak}/{reserved_peak} MiB, <wbr>Sys VRAM: {sys_peak}/{sys_total} MiB ({sys_pct}%)</p>"
100
+ else:
101
+ vram_html = ''
102
+
103
+ # last item is always HTML
104
+ res[-1] += f"<div class='performance'><p class='time'>Time taken: <wbr>{elapsed_text}</p>{vram_html}</div>"
105
+
106
+ return tuple(res)
107
+
108
+ return f
109
+
modules/codeformer/codeformer_arch.py ADDED
@@ -0,0 +1,278 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # this file is copied from CodeFormer repository. Please see comment in modules/codeformer_model.py
2
+
3
+ import math
4
+ import numpy as np
5
+ import torch
6
+ from torch import nn, Tensor
7
+ import torch.nn.functional as F
8
+ from typing import Optional, List
9
+
10
+ from modules.codeformer.vqgan_arch import *
11
+ from basicsr.utils import get_root_logger
12
+ from basicsr.utils.registry import ARCH_REGISTRY
13
+
14
+ def calc_mean_std(feat, eps=1e-5):
15
+ """Calculate mean and std for adaptive_instance_normalization.
16
+
17
+ Args:
18
+ feat (Tensor): 4D tensor.
19
+ eps (float): A small value added to the variance to avoid
20
+ divide-by-zero. Default: 1e-5.
21
+ """
22
+ size = feat.size()
23
+ assert len(size) == 4, 'The input feature should be 4D tensor.'
24
+ b, c = size[:2]
25
+ feat_var = feat.view(b, c, -1).var(dim=2) + eps
26
+ feat_std = feat_var.sqrt().view(b, c, 1, 1)
27
+ feat_mean = feat.view(b, c, -1).mean(dim=2).view(b, c, 1, 1)
28
+ return feat_mean, feat_std
29
+
30
+
31
+ def adaptive_instance_normalization(content_feat, style_feat):
32
+ """Adaptive instance normalization.
33
+
34
+ Adjust the reference features to have the similar color and illuminations
35
+ as those in the degradate features.
36
+
37
+ Args:
38
+ content_feat (Tensor): The reference feature.
39
+ style_feat (Tensor): The degradate features.
40
+ """
41
+ size = content_feat.size()
42
+ style_mean, style_std = calc_mean_std(style_feat)
43
+ content_mean, content_std = calc_mean_std(content_feat)
44
+ normalized_feat = (content_feat - content_mean.expand(size)) / content_std.expand(size)
45
+ return normalized_feat * style_std.expand(size) + style_mean.expand(size)
46
+
47
+
48
+ class PositionEmbeddingSine(nn.Module):
49
+ """
50
+ This is a more standard version of the position embedding, very similar to the one
51
+ used by the Attention is all you need paper, generalized to work on images.
52
+ """
53
+
54
+ def __init__(self, num_pos_feats=64, temperature=10000, normalize=False, scale=None):
55
+ super().__init__()
56
+ self.num_pos_feats = num_pos_feats
57
+ self.temperature = temperature
58
+ self.normalize = normalize
59
+ if scale is not None and normalize is False:
60
+ raise ValueError("normalize should be True if scale is passed")
61
+ if scale is None:
62
+ scale = 2 * math.pi
63
+ self.scale = scale
64
+
65
+ def forward(self, x, mask=None):
66
+ if mask is None:
67
+ mask = torch.zeros((x.size(0), x.size(2), x.size(3)), device=x.device, dtype=torch.bool)
68
+ not_mask = ~mask
69
+ y_embed = not_mask.cumsum(1, dtype=torch.float32)
70
+ x_embed = not_mask.cumsum(2, dtype=torch.float32)
71
+ if self.normalize:
72
+ eps = 1e-6
73
+ y_embed = y_embed / (y_embed[:, -1:, :] + eps) * self.scale
74
+ x_embed = x_embed / (x_embed[:, :, -1:] + eps) * self.scale
75
+
76
+ dim_t = torch.arange(self.num_pos_feats, dtype=torch.float32, device=x.device)
77
+ dim_t = self.temperature ** (2 * (dim_t // 2) / self.num_pos_feats)
78
+
79
+ pos_x = x_embed[:, :, :, None] / dim_t
80
+ pos_y = y_embed[:, :, :, None] / dim_t
81
+ pos_x = torch.stack(
82
+ (pos_x[:, :, :, 0::2].sin(), pos_x[:, :, :, 1::2].cos()), dim=4
83
+ ).flatten(3)
84
+ pos_y = torch.stack(
85
+ (pos_y[:, :, :, 0::2].sin(), pos_y[:, :, :, 1::2].cos()), dim=4
86
+ ).flatten(3)
87
+ pos = torch.cat((pos_y, pos_x), dim=3).permute(0, 3, 1, 2)
88
+ return pos
89
+
90
+ def _get_activation_fn(activation):
91
+ """Return an activation function given a string"""
92
+ if activation == "relu":
93
+ return F.relu
94
+ if activation == "gelu":
95
+ return F.gelu
96
+ if activation == "glu":
97
+ return F.glu
98
+ raise RuntimeError(F"activation should be relu/gelu, not {activation}.")
99
+
100
+
101
+ class TransformerSALayer(nn.Module):
102
+ def __init__(self, embed_dim, nhead=8, dim_mlp=2048, dropout=0.0, activation="gelu"):
103
+ super().__init__()
104
+ self.self_attn = nn.MultiheadAttention(embed_dim, nhead, dropout=dropout)
105
+ # Implementation of Feedforward model - MLP
106
+ self.linear1 = nn.Linear(embed_dim, dim_mlp)
107
+ self.dropout = nn.Dropout(dropout)
108
+ self.linear2 = nn.Linear(dim_mlp, embed_dim)
109
+
110
+ self.norm1 = nn.LayerNorm(embed_dim)
111
+ self.norm2 = nn.LayerNorm(embed_dim)
112
+ self.dropout1 = nn.Dropout(dropout)
113
+ self.dropout2 = nn.Dropout(dropout)
114
+
115
+ self.activation = _get_activation_fn(activation)
116
+
117
+ def with_pos_embed(self, tensor, pos: Optional[Tensor]):
118
+ return tensor if pos is None else tensor + pos
119
+
120
+ def forward(self, tgt,
121
+ tgt_mask: Optional[Tensor] = None,
122
+ tgt_key_padding_mask: Optional[Tensor] = None,
123
+ query_pos: Optional[Tensor] = None):
124
+
125
+ # self attention
126
+ tgt2 = self.norm1(tgt)
127
+ q = k = self.with_pos_embed(tgt2, query_pos)
128
+ tgt2 = self.self_attn(q, k, value=tgt2, attn_mask=tgt_mask,
129
+ key_padding_mask=tgt_key_padding_mask)[0]
130
+ tgt = tgt + self.dropout1(tgt2)
131
+
132
+ # ffn
133
+ tgt2 = self.norm2(tgt)
134
+ tgt2 = self.linear2(self.dropout(self.activation(self.linear1(tgt2))))
135
+ tgt = tgt + self.dropout2(tgt2)
136
+ return tgt
137
+
138
+ class Fuse_sft_block(nn.Module):
139
+ def __init__(self, in_ch, out_ch):
140
+ super().__init__()
141
+ self.encode_enc = ResBlock(2*in_ch, out_ch)
142
+
143
+ self.scale = nn.Sequential(
144
+ nn.Conv2d(in_ch, out_ch, kernel_size=3, padding=1),
145
+ nn.LeakyReLU(0.2, True),
146
+ nn.Conv2d(out_ch, out_ch, kernel_size=3, padding=1))
147
+
148
+ self.shift = nn.Sequential(
149
+ nn.Conv2d(in_ch, out_ch, kernel_size=3, padding=1),
150
+ nn.LeakyReLU(0.2, True),
151
+ nn.Conv2d(out_ch, out_ch, kernel_size=3, padding=1))
152
+
153
+ def forward(self, enc_feat, dec_feat, w=1):
154
+ enc_feat = self.encode_enc(torch.cat([enc_feat, dec_feat], dim=1))
155
+ scale = self.scale(enc_feat)
156
+ shift = self.shift(enc_feat)
157
+ residual = w * (dec_feat * scale + shift)
158
+ out = dec_feat + residual
159
+ return out
160
+
161
+
162
+ @ARCH_REGISTRY.register()
163
+ class CodeFormer(VQAutoEncoder):
164
+ def __init__(self, dim_embd=512, n_head=8, n_layers=9,
165
+ codebook_size=1024, latent_size=256,
166
+ connect_list=['32', '64', '128', '256'],
167
+ fix_modules=['quantize','generator']):
168
+ super(CodeFormer, self).__init__(512, 64, [1, 2, 2, 4, 4, 8], 'nearest',2, [16], codebook_size)
169
+
170
+ if fix_modules is not None:
171
+ for module in fix_modules:
172
+ for param in getattr(self, module).parameters():
173
+ param.requires_grad = False
174
+
175
+ self.connect_list = connect_list
176
+ self.n_layers = n_layers
177
+ self.dim_embd = dim_embd
178
+ self.dim_mlp = dim_embd*2
179
+
180
+ self.position_emb = nn.Parameter(torch.zeros(latent_size, self.dim_embd))
181
+ self.feat_emb = nn.Linear(256, self.dim_embd)
182
+
183
+ # transformer
184
+ self.ft_layers = nn.Sequential(*[TransformerSALayer(embed_dim=dim_embd, nhead=n_head, dim_mlp=self.dim_mlp, dropout=0.0)
185
+ for _ in range(self.n_layers)])
186
+
187
+ # logits_predict head
188
+ self.idx_pred_layer = nn.Sequential(
189
+ nn.LayerNorm(dim_embd),
190
+ nn.Linear(dim_embd, codebook_size, bias=False))
191
+
192
+ self.channels = {
193
+ '16': 512,
194
+ '32': 256,
195
+ '64': 256,
196
+ '128': 128,
197
+ '256': 128,
198
+ '512': 64,
199
+ }
200
+
201
+ # after second residual block for > 16, before attn layer for ==16
202
+ self.fuse_encoder_block = {'512':2, '256':5, '128':8, '64':11, '32':14, '16':18}
203
+ # after first residual block for > 16, before attn layer for ==16
204
+ self.fuse_generator_block = {'16':6, '32': 9, '64':12, '128':15, '256':18, '512':21}
205
+
206
+ # fuse_convs_dict
207
+ self.fuse_convs_dict = nn.ModuleDict()
208
+ for f_size in self.connect_list:
209
+ in_ch = self.channels[f_size]
210
+ self.fuse_convs_dict[f_size] = Fuse_sft_block(in_ch, in_ch)
211
+
212
+ def _init_weights(self, module):
213
+ if isinstance(module, (nn.Linear, nn.Embedding)):
214
+ module.weight.data.normal_(mean=0.0, std=0.02)
215
+ if isinstance(module, nn.Linear) and module.bias is not None:
216
+ module.bias.data.zero_()
217
+ elif isinstance(module, nn.LayerNorm):
218
+ module.bias.data.zero_()
219
+ module.weight.data.fill_(1.0)
220
+
221
+ def forward(self, x, w=0, detach_16=True, code_only=False, adain=False):
222
+ # ################### Encoder #####################
223
+ enc_feat_dict = {}
224
+ out_list = [self.fuse_encoder_block[f_size] for f_size in self.connect_list]
225
+ for i, block in enumerate(self.encoder.blocks):
226
+ x = block(x)
227
+ if i in out_list:
228
+ enc_feat_dict[str(x.shape[-1])] = x.clone()
229
+
230
+ lq_feat = x
231
+ # ################# Transformer ###################
232
+ # quant_feat, codebook_loss, quant_stats = self.quantize(lq_feat)
233
+ pos_emb = self.position_emb.unsqueeze(1).repeat(1,x.shape[0],1)
234
+ # BCHW -> BC(HW) -> (HW)BC
235
+ feat_emb = self.feat_emb(lq_feat.flatten(2).permute(2,0,1))
236
+ query_emb = feat_emb
237
+ # Transformer encoder
238
+ for layer in self.ft_layers:
239
+ query_emb = layer(query_emb, query_pos=pos_emb)
240
+
241
+ # output logits
242
+ logits = self.idx_pred_layer(query_emb) # (hw)bn
243
+ logits = logits.permute(1,0,2) # (hw)bn -> b(hw)n
244
+
245
+ if code_only: # for training stage II
246
+ # logits doesn't need softmax before cross_entropy loss
247
+ return logits, lq_feat
248
+
249
+ # ################# Quantization ###################
250
+ # if self.training:
251
+ # quant_feat = torch.einsum('btn,nc->btc', [soft_one_hot, self.quantize.embedding.weight])
252
+ # # b(hw)c -> bc(hw) -> bchw
253
+ # quant_feat = quant_feat.permute(0,2,1).view(lq_feat.shape)
254
+ # ------------
255
+ soft_one_hot = F.softmax(logits, dim=2)
256
+ _, top_idx = torch.topk(soft_one_hot, 1, dim=2)
257
+ quant_feat = self.quantize.get_codebook_feat(top_idx, shape=[x.shape[0],16,16,256])
258
+ # preserve gradients
259
+ # quant_feat = lq_feat + (quant_feat - lq_feat).detach()
260
+
261
+ if detach_16:
262
+ quant_feat = quant_feat.detach() # for training stage III
263
+ if adain:
264
+ quant_feat = adaptive_instance_normalization(quant_feat, lq_feat)
265
+
266
+ # ################## Generator ####################
267
+ x = quant_feat
268
+ fuse_list = [self.fuse_generator_block[f_size] for f_size in self.connect_list]
269
+
270
+ for i, block in enumerate(self.generator.blocks):
271
+ x = block(x)
272
+ if i in fuse_list: # fuse after i-th block
273
+ f_size = str(x.shape[-1])
274
+ if w>0:
275
+ x = self.fuse_convs_dict[f_size](enc_feat_dict[f_size].detach(), x, w)
276
+ out = x
277
+ # logits doesn't need softmax before cross_entropy loss
278
+ return out, logits, lq_feat
modules/codeformer/vqgan_arch.py ADDED
@@ -0,0 +1,437 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # this file is copied from CodeFormer repository. Please see comment in modules/codeformer_model.py
2
+
3
+ '''
4
+ VQGAN code, adapted from the original created by the Unleashing Transformers authors:
5
+ https://github.com/samb-t/unleashing-transformers/blob/master/models/vqgan.py
6
+
7
+ '''
8
+ import numpy as np
9
+ import torch
10
+ import torch.nn as nn
11
+ import torch.nn.functional as F
12
+ import copy
13
+ from basicsr.utils import get_root_logger
14
+ from basicsr.utils.registry import ARCH_REGISTRY
15
+
16
+ def normalize(in_channels):
17
+ return torch.nn.GroupNorm(num_groups=32, num_channels=in_channels, eps=1e-6, affine=True)
18
+
19
+
20
+ @torch.jit.script
21
+ def swish(x):
22
+ return x*torch.sigmoid(x)
23
+
24
+
25
+ # Define VQVAE classes
26
+ class VectorQuantizer(nn.Module):
27
+ def __init__(self, codebook_size, emb_dim, beta):
28
+ super(VectorQuantizer, self).__init__()
29
+ self.codebook_size = codebook_size # number of embeddings
30
+ self.emb_dim = emb_dim # dimension of embedding
31
+ self.beta = beta # commitment cost used in loss term, beta * ||z_e(x)-sg[e]||^2
32
+ self.embedding = nn.Embedding(self.codebook_size, self.emb_dim)
33
+ self.embedding.weight.data.uniform_(-1.0 / self.codebook_size, 1.0 / self.codebook_size)
34
+
35
+ def forward(self, z):
36
+ # reshape z -> (batch, height, width, channel) and flatten
37
+ z = z.permute(0, 2, 3, 1).contiguous()
38
+ z_flattened = z.view(-1, self.emb_dim)
39
+
40
+ # distances from z to embeddings e_j (z - e)^2 = z^2 + e^2 - 2 e * z
41
+ d = (z_flattened ** 2).sum(dim=1, keepdim=True) + (self.embedding.weight**2).sum(1) - \
42
+ 2 * torch.matmul(z_flattened, self.embedding.weight.t())
43
+
44
+ mean_distance = torch.mean(d)
45
+ # find closest encodings
46
+ # min_encoding_indices = torch.argmin(d, dim=1).unsqueeze(1)
47
+ min_encoding_scores, min_encoding_indices = torch.topk(d, 1, dim=1, largest=False)
48
+ # [0-1], higher score, higher confidence
49
+ min_encoding_scores = torch.exp(-min_encoding_scores/10)
50
+
51
+ min_encodings = torch.zeros(min_encoding_indices.shape[0], self.codebook_size).to(z)
52
+ min_encodings.scatter_(1, min_encoding_indices, 1)
53
+
54
+ # get quantized latent vectors
55
+ z_q = torch.matmul(min_encodings, self.embedding.weight).view(z.shape)
56
+ # compute loss for embedding
57
+ loss = torch.mean((z_q.detach()-z)**2) + self.beta * torch.mean((z_q - z.detach()) ** 2)
58
+ # preserve gradients
59
+ z_q = z + (z_q - z).detach()
60
+
61
+ # perplexity
62
+ e_mean = torch.mean(min_encodings, dim=0)
63
+ perplexity = torch.exp(-torch.sum(e_mean * torch.log(e_mean + 1e-10)))
64
+ # reshape back to match original input shape
65
+ z_q = z_q.permute(0, 3, 1, 2).contiguous()
66
+
67
+ return z_q, loss, {
68
+ "perplexity": perplexity,
69
+ "min_encodings": min_encodings,
70
+ "min_encoding_indices": min_encoding_indices,
71
+ "min_encoding_scores": min_encoding_scores,
72
+ "mean_distance": mean_distance
73
+ }
74
+
75
+ def get_codebook_feat(self, indices, shape):
76
+ # input indices: batch*token_num -> (batch*token_num)*1
77
+ # shape: batch, height, width, channel
78
+ indices = indices.view(-1,1)
79
+ min_encodings = torch.zeros(indices.shape[0], self.codebook_size).to(indices)
80
+ min_encodings.scatter_(1, indices, 1)
81
+ # get quantized latent vectors
82
+ z_q = torch.matmul(min_encodings.float(), self.embedding.weight)
83
+
84
+ if shape is not None: # reshape back to match original input shape
85
+ z_q = z_q.view(shape).permute(0, 3, 1, 2).contiguous()
86
+
87
+ return z_q
88
+
89
+
90
+ class GumbelQuantizer(nn.Module):
91
+ def __init__(self, codebook_size, emb_dim, num_hiddens, straight_through=False, kl_weight=5e-4, temp_init=1.0):
92
+ super().__init__()
93
+ self.codebook_size = codebook_size # number of embeddings
94
+ self.emb_dim = emb_dim # dimension of embedding
95
+ self.straight_through = straight_through
96
+ self.temperature = temp_init
97
+ self.kl_weight = kl_weight
98
+ self.proj = nn.Conv2d(num_hiddens, codebook_size, 1) # projects last encoder layer to quantized logits
99
+ self.embed = nn.Embedding(codebook_size, emb_dim)
100
+
101
+ def forward(self, z):
102
+ hard = self.straight_through if self.training else True
103
+
104
+ logits = self.proj(z)
105
+
106
+ soft_one_hot = F.gumbel_softmax(logits, tau=self.temperature, dim=1, hard=hard)
107
+
108
+ z_q = torch.einsum("b n h w, n d -> b d h w", soft_one_hot, self.embed.weight)
109
+
110
+ # + kl divergence to the prior loss
111
+ qy = F.softmax(logits, dim=1)
112
+ diff = self.kl_weight * torch.sum(qy * torch.log(qy * self.codebook_size + 1e-10), dim=1).mean()
113
+ min_encoding_indices = soft_one_hot.argmax(dim=1)
114
+
115
+ return z_q, diff, {
116
+ "min_encoding_indices": min_encoding_indices
117
+ }
118
+
119
+
120
+ class Downsample(nn.Module):
121
+ def __init__(self, in_channels):
122
+ super().__init__()
123
+ self.conv = torch.nn.Conv2d(in_channels, in_channels, kernel_size=3, stride=2, padding=0)
124
+
125
+ def forward(self, x):
126
+ pad = (0, 1, 0, 1)
127
+ x = torch.nn.functional.pad(x, pad, mode="constant", value=0)
128
+ x = self.conv(x)
129
+ return x
130
+
131
+
132
+ class Upsample(nn.Module):
133
+ def __init__(self, in_channels):
134
+ super().__init__()
135
+ self.conv = nn.Conv2d(in_channels, in_channels, kernel_size=3, stride=1, padding=1)
136
+
137
+ def forward(self, x):
138
+ x = F.interpolate(x, scale_factor=2.0, mode="nearest")
139
+ x = self.conv(x)
140
+
141
+ return x
142
+
143
+
144
+ class ResBlock(nn.Module):
145
+ def __init__(self, in_channels, out_channels=None):
146
+ super(ResBlock, self).__init__()
147
+ self.in_channels = in_channels
148
+ self.out_channels = in_channels if out_channels is None else out_channels
149
+ self.norm1 = normalize(in_channels)
150
+ self.conv1 = nn.Conv2d(in_channels, out_channels, kernel_size=3, stride=1, padding=1)
151
+ self.norm2 = normalize(out_channels)
152
+ self.conv2 = nn.Conv2d(out_channels, out_channels, kernel_size=3, stride=1, padding=1)
153
+ if self.in_channels != self.out_channels:
154
+ self.conv_out = nn.Conv2d(in_channels, out_channels, kernel_size=1, stride=1, padding=0)
155
+
156
+ def forward(self, x_in):
157
+ x = x_in
158
+ x = self.norm1(x)
159
+ x = swish(x)
160
+ x = self.conv1(x)
161
+ x = self.norm2(x)
162
+ x = swish(x)
163
+ x = self.conv2(x)
164
+ if self.in_channels != self.out_channels:
165
+ x_in = self.conv_out(x_in)
166
+
167
+ return x + x_in
168
+
169
+
170
+ class AttnBlock(nn.Module):
171
+ def __init__(self, in_channels):
172
+ super().__init__()
173
+ self.in_channels = in_channels
174
+
175
+ self.norm = normalize(in_channels)
176
+ self.q = torch.nn.Conv2d(
177
+ in_channels,
178
+ in_channels,
179
+ kernel_size=1,
180
+ stride=1,
181
+ padding=0
182
+ )
183
+ self.k = torch.nn.Conv2d(
184
+ in_channels,
185
+ in_channels,
186
+ kernel_size=1,
187
+ stride=1,
188
+ padding=0
189
+ )
190
+ self.v = torch.nn.Conv2d(
191
+ in_channels,
192
+ in_channels,
193
+ kernel_size=1,
194
+ stride=1,
195
+ padding=0
196
+ )
197
+ self.proj_out = torch.nn.Conv2d(
198
+ in_channels,
199
+ in_channels,
200
+ kernel_size=1,
201
+ stride=1,
202
+ padding=0
203
+ )
204
+
205
+ def forward(self, x):
206
+ h_ = x
207
+ h_ = self.norm(h_)
208
+ q = self.q(h_)
209
+ k = self.k(h_)
210
+ v = self.v(h_)
211
+
212
+ # compute attention
213
+ b, c, h, w = q.shape
214
+ q = q.reshape(b, c, h*w)
215
+ q = q.permute(0, 2, 1)
216
+ k = k.reshape(b, c, h*w)
217
+ w_ = torch.bmm(q, k)
218
+ w_ = w_ * (int(c)**(-0.5))
219
+ w_ = F.softmax(w_, dim=2)
220
+
221
+ # attend to values
222
+ v = v.reshape(b, c, h*w)
223
+ w_ = w_.permute(0, 2, 1)
224
+ h_ = torch.bmm(v, w_)
225
+ h_ = h_.reshape(b, c, h, w)
226
+
227
+ h_ = self.proj_out(h_)
228
+
229
+ return x+h_
230
+
231
+
232
+ class Encoder(nn.Module):
233
+ def __init__(self, in_channels, nf, emb_dim, ch_mult, num_res_blocks, resolution, attn_resolutions):
234
+ super().__init__()
235
+ self.nf = nf
236
+ self.num_resolutions = len(ch_mult)
237
+ self.num_res_blocks = num_res_blocks
238
+ self.resolution = resolution
239
+ self.attn_resolutions = attn_resolutions
240
+
241
+ curr_res = self.resolution
242
+ in_ch_mult = (1,)+tuple(ch_mult)
243
+
244
+ blocks = []
245
+ # initial convultion
246
+ blocks.append(nn.Conv2d(in_channels, nf, kernel_size=3, stride=1, padding=1))
247
+
248
+ # residual and downsampling blocks, with attention on smaller res (16x16)
249
+ for i in range(self.num_resolutions):
250
+ block_in_ch = nf * in_ch_mult[i]
251
+ block_out_ch = nf * ch_mult[i]
252
+ for _ in range(self.num_res_blocks):
253
+ blocks.append(ResBlock(block_in_ch, block_out_ch))
254
+ block_in_ch = block_out_ch
255
+ if curr_res in attn_resolutions:
256
+ blocks.append(AttnBlock(block_in_ch))
257
+
258
+ if i != self.num_resolutions - 1:
259
+ blocks.append(Downsample(block_in_ch))
260
+ curr_res = curr_res // 2
261
+
262
+ # non-local attention block
263
+ blocks.append(ResBlock(block_in_ch, block_in_ch))
264
+ blocks.append(AttnBlock(block_in_ch))
265
+ blocks.append(ResBlock(block_in_ch, block_in_ch))
266
+
267
+ # normalise and convert to latent size
268
+ blocks.append(normalize(block_in_ch))
269
+ blocks.append(nn.Conv2d(block_in_ch, emb_dim, kernel_size=3, stride=1, padding=1))
270
+ self.blocks = nn.ModuleList(blocks)
271
+
272
+ def forward(self, x):
273
+ for block in self.blocks:
274
+ x = block(x)
275
+
276
+ return x
277
+
278
+
279
+ class Generator(nn.Module):
280
+ def __init__(self, nf, emb_dim, ch_mult, res_blocks, img_size, attn_resolutions):
281
+ super().__init__()
282
+ self.nf = nf
283
+ self.ch_mult = ch_mult
284
+ self.num_resolutions = len(self.ch_mult)
285
+ self.num_res_blocks = res_blocks
286
+ self.resolution = img_size
287
+ self.attn_resolutions = attn_resolutions
288
+ self.in_channels = emb_dim
289
+ self.out_channels = 3
290
+ block_in_ch = self.nf * self.ch_mult[-1]
291
+ curr_res = self.resolution // 2 ** (self.num_resolutions-1)
292
+
293
+ blocks = []
294
+ # initial conv
295
+ blocks.append(nn.Conv2d(self.in_channels, block_in_ch, kernel_size=3, stride=1, padding=1))
296
+
297
+ # non-local attention block
298
+ blocks.append(ResBlock(block_in_ch, block_in_ch))
299
+ blocks.append(AttnBlock(block_in_ch))
300
+ blocks.append(ResBlock(block_in_ch, block_in_ch))
301
+
302
+ for i in reversed(range(self.num_resolutions)):
303
+ block_out_ch = self.nf * self.ch_mult[i]
304
+
305
+ for _ in range(self.num_res_blocks):
306
+ blocks.append(ResBlock(block_in_ch, block_out_ch))
307
+ block_in_ch = block_out_ch
308
+
309
+ if curr_res in self.attn_resolutions:
310
+ blocks.append(AttnBlock(block_in_ch))
311
+
312
+ if i != 0:
313
+ blocks.append(Upsample(block_in_ch))
314
+ curr_res = curr_res * 2
315
+
316
+ blocks.append(normalize(block_in_ch))
317
+ blocks.append(nn.Conv2d(block_in_ch, self.out_channels, kernel_size=3, stride=1, padding=1))
318
+
319
+ self.blocks = nn.ModuleList(blocks)
320
+
321
+
322
+ def forward(self, x):
323
+ for block in self.blocks:
324
+ x = block(x)
325
+
326
+ return x
327
+
328
+
329
+ @ARCH_REGISTRY.register()
330
+ class VQAutoEncoder(nn.Module):
331
+ def __init__(self, img_size, nf, ch_mult, quantizer="nearest", res_blocks=2, attn_resolutions=[16], codebook_size=1024, emb_dim=256,
332
+ beta=0.25, gumbel_straight_through=False, gumbel_kl_weight=1e-8, model_path=None):
333
+ super().__init__()
334
+ logger = get_root_logger()
335
+ self.in_channels = 3
336
+ self.nf = nf
337
+ self.n_blocks = res_blocks
338
+ self.codebook_size = codebook_size
339
+ self.embed_dim = emb_dim
340
+ self.ch_mult = ch_mult
341
+ self.resolution = img_size
342
+ self.attn_resolutions = attn_resolutions
343
+ self.quantizer_type = quantizer
344
+ self.encoder = Encoder(
345
+ self.in_channels,
346
+ self.nf,
347
+ self.embed_dim,
348
+ self.ch_mult,
349
+ self.n_blocks,
350
+ self.resolution,
351
+ self.attn_resolutions
352
+ )
353
+ if self.quantizer_type == "nearest":
354
+ self.beta = beta #0.25
355
+ self.quantize = VectorQuantizer(self.codebook_size, self.embed_dim, self.beta)
356
+ elif self.quantizer_type == "gumbel":
357
+ self.gumbel_num_hiddens = emb_dim
358
+ self.straight_through = gumbel_straight_through
359
+ self.kl_weight = gumbel_kl_weight
360
+ self.quantize = GumbelQuantizer(
361
+ self.codebook_size,
362
+ self.embed_dim,
363
+ self.gumbel_num_hiddens,
364
+ self.straight_through,
365
+ self.kl_weight
366
+ )
367
+ self.generator = Generator(
368
+ self.nf,
369
+ self.embed_dim,
370
+ self.ch_mult,
371
+ self.n_blocks,
372
+ self.resolution,
373
+ self.attn_resolutions
374
+ )
375
+
376
+ if model_path is not None:
377
+ chkpt = torch.load(model_path, map_location='cpu')
378
+ if 'params_ema' in chkpt:
379
+ self.load_state_dict(torch.load(model_path, map_location='cpu')['params_ema'])
380
+ logger.info(f'vqgan is loaded from: {model_path} [params_ema]')
381
+ elif 'params' in chkpt:
382
+ self.load_state_dict(torch.load(model_path, map_location='cpu')['params'])
383
+ logger.info(f'vqgan is loaded from: {model_path} [params]')
384
+ else:
385
+ raise ValueError('Wrong params!')
386
+
387
+
388
+ def forward(self, x):
389
+ x = self.encoder(x)
390
+ quant, codebook_loss, quant_stats = self.quantize(x)
391
+ x = self.generator(quant)
392
+ return x, codebook_loss, quant_stats
393
+
394
+
395
+
396
+ # patch based discriminator
397
+ @ARCH_REGISTRY.register()
398
+ class VQGANDiscriminator(nn.Module):
399
+ def __init__(self, nc=3, ndf=64, n_layers=4, model_path=None):
400
+ super().__init__()
401
+
402
+ layers = [nn.Conv2d(nc, ndf, kernel_size=4, stride=2, padding=1), nn.LeakyReLU(0.2, True)]
403
+ ndf_mult = 1
404
+ ndf_mult_prev = 1
405
+ for n in range(1, n_layers): # gradually increase the number of filters
406
+ ndf_mult_prev = ndf_mult
407
+ ndf_mult = min(2 ** n, 8)
408
+ layers += [
409
+ nn.Conv2d(ndf * ndf_mult_prev, ndf * ndf_mult, kernel_size=4, stride=2, padding=1, bias=False),
410
+ nn.BatchNorm2d(ndf * ndf_mult),
411
+ nn.LeakyReLU(0.2, True)
412
+ ]
413
+
414
+ ndf_mult_prev = ndf_mult
415
+ ndf_mult = min(2 ** n_layers, 8)
416
+
417
+ layers += [
418
+ nn.Conv2d(ndf * ndf_mult_prev, ndf * ndf_mult, kernel_size=4, stride=1, padding=1, bias=False),
419
+ nn.BatchNorm2d(ndf * ndf_mult),
420
+ nn.LeakyReLU(0.2, True)
421
+ ]
422
+
423
+ layers += [
424
+ nn.Conv2d(ndf * ndf_mult, 1, kernel_size=4, stride=1, padding=1)] # output 1 channel prediction map
425
+ self.main = nn.Sequential(*layers)
426
+
427
+ if model_path is not None:
428
+ chkpt = torch.load(model_path, map_location='cpu')
429
+ if 'params_d' in chkpt:
430
+ self.load_state_dict(torch.load(model_path, map_location='cpu')['params_d'])
431
+ elif 'params' in chkpt:
432
+ self.load_state_dict(torch.load(model_path, map_location='cpu')['params'])
433
+ else:
434
+ raise ValueError('Wrong params!')
435
+
436
+ def forward(self, x):
437
+ return self.main(x)
modules/codeformer_model.py ADDED
@@ -0,0 +1,143 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import sys
3
+ import traceback
4
+
5
+ import cv2
6
+ import torch
7
+
8
+ import modules.face_restoration
9
+ import modules.shared
10
+ from modules import shared, devices, modelloader
11
+ from modules.paths import models_path
12
+
13
+ # codeformer people made a choice to include modified basicsr library to their project which makes
14
+ # it utterly impossible to use it alongside with other libraries that also use basicsr, like GFPGAN.
15
+ # I am making a choice to include some files from codeformer to work around this issue.
16
+ model_dir = "Codeformer"
17
+ model_path = os.path.join(models_path, model_dir)
18
+ model_url = 'https://github.com/sczhou/CodeFormer/releases/download/v0.1.0/codeformer.pth'
19
+
20
+ have_codeformer = False
21
+ codeformer = None
22
+
23
+
24
+ def setup_model(dirname):
25
+ global model_path
26
+ if not os.path.exists(model_path):
27
+ os.makedirs(model_path)
28
+
29
+ path = modules.paths.paths.get("CodeFormer", None)
30
+ if path is None:
31
+ return
32
+
33
+ try:
34
+ from torchvision.transforms.functional import normalize
35
+ from modules.codeformer.codeformer_arch import CodeFormer
36
+ from basicsr.utils.download_util import load_file_from_url
37
+ from basicsr.utils import imwrite, img2tensor, tensor2img
38
+ from facelib.utils.face_restoration_helper import FaceRestoreHelper
39
+ from facelib.detection.retinaface import retinaface
40
+ from modules.shared import cmd_opts
41
+
42
+ net_class = CodeFormer
43
+
44
+ class FaceRestorerCodeFormer(modules.face_restoration.FaceRestoration):
45
+ def name(self):
46
+ return "CodeFormer"
47
+
48
+ def __init__(self, dirname):
49
+ self.net = None
50
+ self.face_helper = None
51
+ self.cmd_dir = dirname
52
+
53
+ def create_models(self):
54
+
55
+ if self.net is not None and self.face_helper is not None:
56
+ self.net.to(devices.device_codeformer)
57
+ return self.net, self.face_helper
58
+ model_paths = modelloader.load_models(model_path, model_url, self.cmd_dir, download_name='codeformer-v0.1.0.pth')
59
+ if len(model_paths) != 0:
60
+ ckpt_path = model_paths[0]
61
+ else:
62
+ print("Unable to load codeformer model.")
63
+ return None, None
64
+ net = net_class(dim_embd=512, codebook_size=1024, n_head=8, n_layers=9, connect_list=['32', '64', '128', '256']).to(devices.device_codeformer)
65
+ checkpoint = torch.load(ckpt_path)['params_ema']
66
+ net.load_state_dict(checkpoint)
67
+ net.eval()
68
+
69
+ if hasattr(retinaface, 'device'):
70
+ retinaface.device = devices.device_codeformer
71
+ face_helper = FaceRestoreHelper(1, face_size=512, crop_ratio=(1, 1), det_model='retinaface_resnet50', save_ext='png', use_parse=True, device=devices.device_codeformer)
72
+
73
+ self.net = net
74
+ self.face_helper = face_helper
75
+
76
+ return net, face_helper
77
+
78
+ def send_model_to(self, device):
79
+ self.net.to(device)
80
+ self.face_helper.face_det.to(device)
81
+ self.face_helper.face_parse.to(device)
82
+
83
+ def restore(self, np_image, w=None):
84
+ np_image = np_image[:, :, ::-1]
85
+
86
+ original_resolution = np_image.shape[0:2]
87
+
88
+ self.create_models()
89
+ if self.net is None or self.face_helper is None:
90
+ return np_image
91
+
92
+ self.send_model_to(devices.device_codeformer)
93
+
94
+ self.face_helper.clean_all()
95
+ self.face_helper.read_image(np_image)
96
+ self.face_helper.get_face_landmarks_5(only_center_face=False, resize=640, eye_dist_threshold=5)
97
+ self.face_helper.align_warp_face()
98
+
99
+ for idx, cropped_face in enumerate(self.face_helper.cropped_faces):
100
+ cropped_face_t = img2tensor(cropped_face / 255., bgr2rgb=True, float32=True)
101
+ normalize(cropped_face_t, (0.5, 0.5, 0.5), (0.5, 0.5, 0.5), inplace=True)
102
+ cropped_face_t = cropped_face_t.unsqueeze(0).to(devices.device_codeformer)
103
+
104
+ try:
105
+ with torch.no_grad():
106
+ output = self.net(cropped_face_t, w=w if w is not None else shared.opts.code_former_weight, adain=True)[0]
107
+ restored_face = tensor2img(output, rgb2bgr=True, min_max=(-1, 1))
108
+ del output
109
+ torch.cuda.empty_cache()
110
+ except Exception as error:
111
+ print(f'\tFailed inference for CodeFormer: {error}', file=sys.stderr)
112
+ restored_face = tensor2img(cropped_face_t, rgb2bgr=True, min_max=(-1, 1))
113
+
114
+ restored_face = restored_face.astype('uint8')
115
+ self.face_helper.add_restored_face(restored_face)
116
+
117
+ self.face_helper.get_inverse_affine(None)
118
+
119
+ restored_img = self.face_helper.paste_faces_to_input_image()
120
+ restored_img = restored_img[:, :, ::-1]
121
+
122
+ if original_resolution != restored_img.shape[0:2]:
123
+ restored_img = cv2.resize(restored_img, (0, 0), fx=original_resolution[1]/restored_img.shape[1], fy=original_resolution[0]/restored_img.shape[0], interpolation=cv2.INTER_LINEAR)
124
+
125
+ self.face_helper.clean_all()
126
+
127
+ if shared.opts.face_restoration_unload:
128
+ self.send_model_to(devices.cpu)
129
+
130
+ return restored_img
131
+
132
+ global have_codeformer
133
+ have_codeformer = True
134
+
135
+ global codeformer
136
+ codeformer = FaceRestorerCodeFormer(dirname)
137
+ shared.face_restorers.append(codeformer)
138
+
139
+ except Exception:
140
+ print("Error setting up CodeFormer:", file=sys.stderr)
141
+ print(traceback.format_exc(), file=sys.stderr)
142
+
143
+ # sys.path = stored_sys_path
modules/deepbooru.py ADDED
@@ -0,0 +1,99 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import re
3
+
4
+ import torch
5
+ from PIL import Image
6
+ import numpy as np
7
+
8
+ from modules import modelloader, paths, deepbooru_model, devices, images, shared
9
+
10
+ re_special = re.compile(r'([\\()])')
11
+
12
+
13
+ class DeepDanbooru:
14
+ def __init__(self):
15
+ self.model = None
16
+
17
+ def load(self):
18
+ if self.model is not None:
19
+ return
20
+
21
+ files = modelloader.load_models(
22
+ model_path=os.path.join(paths.models_path, "torch_deepdanbooru"),
23
+ model_url='https://github.com/AUTOMATIC1111/TorchDeepDanbooru/releases/download/v1/model-resnet_custom_v3.pt',
24
+ ext_filter=[".pt"],
25
+ download_name='model-resnet_custom_v3.pt',
26
+ )
27
+
28
+ self.model = deepbooru_model.DeepDanbooruModel()
29
+ self.model.load_state_dict(torch.load(files[0], map_location="cpu"))
30
+
31
+ self.model.eval()
32
+ self.model.to(devices.cpu, devices.dtype)
33
+
34
+ def start(self):
35
+ self.load()
36
+ self.model.to(devices.device)
37
+
38
+ def stop(self):
39
+ if not shared.opts.interrogate_keep_models_in_memory:
40
+ self.model.to(devices.cpu)
41
+ devices.torch_gc()
42
+
43
+ def tag(self, pil_image):
44
+ self.start()
45
+ res = self.tag_multi(pil_image)
46
+ self.stop()
47
+
48
+ return res
49
+
50
+ def tag_multi(self, pil_image, force_disable_ranks=False):
51
+ threshold = shared.opts.interrogate_deepbooru_score_threshold
52
+ use_spaces = shared.opts.deepbooru_use_spaces
53
+ use_escape = shared.opts.deepbooru_escape
54
+ alpha_sort = shared.opts.deepbooru_sort_alpha
55
+ include_ranks = shared.opts.interrogate_return_ranks and not force_disable_ranks
56
+
57
+ pic = images.resize_image(2, pil_image.convert("RGB"), 512, 512)
58
+ a = np.expand_dims(np.array(pic, dtype=np.float32), 0) / 255
59
+
60
+ with torch.no_grad(), devices.autocast():
61
+ x = torch.from_numpy(a).to(devices.device)
62
+ y = self.model(x)[0].detach().cpu().numpy()
63
+
64
+ probability_dict = {}
65
+
66
+ for tag, probability in zip(self.model.tags, y):
67
+ if probability < threshold:
68
+ continue
69
+
70
+ if tag.startswith("rating:"):
71
+ continue
72
+
73
+ probability_dict[tag] = probability
74
+
75
+ if alpha_sort:
76
+ tags = sorted(probability_dict)
77
+ else:
78
+ tags = [tag for tag, _ in sorted(probability_dict.items(), key=lambda x: -x[1])]
79
+
80
+ res = []
81
+
82
+ filtertags = set([x.strip().replace(' ', '_') for x in shared.opts.deepbooru_filter_tags.split(",")])
83
+
84
+ for tag in [x for x in tags if x not in filtertags]:
85
+ probability = probability_dict[tag]
86
+ tag_outformat = tag
87
+ if use_spaces:
88
+ tag_outformat = tag_outformat.replace('_', ' ')
89
+ if use_escape:
90
+ tag_outformat = re.sub(re_special, r'\\\1', tag_outformat)
91
+ if include_ranks:
92
+ tag_outformat = f"({tag_outformat}:{probability:.3f})"
93
+
94
+ res.append(tag_outformat)
95
+
96
+ return ", ".join(res)
97
+
98
+
99
+ model = DeepDanbooru()
modules/deepbooru_model.py ADDED
@@ -0,0 +1,678 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ import torch.nn as nn
3
+ import torch.nn.functional as F
4
+
5
+ from modules import devices
6
+
7
+ # see https://github.com/AUTOMATIC1111/TorchDeepDanbooru for more
8
+
9
+
10
+ class DeepDanbooruModel(nn.Module):
11
+ def __init__(self):
12
+ super(DeepDanbooruModel, self).__init__()
13
+
14
+ self.tags = []
15
+
16
+ self.n_Conv_0 = nn.Conv2d(kernel_size=(7, 7), in_channels=3, out_channels=64, stride=(2, 2))
17
+ self.n_MaxPool_0 = nn.MaxPool2d(kernel_size=(3, 3), stride=(2, 2))
18
+ self.n_Conv_1 = nn.Conv2d(kernel_size=(1, 1), in_channels=64, out_channels=256)
19
+ self.n_Conv_2 = nn.Conv2d(kernel_size=(1, 1), in_channels=64, out_channels=64)
20
+ self.n_Conv_3 = nn.Conv2d(kernel_size=(3, 3), in_channels=64, out_channels=64)
21
+ self.n_Conv_4 = nn.Conv2d(kernel_size=(1, 1), in_channels=64, out_channels=256)
22
+ self.n_Conv_5 = nn.Conv2d(kernel_size=(1, 1), in_channels=256, out_channels=64)
23
+ self.n_Conv_6 = nn.Conv2d(kernel_size=(3, 3), in_channels=64, out_channels=64)
24
+ self.n_Conv_7 = nn.Conv2d(kernel_size=(1, 1), in_channels=64, out_channels=256)
25
+ self.n_Conv_8 = nn.Conv2d(kernel_size=(1, 1), in_channels=256, out_channels=64)
26
+ self.n_Conv_9 = nn.Conv2d(kernel_size=(3, 3), in_channels=64, out_channels=64)
27
+ self.n_Conv_10 = nn.Conv2d(kernel_size=(1, 1), in_channels=64, out_channels=256)
28
+ self.n_Conv_11 = nn.Conv2d(kernel_size=(1, 1), in_channels=256, out_channels=512, stride=(2, 2))
29
+ self.n_Conv_12 = nn.Conv2d(kernel_size=(1, 1), in_channels=256, out_channels=128)
30
+ self.n_Conv_13 = nn.Conv2d(kernel_size=(3, 3), in_channels=128, out_channels=128, stride=(2, 2))
31
+ self.n_Conv_14 = nn.Conv2d(kernel_size=(1, 1), in_channels=128, out_channels=512)
32
+ self.n_Conv_15 = nn.Conv2d(kernel_size=(1, 1), in_channels=512, out_channels=128)
33
+ self.n_Conv_16 = nn.Conv2d(kernel_size=(3, 3), in_channels=128, out_channels=128)
34
+ self.n_Conv_17 = nn.Conv2d(kernel_size=(1, 1), in_channels=128, out_channels=512)
35
+ self.n_Conv_18 = nn.Conv2d(kernel_size=(1, 1), in_channels=512, out_channels=128)
36
+ self.n_Conv_19 = nn.Conv2d(kernel_size=(3, 3), in_channels=128, out_channels=128)
37
+ self.n_Conv_20 = nn.Conv2d(kernel_size=(1, 1), in_channels=128, out_channels=512)
38
+ self.n_Conv_21 = nn.Conv2d(kernel_size=(1, 1), in_channels=512, out_channels=128)
39
+ self.n_Conv_22 = nn.Conv2d(kernel_size=(3, 3), in_channels=128, out_channels=128)
40
+ self.n_Conv_23 = nn.Conv2d(kernel_size=(1, 1), in_channels=128, out_channels=512)
41
+ self.n_Conv_24 = nn.Conv2d(kernel_size=(1, 1), in_channels=512, out_channels=128)
42
+ self.n_Conv_25 = nn.Conv2d(kernel_size=(3, 3), in_channels=128, out_channels=128)
43
+ self.n_Conv_26 = nn.Conv2d(kernel_size=(1, 1), in_channels=128, out_channels=512)
44
+ self.n_Conv_27 = nn.Conv2d(kernel_size=(1, 1), in_channels=512, out_channels=128)
45
+ self.n_Conv_28 = nn.Conv2d(kernel_size=(3, 3), in_channels=128, out_channels=128)
46
+ self.n_Conv_29 = nn.Conv2d(kernel_size=(1, 1), in_channels=128, out_channels=512)
47
+ self.n_Conv_30 = nn.Conv2d(kernel_size=(1, 1), in_channels=512, out_channels=128)
48
+ self.n_Conv_31 = nn.Conv2d(kernel_size=(3, 3), in_channels=128, out_channels=128)
49
+ self.n_Conv_32 = nn.Conv2d(kernel_size=(1, 1), in_channels=128, out_channels=512)
50
+ self.n_Conv_33 = nn.Conv2d(kernel_size=(1, 1), in_channels=512, out_channels=128)
51
+ self.n_Conv_34 = nn.Conv2d(kernel_size=(3, 3), in_channels=128, out_channels=128)
52
+ self.n_Conv_35 = nn.Conv2d(kernel_size=(1, 1), in_channels=128, out_channels=512)
53
+ self.n_Conv_36 = nn.Conv2d(kernel_size=(1, 1), in_channels=512, out_channels=1024, stride=(2, 2))
54
+ self.n_Conv_37 = nn.Conv2d(kernel_size=(1, 1), in_channels=512, out_channels=256)
55
+ self.n_Conv_38 = nn.Conv2d(kernel_size=(3, 3), in_channels=256, out_channels=256, stride=(2, 2))
56
+ self.n_Conv_39 = nn.Conv2d(kernel_size=(1, 1), in_channels=256, out_channels=1024)
57
+ self.n_Conv_40 = nn.Conv2d(kernel_size=(1, 1), in_channels=1024, out_channels=256)
58
+ self.n_Conv_41 = nn.Conv2d(kernel_size=(3, 3), in_channels=256, out_channels=256)
59
+ self.n_Conv_42 = nn.Conv2d(kernel_size=(1, 1), in_channels=256, out_channels=1024)
60
+ self.n_Conv_43 = nn.Conv2d(kernel_size=(1, 1), in_channels=1024, out_channels=256)
61
+ self.n_Conv_44 = nn.Conv2d(kernel_size=(3, 3), in_channels=256, out_channels=256)
62
+ self.n_Conv_45 = nn.Conv2d(kernel_size=(1, 1), in_channels=256, out_channels=1024)
63
+ self.n_Conv_46 = nn.Conv2d(kernel_size=(1, 1), in_channels=1024, out_channels=256)
64
+ self.n_Conv_47 = nn.Conv2d(kernel_size=(3, 3), in_channels=256, out_channels=256)
65
+ self.n_Conv_48 = nn.Conv2d(kernel_size=(1, 1), in_channels=256, out_channels=1024)
66
+ self.n_Conv_49 = nn.Conv2d(kernel_size=(1, 1), in_channels=1024, out_channels=256)
67
+ self.n_Conv_50 = nn.Conv2d(kernel_size=(3, 3), in_channels=256, out_channels=256)
68
+ self.n_Conv_51 = nn.Conv2d(kernel_size=(1, 1), in_channels=256, out_channels=1024)
69
+ self.n_Conv_52 = nn.Conv2d(kernel_size=(1, 1), in_channels=1024, out_channels=256)
70
+ self.n_Conv_53 = nn.Conv2d(kernel_size=(3, 3), in_channels=256, out_channels=256)
71
+ self.n_Conv_54 = nn.Conv2d(kernel_size=(1, 1), in_channels=256, out_channels=1024)
72
+ self.n_Conv_55 = nn.Conv2d(kernel_size=(1, 1), in_channels=1024, out_channels=256)
73
+ self.n_Conv_56 = nn.Conv2d(kernel_size=(3, 3), in_channels=256, out_channels=256)
74
+ self.n_Conv_57 = nn.Conv2d(kernel_size=(1, 1), in_channels=256, out_channels=1024)
75
+ self.n_Conv_58 = nn.Conv2d(kernel_size=(1, 1), in_channels=1024, out_channels=256)
76
+ self.n_Conv_59 = nn.Conv2d(kernel_size=(3, 3), in_channels=256, out_channels=256)
77
+ self.n_Conv_60 = nn.Conv2d(kernel_size=(1, 1), in_channels=256, out_channels=1024)
78
+ self.n_Conv_61 = nn.Conv2d(kernel_size=(1, 1), in_channels=1024, out_channels=256)
79
+ self.n_Conv_62 = nn.Conv2d(kernel_size=(3, 3), in_channels=256, out_channels=256)
80
+ self.n_Conv_63 = nn.Conv2d(kernel_size=(1, 1), in_channels=256, out_channels=1024)
81
+ self.n_Conv_64 = nn.Conv2d(kernel_size=(1, 1), in_channels=1024, out_channels=256)
82
+ self.n_Conv_65 = nn.Conv2d(kernel_size=(3, 3), in_channels=256, out_channels=256)
83
+ self.n_Conv_66 = nn.Conv2d(kernel_size=(1, 1), in_channels=256, out_channels=1024)
84
+ self.n_Conv_67 = nn.Conv2d(kernel_size=(1, 1), in_channels=1024, out_channels=256)
85
+ self.n_Conv_68 = nn.Conv2d(kernel_size=(3, 3), in_channels=256, out_channels=256)
86
+ self.n_Conv_69 = nn.Conv2d(kernel_size=(1, 1), in_channels=256, out_channels=1024)
87
+ self.n_Conv_70 = nn.Conv2d(kernel_size=(1, 1), in_channels=1024, out_channels=256)
88
+ self.n_Conv_71 = nn.Conv2d(kernel_size=(3, 3), in_channels=256, out_channels=256)
89
+ self.n_Conv_72 = nn.Conv2d(kernel_size=(1, 1), in_channels=256, out_channels=1024)
90
+ self.n_Conv_73 = nn.Conv2d(kernel_size=(1, 1), in_channels=1024, out_channels=256)
91
+ self.n_Conv_74 = nn.Conv2d(kernel_size=(3, 3), in_channels=256, out_channels=256)
92
+ self.n_Conv_75 = nn.Conv2d(kernel_size=(1, 1), in_channels=256, out_channels=1024)
93
+ self.n_Conv_76 = nn.Conv2d(kernel_size=(1, 1), in_channels=1024, out_channels=256)
94
+ self.n_Conv_77 = nn.Conv2d(kernel_size=(3, 3), in_channels=256, out_channels=256)
95
+ self.n_Conv_78 = nn.Conv2d(kernel_size=(1, 1), in_channels=256, out_channels=1024)
96
+ self.n_Conv_79 = nn.Conv2d(kernel_size=(1, 1), in_channels=1024, out_channels=256)
97
+ self.n_Conv_80 = nn.Conv2d(kernel_size=(3, 3), in_channels=256, out_channels=256)
98
+ self.n_Conv_81 = nn.Conv2d(kernel_size=(1, 1), in_channels=256, out_channels=1024)
99
+ self.n_Conv_82 = nn.Conv2d(kernel_size=(1, 1), in_channels=1024, out_channels=256)
100
+ self.n_Conv_83 = nn.Conv2d(kernel_size=(3, 3), in_channels=256, out_channels=256)
101
+ self.n_Conv_84 = nn.Conv2d(kernel_size=(1, 1), in_channels=256, out_channels=1024)
102
+ self.n_Conv_85 = nn.Conv2d(kernel_size=(1, 1), in_channels=1024, out_channels=256)
103
+ self.n_Conv_86 = nn.Conv2d(kernel_size=(3, 3), in_channels=256, out_channels=256)
104
+ self.n_Conv_87 = nn.Conv2d(kernel_size=(1, 1), in_channels=256, out_channels=1024)
105
+ self.n_Conv_88 = nn.Conv2d(kernel_size=(1, 1), in_channels=1024, out_channels=256)
106
+ self.n_Conv_89 = nn.Conv2d(kernel_size=(3, 3), in_channels=256, out_channels=256)
107
+ self.n_Conv_90 = nn.Conv2d(kernel_size=(1, 1), in_channels=256, out_channels=1024)
108
+ self.n_Conv_91 = nn.Conv2d(kernel_size=(1, 1), in_channels=1024, out_channels=256)
109
+ self.n_Conv_92 = nn.Conv2d(kernel_size=(3, 3), in_channels=256, out_channels=256)
110
+ self.n_Conv_93 = nn.Conv2d(kernel_size=(1, 1), in_channels=256, out_channels=1024)
111
+ self.n_Conv_94 = nn.Conv2d(kernel_size=(1, 1), in_channels=1024, out_channels=256)
112
+ self.n_Conv_95 = nn.Conv2d(kernel_size=(3, 3), in_channels=256, out_channels=256)
113
+ self.n_Conv_96 = nn.Conv2d(kernel_size=(1, 1), in_channels=256, out_channels=1024)
114
+ self.n_Conv_97 = nn.Conv2d(kernel_size=(1, 1), in_channels=1024, out_channels=256)
115
+ self.n_Conv_98 = nn.Conv2d(kernel_size=(3, 3), in_channels=256, out_channels=256, stride=(2, 2))
116
+ self.n_Conv_99 = nn.Conv2d(kernel_size=(1, 1), in_channels=256, out_channels=1024)
117
+ self.n_Conv_100 = nn.Conv2d(kernel_size=(1, 1), in_channels=1024, out_channels=1024, stride=(2, 2))
118
+ self.n_Conv_101 = nn.Conv2d(kernel_size=(1, 1), in_channels=1024, out_channels=256)
119
+ self.n_Conv_102 = nn.Conv2d(kernel_size=(3, 3), in_channels=256, out_channels=256)
120
+ self.n_Conv_103 = nn.Conv2d(kernel_size=(1, 1), in_channels=256, out_channels=1024)
121
+ self.n_Conv_104 = nn.Conv2d(kernel_size=(1, 1), in_channels=1024, out_channels=256)
122
+ self.n_Conv_105 = nn.Conv2d(kernel_size=(3, 3), in_channels=256, out_channels=256)
123
+ self.n_Conv_106 = nn.Conv2d(kernel_size=(1, 1), in_channels=256, out_channels=1024)
124
+ self.n_Conv_107 = nn.Conv2d(kernel_size=(1, 1), in_channels=1024, out_channels=256)
125
+ self.n_Conv_108 = nn.Conv2d(kernel_size=(3, 3), in_channels=256, out_channels=256)
126
+ self.n_Conv_109 = nn.Conv2d(kernel_size=(1, 1), in_channels=256, out_channels=1024)
127
+ self.n_Conv_110 = nn.Conv2d(kernel_size=(1, 1), in_channels=1024, out_channels=256)
128
+ self.n_Conv_111 = nn.Conv2d(kernel_size=(3, 3), in_channels=256, out_channels=256)
129
+ self.n_Conv_112 = nn.Conv2d(kernel_size=(1, 1), in_channels=256, out_channels=1024)
130
+ self.n_Conv_113 = nn.Conv2d(kernel_size=(1, 1), in_channels=1024, out_channels=256)
131
+ self.n_Conv_114 = nn.Conv2d(kernel_size=(3, 3), in_channels=256, out_channels=256)
132
+ self.n_Conv_115 = nn.Conv2d(kernel_size=(1, 1), in_channels=256, out_channels=1024)
133
+ self.n_Conv_116 = nn.Conv2d(kernel_size=(1, 1), in_channels=1024, out_channels=256)
134
+ self.n_Conv_117 = nn.Conv2d(kernel_size=(3, 3), in_channels=256, out_channels=256)
135
+ self.n_Conv_118 = nn.Conv2d(kernel_size=(1, 1), in_channels=256, out_channels=1024)
136
+ self.n_Conv_119 = nn.Conv2d(kernel_size=(1, 1), in_channels=1024, out_channels=256)
137
+ self.n_Conv_120 = nn.Conv2d(kernel_size=(3, 3), in_channels=256, out_channels=256)
138
+ self.n_Conv_121 = nn.Conv2d(kernel_size=(1, 1), in_channels=256, out_channels=1024)
139
+ self.n_Conv_122 = nn.Conv2d(kernel_size=(1, 1), in_channels=1024, out_channels=256)
140
+ self.n_Conv_123 = nn.Conv2d(kernel_size=(3, 3), in_channels=256, out_channels=256)
141
+ self.n_Conv_124 = nn.Conv2d(kernel_size=(1, 1), in_channels=256, out_channels=1024)
142
+ self.n_Conv_125 = nn.Conv2d(kernel_size=(1, 1), in_channels=1024, out_channels=256)
143
+ self.n_Conv_126 = nn.Conv2d(kernel_size=(3, 3), in_channels=256, out_channels=256)
144
+ self.n_Conv_127 = nn.Conv2d(kernel_size=(1, 1), in_channels=256, out_channels=1024)
145
+ self.n_Conv_128 = nn.Conv2d(kernel_size=(1, 1), in_channels=1024, out_channels=256)
146
+ self.n_Conv_129 = nn.Conv2d(kernel_size=(3, 3), in_channels=256, out_channels=256)
147
+ self.n_Conv_130 = nn.Conv2d(kernel_size=(1, 1), in_channels=256, out_channels=1024)
148
+ self.n_Conv_131 = nn.Conv2d(kernel_size=(1, 1), in_channels=1024, out_channels=256)
149
+ self.n_Conv_132 = nn.Conv2d(kernel_size=(3, 3), in_channels=256, out_channels=256)
150
+ self.n_Conv_133 = nn.Conv2d(kernel_size=(1, 1), in_channels=256, out_channels=1024)
151
+ self.n_Conv_134 = nn.Conv2d(kernel_size=(1, 1), in_channels=1024, out_channels=256)
152
+ self.n_Conv_135 = nn.Conv2d(kernel_size=(3, 3), in_channels=256, out_channels=256)
153
+ self.n_Conv_136 = nn.Conv2d(kernel_size=(1, 1), in_channels=256, out_channels=1024)
154
+ self.n_Conv_137 = nn.Conv2d(kernel_size=(1, 1), in_channels=1024, out_channels=256)
155
+ self.n_Conv_138 = nn.Conv2d(kernel_size=(3, 3), in_channels=256, out_channels=256)
156
+ self.n_Conv_139 = nn.Conv2d(kernel_size=(1, 1), in_channels=256, out_channels=1024)
157
+ self.n_Conv_140 = nn.Conv2d(kernel_size=(1, 1), in_channels=1024, out_channels=256)
158
+ self.n_Conv_141 = nn.Conv2d(kernel_size=(3, 3), in_channels=256, out_channels=256)
159
+ self.n_Conv_142 = nn.Conv2d(kernel_size=(1, 1), in_channels=256, out_channels=1024)
160
+ self.n_Conv_143 = nn.Conv2d(kernel_size=(1, 1), in_channels=1024, out_channels=256)
161
+ self.n_Conv_144 = nn.Conv2d(kernel_size=(3, 3), in_channels=256, out_channels=256)
162
+ self.n_Conv_145 = nn.Conv2d(kernel_size=(1, 1), in_channels=256, out_channels=1024)
163
+ self.n_Conv_146 = nn.Conv2d(kernel_size=(1, 1), in_channels=1024, out_channels=256)
164
+ self.n_Conv_147 = nn.Conv2d(kernel_size=(3, 3), in_channels=256, out_channels=256)
165
+ self.n_Conv_148 = nn.Conv2d(kernel_size=(1, 1), in_channels=256, out_channels=1024)
166
+ self.n_Conv_149 = nn.Conv2d(kernel_size=(1, 1), in_channels=1024, out_channels=256)
167
+ self.n_Conv_150 = nn.Conv2d(kernel_size=(3, 3), in_channels=256, out_channels=256)
168
+ self.n_Conv_151 = nn.Conv2d(kernel_size=(1, 1), in_channels=256, out_channels=1024)
169
+ self.n_Conv_152 = nn.Conv2d(kernel_size=(1, 1), in_channels=1024, out_channels=256)
170
+ self.n_Conv_153 = nn.Conv2d(kernel_size=(3, 3), in_channels=256, out_channels=256)
171
+ self.n_Conv_154 = nn.Conv2d(kernel_size=(1, 1), in_channels=256, out_channels=1024)
172
+ self.n_Conv_155 = nn.Conv2d(kernel_size=(1, 1), in_channels=1024, out_channels=256)
173
+ self.n_Conv_156 = nn.Conv2d(kernel_size=(3, 3), in_channels=256, out_channels=256)
174
+ self.n_Conv_157 = nn.Conv2d(kernel_size=(1, 1), in_channels=256, out_channels=1024)
175
+ self.n_Conv_158 = nn.Conv2d(kernel_size=(1, 1), in_channels=1024, out_channels=2048, stride=(2, 2))
176
+ self.n_Conv_159 = nn.Conv2d(kernel_size=(1, 1), in_channels=1024, out_channels=512)
177
+ self.n_Conv_160 = nn.Conv2d(kernel_size=(3, 3), in_channels=512, out_channels=512, stride=(2, 2))
178
+ self.n_Conv_161 = nn.Conv2d(kernel_size=(1, 1), in_channels=512, out_channels=2048)
179
+ self.n_Conv_162 = nn.Conv2d(kernel_size=(1, 1), in_channels=2048, out_channels=512)
180
+ self.n_Conv_163 = nn.Conv2d(kernel_size=(3, 3), in_channels=512, out_channels=512)
181
+ self.n_Conv_164 = nn.Conv2d(kernel_size=(1, 1), in_channels=512, out_channels=2048)
182
+ self.n_Conv_165 = nn.Conv2d(kernel_size=(1, 1), in_channels=2048, out_channels=512)
183
+ self.n_Conv_166 = nn.Conv2d(kernel_size=(3, 3), in_channels=512, out_channels=512)
184
+ self.n_Conv_167 = nn.Conv2d(kernel_size=(1, 1), in_channels=512, out_channels=2048)
185
+ self.n_Conv_168 = nn.Conv2d(kernel_size=(1, 1), in_channels=2048, out_channels=4096, stride=(2, 2))
186
+ self.n_Conv_169 = nn.Conv2d(kernel_size=(1, 1), in_channels=2048, out_channels=1024)
187
+ self.n_Conv_170 = nn.Conv2d(kernel_size=(3, 3), in_channels=1024, out_channels=1024, stride=(2, 2))
188
+ self.n_Conv_171 = nn.Conv2d(kernel_size=(1, 1), in_channels=1024, out_channels=4096)
189
+ self.n_Conv_172 = nn.Conv2d(kernel_size=(1, 1), in_channels=4096, out_channels=1024)
190
+ self.n_Conv_173 = nn.Conv2d(kernel_size=(3, 3), in_channels=1024, out_channels=1024)
191
+ self.n_Conv_174 = nn.Conv2d(kernel_size=(1, 1), in_channels=1024, out_channels=4096)
192
+ self.n_Conv_175 = nn.Conv2d(kernel_size=(1, 1), in_channels=4096, out_channels=1024)
193
+ self.n_Conv_176 = nn.Conv2d(kernel_size=(3, 3), in_channels=1024, out_channels=1024)
194
+ self.n_Conv_177 = nn.Conv2d(kernel_size=(1, 1), in_channels=1024, out_channels=4096)
195
+ self.n_Conv_178 = nn.Conv2d(kernel_size=(1, 1), in_channels=4096, out_channels=9176, bias=False)
196
+
197
+ def forward(self, *inputs):
198
+ t_358, = inputs
199
+ t_359 = t_358.permute(*[0, 3, 1, 2])
200
+ t_359_padded = F.pad(t_359, [2, 3, 2, 3], value=0)
201
+ t_360 = self.n_Conv_0(t_359_padded.to(self.n_Conv_0.bias.dtype) if devices.unet_needs_upcast else t_359_padded)
202
+ t_361 = F.relu(t_360)
203
+ t_361 = F.pad(t_361, [0, 1, 0, 1], value=float('-inf'))
204
+ t_362 = self.n_MaxPool_0(t_361)
205
+ t_363 = self.n_Conv_1(t_362)
206
+ t_364 = self.n_Conv_2(t_362)
207
+ t_365 = F.relu(t_364)
208
+ t_365_padded = F.pad(t_365, [1, 1, 1, 1], value=0)
209
+ t_366 = self.n_Conv_3(t_365_padded)
210
+ t_367 = F.relu(t_366)
211
+ t_368 = self.n_Conv_4(t_367)
212
+ t_369 = torch.add(t_368, t_363)
213
+ t_370 = F.relu(t_369)
214
+ t_371 = self.n_Conv_5(t_370)
215
+ t_372 = F.relu(t_371)
216
+ t_372_padded = F.pad(t_372, [1, 1, 1, 1], value=0)
217
+ t_373 = self.n_Conv_6(t_372_padded)
218
+ t_374 = F.relu(t_373)
219
+ t_375 = self.n_Conv_7(t_374)
220
+ t_376 = torch.add(t_375, t_370)
221
+ t_377 = F.relu(t_376)
222
+ t_378 = self.n_Conv_8(t_377)
223
+ t_379 = F.relu(t_378)
224
+ t_379_padded = F.pad(t_379, [1, 1, 1, 1], value=0)
225
+ t_380 = self.n_Conv_9(t_379_padded)
226
+ t_381 = F.relu(t_380)
227
+ t_382 = self.n_Conv_10(t_381)
228
+ t_383 = torch.add(t_382, t_377)
229
+ t_384 = F.relu(t_383)
230
+ t_385 = self.n_Conv_11(t_384)
231
+ t_386 = self.n_Conv_12(t_384)
232
+ t_387 = F.relu(t_386)
233
+ t_387_padded = F.pad(t_387, [0, 1, 0, 1], value=0)
234
+ t_388 = self.n_Conv_13(t_387_padded)
235
+ t_389 = F.relu(t_388)
236
+ t_390 = self.n_Conv_14(t_389)
237
+ t_391 = torch.add(t_390, t_385)
238
+ t_392 = F.relu(t_391)
239
+ t_393 = self.n_Conv_15(t_392)
240
+ t_394 = F.relu(t_393)
241
+ t_394_padded = F.pad(t_394, [1, 1, 1, 1], value=0)
242
+ t_395 = self.n_Conv_16(t_394_padded)
243
+ t_396 = F.relu(t_395)
244
+ t_397 = self.n_Conv_17(t_396)
245
+ t_398 = torch.add(t_397, t_392)
246
+ t_399 = F.relu(t_398)
247
+ t_400 = self.n_Conv_18(t_399)
248
+ t_401 = F.relu(t_400)
249
+ t_401_padded = F.pad(t_401, [1, 1, 1, 1], value=0)
250
+ t_402 = self.n_Conv_19(t_401_padded)
251
+ t_403 = F.relu(t_402)
252
+ t_404 = self.n_Conv_20(t_403)
253
+ t_405 = torch.add(t_404, t_399)
254
+ t_406 = F.relu(t_405)
255
+ t_407 = self.n_Conv_21(t_406)
256
+ t_408 = F.relu(t_407)
257
+ t_408_padded = F.pad(t_408, [1, 1, 1, 1], value=0)
258
+ t_409 = self.n_Conv_22(t_408_padded)
259
+ t_410 = F.relu(t_409)
260
+ t_411 = self.n_Conv_23(t_410)
261
+ t_412 = torch.add(t_411, t_406)
262
+ t_413 = F.relu(t_412)
263
+ t_414 = self.n_Conv_24(t_413)
264
+ t_415 = F.relu(t_414)
265
+ t_415_padded = F.pad(t_415, [1, 1, 1, 1], value=0)
266
+ t_416 = self.n_Conv_25(t_415_padded)
267
+ t_417 = F.relu(t_416)
268
+ t_418 = self.n_Conv_26(t_417)
269
+ t_419 = torch.add(t_418, t_413)
270
+ t_420 = F.relu(t_419)
271
+ t_421 = self.n_Conv_27(t_420)
272
+ t_422 = F.relu(t_421)
273
+ t_422_padded = F.pad(t_422, [1, 1, 1, 1], value=0)
274
+ t_423 = self.n_Conv_28(t_422_padded)
275
+ t_424 = F.relu(t_423)
276
+ t_425 = self.n_Conv_29(t_424)
277
+ t_426 = torch.add(t_425, t_420)
278
+ t_427 = F.relu(t_426)
279
+ t_428 = self.n_Conv_30(t_427)
280
+ t_429 = F.relu(t_428)
281
+ t_429_padded = F.pad(t_429, [1, 1, 1, 1], value=0)
282
+ t_430 = self.n_Conv_31(t_429_padded)
283
+ t_431 = F.relu(t_430)
284
+ t_432 = self.n_Conv_32(t_431)
285
+ t_433 = torch.add(t_432, t_427)
286
+ t_434 = F.relu(t_433)
287
+ t_435 = self.n_Conv_33(t_434)
288
+ t_436 = F.relu(t_435)
289
+ t_436_padded = F.pad(t_436, [1, 1, 1, 1], value=0)
290
+ t_437 = self.n_Conv_34(t_436_padded)
291
+ t_438 = F.relu(t_437)
292
+ t_439 = self.n_Conv_35(t_438)
293
+ t_440 = torch.add(t_439, t_434)
294
+ t_441 = F.relu(t_440)
295
+ t_442 = self.n_Conv_36(t_441)
296
+ t_443 = self.n_Conv_37(t_441)
297
+ t_444 = F.relu(t_443)
298
+ t_444_padded = F.pad(t_444, [0, 1, 0, 1], value=0)
299
+ t_445 = self.n_Conv_38(t_444_padded)
300
+ t_446 = F.relu(t_445)
301
+ t_447 = self.n_Conv_39(t_446)
302
+ t_448 = torch.add(t_447, t_442)
303
+ t_449 = F.relu(t_448)
304
+ t_450 = self.n_Conv_40(t_449)
305
+ t_451 = F.relu(t_450)
306
+ t_451_padded = F.pad(t_451, [1, 1, 1, 1], value=0)
307
+ t_452 = self.n_Conv_41(t_451_padded)
308
+ t_453 = F.relu(t_452)
309
+ t_454 = self.n_Conv_42(t_453)
310
+ t_455 = torch.add(t_454, t_449)
311
+ t_456 = F.relu(t_455)
312
+ t_457 = self.n_Conv_43(t_456)
313
+ t_458 = F.relu(t_457)
314
+ t_458_padded = F.pad(t_458, [1, 1, 1, 1], value=0)
315
+ t_459 = self.n_Conv_44(t_458_padded)
316
+ t_460 = F.relu(t_459)
317
+ t_461 = self.n_Conv_45(t_460)
318
+ t_462 = torch.add(t_461, t_456)
319
+ t_463 = F.relu(t_462)
320
+ t_464 = self.n_Conv_46(t_463)
321
+ t_465 = F.relu(t_464)
322
+ t_465_padded = F.pad(t_465, [1, 1, 1, 1], value=0)
323
+ t_466 = self.n_Conv_47(t_465_padded)
324
+ t_467 = F.relu(t_466)
325
+ t_468 = self.n_Conv_48(t_467)
326
+ t_469 = torch.add(t_468, t_463)
327
+ t_470 = F.relu(t_469)
328
+ t_471 = self.n_Conv_49(t_470)
329
+ t_472 = F.relu(t_471)
330
+ t_472_padded = F.pad(t_472, [1, 1, 1, 1], value=0)
331
+ t_473 = self.n_Conv_50(t_472_padded)
332
+ t_474 = F.relu(t_473)
333
+ t_475 = self.n_Conv_51(t_474)
334
+ t_476 = torch.add(t_475, t_470)
335
+ t_477 = F.relu(t_476)
336
+ t_478 = self.n_Conv_52(t_477)
337
+ t_479 = F.relu(t_478)
338
+ t_479_padded = F.pad(t_479, [1, 1, 1, 1], value=0)
339
+ t_480 = self.n_Conv_53(t_479_padded)
340
+ t_481 = F.relu(t_480)
341
+ t_482 = self.n_Conv_54(t_481)
342
+ t_483 = torch.add(t_482, t_477)
343
+ t_484 = F.relu(t_483)
344
+ t_485 = self.n_Conv_55(t_484)
345
+ t_486 = F.relu(t_485)
346
+ t_486_padded = F.pad(t_486, [1, 1, 1, 1], value=0)
347
+ t_487 = self.n_Conv_56(t_486_padded)
348
+ t_488 = F.relu(t_487)
349
+ t_489 = self.n_Conv_57(t_488)
350
+ t_490 = torch.add(t_489, t_484)
351
+ t_491 = F.relu(t_490)
352
+ t_492 = self.n_Conv_58(t_491)
353
+ t_493 = F.relu(t_492)
354
+ t_493_padded = F.pad(t_493, [1, 1, 1, 1], value=0)
355
+ t_494 = self.n_Conv_59(t_493_padded)
356
+ t_495 = F.relu(t_494)
357
+ t_496 = self.n_Conv_60(t_495)
358
+ t_497 = torch.add(t_496, t_491)
359
+ t_498 = F.relu(t_497)
360
+ t_499 = self.n_Conv_61(t_498)
361
+ t_500 = F.relu(t_499)
362
+ t_500_padded = F.pad(t_500, [1, 1, 1, 1], value=0)
363
+ t_501 = self.n_Conv_62(t_500_padded)
364
+ t_502 = F.relu(t_501)
365
+ t_503 = self.n_Conv_63(t_502)
366
+ t_504 = torch.add(t_503, t_498)
367
+ t_505 = F.relu(t_504)
368
+ t_506 = self.n_Conv_64(t_505)
369
+ t_507 = F.relu(t_506)
370
+ t_507_padded = F.pad(t_507, [1, 1, 1, 1], value=0)
371
+ t_508 = self.n_Conv_65(t_507_padded)
372
+ t_509 = F.relu(t_508)
373
+ t_510 = self.n_Conv_66(t_509)
374
+ t_511 = torch.add(t_510, t_505)
375
+ t_512 = F.relu(t_511)
376
+ t_513 = self.n_Conv_67(t_512)
377
+ t_514 = F.relu(t_513)
378
+ t_514_padded = F.pad(t_514, [1, 1, 1, 1], value=0)
379
+ t_515 = self.n_Conv_68(t_514_padded)
380
+ t_516 = F.relu(t_515)
381
+ t_517 = self.n_Conv_69(t_516)
382
+ t_518 = torch.add(t_517, t_512)
383
+ t_519 = F.relu(t_518)
384
+ t_520 = self.n_Conv_70(t_519)
385
+ t_521 = F.relu(t_520)
386
+ t_521_padded = F.pad(t_521, [1, 1, 1, 1], value=0)
387
+ t_522 = self.n_Conv_71(t_521_padded)
388
+ t_523 = F.relu(t_522)
389
+ t_524 = self.n_Conv_72(t_523)
390
+ t_525 = torch.add(t_524, t_519)
391
+ t_526 = F.relu(t_525)
392
+ t_527 = self.n_Conv_73(t_526)
393
+ t_528 = F.relu(t_527)
394
+ t_528_padded = F.pad(t_528, [1, 1, 1, 1], value=0)
395
+ t_529 = self.n_Conv_74(t_528_padded)
396
+ t_530 = F.relu(t_529)
397
+ t_531 = self.n_Conv_75(t_530)
398
+ t_532 = torch.add(t_531, t_526)
399
+ t_533 = F.relu(t_532)
400
+ t_534 = self.n_Conv_76(t_533)
401
+ t_535 = F.relu(t_534)
402
+ t_535_padded = F.pad(t_535, [1, 1, 1, 1], value=0)
403
+ t_536 = self.n_Conv_77(t_535_padded)
404
+ t_537 = F.relu(t_536)
405
+ t_538 = self.n_Conv_78(t_537)
406
+ t_539 = torch.add(t_538, t_533)
407
+ t_540 = F.relu(t_539)
408
+ t_541 = self.n_Conv_79(t_540)
409
+ t_542 = F.relu(t_541)
410
+ t_542_padded = F.pad(t_542, [1, 1, 1, 1], value=0)
411
+ t_543 = self.n_Conv_80(t_542_padded)
412
+ t_544 = F.relu(t_543)
413
+ t_545 = self.n_Conv_81(t_544)
414
+ t_546 = torch.add(t_545, t_540)
415
+ t_547 = F.relu(t_546)
416
+ t_548 = self.n_Conv_82(t_547)
417
+ t_549 = F.relu(t_548)
418
+ t_549_padded = F.pad(t_549, [1, 1, 1, 1], value=0)
419
+ t_550 = self.n_Conv_83(t_549_padded)
420
+ t_551 = F.relu(t_550)
421
+ t_552 = self.n_Conv_84(t_551)
422
+ t_553 = torch.add(t_552, t_547)
423
+ t_554 = F.relu(t_553)
424
+ t_555 = self.n_Conv_85(t_554)
425
+ t_556 = F.relu(t_555)
426
+ t_556_padded = F.pad(t_556, [1, 1, 1, 1], value=0)
427
+ t_557 = self.n_Conv_86(t_556_padded)
428
+ t_558 = F.relu(t_557)
429
+ t_559 = self.n_Conv_87(t_558)
430
+ t_560 = torch.add(t_559, t_554)
431
+ t_561 = F.relu(t_560)
432
+ t_562 = self.n_Conv_88(t_561)
433
+ t_563 = F.relu(t_562)
434
+ t_563_padded = F.pad(t_563, [1, 1, 1, 1], value=0)
435
+ t_564 = self.n_Conv_89(t_563_padded)
436
+ t_565 = F.relu(t_564)
437
+ t_566 = self.n_Conv_90(t_565)
438
+ t_567 = torch.add(t_566, t_561)
439
+ t_568 = F.relu(t_567)
440
+ t_569 = self.n_Conv_91(t_568)
441
+ t_570 = F.relu(t_569)
442
+ t_570_padded = F.pad(t_570, [1, 1, 1, 1], value=0)
443
+ t_571 = self.n_Conv_92(t_570_padded)
444
+ t_572 = F.relu(t_571)
445
+ t_573 = self.n_Conv_93(t_572)
446
+ t_574 = torch.add(t_573, t_568)
447
+ t_575 = F.relu(t_574)
448
+ t_576 = self.n_Conv_94(t_575)
449
+ t_577 = F.relu(t_576)
450
+ t_577_padded = F.pad(t_577, [1, 1, 1, 1], value=0)
451
+ t_578 = self.n_Conv_95(t_577_padded)
452
+ t_579 = F.relu(t_578)
453
+ t_580 = self.n_Conv_96(t_579)
454
+ t_581 = torch.add(t_580, t_575)
455
+ t_582 = F.relu(t_581)
456
+ t_583 = self.n_Conv_97(t_582)
457
+ t_584 = F.relu(t_583)
458
+ t_584_padded = F.pad(t_584, [0, 1, 0, 1], value=0)
459
+ t_585 = self.n_Conv_98(t_584_padded)
460
+ t_586 = F.relu(t_585)
461
+ t_587 = self.n_Conv_99(t_586)
462
+ t_588 = self.n_Conv_100(t_582)
463
+ t_589 = torch.add(t_587, t_588)
464
+ t_590 = F.relu(t_589)
465
+ t_591 = self.n_Conv_101(t_590)
466
+ t_592 = F.relu(t_591)
467
+ t_592_padded = F.pad(t_592, [1, 1, 1, 1], value=0)
468
+ t_593 = self.n_Conv_102(t_592_padded)
469
+ t_594 = F.relu(t_593)
470
+ t_595 = self.n_Conv_103(t_594)
471
+ t_596 = torch.add(t_595, t_590)
472
+ t_597 = F.relu(t_596)
473
+ t_598 = self.n_Conv_104(t_597)
474
+ t_599 = F.relu(t_598)
475
+ t_599_padded = F.pad(t_599, [1, 1, 1, 1], value=0)
476
+ t_600 = self.n_Conv_105(t_599_padded)
477
+ t_601 = F.relu(t_600)
478
+ t_602 = self.n_Conv_106(t_601)
479
+ t_603 = torch.add(t_602, t_597)
480
+ t_604 = F.relu(t_603)
481
+ t_605 = self.n_Conv_107(t_604)
482
+ t_606 = F.relu(t_605)
483
+ t_606_padded = F.pad(t_606, [1, 1, 1, 1], value=0)
484
+ t_607 = self.n_Conv_108(t_606_padded)
485
+ t_608 = F.relu(t_607)
486
+ t_609 = self.n_Conv_109(t_608)
487
+ t_610 = torch.add(t_609, t_604)
488
+ t_611 = F.relu(t_610)
489
+ t_612 = self.n_Conv_110(t_611)
490
+ t_613 = F.relu(t_612)
491
+ t_613_padded = F.pad(t_613, [1, 1, 1, 1], value=0)
492
+ t_614 = self.n_Conv_111(t_613_padded)
493
+ t_615 = F.relu(t_614)
494
+ t_616 = self.n_Conv_112(t_615)
495
+ t_617 = torch.add(t_616, t_611)
496
+ t_618 = F.relu(t_617)
497
+ t_619 = self.n_Conv_113(t_618)
498
+ t_620 = F.relu(t_619)
499
+ t_620_padded = F.pad(t_620, [1, 1, 1, 1], value=0)
500
+ t_621 = self.n_Conv_114(t_620_padded)
501
+ t_622 = F.relu(t_621)
502
+ t_623 = self.n_Conv_115(t_622)
503
+ t_624 = torch.add(t_623, t_618)
504
+ t_625 = F.relu(t_624)
505
+ t_626 = self.n_Conv_116(t_625)
506
+ t_627 = F.relu(t_626)
507
+ t_627_padded = F.pad(t_627, [1, 1, 1, 1], value=0)
508
+ t_628 = self.n_Conv_117(t_627_padded)
509
+ t_629 = F.relu(t_628)
510
+ t_630 = self.n_Conv_118(t_629)
511
+ t_631 = torch.add(t_630, t_625)
512
+ t_632 = F.relu(t_631)
513
+ t_633 = self.n_Conv_119(t_632)
514
+ t_634 = F.relu(t_633)
515
+ t_634_padded = F.pad(t_634, [1, 1, 1, 1], value=0)
516
+ t_635 = self.n_Conv_120(t_634_padded)
517
+ t_636 = F.relu(t_635)
518
+ t_637 = self.n_Conv_121(t_636)
519
+ t_638 = torch.add(t_637, t_632)
520
+ t_639 = F.relu(t_638)
521
+ t_640 = self.n_Conv_122(t_639)
522
+ t_641 = F.relu(t_640)
523
+ t_641_padded = F.pad(t_641, [1, 1, 1, 1], value=0)
524
+ t_642 = self.n_Conv_123(t_641_padded)
525
+ t_643 = F.relu(t_642)
526
+ t_644 = self.n_Conv_124(t_643)
527
+ t_645 = torch.add(t_644, t_639)
528
+ t_646 = F.relu(t_645)
529
+ t_647 = self.n_Conv_125(t_646)
530
+ t_648 = F.relu(t_647)
531
+ t_648_padded = F.pad(t_648, [1, 1, 1, 1], value=0)
532
+ t_649 = self.n_Conv_126(t_648_padded)
533
+ t_650 = F.relu(t_649)
534
+ t_651 = self.n_Conv_127(t_650)
535
+ t_652 = torch.add(t_651, t_646)
536
+ t_653 = F.relu(t_652)
537
+ t_654 = self.n_Conv_128(t_653)
538
+ t_655 = F.relu(t_654)
539
+ t_655_padded = F.pad(t_655, [1, 1, 1, 1], value=0)
540
+ t_656 = self.n_Conv_129(t_655_padded)
541
+ t_657 = F.relu(t_656)
542
+ t_658 = self.n_Conv_130(t_657)
543
+ t_659 = torch.add(t_658, t_653)
544
+ t_660 = F.relu(t_659)
545
+ t_661 = self.n_Conv_131(t_660)
546
+ t_662 = F.relu(t_661)
547
+ t_662_padded = F.pad(t_662, [1, 1, 1, 1], value=0)
548
+ t_663 = self.n_Conv_132(t_662_padded)
549
+ t_664 = F.relu(t_663)
550
+ t_665 = self.n_Conv_133(t_664)
551
+ t_666 = torch.add(t_665, t_660)
552
+ t_667 = F.relu(t_666)
553
+ t_668 = self.n_Conv_134(t_667)
554
+ t_669 = F.relu(t_668)
555
+ t_669_padded = F.pad(t_669, [1, 1, 1, 1], value=0)
556
+ t_670 = self.n_Conv_135(t_669_padded)
557
+ t_671 = F.relu(t_670)
558
+ t_672 = self.n_Conv_136(t_671)
559
+ t_673 = torch.add(t_672, t_667)
560
+ t_674 = F.relu(t_673)
561
+ t_675 = self.n_Conv_137(t_674)
562
+ t_676 = F.relu(t_675)
563
+ t_676_padded = F.pad(t_676, [1, 1, 1, 1], value=0)
564
+ t_677 = self.n_Conv_138(t_676_padded)
565
+ t_678 = F.relu(t_677)
566
+ t_679 = self.n_Conv_139(t_678)
567
+ t_680 = torch.add(t_679, t_674)
568
+ t_681 = F.relu(t_680)
569
+ t_682 = self.n_Conv_140(t_681)
570
+ t_683 = F.relu(t_682)
571
+ t_683_padded = F.pad(t_683, [1, 1, 1, 1], value=0)
572
+ t_684 = self.n_Conv_141(t_683_padded)
573
+ t_685 = F.relu(t_684)
574
+ t_686 = self.n_Conv_142(t_685)
575
+ t_687 = torch.add(t_686, t_681)
576
+ t_688 = F.relu(t_687)
577
+ t_689 = self.n_Conv_143(t_688)
578
+ t_690 = F.relu(t_689)
579
+ t_690_padded = F.pad(t_690, [1, 1, 1, 1], value=0)
580
+ t_691 = self.n_Conv_144(t_690_padded)
581
+ t_692 = F.relu(t_691)
582
+ t_693 = self.n_Conv_145(t_692)
583
+ t_694 = torch.add(t_693, t_688)
584
+ t_695 = F.relu(t_694)
585
+ t_696 = self.n_Conv_146(t_695)
586
+ t_697 = F.relu(t_696)
587
+ t_697_padded = F.pad(t_697, [1, 1, 1, 1], value=0)
588
+ t_698 = self.n_Conv_147(t_697_padded)
589
+ t_699 = F.relu(t_698)
590
+ t_700 = self.n_Conv_148(t_699)
591
+ t_701 = torch.add(t_700, t_695)
592
+ t_702 = F.relu(t_701)
593
+ t_703 = self.n_Conv_149(t_702)
594
+ t_704 = F.relu(t_703)
595
+ t_704_padded = F.pad(t_704, [1, 1, 1, 1], value=0)
596
+ t_705 = self.n_Conv_150(t_704_padded)
597
+ t_706 = F.relu(t_705)
598
+ t_707 = self.n_Conv_151(t_706)
599
+ t_708 = torch.add(t_707, t_702)
600
+ t_709 = F.relu(t_708)
601
+ t_710 = self.n_Conv_152(t_709)
602
+ t_711 = F.relu(t_710)
603
+ t_711_padded = F.pad(t_711, [1, 1, 1, 1], value=0)
604
+ t_712 = self.n_Conv_153(t_711_padded)
605
+ t_713 = F.relu(t_712)
606
+ t_714 = self.n_Conv_154(t_713)
607
+ t_715 = torch.add(t_714, t_709)
608
+ t_716 = F.relu(t_715)
609
+ t_717 = self.n_Conv_155(t_716)
610
+ t_718 = F.relu(t_717)
611
+ t_718_padded = F.pad(t_718, [1, 1, 1, 1], value=0)
612
+ t_719 = self.n_Conv_156(t_718_padded)
613
+ t_720 = F.relu(t_719)
614
+ t_721 = self.n_Conv_157(t_720)
615
+ t_722 = torch.add(t_721, t_716)
616
+ t_723 = F.relu(t_722)
617
+ t_724 = self.n_Conv_158(t_723)
618
+ t_725 = self.n_Conv_159(t_723)
619
+ t_726 = F.relu(t_725)
620
+ t_726_padded = F.pad(t_726, [0, 1, 0, 1], value=0)
621
+ t_727 = self.n_Conv_160(t_726_padded)
622
+ t_728 = F.relu(t_727)
623
+ t_729 = self.n_Conv_161(t_728)
624
+ t_730 = torch.add(t_729, t_724)
625
+ t_731 = F.relu(t_730)
626
+ t_732 = self.n_Conv_162(t_731)
627
+ t_733 = F.relu(t_732)
628
+ t_733_padded = F.pad(t_733, [1, 1, 1, 1], value=0)
629
+ t_734 = self.n_Conv_163(t_733_padded)
630
+ t_735 = F.relu(t_734)
631
+ t_736 = self.n_Conv_164(t_735)
632
+ t_737 = torch.add(t_736, t_731)
633
+ t_738 = F.relu(t_737)
634
+ t_739 = self.n_Conv_165(t_738)
635
+ t_740 = F.relu(t_739)
636
+ t_740_padded = F.pad(t_740, [1, 1, 1, 1], value=0)
637
+ t_741 = self.n_Conv_166(t_740_padded)
638
+ t_742 = F.relu(t_741)
639
+ t_743 = self.n_Conv_167(t_742)
640
+ t_744 = torch.add(t_743, t_738)
641
+ t_745 = F.relu(t_744)
642
+ t_746 = self.n_Conv_168(t_745)
643
+ t_747 = self.n_Conv_169(t_745)
644
+ t_748 = F.relu(t_747)
645
+ t_748_padded = F.pad(t_748, [0, 1, 0, 1], value=0)
646
+ t_749 = self.n_Conv_170(t_748_padded)
647
+ t_750 = F.relu(t_749)
648
+ t_751 = self.n_Conv_171(t_750)
649
+ t_752 = torch.add(t_751, t_746)
650
+ t_753 = F.relu(t_752)
651
+ t_754 = self.n_Conv_172(t_753)
652
+ t_755 = F.relu(t_754)
653
+ t_755_padded = F.pad(t_755, [1, 1, 1, 1], value=0)
654
+ t_756 = self.n_Conv_173(t_755_padded)
655
+ t_757 = F.relu(t_756)
656
+ t_758 = self.n_Conv_174(t_757)
657
+ t_759 = torch.add(t_758, t_753)
658
+ t_760 = F.relu(t_759)
659
+ t_761 = self.n_Conv_175(t_760)
660
+ t_762 = F.relu(t_761)
661
+ t_762_padded = F.pad(t_762, [1, 1, 1, 1], value=0)
662
+ t_763 = self.n_Conv_176(t_762_padded)
663
+ t_764 = F.relu(t_763)
664
+ t_765 = self.n_Conv_177(t_764)
665
+ t_766 = torch.add(t_765, t_760)
666
+ t_767 = F.relu(t_766)
667
+ t_768 = self.n_Conv_178(t_767)
668
+ t_769 = F.avg_pool2d(t_768, kernel_size=t_768.shape[-2:])
669
+ t_770 = torch.squeeze(t_769, 3)
670
+ t_770 = torch.squeeze(t_770, 2)
671
+ t_771 = torch.sigmoid(t_770)
672
+ return t_771
673
+
674
+ def load_state_dict(self, state_dict, **kwargs):
675
+ self.tags = state_dict.get('tags', [])
676
+
677
+ super(DeepDanbooruModel, self).load_state_dict({k: v for k, v in state_dict.items() if k != 'tags'})
678
+
modules/devices.py ADDED
@@ -0,0 +1,152 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import sys
2
+ import contextlib
3
+ import torch
4
+ from modules import errors
5
+
6
+ if sys.platform == "darwin":
7
+ from modules import mac_specific
8
+
9
+
10
+ def has_mps() -> bool:
11
+ if sys.platform != "darwin":
12
+ return False
13
+ else:
14
+ return mac_specific.has_mps
15
+
16
+ def extract_device_id(args, name):
17
+ for x in range(len(args)):
18
+ if name in args[x]:
19
+ return args[x + 1]
20
+
21
+ return None
22
+
23
+
24
+ def get_cuda_device_string():
25
+ from modules import shared
26
+
27
+ if shared.cmd_opts.device_id is not None:
28
+ return f"cuda:{shared.cmd_opts.device_id}"
29
+
30
+ return "cuda"
31
+
32
+
33
+ def get_optimal_device_name():
34
+ if torch.cuda.is_available():
35
+ return get_cuda_device_string()
36
+
37
+ if has_mps():
38
+ return "mps"
39
+
40
+ return "cpu"
41
+
42
+
43
+ def get_optimal_device():
44
+ return torch.device(get_optimal_device_name())
45
+
46
+
47
+ def get_device_for(task):
48
+ from modules import shared
49
+
50
+ if task in shared.cmd_opts.use_cpu:
51
+ return cpu
52
+
53
+ return get_optimal_device()
54
+
55
+
56
+ def torch_gc():
57
+ if torch.cuda.is_available():
58
+ with torch.cuda.device(get_cuda_device_string()):
59
+ torch.cuda.empty_cache()
60
+ torch.cuda.ipc_collect()
61
+
62
+
63
+ def enable_tf32():
64
+ if torch.cuda.is_available():
65
+
66
+ # enabling benchmark option seems to enable a range of cards to do fp16 when they otherwise can't
67
+ # see https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/4407
68
+ if any([torch.cuda.get_device_capability(devid) == (7, 5) for devid in range(0, torch.cuda.device_count())]):
69
+ torch.backends.cudnn.benchmark = True
70
+
71
+ torch.backends.cuda.matmul.allow_tf32 = True
72
+ torch.backends.cudnn.allow_tf32 = True
73
+
74
+
75
+
76
+ errors.run(enable_tf32, "Enabling TF32")
77
+
78
+ cpu = torch.device("cpu")
79
+ device = device_interrogate = device_gfpgan = device_esrgan = device_codeformer = None
80
+ dtype = torch.float16
81
+ dtype_vae = torch.float16
82
+ dtype_unet = torch.float16
83
+ unet_needs_upcast = False
84
+
85
+
86
+ def cond_cast_unet(input):
87
+ return input.to(dtype_unet) if unet_needs_upcast else input
88
+
89
+
90
+ def cond_cast_float(input):
91
+ return input.float() if unet_needs_upcast else input
92
+
93
+
94
+ def randn(seed, shape):
95
+ torch.manual_seed(seed)
96
+ if device.type == 'mps':
97
+ return torch.randn(shape, device=cpu).to(device)
98
+ return torch.randn(shape, device=device)
99
+
100
+
101
+ def randn_without_seed(shape):
102
+ if device.type == 'mps':
103
+ return torch.randn(shape, device=cpu).to(device)
104
+ return torch.randn(shape, device=device)
105
+
106
+
107
+ def autocast(disable=False):
108
+ from modules import shared
109
+
110
+ if disable:
111
+ return contextlib.nullcontext()
112
+
113
+ if dtype == torch.float32 or shared.cmd_opts.precision == "full":
114
+ return contextlib.nullcontext()
115
+
116
+ return torch.autocast("cuda")
117
+
118
+
119
+ def without_autocast(disable=False):
120
+ return torch.autocast("cuda", enabled=False) if torch.is_autocast_enabled() and not disable else contextlib.nullcontext()
121
+
122
+
123
+ class NansException(Exception):
124
+ pass
125
+
126
+
127
+ def test_for_nans(x, where):
128
+ from modules import shared
129
+
130
+ if shared.cmd_opts.disable_nan_check:
131
+ return
132
+
133
+ if not torch.all(torch.isnan(x)).item():
134
+ return
135
+
136
+ if where == "unet":
137
+ message = "A tensor with all NaNs was produced in Unet."
138
+
139
+ if not shared.cmd_opts.no_half:
140
+ message += " This could be either because there's not enough precision to represent the picture, or because your video card does not support half type. Try setting the \"Upcast cross attention layer to float32\" option in Settings > Stable Diffusion or using the --no-half commandline argument to fix this."
141
+
142
+ elif where == "vae":
143
+ message = "A tensor with all NaNs was produced in VAE."
144
+
145
+ if not shared.cmd_opts.no_half and not shared.cmd_opts.no_half_vae:
146
+ message += " This could be because there's not enough precision to represent the picture. Try adding --no-half-vae commandline argument to fix this."
147
+ else:
148
+ message = "A tensor with all NaNs was produced."
149
+
150
+ message += " Use --disable-nan-check commandline argument to disable this check."
151
+
152
+ raise NansException(message)
modules/errors.py ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import sys
2
+ import traceback
3
+
4
+
5
+ def print_error_explanation(message):
6
+ lines = message.strip().split("\n")
7
+ max_len = max([len(x) for x in lines])
8
+
9
+ print('=' * max_len, file=sys.stderr)
10
+ for line in lines:
11
+ print(line, file=sys.stderr)
12
+ print('=' * max_len, file=sys.stderr)
13
+
14
+
15
+ def display(e: Exception, task):
16
+ print(f"{task or 'error'}: {type(e).__name__}", file=sys.stderr)
17
+ print(traceback.format_exc(), file=sys.stderr)
18
+
19
+ message = str(e)
20
+ if "copying a param with shape torch.Size([640, 1024]) from checkpoint, the shape in current model is torch.Size([640, 768])" in message:
21
+ print_error_explanation("""
22
+ The most likely cause of this is you are trying to load Stable Diffusion 2.0 model without specifying its config file.
23
+ See https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Features#stable-diffusion-20 for how to solve this.
24
+ """)
25
+
26
+
27
+ already_displayed = {}
28
+
29
+
30
+ def display_once(e: Exception, task):
31
+ if task in already_displayed:
32
+ return
33
+
34
+ display(e, task)
35
+
36
+ already_displayed[task] = 1
37
+
38
+
39
+ def run(code, task):
40
+ try:
41
+ code()
42
+ except Exception as e:
43
+ display(task, e)
modules/esrgan_model.py ADDED
@@ -0,0 +1,233 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+
3
+ import numpy as np
4
+ import torch
5
+ from PIL import Image
6
+ from basicsr.utils.download_util import load_file_from_url
7
+
8
+ import modules.esrgan_model_arch as arch
9
+ from modules import shared, modelloader, images, devices
10
+ from modules.upscaler import Upscaler, UpscalerData
11
+ from modules.shared import opts
12
+
13
+
14
+
15
+ def mod2normal(state_dict):
16
+ # this code is copied from https://github.com/victorca25/iNNfer
17
+ if 'conv_first.weight' in state_dict:
18
+ crt_net = {}
19
+ items = []
20
+ for k, v in state_dict.items():
21
+ items.append(k)
22
+
23
+ crt_net['model.0.weight'] = state_dict['conv_first.weight']
24
+ crt_net['model.0.bias'] = state_dict['conv_first.bias']
25
+
26
+ for k in items.copy():
27
+ if 'RDB' in k:
28
+ ori_k = k.replace('RRDB_trunk.', 'model.1.sub.')
29
+ if '.weight' in k:
30
+ ori_k = ori_k.replace('.weight', '.0.weight')
31
+ elif '.bias' in k:
32
+ ori_k = ori_k.replace('.bias', '.0.bias')
33
+ crt_net[ori_k] = state_dict[k]
34
+ items.remove(k)
35
+
36
+ crt_net['model.1.sub.23.weight'] = state_dict['trunk_conv.weight']
37
+ crt_net['model.1.sub.23.bias'] = state_dict['trunk_conv.bias']
38
+ crt_net['model.3.weight'] = state_dict['upconv1.weight']
39
+ crt_net['model.3.bias'] = state_dict['upconv1.bias']
40
+ crt_net['model.6.weight'] = state_dict['upconv2.weight']
41
+ crt_net['model.6.bias'] = state_dict['upconv2.bias']
42
+ crt_net['model.8.weight'] = state_dict['HRconv.weight']
43
+ crt_net['model.8.bias'] = state_dict['HRconv.bias']
44
+ crt_net['model.10.weight'] = state_dict['conv_last.weight']
45
+ crt_net['model.10.bias'] = state_dict['conv_last.bias']
46
+ state_dict = crt_net
47
+ return state_dict
48
+
49
+
50
+ def resrgan2normal(state_dict, nb=23):
51
+ # this code is copied from https://github.com/victorca25/iNNfer
52
+ if "conv_first.weight" in state_dict and "body.0.rdb1.conv1.weight" in state_dict:
53
+ re8x = 0
54
+ crt_net = {}
55
+ items = []
56
+ for k, v in state_dict.items():
57
+ items.append(k)
58
+
59
+ crt_net['model.0.weight'] = state_dict['conv_first.weight']
60
+ crt_net['model.0.bias'] = state_dict['conv_first.bias']
61
+
62
+ for k in items.copy():
63
+ if "rdb" in k:
64
+ ori_k = k.replace('body.', 'model.1.sub.')
65
+ ori_k = ori_k.replace('.rdb', '.RDB')
66
+ if '.weight' in k:
67
+ ori_k = ori_k.replace('.weight', '.0.weight')
68
+ elif '.bias' in k:
69
+ ori_k = ori_k.replace('.bias', '.0.bias')
70
+ crt_net[ori_k] = state_dict[k]
71
+ items.remove(k)
72
+
73
+ crt_net[f'model.1.sub.{nb}.weight'] = state_dict['conv_body.weight']
74
+ crt_net[f'model.1.sub.{nb}.bias'] = state_dict['conv_body.bias']
75
+ crt_net['model.3.weight'] = state_dict['conv_up1.weight']
76
+ crt_net['model.3.bias'] = state_dict['conv_up1.bias']
77
+ crt_net['model.6.weight'] = state_dict['conv_up2.weight']
78
+ crt_net['model.6.bias'] = state_dict['conv_up2.bias']
79
+
80
+ if 'conv_up3.weight' in state_dict:
81
+ # modification supporting: https://github.com/ai-forever/Real-ESRGAN/blob/main/RealESRGAN/rrdbnet_arch.py
82
+ re8x = 3
83
+ crt_net['model.9.weight'] = state_dict['conv_up3.weight']
84
+ crt_net['model.9.bias'] = state_dict['conv_up3.bias']
85
+
86
+ crt_net[f'model.{8+re8x}.weight'] = state_dict['conv_hr.weight']
87
+ crt_net[f'model.{8+re8x}.bias'] = state_dict['conv_hr.bias']
88
+ crt_net[f'model.{10+re8x}.weight'] = state_dict['conv_last.weight']
89
+ crt_net[f'model.{10+re8x}.bias'] = state_dict['conv_last.bias']
90
+
91
+ state_dict = crt_net
92
+ return state_dict
93
+
94
+
95
+ def infer_params(state_dict):
96
+ # this code is copied from https://github.com/victorca25/iNNfer
97
+ scale2x = 0
98
+ scalemin = 6
99
+ n_uplayer = 0
100
+ plus = False
101
+
102
+ for block in list(state_dict):
103
+ parts = block.split(".")
104
+ n_parts = len(parts)
105
+ if n_parts == 5 and parts[2] == "sub":
106
+ nb = int(parts[3])
107
+ elif n_parts == 3:
108
+ part_num = int(parts[1])
109
+ if (part_num > scalemin
110
+ and parts[0] == "model"
111
+ and parts[2] == "weight"):
112
+ scale2x += 1
113
+ if part_num > n_uplayer:
114
+ n_uplayer = part_num
115
+ out_nc = state_dict[block].shape[0]
116
+ if not plus and "conv1x1" in block:
117
+ plus = True
118
+
119
+ nf = state_dict["model.0.weight"].shape[0]
120
+ in_nc = state_dict["model.0.weight"].shape[1]
121
+ out_nc = out_nc
122
+ scale = 2 ** scale2x
123
+
124
+ return in_nc, out_nc, nf, nb, plus, scale
125
+
126
+
127
+ class UpscalerESRGAN(Upscaler):
128
+ def __init__(self, dirname):
129
+ self.name = "ESRGAN"
130
+ self.model_url = "https://github.com/cszn/KAIR/releases/download/v1.0/ESRGAN.pth"
131
+ self.model_name = "ESRGAN_4x"
132
+ self.scalers = []
133
+ self.user_path = dirname
134
+ super().__init__()
135
+ model_paths = self.find_models(ext_filter=[".pt", ".pth"])
136
+ scalers = []
137
+ if len(model_paths) == 0:
138
+ scaler_data = UpscalerData(self.model_name, self.model_url, self, 4)
139
+ scalers.append(scaler_data)
140
+ for file in model_paths:
141
+ if "http" in file:
142
+ name = self.model_name
143
+ else:
144
+ name = modelloader.friendly_name(file)
145
+
146
+ scaler_data = UpscalerData(name, file, self, 4)
147
+ self.scalers.append(scaler_data)
148
+
149
+ def do_upscale(self, img, selected_model):
150
+ model = self.load_model(selected_model)
151
+ if model is None:
152
+ return img
153
+ model.to(devices.device_esrgan)
154
+ img = esrgan_upscale(model, img)
155
+ return img
156
+
157
+ def load_model(self, path: str):
158
+ if "http" in path:
159
+ filename = load_file_from_url(url=self.model_url, model_dir=self.model_path,
160
+ file_name="%s.pth" % self.model_name,
161
+ progress=True)
162
+ else:
163
+ filename = path
164
+ if not os.path.exists(filename) or filename is None:
165
+ print("Unable to load %s from %s" % (self.model_path, filename))
166
+ return None
167
+
168
+ state_dict = torch.load(filename, map_location='cpu' if devices.device_esrgan.type == 'mps' else None)
169
+
170
+ if "params_ema" in state_dict:
171
+ state_dict = state_dict["params_ema"]
172
+ elif "params" in state_dict:
173
+ state_dict = state_dict["params"]
174
+ num_conv = 16 if "realesr-animevideov3" in filename else 32
175
+ model = arch.SRVGGNetCompact(num_in_ch=3, num_out_ch=3, num_feat=64, num_conv=num_conv, upscale=4, act_type='prelu')
176
+ model.load_state_dict(state_dict)
177
+ model.eval()
178
+ return model
179
+
180
+ if "body.0.rdb1.conv1.weight" in state_dict and "conv_first.weight" in state_dict:
181
+ nb = 6 if "RealESRGAN_x4plus_anime_6B" in filename else 23
182
+ state_dict = resrgan2normal(state_dict, nb)
183
+ elif "conv_first.weight" in state_dict:
184
+ state_dict = mod2normal(state_dict)
185
+ elif "model.0.weight" not in state_dict:
186
+ raise Exception("The file is not a recognized ESRGAN model.")
187
+
188
+ in_nc, out_nc, nf, nb, plus, mscale = infer_params(state_dict)
189
+
190
+ model = arch.RRDBNet(in_nc=in_nc, out_nc=out_nc, nf=nf, nb=nb, upscale=mscale, plus=plus)
191
+ model.load_state_dict(state_dict)
192
+ model.eval()
193
+
194
+ return model
195
+
196
+
197
+ def upscale_without_tiling(model, img):
198
+ img = np.array(img)
199
+ img = img[:, :, ::-1]
200
+ img = np.ascontiguousarray(np.transpose(img, (2, 0, 1))) / 255
201
+ img = torch.from_numpy(img).float()
202
+ img = img.unsqueeze(0).to(devices.device_esrgan)
203
+ with torch.no_grad():
204
+ output = model(img)
205
+ output = output.squeeze().float().cpu().clamp_(0, 1).numpy()
206
+ output = 255. * np.moveaxis(output, 0, 2)
207
+ output = output.astype(np.uint8)
208
+ output = output[:, :, ::-1]
209
+ return Image.fromarray(output, 'RGB')
210
+
211
+
212
+ def esrgan_upscale(model, img):
213
+ if opts.ESRGAN_tile == 0:
214
+ return upscale_without_tiling(model, img)
215
+
216
+ grid = images.split_grid(img, opts.ESRGAN_tile, opts.ESRGAN_tile, opts.ESRGAN_tile_overlap)
217
+ newtiles = []
218
+ scale_factor = 1
219
+
220
+ for y, h, row in grid.tiles:
221
+ newrow = []
222
+ for tiledata in row:
223
+ x, w, tile = tiledata
224
+
225
+ output = upscale_without_tiling(model, tile)
226
+ scale_factor = output.width // tile.width
227
+
228
+ newrow.append([x * scale_factor, w * scale_factor, output])
229
+ newtiles.append([y * scale_factor, h * scale_factor, newrow])
230
+
231
+ newgrid = images.Grid(newtiles, grid.tile_w * scale_factor, grid.tile_h * scale_factor, grid.image_w * scale_factor, grid.image_h * scale_factor, grid.overlap * scale_factor)
232
+ output = images.combine_grid(newgrid)
233
+ return output
modules/esrgan_model_arch.py ADDED
@@ -0,0 +1,464 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # this file is adapted from https://github.com/victorca25/iNNfer
2
+
3
+ from collections import OrderedDict
4
+ import math
5
+ import functools
6
+ import torch
7
+ import torch.nn as nn
8
+ import torch.nn.functional as F
9
+
10
+
11
+ ####################
12
+ # RRDBNet Generator
13
+ ####################
14
+
15
+ class RRDBNet(nn.Module):
16
+ def __init__(self, in_nc, out_nc, nf, nb, nr=3, gc=32, upscale=4, norm_type=None,
17
+ act_type='leakyrelu', mode='CNA', upsample_mode='upconv', convtype='Conv2D',
18
+ finalact=None, gaussian_noise=False, plus=False):
19
+ super(RRDBNet, self).__init__()
20
+ n_upscale = int(math.log(upscale, 2))
21
+ if upscale == 3:
22
+ n_upscale = 1
23
+
24
+ self.resrgan_scale = 0
25
+ if in_nc % 16 == 0:
26
+ self.resrgan_scale = 1
27
+ elif in_nc != 4 and in_nc % 4 == 0:
28
+ self.resrgan_scale = 2
29
+
30
+ fea_conv = conv_block(in_nc, nf, kernel_size=3, norm_type=None, act_type=None, convtype=convtype)
31
+ rb_blocks = [RRDB(nf, nr, kernel_size=3, gc=32, stride=1, bias=1, pad_type='zero',
32
+ norm_type=norm_type, act_type=act_type, mode='CNA', convtype=convtype,
33
+ gaussian_noise=gaussian_noise, plus=plus) for _ in range(nb)]
34
+ LR_conv = conv_block(nf, nf, kernel_size=3, norm_type=norm_type, act_type=None, mode=mode, convtype=convtype)
35
+
36
+ if upsample_mode == 'upconv':
37
+ upsample_block = upconv_block
38
+ elif upsample_mode == 'pixelshuffle':
39
+ upsample_block = pixelshuffle_block
40
+ else:
41
+ raise NotImplementedError('upsample mode [{:s}] is not found'.format(upsample_mode))
42
+ if upscale == 3:
43
+ upsampler = upsample_block(nf, nf, 3, act_type=act_type, convtype=convtype)
44
+ else:
45
+ upsampler = [upsample_block(nf, nf, act_type=act_type, convtype=convtype) for _ in range(n_upscale)]
46
+ HR_conv0 = conv_block(nf, nf, kernel_size=3, norm_type=None, act_type=act_type, convtype=convtype)
47
+ HR_conv1 = conv_block(nf, out_nc, kernel_size=3, norm_type=None, act_type=None, convtype=convtype)
48
+
49
+ outact = act(finalact) if finalact else None
50
+
51
+ self.model = sequential(fea_conv, ShortcutBlock(sequential(*rb_blocks, LR_conv)),
52
+ *upsampler, HR_conv0, HR_conv1, outact)
53
+
54
+ def forward(self, x, outm=None):
55
+ if self.resrgan_scale == 1:
56
+ feat = pixel_unshuffle(x, scale=4)
57
+ elif self.resrgan_scale == 2:
58
+ feat = pixel_unshuffle(x, scale=2)
59
+ else:
60
+ feat = x
61
+
62
+ return self.model(feat)
63
+
64
+
65
+ class RRDB(nn.Module):
66
+ """
67
+ Residual in Residual Dense Block
68
+ (ESRGAN: Enhanced Super-Resolution Generative Adversarial Networks)
69
+ """
70
+
71
+ def __init__(self, nf, nr=3, kernel_size=3, gc=32, stride=1, bias=1, pad_type='zero',
72
+ norm_type=None, act_type='leakyrelu', mode='CNA', convtype='Conv2D',
73
+ spectral_norm=False, gaussian_noise=False, plus=False):
74
+ super(RRDB, self).__init__()
75
+ # This is for backwards compatibility with existing models
76
+ if nr == 3:
77
+ self.RDB1 = ResidualDenseBlock_5C(nf, kernel_size, gc, stride, bias, pad_type,
78
+ norm_type, act_type, mode, convtype, spectral_norm=spectral_norm,
79
+ gaussian_noise=gaussian_noise, plus=plus)
80
+ self.RDB2 = ResidualDenseBlock_5C(nf, kernel_size, gc, stride, bias, pad_type,
81
+ norm_type, act_type, mode, convtype, spectral_norm=spectral_norm,
82
+ gaussian_noise=gaussian_noise, plus=plus)
83
+ self.RDB3 = ResidualDenseBlock_5C(nf, kernel_size, gc, stride, bias, pad_type,
84
+ norm_type, act_type, mode, convtype, spectral_norm=spectral_norm,
85
+ gaussian_noise=gaussian_noise, plus=plus)
86
+ else:
87
+ RDB_list = [ResidualDenseBlock_5C(nf, kernel_size, gc, stride, bias, pad_type,
88
+ norm_type, act_type, mode, convtype, spectral_norm=spectral_norm,
89
+ gaussian_noise=gaussian_noise, plus=plus) for _ in range(nr)]
90
+ self.RDBs = nn.Sequential(*RDB_list)
91
+
92
+ def forward(self, x):
93
+ if hasattr(self, 'RDB1'):
94
+ out = self.RDB1(x)
95
+ out = self.RDB2(out)
96
+ out = self.RDB3(out)
97
+ else:
98
+ out = self.RDBs(x)
99
+ return out * 0.2 + x
100
+
101
+
102
+ class ResidualDenseBlock_5C(nn.Module):
103
+ """
104
+ Residual Dense Block
105
+ The core module of paper: (Residual Dense Network for Image Super-Resolution, CVPR 18)
106
+ Modified options that can be used:
107
+ - "Partial Convolution based Padding" arXiv:1811.11718
108
+ - "Spectral normalization" arXiv:1802.05957
109
+ - "ICASSP 2020 - ESRGAN+ : Further Improving ESRGAN" N. C.
110
+ {Rakotonirina} and A. {Rasoanaivo}
111
+ """
112
+
113
+ def __init__(self, nf=64, kernel_size=3, gc=32, stride=1, bias=1, pad_type='zero',
114
+ norm_type=None, act_type='leakyrelu', mode='CNA', convtype='Conv2D',
115
+ spectral_norm=False, gaussian_noise=False, plus=False):
116
+ super(ResidualDenseBlock_5C, self).__init__()
117
+
118
+ self.noise = GaussianNoise() if gaussian_noise else None
119
+ self.conv1x1 = conv1x1(nf, gc) if plus else None
120
+
121
+ self.conv1 = conv_block(nf, gc, kernel_size, stride, bias=bias, pad_type=pad_type,
122
+ norm_type=norm_type, act_type=act_type, mode=mode, convtype=convtype,
123
+ spectral_norm=spectral_norm)
124
+ self.conv2 = conv_block(nf+gc, gc, kernel_size, stride, bias=bias, pad_type=pad_type,
125
+ norm_type=norm_type, act_type=act_type, mode=mode, convtype=convtype,
126
+ spectral_norm=spectral_norm)
127
+ self.conv3 = conv_block(nf+2*gc, gc, kernel_size, stride, bias=bias, pad_type=pad_type,
128
+ norm_type=norm_type, act_type=act_type, mode=mode, convtype=convtype,
129
+ spectral_norm=spectral_norm)
130
+ self.conv4 = conv_block(nf+3*gc, gc, kernel_size, stride, bias=bias, pad_type=pad_type,
131
+ norm_type=norm_type, act_type=act_type, mode=mode, convtype=convtype,
132
+ spectral_norm=spectral_norm)
133
+ if mode == 'CNA':
134
+ last_act = None
135
+ else:
136
+ last_act = act_type
137
+ self.conv5 = conv_block(nf+4*gc, nf, 3, stride, bias=bias, pad_type=pad_type,
138
+ norm_type=norm_type, act_type=last_act, mode=mode, convtype=convtype,
139
+ spectral_norm=spectral_norm)
140
+
141
+ def forward(self, x):
142
+ x1 = self.conv1(x)
143
+ x2 = self.conv2(torch.cat((x, x1), 1))
144
+ if self.conv1x1:
145
+ x2 = x2 + self.conv1x1(x)
146
+ x3 = self.conv3(torch.cat((x, x1, x2), 1))
147
+ x4 = self.conv4(torch.cat((x, x1, x2, x3), 1))
148
+ if self.conv1x1:
149
+ x4 = x4 + x2
150
+ x5 = self.conv5(torch.cat((x, x1, x2, x3, x4), 1))
151
+ if self.noise:
152
+ return self.noise(x5.mul(0.2) + x)
153
+ else:
154
+ return x5 * 0.2 + x
155
+
156
+
157
+ ####################
158
+ # ESRGANplus
159
+ ####################
160
+
161
+ class GaussianNoise(nn.Module):
162
+ def __init__(self, sigma=0.1, is_relative_detach=False):
163
+ super().__init__()
164
+ self.sigma = sigma
165
+ self.is_relative_detach = is_relative_detach
166
+ self.noise = torch.tensor(0, dtype=torch.float)
167
+
168
+ def forward(self, x):
169
+ if self.training and self.sigma != 0:
170
+ self.noise = self.noise.to(x.device)
171
+ scale = self.sigma * x.detach() if self.is_relative_detach else self.sigma * x
172
+ sampled_noise = self.noise.repeat(*x.size()).normal_() * scale
173
+ x = x + sampled_noise
174
+ return x
175
+
176
+ def conv1x1(in_planes, out_planes, stride=1):
177
+ return nn.Conv2d(in_planes, out_planes, kernel_size=1, stride=stride, bias=False)
178
+
179
+
180
+ ####################
181
+ # SRVGGNetCompact
182
+ ####################
183
+
184
+ class SRVGGNetCompact(nn.Module):
185
+ """A compact VGG-style network structure for super-resolution.
186
+ This class is copied from https://github.com/xinntao/Real-ESRGAN
187
+ """
188
+
189
+ def __init__(self, num_in_ch=3, num_out_ch=3, num_feat=64, num_conv=16, upscale=4, act_type='prelu'):
190
+ super(SRVGGNetCompact, self).__init__()
191
+ self.num_in_ch = num_in_ch
192
+ self.num_out_ch = num_out_ch
193
+ self.num_feat = num_feat
194
+ self.num_conv = num_conv
195
+ self.upscale = upscale
196
+ self.act_type = act_type
197
+
198
+ self.body = nn.ModuleList()
199
+ # the first conv
200
+ self.body.append(nn.Conv2d(num_in_ch, num_feat, 3, 1, 1))
201
+ # the first activation
202
+ if act_type == 'relu':
203
+ activation = nn.ReLU(inplace=True)
204
+ elif act_type == 'prelu':
205
+ activation = nn.PReLU(num_parameters=num_feat)
206
+ elif act_type == 'leakyrelu':
207
+ activation = nn.LeakyReLU(negative_slope=0.1, inplace=True)
208
+ self.body.append(activation)
209
+
210
+ # the body structure
211
+ for _ in range(num_conv):
212
+ self.body.append(nn.Conv2d(num_feat, num_feat, 3, 1, 1))
213
+ # activation
214
+ if act_type == 'relu':
215
+ activation = nn.ReLU(inplace=True)
216
+ elif act_type == 'prelu':
217
+ activation = nn.PReLU(num_parameters=num_feat)
218
+ elif act_type == 'leakyrelu':
219
+ activation = nn.LeakyReLU(negative_slope=0.1, inplace=True)
220
+ self.body.append(activation)
221
+
222
+ # the last conv
223
+ self.body.append(nn.Conv2d(num_feat, num_out_ch * upscale * upscale, 3, 1, 1))
224
+ # upsample
225
+ self.upsampler = nn.PixelShuffle(upscale)
226
+
227
+ def forward(self, x):
228
+ out = x
229
+ for i in range(0, len(self.body)):
230
+ out = self.body[i](out)
231
+
232
+ out = self.upsampler(out)
233
+ # add the nearest upsampled image, so that the network learns the residual
234
+ base = F.interpolate(x, scale_factor=self.upscale, mode='nearest')
235
+ out += base
236
+ return out
237
+
238
+
239
+ ####################
240
+ # Upsampler
241
+ ####################
242
+
243
+ class Upsample(nn.Module):
244
+ r"""Upsamples a given multi-channel 1D (temporal), 2D (spatial) or 3D (volumetric) data.
245
+ The input data is assumed to be of the form
246
+ `minibatch x channels x [optional depth] x [optional height] x width`.
247
+ """
248
+
249
+ def __init__(self, size=None, scale_factor=None, mode="nearest", align_corners=None):
250
+ super(Upsample, self).__init__()
251
+ if isinstance(scale_factor, tuple):
252
+ self.scale_factor = tuple(float(factor) for factor in scale_factor)
253
+ else:
254
+ self.scale_factor = float(scale_factor) if scale_factor else None
255
+ self.mode = mode
256
+ self.size = size
257
+ self.align_corners = align_corners
258
+
259
+ def forward(self, x):
260
+ return nn.functional.interpolate(x, size=self.size, scale_factor=self.scale_factor, mode=self.mode, align_corners=self.align_corners)
261
+
262
+ def extra_repr(self):
263
+ if self.scale_factor is not None:
264
+ info = 'scale_factor=' + str(self.scale_factor)
265
+ else:
266
+ info = 'size=' + str(self.size)
267
+ info += ', mode=' + self.mode
268
+ return info
269
+
270
+
271
+ def pixel_unshuffle(x, scale):
272
+ """ Pixel unshuffle.
273
+ Args:
274
+ x (Tensor): Input feature with shape (b, c, hh, hw).
275
+ scale (int): Downsample ratio.
276
+ Returns:
277
+ Tensor: the pixel unshuffled feature.
278
+ """
279
+ b, c, hh, hw = x.size()
280
+ out_channel = c * (scale**2)
281
+ assert hh % scale == 0 and hw % scale == 0
282
+ h = hh // scale
283
+ w = hw // scale
284
+ x_view = x.view(b, c, h, scale, w, scale)
285
+ return x_view.permute(0, 1, 3, 5, 2, 4).reshape(b, out_channel, h, w)
286
+
287
+
288
+ def pixelshuffle_block(in_nc, out_nc, upscale_factor=2, kernel_size=3, stride=1, bias=True,
289
+ pad_type='zero', norm_type=None, act_type='relu', convtype='Conv2D'):
290
+ """
291
+ Pixel shuffle layer
292
+ (Real-Time Single Image and Video Super-Resolution Using an Efficient Sub-Pixel Convolutional
293
+ Neural Network, CVPR17)
294
+ """
295
+ conv = conv_block(in_nc, out_nc * (upscale_factor ** 2), kernel_size, stride, bias=bias,
296
+ pad_type=pad_type, norm_type=None, act_type=None, convtype=convtype)
297
+ pixel_shuffle = nn.PixelShuffle(upscale_factor)
298
+
299
+ n = norm(norm_type, out_nc) if norm_type else None
300
+ a = act(act_type) if act_type else None
301
+ return sequential(conv, pixel_shuffle, n, a)
302
+
303
+
304
+ def upconv_block(in_nc, out_nc, upscale_factor=2, kernel_size=3, stride=1, bias=True,
305
+ pad_type='zero', norm_type=None, act_type='relu', mode='nearest', convtype='Conv2D'):
306
+ """ Upconv layer """
307
+ upscale_factor = (1, upscale_factor, upscale_factor) if convtype == 'Conv3D' else upscale_factor
308
+ upsample = Upsample(scale_factor=upscale_factor, mode=mode)
309
+ conv = conv_block(in_nc, out_nc, kernel_size, stride, bias=bias,
310
+ pad_type=pad_type, norm_type=norm_type, act_type=act_type, convtype=convtype)
311
+ return sequential(upsample, conv)
312
+
313
+
314
+
315
+
316
+
317
+
318
+
319
+
320
+ ####################
321
+ # Basic blocks
322
+ ####################
323
+
324
+
325
+ def make_layer(basic_block, num_basic_block, **kwarg):
326
+ """Make layers by stacking the same blocks.
327
+ Args:
328
+ basic_block (nn.module): nn.module class for basic block. (block)
329
+ num_basic_block (int): number of blocks. (n_layers)
330
+ Returns:
331
+ nn.Sequential: Stacked blocks in nn.Sequential.
332
+ """
333
+ layers = []
334
+ for _ in range(num_basic_block):
335
+ layers.append(basic_block(**kwarg))
336
+ return nn.Sequential(*layers)
337
+
338
+
339
+ def act(act_type, inplace=True, neg_slope=0.2, n_prelu=1, beta=1.0):
340
+ """ activation helper """
341
+ act_type = act_type.lower()
342
+ if act_type == 'relu':
343
+ layer = nn.ReLU(inplace)
344
+ elif act_type in ('leakyrelu', 'lrelu'):
345
+ layer = nn.LeakyReLU(neg_slope, inplace)
346
+ elif act_type == 'prelu':
347
+ layer = nn.PReLU(num_parameters=n_prelu, init=neg_slope)
348
+ elif act_type == 'tanh': # [-1, 1] range output
349
+ layer = nn.Tanh()
350
+ elif act_type == 'sigmoid': # [0, 1] range output
351
+ layer = nn.Sigmoid()
352
+ else:
353
+ raise NotImplementedError('activation layer [{:s}] is not found'.format(act_type))
354
+ return layer
355
+
356
+
357
+ class Identity(nn.Module):
358
+ def __init__(self, *kwargs):
359
+ super(Identity, self).__init__()
360
+
361
+ def forward(self, x, *kwargs):
362
+ return x
363
+
364
+
365
+ def norm(norm_type, nc):
366
+ """ Return a normalization layer """
367
+ norm_type = norm_type.lower()
368
+ if norm_type == 'batch':
369
+ layer = nn.BatchNorm2d(nc, affine=True)
370
+ elif norm_type == 'instance':
371
+ layer = nn.InstanceNorm2d(nc, affine=False)
372
+ elif norm_type == 'none':
373
+ def norm_layer(x): return Identity()
374
+ else:
375
+ raise NotImplementedError('normalization layer [{:s}] is not found'.format(norm_type))
376
+ return layer
377
+
378
+
379
+ def pad(pad_type, padding):
380
+ """ padding layer helper """
381
+ pad_type = pad_type.lower()
382
+ if padding == 0:
383
+ return None
384
+ if pad_type == 'reflect':
385
+ layer = nn.ReflectionPad2d(padding)
386
+ elif pad_type == 'replicate':
387
+ layer = nn.ReplicationPad2d(padding)
388
+ elif pad_type == 'zero':
389
+ layer = nn.ZeroPad2d(padding)
390
+ else:
391
+ raise NotImplementedError('padding layer [{:s}] is not implemented'.format(pad_type))
392
+ return layer
393
+
394
+
395
+ def get_valid_padding(kernel_size, dilation):
396
+ kernel_size = kernel_size + (kernel_size - 1) * (dilation - 1)
397
+ padding = (kernel_size - 1) // 2
398
+ return padding
399
+
400
+
401
+ class ShortcutBlock(nn.Module):
402
+ """ Elementwise sum the output of a submodule to its input """
403
+ def __init__(self, submodule):
404
+ super(ShortcutBlock, self).__init__()
405
+ self.sub = submodule
406
+
407
+ def forward(self, x):
408
+ output = x + self.sub(x)
409
+ return output
410
+
411
+ def __repr__(self):
412
+ return 'Identity + \n|' + self.sub.__repr__().replace('\n', '\n|')
413
+
414
+
415
+ def sequential(*args):
416
+ """ Flatten Sequential. It unwraps nn.Sequential. """
417
+ if len(args) == 1:
418
+ if isinstance(args[0], OrderedDict):
419
+ raise NotImplementedError('sequential does not support OrderedDict input.')
420
+ return args[0] # No sequential is needed.
421
+ modules = []
422
+ for module in args:
423
+ if isinstance(module, nn.Sequential):
424
+ for submodule in module.children():
425
+ modules.append(submodule)
426
+ elif isinstance(module, nn.Module):
427
+ modules.append(module)
428
+ return nn.Sequential(*modules)
429
+
430
+
431
+ def conv_block(in_nc, out_nc, kernel_size, stride=1, dilation=1, groups=1, bias=True,
432
+ pad_type='zero', norm_type=None, act_type='relu', mode='CNA', convtype='Conv2D',
433
+ spectral_norm=False):
434
+ """ Conv layer with padding, normalization, activation """
435
+ assert mode in ['CNA', 'NAC', 'CNAC'], 'Wrong conv mode [{:s}]'.format(mode)
436
+ padding = get_valid_padding(kernel_size, dilation)
437
+ p = pad(pad_type, padding) if pad_type and pad_type != 'zero' else None
438
+ padding = padding if pad_type == 'zero' else 0
439
+
440
+ if convtype=='PartialConv2D':
441
+ c = PartialConv2d(in_nc, out_nc, kernel_size=kernel_size, stride=stride, padding=padding,
442
+ dilation=dilation, bias=bias, groups=groups)
443
+ elif convtype=='DeformConv2D':
444
+ c = DeformConv2d(in_nc, out_nc, kernel_size=kernel_size, stride=stride, padding=padding,
445
+ dilation=dilation, bias=bias, groups=groups)
446
+ elif convtype=='Conv3D':
447
+ c = nn.Conv3d(in_nc, out_nc, kernel_size=kernel_size, stride=stride, padding=padding,
448
+ dilation=dilation, bias=bias, groups=groups)
449
+ else:
450
+ c = nn.Conv2d(in_nc, out_nc, kernel_size=kernel_size, stride=stride, padding=padding,
451
+ dilation=dilation, bias=bias, groups=groups)
452
+
453
+ if spectral_norm:
454
+ c = nn.utils.spectral_norm(c)
455
+
456
+ a = act(act_type) if act_type else None
457
+ if 'CNA' in mode:
458
+ n = norm(norm_type, out_nc) if norm_type else None
459
+ return sequential(p, c, n, a)
460
+ elif mode == 'NAC':
461
+ if norm_type is None and act_type is not None:
462
+ a = act(act_type, inplace=False)
463
+ n = norm(norm_type, in_nc) if norm_type else None
464
+ return sequential(n, a, p, c)
modules/extensions.py ADDED
@@ -0,0 +1,107 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import sys
3
+ import traceback
4
+
5
+ import time
6
+ import git
7
+
8
+ from modules import paths, shared
9
+
10
+ extensions = []
11
+ extensions_dir = os.path.join(paths.data_path, "extensions")
12
+ extensions_builtin_dir = os.path.join(paths.script_path, "extensions-builtin")
13
+
14
+ if not os.path.exists(extensions_dir):
15
+ os.makedirs(extensions_dir)
16
+
17
+ def active():
18
+ return [x for x in extensions if x.enabled]
19
+
20
+
21
+ class Extension:
22
+ def __init__(self, name, path, enabled=True, is_builtin=False):
23
+ self.name = name
24
+ self.path = path
25
+ self.enabled = enabled
26
+ self.status = ''
27
+ self.can_update = False
28
+ self.is_builtin = is_builtin
29
+ self.version = ''
30
+
31
+ repo = None
32
+ try:
33
+ if os.path.exists(os.path.join(path, ".git")):
34
+ repo = git.Repo(path)
35
+ except Exception:
36
+ print(f"Error reading github repository info from {path}:", file=sys.stderr)
37
+ print(traceback.format_exc(), file=sys.stderr)
38
+
39
+ if repo is None or repo.bare:
40
+ self.remote = None
41
+ else:
42
+ try:
43
+ self.remote = next(repo.remote().urls, None)
44
+ self.status = 'unknown'
45
+ head = repo.head.commit
46
+ ts = time.asctime(time.gmtime(repo.head.commit.committed_date))
47
+ self.version = f'{head.hexsha[:8]} ({ts})'
48
+
49
+ except Exception:
50
+ self.remote = None
51
+
52
+ def list_files(self, subdir, extension):
53
+ from modules import scripts
54
+
55
+ dirpath = os.path.join(self.path, subdir)
56
+ if not os.path.isdir(dirpath):
57
+ return []
58
+
59
+ res = []
60
+ for filename in sorted(os.listdir(dirpath)):
61
+ res.append(scripts.ScriptFile(self.path, filename, os.path.join(dirpath, filename)))
62
+
63
+ res = [x for x in res if os.path.splitext(x.path)[1].lower() == extension and os.path.isfile(x.path)]
64
+
65
+ return res
66
+
67
+ def check_updates(self):
68
+ repo = git.Repo(self.path)
69
+ for fetch in repo.remote().fetch("--dry-run"):
70
+ if fetch.flags != fetch.HEAD_UPTODATE:
71
+ self.can_update = True
72
+ self.status = "behind"
73
+ return
74
+
75
+ self.can_update = False
76
+ self.status = "latest"
77
+
78
+ def fetch_and_reset_hard(self):
79
+ repo = git.Repo(self.path)
80
+ # Fix: `error: Your local changes to the following files would be overwritten by merge`,
81
+ # because WSL2 Docker set 755 file permissions instead of 644, this results to the error.
82
+ repo.git.fetch('--all')
83
+ repo.git.reset('--hard', 'origin')
84
+
85
+
86
+ def list_extensions():
87
+ extensions.clear()
88
+
89
+ if not os.path.isdir(extensions_dir):
90
+ return
91
+
92
+ paths = []
93
+ for dirname in [extensions_dir, extensions_builtin_dir]:
94
+ if not os.path.isdir(dirname):
95
+ return
96
+
97
+ for extension_dirname in sorted(os.listdir(dirname)):
98
+ path = os.path.join(dirname, extension_dirname)
99
+ if not os.path.isdir(path):
100
+ continue
101
+
102
+ paths.append((extension_dirname, path, dirname == extensions_builtin_dir))
103
+
104
+ for dirname, path, is_builtin in paths:
105
+ extension = Extension(name=dirname, path=path, enabled=dirname not in shared.opts.disabled_extensions, is_builtin=is_builtin)
106
+ extensions.append(extension)
107
+
modules/extra_networks.py ADDED
@@ -0,0 +1,147 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import re
2
+ from collections import defaultdict
3
+
4
+ from modules import errors
5
+
6
+ extra_network_registry = {}
7
+
8
+
9
+ def initialize():
10
+ extra_network_registry.clear()
11
+
12
+
13
+ def register_extra_network(extra_network):
14
+ extra_network_registry[extra_network.name] = extra_network
15
+
16
+
17
+ class ExtraNetworkParams:
18
+ def __init__(self, items=None):
19
+ self.items = items or []
20
+
21
+
22
+ class ExtraNetwork:
23
+ def __init__(self, name):
24
+ self.name = name
25
+
26
+ def activate(self, p, params_list):
27
+ """
28
+ Called by processing on every run. Whatever the extra network is meant to do should be activated here.
29
+ Passes arguments related to this extra network in params_list.
30
+ User passes arguments by specifying this in his prompt:
31
+
32
+ <name:arg1:arg2:arg3>
33
+
34
+ Where name matches the name of this ExtraNetwork object, and arg1:arg2:arg3 are any natural number of text arguments
35
+ separated by colon.
36
+
37
+ Even if the user does not mention this ExtraNetwork in his prompt, the call will stil be made, with empty params_list -
38
+ in this case, all effects of this extra networks should be disabled.
39
+
40
+ Can be called multiple times before deactivate() - each new call should override the previous call completely.
41
+
42
+ For example, if this ExtraNetwork's name is 'hypernet' and user's prompt is:
43
+
44
+ > "1girl, <hypernet:agm:1.1> <extrasupernet:master:12:13:14> <hypernet:ray>"
45
+
46
+ params_list will be:
47
+
48
+ [
49
+ ExtraNetworkParams(items=["agm", "1.1"]),
50
+ ExtraNetworkParams(items=["ray"])
51
+ ]
52
+
53
+ """
54
+ raise NotImplementedError
55
+
56
+ def deactivate(self, p):
57
+ """
58
+ Called at the end of processing for housekeeping. No need to do anything here.
59
+ """
60
+
61
+ raise NotImplementedError
62
+
63
+
64
+ def activate(p, extra_network_data):
65
+ """call activate for extra networks in extra_network_data in specified order, then call
66
+ activate for all remaining registered networks with an empty argument list"""
67
+
68
+ for extra_network_name, extra_network_args in extra_network_data.items():
69
+ extra_network = extra_network_registry.get(extra_network_name, None)
70
+ if extra_network is None:
71
+ print(f"Skipping unknown extra network: {extra_network_name}")
72
+ continue
73
+
74
+ try:
75
+ extra_network.activate(p, extra_network_args)
76
+ except Exception as e:
77
+ errors.display(e, f"activating extra network {extra_network_name} with arguments {extra_network_args}")
78
+
79
+ for extra_network_name, extra_network in extra_network_registry.items():
80
+ args = extra_network_data.get(extra_network_name, None)
81
+ if args is not None:
82
+ continue
83
+
84
+ try:
85
+ extra_network.activate(p, [])
86
+ except Exception as e:
87
+ errors.display(e, f"activating extra network {extra_network_name}")
88
+
89
+
90
+ def deactivate(p, extra_network_data):
91
+ """call deactivate for extra networks in extra_network_data in specified order, then call
92
+ deactivate for all remaining registered networks"""
93
+
94
+ for extra_network_name, extra_network_args in extra_network_data.items():
95
+ extra_network = extra_network_registry.get(extra_network_name, None)
96
+ if extra_network is None:
97
+ continue
98
+
99
+ try:
100
+ extra_network.deactivate(p)
101
+ except Exception as e:
102
+ errors.display(e, f"deactivating extra network {extra_network_name}")
103
+
104
+ for extra_network_name, extra_network in extra_network_registry.items():
105
+ args = extra_network_data.get(extra_network_name, None)
106
+ if args is not None:
107
+ continue
108
+
109
+ try:
110
+ extra_network.deactivate(p)
111
+ except Exception as e:
112
+ errors.display(e, f"deactivating unmentioned extra network {extra_network_name}")
113
+
114
+
115
+ re_extra_net = re.compile(r"<(\w+):([^>]+)>")
116
+
117
+
118
+ def parse_prompt(prompt):
119
+ res = defaultdict(list)
120
+
121
+ def found(m):
122
+ name = m.group(1)
123
+ args = m.group(2)
124
+
125
+ res[name].append(ExtraNetworkParams(items=args.split(":")))
126
+
127
+ return ""
128
+
129
+ prompt = re.sub(re_extra_net, found, prompt)
130
+
131
+ return prompt, res
132
+
133
+
134
+ def parse_prompts(prompts):
135
+ res = []
136
+ extra_data = None
137
+
138
+ for prompt in prompts:
139
+ updated_prompt, parsed_extra_data = parse_prompt(prompt)
140
+
141
+ if extra_data is None:
142
+ extra_data = parsed_extra_data
143
+
144
+ res.append(updated_prompt)
145
+
146
+ return res, extra_data
147
+
modules/extra_networks_hypernet.py ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from modules import extra_networks, shared, extra_networks
2
+ from modules.hypernetworks import hypernetwork
3
+
4
+
5
+ class ExtraNetworkHypernet(extra_networks.ExtraNetwork):
6
+ def __init__(self):
7
+ super().__init__('hypernet')
8
+
9
+ def activate(self, p, params_list):
10
+ additional = shared.opts.sd_hypernetwork
11
+
12
+ if additional != "" and additional in shared.hypernetworks and len([x for x in params_list if x.items[0] == additional]) == 0:
13
+ p.all_prompts = [x + f"<hypernet:{additional}:{shared.opts.extra_networks_default_multiplier}>" for x in p.all_prompts]
14
+ params_list.append(extra_networks.ExtraNetworkParams(items=[additional, shared.opts.extra_networks_default_multiplier]))
15
+
16
+ names = []
17
+ multipliers = []
18
+ for params in params_list:
19
+ assert len(params.items) > 0
20
+
21
+ names.append(params.items[0])
22
+ multipliers.append(float(params.items[1]) if len(params.items) > 1 else 1.0)
23
+
24
+ hypernetwork.load_hypernetworks(names, multipliers)
25
+
26
+ def deactivate(self, p):
27
+ pass
modules/extras.py ADDED
@@ -0,0 +1,258 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import re
3
+ import shutil
4
+
5
+
6
+ import torch
7
+ import tqdm
8
+
9
+ from modules import shared, images, sd_models, sd_vae, sd_models_config
10
+ from modules.ui_common import plaintext_to_html
11
+ import gradio as gr
12
+ import safetensors.torch
13
+
14
+
15
+ def run_pnginfo(image):
16
+ if image is None:
17
+ return '', '', ''
18
+
19
+ geninfo, items = images.read_info_from_image(image)
20
+ items = {**{'parameters': geninfo}, **items}
21
+
22
+ info = ''
23
+ for key, text in items.items():
24
+ info += f"""
25
+ <div>
26
+ <p><b>{plaintext_to_html(str(key))}</b></p>
27
+ <p>{plaintext_to_html(str(text))}</p>
28
+ </div>
29
+ """.strip()+"\n"
30
+
31
+ if len(info) == 0:
32
+ message = "Nothing found in the image."
33
+ info = f"<div><p>{message}<p></div>"
34
+
35
+ return '', geninfo, info
36
+
37
+
38
+ def create_config(ckpt_result, config_source, a, b, c):
39
+ def config(x):
40
+ res = sd_models_config.find_checkpoint_config_near_filename(x) if x else None
41
+ return res if res != shared.sd_default_config else None
42
+
43
+ if config_source == 0:
44
+ cfg = config(a) or config(b) or config(c)
45
+ elif config_source == 1:
46
+ cfg = config(b)
47
+ elif config_source == 2:
48
+ cfg = config(c)
49
+ else:
50
+ cfg = None
51
+
52
+ if cfg is None:
53
+ return
54
+
55
+ filename, _ = os.path.splitext(ckpt_result)
56
+ checkpoint_filename = filename + ".yaml"
57
+
58
+ print("Copying config:")
59
+ print(" from:", cfg)
60
+ print(" to:", checkpoint_filename)
61
+ shutil.copyfile(cfg, checkpoint_filename)
62
+
63
+
64
+ checkpoint_dict_skip_on_merge = ["cond_stage_model.transformer.text_model.embeddings.position_ids"]
65
+
66
+
67
+ def to_half(tensor, enable):
68
+ if enable and tensor.dtype == torch.float:
69
+ return tensor.half()
70
+
71
+ return tensor
72
+
73
+
74
+ def run_modelmerger(id_task, primary_model_name, secondary_model_name, tertiary_model_name, interp_method, multiplier, save_as_half, custom_name, checkpoint_format, config_source, bake_in_vae, discard_weights):
75
+ shared.state.begin()
76
+ shared.state.job = 'model-merge'
77
+
78
+ def fail(message):
79
+ shared.state.textinfo = message
80
+ shared.state.end()
81
+ return [*[gr.update() for _ in range(4)], message]
82
+
83
+ def weighted_sum(theta0, theta1, alpha):
84
+ return ((1 - alpha) * theta0) + (alpha * theta1)
85
+
86
+ def get_difference(theta1, theta2):
87
+ return theta1 - theta2
88
+
89
+ def add_difference(theta0, theta1_2_diff, alpha):
90
+ return theta0 + (alpha * theta1_2_diff)
91
+
92
+ def filename_weighted_sum():
93
+ a = primary_model_info.model_name
94
+ b = secondary_model_info.model_name
95
+ Ma = round(1 - multiplier, 2)
96
+ Mb = round(multiplier, 2)
97
+
98
+ return f"{Ma}({a}) + {Mb}({b})"
99
+
100
+ def filename_add_difference():
101
+ a = primary_model_info.model_name
102
+ b = secondary_model_info.model_name
103
+ c = tertiary_model_info.model_name
104
+ M = round(multiplier, 2)
105
+
106
+ return f"{a} + {M}({b} - {c})"
107
+
108
+ def filename_nothing():
109
+ return primary_model_info.model_name
110
+
111
+ theta_funcs = {
112
+ "Weighted sum": (filename_weighted_sum, None, weighted_sum),
113
+ "Add difference": (filename_add_difference, get_difference, add_difference),
114
+ "No interpolation": (filename_nothing, None, None),
115
+ }
116
+ filename_generator, theta_func1, theta_func2 = theta_funcs[interp_method]
117
+ shared.state.job_count = (1 if theta_func1 else 0) + (1 if theta_func2 else 0)
118
+
119
+ if not primary_model_name:
120
+ return fail("Failed: Merging requires a primary model.")
121
+
122
+ primary_model_info = sd_models.checkpoints_list[primary_model_name]
123
+
124
+ if theta_func2 and not secondary_model_name:
125
+ return fail("Failed: Merging requires a secondary model.")
126
+
127
+ secondary_model_info = sd_models.checkpoints_list[secondary_model_name] if theta_func2 else None
128
+
129
+ if theta_func1 and not tertiary_model_name:
130
+ return fail(f"Failed: Interpolation method ({interp_method}) requires a tertiary model.")
131
+
132
+ tertiary_model_info = sd_models.checkpoints_list[tertiary_model_name] if theta_func1 else None
133
+
134
+ result_is_inpainting_model = False
135
+ result_is_instruct_pix2pix_model = False
136
+
137
+ if theta_func2:
138
+ shared.state.textinfo = f"Loading B"
139
+ print(f"Loading {secondary_model_info.filename}...")
140
+ theta_1 = sd_models.read_state_dict(secondary_model_info.filename, map_location='cpu')
141
+ else:
142
+ theta_1 = None
143
+
144
+ if theta_func1:
145
+ shared.state.textinfo = f"Loading C"
146
+ print(f"Loading {tertiary_model_info.filename}...")
147
+ theta_2 = sd_models.read_state_dict(tertiary_model_info.filename, map_location='cpu')
148
+
149
+ shared.state.textinfo = 'Merging B and C'
150
+ shared.state.sampling_steps = len(theta_1.keys())
151
+ for key in tqdm.tqdm(theta_1.keys()):
152
+ if key in checkpoint_dict_skip_on_merge:
153
+ continue
154
+
155
+ if 'model' in key:
156
+ if key in theta_2:
157
+ t2 = theta_2.get(key, torch.zeros_like(theta_1[key]))
158
+ theta_1[key] = theta_func1(theta_1[key], t2)
159
+ else:
160
+ theta_1[key] = torch.zeros_like(theta_1[key])
161
+
162
+ shared.state.sampling_step += 1
163
+ del theta_2
164
+
165
+ shared.state.nextjob()
166
+
167
+ shared.state.textinfo = f"Loading {primary_model_info.filename}..."
168
+ print(f"Loading {primary_model_info.filename}...")
169
+ theta_0 = sd_models.read_state_dict(primary_model_info.filename, map_location='cpu')
170
+
171
+ print("Merging...")
172
+ shared.state.textinfo = 'Merging A and B'
173
+ shared.state.sampling_steps = len(theta_0.keys())
174
+ for key in tqdm.tqdm(theta_0.keys()):
175
+ if theta_1 and 'model' in key and key in theta_1:
176
+
177
+ if key in checkpoint_dict_skip_on_merge:
178
+ continue
179
+
180
+ a = theta_0[key]
181
+ b = theta_1[key]
182
+
183
+ # this enables merging an inpainting model (A) with another one (B);
184
+ # where normal model would have 4 channels, for latenst space, inpainting model would
185
+ # have another 4 channels for unmasked picture's latent space, plus one channel for mask, for a total of 9
186
+ if a.shape != b.shape and a.shape[0:1] + a.shape[2:] == b.shape[0:1] + b.shape[2:]:
187
+ if a.shape[1] == 4 and b.shape[1] == 9:
188
+ raise RuntimeError("When merging inpainting model with a normal one, A must be the inpainting model.")
189
+ if a.shape[1] == 4 and b.shape[1] == 8:
190
+ raise RuntimeError("When merging instruct-pix2pix model with a normal one, A must be the instruct-pix2pix model.")
191
+
192
+ if a.shape[1] == 8 and b.shape[1] == 4:#If we have an Instruct-Pix2Pix model...
193
+ theta_0[key][:, 0:4, :, :] = theta_func2(a[:, 0:4, :, :], b, multiplier)#Merge only the vectors the models have in common. Otherwise we get an error due to dimension mismatch.
194
+ result_is_instruct_pix2pix_model = True
195
+ else:
196
+ assert a.shape[1] == 9 and b.shape[1] == 4, f"Bad dimensions for merged layer {key}: A={a.shape}, B={b.shape}"
197
+ theta_0[key][:, 0:4, :, :] = theta_func2(a[:, 0:4, :, :], b, multiplier)
198
+ result_is_inpainting_model = True
199
+ else:
200
+ theta_0[key] = theta_func2(a, b, multiplier)
201
+
202
+ theta_0[key] = to_half(theta_0[key], save_as_half)
203
+
204
+ shared.state.sampling_step += 1
205
+
206
+ del theta_1
207
+
208
+ bake_in_vae_filename = sd_vae.vae_dict.get(bake_in_vae, None)
209
+ if bake_in_vae_filename is not None:
210
+ print(f"Baking in VAE from {bake_in_vae_filename}")
211
+ shared.state.textinfo = 'Baking in VAE'
212
+ vae_dict = sd_vae.load_vae_dict(bake_in_vae_filename, map_location='cpu')
213
+
214
+ for key in vae_dict.keys():
215
+ theta_0_key = 'first_stage_model.' + key
216
+ if theta_0_key in theta_0:
217
+ theta_0[theta_0_key] = to_half(vae_dict[key], save_as_half)
218
+
219
+ del vae_dict
220
+
221
+ if save_as_half and not theta_func2:
222
+ for key in theta_0.keys():
223
+ theta_0[key] = to_half(theta_0[key], save_as_half)
224
+
225
+ if discard_weights:
226
+ regex = re.compile(discard_weights)
227
+ for key in list(theta_0):
228
+ if re.search(regex, key):
229
+ theta_0.pop(key, None)
230
+
231
+ ckpt_dir = shared.cmd_opts.ckpt_dir or sd_models.model_path
232
+
233
+ filename = filename_generator() if custom_name == '' else custom_name
234
+ filename += ".inpainting" if result_is_inpainting_model else ""
235
+ filename += ".instruct-pix2pix" if result_is_instruct_pix2pix_model else ""
236
+ filename += "." + checkpoint_format
237
+
238
+ output_modelname = os.path.join(ckpt_dir, filename)
239
+
240
+ shared.state.nextjob()
241
+ shared.state.textinfo = "Saving"
242
+ print(f"Saving to {output_modelname}...")
243
+
244
+ _, extension = os.path.splitext(output_modelname)
245
+ if extension.lower() == ".safetensors":
246
+ safetensors.torch.save_file(theta_0, output_modelname, metadata={"format": "pt"})
247
+ else:
248
+ torch.save(theta_0, output_modelname)
249
+
250
+ sd_models.list_models()
251
+
252
+ create_config(output_modelname, config_source, primary_model_info, secondary_model_info, tertiary_model_info)
253
+
254
+ print(f"Checkpoint saved to {output_modelname}.")
255
+ shared.state.textinfo = "Checkpoint saved"
256
+ shared.state.end()
257
+
258
+ return [*[gr.Dropdown.update(choices=sd_models.checkpoint_tiles()) for _ in range(4)], "Checkpoint saved to " + output_modelname]
modules/face_restoration.py ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from modules import shared
2
+
3
+
4
+ class FaceRestoration:
5
+ def name(self):
6
+ return "None"
7
+
8
+ def restore(self, np_image):
9
+ return np_image
10
+
11
+
12
+ def restore_faces(np_image):
13
+ face_restorers = [x for x in shared.face_restorers if x.name() == shared.opts.face_restoration_model or shared.opts.face_restoration_model is None]
14
+ if len(face_restorers) == 0:
15
+ return np_image
16
+
17
+ face_restorer = face_restorers[0]
18
+
19
+ return face_restorer.restore(np_image)
modules/generation_parameters_copypaste.py ADDED
@@ -0,0 +1,402 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import base64
2
+ import html
3
+ import io
4
+ import math
5
+ import os
6
+ import re
7
+ from pathlib import Path
8
+
9
+ import gradio as gr
10
+ from modules.paths import data_path
11
+ from modules import shared, ui_tempdir, script_callbacks
12
+ import tempfile
13
+ from PIL import Image
14
+
15
+ re_param_code = r'\s*([\w ]+):\s*("(?:\\"[^,]|\\"|\\|[^\"])+"|[^,]*)(?:,|$)'
16
+ re_param = re.compile(re_param_code)
17
+ re_imagesize = re.compile(r"^(\d+)x(\d+)$")
18
+ re_hypernet_hash = re.compile("\(([0-9a-f]+)\)$")
19
+ type_of_gr_update = type(gr.update())
20
+
21
+ paste_fields = {}
22
+ registered_param_bindings = []
23
+
24
+
25
+ class ParamBinding:
26
+ def __init__(self, paste_button, tabname, source_text_component=None, source_image_component=None, source_tabname=None, override_settings_component=None):
27
+ self.paste_button = paste_button
28
+ self.tabname = tabname
29
+ self.source_text_component = source_text_component
30
+ self.source_image_component = source_image_component
31
+ self.source_tabname = source_tabname
32
+ self.override_settings_component = override_settings_component
33
+
34
+
35
+ def reset():
36
+ paste_fields.clear()
37
+
38
+
39
+ def quote(text):
40
+ if ',' not in str(text):
41
+ return text
42
+
43
+ text = str(text)
44
+ text = text.replace('\\', '\\\\')
45
+ text = text.replace('"', '\\"')
46
+ return f'"{text}"'
47
+
48
+
49
+ def image_from_url_text(filedata):
50
+ if filedata is None:
51
+ return None
52
+
53
+ if type(filedata) == list and len(filedata) > 0 and type(filedata[0]) == dict and filedata[0].get("is_file", False):
54
+ filedata = filedata[0]
55
+
56
+ if type(filedata) == dict and filedata.get("is_file", False):
57
+ filename = filedata["name"]
58
+ is_in_right_dir = ui_tempdir.check_tmp_file(shared.demo, filename)
59
+ assert is_in_right_dir, 'trying to open image file outside of allowed directories'
60
+
61
+ return Image.open(filename)
62
+
63
+ if type(filedata) == list:
64
+ if len(filedata) == 0:
65
+ return None
66
+
67
+ filedata = filedata[0]
68
+
69
+ if filedata.startswith("data:image/png;base64,"):
70
+ filedata = filedata[len("data:image/png;base64,"):]
71
+
72
+ filedata = base64.decodebytes(filedata.encode('utf-8'))
73
+ image = Image.open(io.BytesIO(filedata))
74
+ return image
75
+
76
+
77
+ def add_paste_fields(tabname, init_img, fields, override_settings_component=None):
78
+ paste_fields[tabname] = {"init_img": init_img, "fields": fields, "override_settings_component": override_settings_component}
79
+
80
+ # backwards compatibility for existing extensions
81
+ import modules.ui
82
+ if tabname == 'txt2img':
83
+ modules.ui.txt2img_paste_fields = fields
84
+ elif tabname == 'img2img':
85
+ modules.ui.img2img_paste_fields = fields
86
+
87
+
88
+ def create_buttons(tabs_list):
89
+ buttons = {}
90
+ for tab in tabs_list:
91
+ buttons[tab] = gr.Button(f"Send to {tab}", elem_id=f"{tab}_tab")
92
+ return buttons
93
+
94
+
95
+ def bind_buttons(buttons, send_image, send_generate_info):
96
+ """old function for backwards compatibility; do not use this, use register_paste_params_button"""
97
+ for tabname, button in buttons.items():
98
+ source_text_component = send_generate_info if isinstance(send_generate_info, gr.components.Component) else None
99
+ source_tabname = send_generate_info if isinstance(send_generate_info, str) else None
100
+
101
+ register_paste_params_button(ParamBinding(paste_button=button, tabname=tabname, source_text_component=source_text_component, source_image_component=send_image, source_tabname=source_tabname))
102
+
103
+
104
+ def register_paste_params_button(binding: ParamBinding):
105
+ registered_param_bindings.append(binding)
106
+
107
+
108
+ def connect_paste_params_buttons():
109
+ binding: ParamBinding
110
+ for binding in registered_param_bindings:
111
+ destination_image_component = paste_fields[binding.tabname]["init_img"]
112
+ fields = paste_fields[binding.tabname]["fields"]
113
+ override_settings_component = binding.override_settings_component or paste_fields[binding.tabname]["override_settings_component"]
114
+
115
+ destination_width_component = next(iter([field for field, name in fields if name == "Size-1"] if fields else []), None)
116
+ destination_height_component = next(iter([field for field, name in fields if name == "Size-2"] if fields else []), None)
117
+
118
+ if binding.source_image_component and destination_image_component:
119
+ if isinstance(binding.source_image_component, gr.Gallery):
120
+ func = send_image_and_dimensions if destination_width_component else image_from_url_text
121
+ jsfunc = "extract_image_from_gallery"
122
+ else:
123
+ func = send_image_and_dimensions if destination_width_component else lambda x: x
124
+ jsfunc = None
125
+
126
+ binding.paste_button.click(
127
+ fn=func,
128
+ _js=jsfunc,
129
+ inputs=[binding.source_image_component],
130
+ outputs=[destination_image_component, destination_width_component, destination_height_component] if destination_width_component else [destination_image_component],
131
+ )
132
+
133
+ if binding.source_text_component is not None and fields is not None:
134
+ connect_paste(binding.paste_button, fields, binding.source_text_component, override_settings_component, binding.tabname)
135
+
136
+ if binding.source_tabname is not None and fields is not None:
137
+ paste_field_names = ['Prompt', 'Negative prompt', 'Steps', 'Face restoration'] + (["Seed"] if shared.opts.send_seed else [])
138
+ binding.paste_button.click(
139
+ fn=lambda *x: x,
140
+ inputs=[field for field, name in paste_fields[binding.source_tabname]["fields"] if name in paste_field_names],
141
+ outputs=[field for field, name in fields if name in paste_field_names],
142
+ )
143
+
144
+ binding.paste_button.click(
145
+ fn=None,
146
+ _js=f"switch_to_{binding.tabname}",
147
+ inputs=None,
148
+ outputs=None,
149
+ )
150
+
151
+
152
+ def send_image_and_dimensions(x):
153
+ if isinstance(x, Image.Image):
154
+ img = x
155
+ else:
156
+ img = image_from_url_text(x)
157
+
158
+ if shared.opts.send_size and isinstance(img, Image.Image):
159
+ w = img.width
160
+ h = img.height
161
+ else:
162
+ w = gr.update()
163
+ h = gr.update()
164
+
165
+ return img, w, h
166
+
167
+
168
+
169
+ def find_hypernetwork_key(hypernet_name, hypernet_hash=None):
170
+ """Determines the config parameter name to use for the hypernet based on the parameters in the infotext.
171
+
172
+ Example: an infotext provides "Hypernet: ke-ta" and "Hypernet hash: 1234abcd". For the "Hypernet" config
173
+ parameter this means there should be an entry that looks like "ke-ta-10000(1234abcd)" to set it to.
174
+
175
+ If the infotext has no hash, then a hypernet with the same name will be selected instead.
176
+ """
177
+ hypernet_name = hypernet_name.lower()
178
+ if hypernet_hash is not None:
179
+ # Try to match the hash in the name
180
+ for hypernet_key in shared.hypernetworks.keys():
181
+ result = re_hypernet_hash.search(hypernet_key)
182
+ if result is not None and result[1] == hypernet_hash:
183
+ return hypernet_key
184
+ else:
185
+ # Fall back to a hypernet with the same name
186
+ for hypernet_key in shared.hypernetworks.keys():
187
+ if hypernet_key.lower().startswith(hypernet_name):
188
+ return hypernet_key
189
+
190
+ return None
191
+
192
+
193
+ def restore_old_hires_fix_params(res):
194
+ """for infotexts that specify old First pass size parameter, convert it into
195
+ width, height, and hr scale"""
196
+
197
+ firstpass_width = res.get('First pass size-1', None)
198
+ firstpass_height = res.get('First pass size-2', None)
199
+
200
+ if shared.opts.use_old_hires_fix_width_height:
201
+ hires_width = int(res.get("Hires resize-1", 0))
202
+ hires_height = int(res.get("Hires resize-2", 0))
203
+
204
+ if hires_width and hires_height:
205
+ res['Size-1'] = hires_width
206
+ res['Size-2'] = hires_height
207
+ return
208
+
209
+ if firstpass_width is None or firstpass_height is None:
210
+ return
211
+
212
+ firstpass_width, firstpass_height = int(firstpass_width), int(firstpass_height)
213
+ width = int(res.get("Size-1", 512))
214
+ height = int(res.get("Size-2", 512))
215
+
216
+ if firstpass_width == 0 or firstpass_height == 0:
217
+ from modules import processing
218
+ firstpass_width, firstpass_height = processing.old_hires_fix_first_pass_dimensions(width, height)
219
+
220
+ res['Size-1'] = firstpass_width
221
+ res['Size-2'] = firstpass_height
222
+ res['Hires resize-1'] = width
223
+ res['Hires resize-2'] = height
224
+
225
+
226
+ def parse_generation_parameters(x: str):
227
+ """parses generation parameters string, the one you see in text field under the picture in UI:
228
+ ```
229
+ girl with an artist's beret, determined, blue eyes, desert scene, computer monitors, heavy makeup, by Alphonse Mucha and Charlie Bowater, ((eyeshadow)), (coquettish), detailed, intricate
230
+ Negative prompt: ugly, fat, obese, chubby, (((deformed))), [blurry], bad anatomy, disfigured, poorly drawn face, mutation, mutated, (extra_limb), (ugly), (poorly drawn hands), messy drawing
231
+ Steps: 20, Sampler: Euler a, CFG scale: 7, Seed: 965400086, Size: 512x512, Model hash: 45dee52b
232
+ ```
233
+
234
+ returns a dict with field values
235
+ """
236
+
237
+ res = {}
238
+
239
+ prompt = ""
240
+ negative_prompt = ""
241
+
242
+ done_with_prompt = False
243
+
244
+ *lines, lastline = x.strip().split("\n")
245
+ if len(re_param.findall(lastline)) < 3:
246
+ lines.append(lastline)
247
+ lastline = ''
248
+
249
+ for i, line in enumerate(lines):
250
+ line = line.strip()
251
+ if line.startswith("Negative prompt:"):
252
+ done_with_prompt = True
253
+ line = line[16:].strip()
254
+
255
+ if done_with_prompt:
256
+ negative_prompt += ("" if negative_prompt == "" else "\n") + line
257
+ else:
258
+ prompt += ("" if prompt == "" else "\n") + line
259
+
260
+ res["Prompt"] = prompt
261
+ res["Negative prompt"] = negative_prompt
262
+
263
+ for k, v in re_param.findall(lastline):
264
+ v = v[1:-1] if v[0] == '"' and v[-1] == '"' else v
265
+ m = re_imagesize.match(v)
266
+ if m is not None:
267
+ res[k+"-1"] = m.group(1)
268
+ res[k+"-2"] = m.group(2)
269
+ else:
270
+ res[k] = v
271
+
272
+ # Missing CLIP skip means it was set to 1 (the default)
273
+ if "Clip skip" not in res:
274
+ res["Clip skip"] = "1"
275
+
276
+ hypernet = res.get("Hypernet", None)
277
+ if hypernet is not None:
278
+ res["Prompt"] += f"""<hypernet:{hypernet}:{res.get("Hypernet strength", "1.0")}>"""
279
+
280
+ if "Hires resize-1" not in res:
281
+ res["Hires resize-1"] = 0
282
+ res["Hires resize-2"] = 0
283
+
284
+ restore_old_hires_fix_params(res)
285
+
286
+ return res
287
+
288
+
289
+ settings_map = {}
290
+
291
+ infotext_to_setting_name_mapping = [
292
+ ('Clip skip', 'CLIP_stop_at_last_layers', ),
293
+ ('Conditional mask weight', 'inpainting_mask_weight'),
294
+ ('Model hash', 'sd_model_checkpoint'),
295
+ ('ENSD', 'eta_noise_seed_delta'),
296
+ ('Noise multiplier', 'initial_noise_multiplier'),
297
+ ('Eta', 'eta_ancestral'),
298
+ ('Eta DDIM', 'eta_ddim'),
299
+ ('Discard penultimate sigma', 'always_discard_next_to_last_sigma')
300
+ ]
301
+
302
+
303
+ def create_override_settings_dict(text_pairs):
304
+ """creates processing's override_settings parameters from gradio's multiselect
305
+
306
+ Example input:
307
+ ['Clip skip: 2', 'Model hash: e6e99610c4', 'ENSD: 31337']
308
+
309
+ Example output:
310
+ {'CLIP_stop_at_last_layers': 2, 'sd_model_checkpoint': 'e6e99610c4', 'eta_noise_seed_delta': 31337}
311
+ """
312
+
313
+ res = {}
314
+
315
+ params = {}
316
+ for pair in text_pairs:
317
+ k, v = pair.split(":", maxsplit=1)
318
+
319
+ params[k] = v.strip()
320
+
321
+ for param_name, setting_name in infotext_to_setting_name_mapping:
322
+ value = params.get(param_name, None)
323
+
324
+ if value is None:
325
+ continue
326
+
327
+ res[setting_name] = shared.opts.cast_value(setting_name, value)
328
+
329
+ return res
330
+
331
+
332
+ def connect_paste(button, paste_fields, input_comp, override_settings_component, tabname):
333
+ def paste_func(prompt):
334
+ if not prompt and not shared.cmd_opts.hide_ui_dir_config:
335
+ filename = os.path.join(data_path, "params.txt")
336
+ if os.path.exists(filename):
337
+ with open(filename, "r", encoding="utf8") as file:
338
+ prompt = file.read()
339
+
340
+ params = parse_generation_parameters(prompt)
341
+ script_callbacks.infotext_pasted_callback(prompt, params)
342
+ res = []
343
+
344
+ for output, key in paste_fields:
345
+ if callable(key):
346
+ v = key(params)
347
+ else:
348
+ v = params.get(key, None)
349
+
350
+ if v is None:
351
+ res.append(gr.update())
352
+ elif isinstance(v, type_of_gr_update):
353
+ res.append(v)
354
+ else:
355
+ try:
356
+ valtype = type(output.value)
357
+
358
+ if valtype == bool and v == "False":
359
+ val = False
360
+ else:
361
+ val = valtype(v)
362
+
363
+ res.append(gr.update(value=val))
364
+ except Exception:
365
+ res.append(gr.update())
366
+
367
+ return res
368
+
369
+ if override_settings_component is not None:
370
+ def paste_settings(params):
371
+ vals = {}
372
+
373
+ for param_name, setting_name in infotext_to_setting_name_mapping:
374
+ v = params.get(param_name, None)
375
+ if v is None:
376
+ continue
377
+
378
+ if setting_name == "sd_model_checkpoint" and shared.opts.disable_weights_auto_swap:
379
+ continue
380
+
381
+ v = shared.opts.cast_value(setting_name, v)
382
+ current_value = getattr(shared.opts, setting_name, None)
383
+
384
+ if v == current_value:
385
+ continue
386
+
387
+ vals[param_name] = v
388
+
389
+ vals_pairs = [f"{k}: {v}" for k, v in vals.items()]
390
+
391
+ return gr.Dropdown.update(value=vals_pairs, choices=vals_pairs, visible=len(vals_pairs) > 0)
392
+
393
+ paste_fields = paste_fields + [(override_settings_component, paste_settings)]
394
+
395
+ button.click(
396
+ fn=paste_func,
397
+ _js=f"recalculate_prompts_{tabname}",
398
+ inputs=[input_comp],
399
+ outputs=[x[0] for x in paste_fields],
400
+ )
401
+
402
+
modules/gfpgan_model.py ADDED
@@ -0,0 +1,116 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import sys
3
+ import traceback
4
+
5
+ import facexlib
6
+ import gfpgan
7
+
8
+ import modules.face_restoration
9
+ from modules import paths, shared, devices, modelloader
10
+
11
+ model_dir = "GFPGAN"
12
+ user_path = None
13
+ model_path = os.path.join(paths.models_path, model_dir)
14
+ model_url = "https://github.com/TencentARC/GFPGAN/releases/download/v1.3.0/GFPGANv1.4.pth"
15
+ have_gfpgan = False
16
+ loaded_gfpgan_model = None
17
+
18
+
19
+ def gfpgann():
20
+ global loaded_gfpgan_model
21
+ global model_path
22
+ if loaded_gfpgan_model is not None:
23
+ loaded_gfpgan_model.gfpgan.to(devices.device_gfpgan)
24
+ return loaded_gfpgan_model
25
+
26
+ if gfpgan_constructor is None:
27
+ return None
28
+
29
+ models = modelloader.load_models(model_path, model_url, user_path, ext_filter="GFPGAN")
30
+ if len(models) == 1 and "http" in models[0]:
31
+ model_file = models[0]
32
+ elif len(models) != 0:
33
+ latest_file = max(models, key=os.path.getctime)
34
+ model_file = latest_file
35
+ else:
36
+ print("Unable to load gfpgan model!")
37
+ return None
38
+ if hasattr(facexlib.detection.retinaface, 'device'):
39
+ facexlib.detection.retinaface.device = devices.device_gfpgan
40
+ model = gfpgan_constructor(model_path=model_file, upscale=1, arch='clean', channel_multiplier=2, bg_upsampler=None, device=devices.device_gfpgan)
41
+ loaded_gfpgan_model = model
42
+
43
+ return model
44
+
45
+
46
+ def send_model_to(model, device):
47
+ model.gfpgan.to(device)
48
+ model.face_helper.face_det.to(device)
49
+ model.face_helper.face_parse.to(device)
50
+
51
+
52
+ def gfpgan_fix_faces(np_image):
53
+ model = gfpgann()
54
+ if model is None:
55
+ return np_image
56
+
57
+ send_model_to(model, devices.device_gfpgan)
58
+
59
+ np_image_bgr = np_image[:, :, ::-1]
60
+ cropped_faces, restored_faces, gfpgan_output_bgr = model.enhance(np_image_bgr, has_aligned=False, only_center_face=False, paste_back=True)
61
+ np_image = gfpgan_output_bgr[:, :, ::-1]
62
+
63
+ model.face_helper.clean_all()
64
+
65
+ if shared.opts.face_restoration_unload:
66
+ send_model_to(model, devices.cpu)
67
+
68
+ return np_image
69
+
70
+
71
+ gfpgan_constructor = None
72
+
73
+
74
+ def setup_model(dirname):
75
+ global model_path
76
+ if not os.path.exists(model_path):
77
+ os.makedirs(model_path)
78
+
79
+ try:
80
+ from gfpgan import GFPGANer
81
+ from facexlib import detection, parsing
82
+ global user_path
83
+ global have_gfpgan
84
+ global gfpgan_constructor
85
+
86
+ load_file_from_url_orig = gfpgan.utils.load_file_from_url
87
+ facex_load_file_from_url_orig = facexlib.detection.load_file_from_url
88
+ facex_load_file_from_url_orig2 = facexlib.parsing.load_file_from_url
89
+
90
+ def my_load_file_from_url(**kwargs):
91
+ return load_file_from_url_orig(**dict(kwargs, model_dir=model_path))
92
+
93
+ def facex_load_file_from_url(**kwargs):
94
+ return facex_load_file_from_url_orig(**dict(kwargs, save_dir=model_path, model_dir=None))
95
+
96
+ def facex_load_file_from_url2(**kwargs):
97
+ return facex_load_file_from_url_orig2(**dict(kwargs, save_dir=model_path, model_dir=None))
98
+
99
+ gfpgan.utils.load_file_from_url = my_load_file_from_url
100
+ facexlib.detection.load_file_from_url = facex_load_file_from_url
101
+ facexlib.parsing.load_file_from_url = facex_load_file_from_url2
102
+ user_path = dirname
103
+ have_gfpgan = True
104
+ gfpgan_constructor = GFPGANer
105
+
106
+ class FaceRestorerGFPGAN(modules.face_restoration.FaceRestoration):
107
+ def name(self):
108
+ return "GFPGAN"
109
+
110
+ def restore(self, np_image):
111
+ return gfpgan_fix_faces(np_image)
112
+
113
+ shared.face_restorers.append(FaceRestorerGFPGAN())
114
+ except Exception:
115
+ print("Error setting up GFPGAN:", file=sys.stderr)
116
+ print(traceback.format_exc(), file=sys.stderr)
modules/hashes.py ADDED
@@ -0,0 +1,91 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import hashlib
2
+ import json
3
+ import os.path
4
+
5
+ import filelock
6
+
7
+ from modules import shared
8
+ from modules.paths import data_path
9
+
10
+
11
+ cache_filename = os.path.join(data_path, "cache.json")
12
+ cache_data = None
13
+
14
+
15
+ def dump_cache():
16
+ with filelock.FileLock(cache_filename+".lock"):
17
+ with open(cache_filename, "w", encoding="utf8") as file:
18
+ json.dump(cache_data, file, indent=4)
19
+
20
+
21
+ def cache(subsection):
22
+ global cache_data
23
+
24
+ if cache_data is None:
25
+ with filelock.FileLock(cache_filename+".lock"):
26
+ if not os.path.isfile(cache_filename):
27
+ cache_data = {}
28
+ else:
29
+ with open(cache_filename, "r", encoding="utf8") as file:
30
+ cache_data = json.load(file)
31
+
32
+ s = cache_data.get(subsection, {})
33
+ cache_data[subsection] = s
34
+
35
+ return s
36
+
37
+
38
+ def calculate_sha256(filename):
39
+ hash_sha256 = hashlib.sha256()
40
+ blksize = 1024 * 1024
41
+
42
+ with open(filename, "rb") as f:
43
+ for chunk in iter(lambda: f.read(blksize), b""):
44
+ hash_sha256.update(chunk)
45
+
46
+ return hash_sha256.hexdigest()
47
+
48
+
49
+ def sha256_from_cache(filename, title):
50
+ hashes = cache("hashes")
51
+ ondisk_mtime = os.path.getmtime(filename)
52
+
53
+ if title not in hashes:
54
+ return None
55
+
56
+ cached_sha256 = hashes[title].get("sha256", None)
57
+ cached_mtime = hashes[title].get("mtime", 0)
58
+
59
+ if ondisk_mtime > cached_mtime or cached_sha256 is None:
60
+ return None
61
+
62
+ return cached_sha256
63
+
64
+
65
+ def sha256(filename, title):
66
+ hashes = cache("hashes")
67
+
68
+ sha256_value = sha256_from_cache(filename, title)
69
+ if sha256_value is not None:
70
+ return sha256_value
71
+
72
+ if shared.cmd_opts.no_hashing:
73
+ return None
74
+
75
+ print(f"Calculating sha256 for {filename}: ", end='')
76
+ sha256_value = calculate_sha256(filename)
77
+ print(f"{sha256_value}")
78
+
79
+ hashes[title] = {
80
+ "mtime": os.path.getmtime(filename),
81
+ "sha256": sha256_value,
82
+ }
83
+
84
+ dump_cache()
85
+
86
+ return sha256_value
87
+
88
+
89
+
90
+
91
+
modules/hypernetworks/hypernetwork.py ADDED
@@ -0,0 +1,811 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import csv
2
+ import datetime
3
+ import glob
4
+ import html
5
+ import os
6
+ import sys
7
+ import traceback
8
+ import inspect
9
+
10
+ import modules.textual_inversion.dataset
11
+ import torch
12
+ import tqdm
13
+ from einops import rearrange, repeat
14
+ from ldm.util import default
15
+ from modules import devices, processing, sd_models, shared, sd_samplers, hashes, sd_hijack_checkpoint
16
+ from modules.textual_inversion import textual_inversion, logging
17
+ from modules.textual_inversion.learn_schedule import LearnRateScheduler
18
+ from torch import einsum
19
+ from torch.nn.init import normal_, xavier_normal_, xavier_uniform_, kaiming_normal_, kaiming_uniform_, zeros_
20
+
21
+ from collections import defaultdict, deque
22
+ from statistics import stdev, mean
23
+
24
+
25
+ optimizer_dict = {optim_name : cls_obj for optim_name, cls_obj in inspect.getmembers(torch.optim, inspect.isclass) if optim_name != "Optimizer"}
26
+
27
+ class HypernetworkModule(torch.nn.Module):
28
+ activation_dict = {
29
+ "linear": torch.nn.Identity,
30
+ "relu": torch.nn.ReLU,
31
+ "leakyrelu": torch.nn.LeakyReLU,
32
+ "elu": torch.nn.ELU,
33
+ "swish": torch.nn.Hardswish,
34
+ "tanh": torch.nn.Tanh,
35
+ "sigmoid": torch.nn.Sigmoid,
36
+ }
37
+ activation_dict.update({cls_name.lower(): cls_obj for cls_name, cls_obj in inspect.getmembers(torch.nn.modules.activation) if inspect.isclass(cls_obj) and cls_obj.__module__ == 'torch.nn.modules.activation'})
38
+
39
+ def __init__(self, dim, state_dict=None, layer_structure=None, activation_func=None, weight_init='Normal',
40
+ add_layer_norm=False, activate_output=False, dropout_structure=None):
41
+ super().__init__()
42
+
43
+ self.multiplier = 1.0
44
+
45
+ assert layer_structure is not None, "layer_structure must not be None"
46
+ assert layer_structure[0] == 1, "Multiplier Sequence should start with size 1!"
47
+ assert layer_structure[-1] == 1, "Multiplier Sequence should end with size 1!"
48
+
49
+ linears = []
50
+ for i in range(len(layer_structure) - 1):
51
+
52
+ # Add a fully-connected layer
53
+ linears.append(torch.nn.Linear(int(dim * layer_structure[i]), int(dim * layer_structure[i+1])))
54
+
55
+ # Add an activation func except last layer
56
+ if activation_func == "linear" or activation_func is None or (i >= len(layer_structure) - 2 and not activate_output):
57
+ pass
58
+ elif activation_func in self.activation_dict:
59
+ linears.append(self.activation_dict[activation_func]())
60
+ else:
61
+ raise RuntimeError(f'hypernetwork uses an unsupported activation function: {activation_func}')
62
+
63
+ # Add layer normalization
64
+ if add_layer_norm:
65
+ linears.append(torch.nn.LayerNorm(int(dim * layer_structure[i+1])))
66
+
67
+ # Everything should be now parsed into dropout structure, and applied here.
68
+ # Since we only have dropouts after layers, dropout structure should start with 0 and end with 0.
69
+ if dropout_structure is not None and dropout_structure[i+1] > 0:
70
+ assert 0 < dropout_structure[i+1] < 1, "Dropout probability should be 0 or float between 0 and 1!"
71
+ linears.append(torch.nn.Dropout(p=dropout_structure[i+1]))
72
+ # Code explanation : [1, 2, 1] -> dropout is missing when last_layer_dropout is false. [1, 2, 2, 1] -> [0, 0.3, 0, 0], when its True, [0, 0.3, 0.3, 0].
73
+
74
+ self.linear = torch.nn.Sequential(*linears)
75
+
76
+ if state_dict is not None:
77
+ self.fix_old_state_dict(state_dict)
78
+ self.load_state_dict(state_dict)
79
+ else:
80
+ for layer in self.linear:
81
+ if type(layer) == torch.nn.Linear or type(layer) == torch.nn.LayerNorm:
82
+ w, b = layer.weight.data, layer.bias.data
83
+ if weight_init == "Normal" or type(layer) == torch.nn.LayerNorm:
84
+ normal_(w, mean=0.0, std=0.01)
85
+ normal_(b, mean=0.0, std=0)
86
+ elif weight_init == 'XavierUniform':
87
+ xavier_uniform_(w)
88
+ zeros_(b)
89
+ elif weight_init == 'XavierNormal':
90
+ xavier_normal_(w)
91
+ zeros_(b)
92
+ elif weight_init == 'KaimingUniform':
93
+ kaiming_uniform_(w, nonlinearity='leaky_relu' if 'leakyrelu' == activation_func else 'relu')
94
+ zeros_(b)
95
+ elif weight_init == 'KaimingNormal':
96
+ kaiming_normal_(w, nonlinearity='leaky_relu' if 'leakyrelu' == activation_func else 'relu')
97
+ zeros_(b)
98
+ else:
99
+ raise KeyError(f"Key {weight_init} is not defined as initialization!")
100
+ self.to(devices.device)
101
+
102
+ def fix_old_state_dict(self, state_dict):
103
+ changes = {
104
+ 'linear1.bias': 'linear.0.bias',
105
+ 'linear1.weight': 'linear.0.weight',
106
+ 'linear2.bias': 'linear.1.bias',
107
+ 'linear2.weight': 'linear.1.weight',
108
+ }
109
+
110
+ for fr, to in changes.items():
111
+ x = state_dict.get(fr, None)
112
+ if x is None:
113
+ continue
114
+
115
+ del state_dict[fr]
116
+ state_dict[to] = x
117
+
118
+ def forward(self, x):
119
+ return x + self.linear(x) * (self.multiplier if not self.training else 1)
120
+
121
+ def trainables(self):
122
+ layer_structure = []
123
+ for layer in self.linear:
124
+ if type(layer) == torch.nn.Linear or type(layer) == torch.nn.LayerNorm:
125
+ layer_structure += [layer.weight, layer.bias]
126
+ return layer_structure
127
+
128
+
129
+ #param layer_structure : sequence used for length, use_dropout : controlling boolean, last_layer_dropout : for compatibility check.
130
+ def parse_dropout_structure(layer_structure, use_dropout, last_layer_dropout):
131
+ if layer_structure is None:
132
+ layer_structure = [1, 2, 1]
133
+ if not use_dropout:
134
+ return [0] * len(layer_structure)
135
+ dropout_values = [0]
136
+ dropout_values.extend([0.3] * (len(layer_structure) - 3))
137
+ if last_layer_dropout:
138
+ dropout_values.append(0.3)
139
+ else:
140
+ dropout_values.append(0)
141
+ dropout_values.append(0)
142
+ return dropout_values
143
+
144
+
145
+ class Hypernetwork:
146
+ filename = None
147
+ name = None
148
+
149
+ def __init__(self, name=None, enable_sizes=None, layer_structure=None, activation_func=None, weight_init=None, add_layer_norm=False, use_dropout=False, activate_output=False, **kwargs):
150
+ self.filename = None
151
+ self.name = name
152
+ self.layers = {}
153
+ self.step = 0
154
+ self.sd_checkpoint = None
155
+ self.sd_checkpoint_name = None
156
+ self.layer_structure = layer_structure
157
+ self.activation_func = activation_func
158
+ self.weight_init = weight_init
159
+ self.add_layer_norm = add_layer_norm
160
+ self.use_dropout = use_dropout
161
+ self.activate_output = activate_output
162
+ self.last_layer_dropout = kwargs.get('last_layer_dropout', True)
163
+ self.dropout_structure = kwargs.get('dropout_structure', None)
164
+ if self.dropout_structure is None:
165
+ self.dropout_structure = parse_dropout_structure(self.layer_structure, self.use_dropout, self.last_layer_dropout)
166
+ self.optimizer_name = None
167
+ self.optimizer_state_dict = None
168
+ self.optional_info = None
169
+
170
+ for size in enable_sizes or []:
171
+ self.layers[size] = (
172
+ HypernetworkModule(size, None, self.layer_structure, self.activation_func, self.weight_init,
173
+ self.add_layer_norm, self.activate_output, dropout_structure=self.dropout_structure),
174
+ HypernetworkModule(size, None, self.layer_structure, self.activation_func, self.weight_init,
175
+ self.add_layer_norm, self.activate_output, dropout_structure=self.dropout_structure),
176
+ )
177
+ self.eval()
178
+
179
+ def weights(self):
180
+ res = []
181
+ for k, layers in self.layers.items():
182
+ for layer in layers:
183
+ res += layer.parameters()
184
+ return res
185
+
186
+ def train(self, mode=True):
187
+ for k, layers in self.layers.items():
188
+ for layer in layers:
189
+ layer.train(mode=mode)
190
+ for param in layer.parameters():
191
+ param.requires_grad = mode
192
+
193
+ def to(self, device):
194
+ for k, layers in self.layers.items():
195
+ for layer in layers:
196
+ layer.to(device)
197
+
198
+ return self
199
+
200
+ def set_multiplier(self, multiplier):
201
+ for k, layers in self.layers.items():
202
+ for layer in layers:
203
+ layer.multiplier = multiplier
204
+
205
+ return self
206
+
207
+ def eval(self):
208
+ for k, layers in self.layers.items():
209
+ for layer in layers:
210
+ layer.eval()
211
+ for param in layer.parameters():
212
+ param.requires_grad = False
213
+
214
+ def save(self, filename):
215
+ state_dict = {}
216
+ optimizer_saved_dict = {}
217
+
218
+ for k, v in self.layers.items():
219
+ state_dict[k] = (v[0].state_dict(), v[1].state_dict())
220
+
221
+ state_dict['step'] = self.step
222
+ state_dict['name'] = self.name
223
+ state_dict['layer_structure'] = self.layer_structure
224
+ state_dict['activation_func'] = self.activation_func
225
+ state_dict['is_layer_norm'] = self.add_layer_norm
226
+ state_dict['weight_initialization'] = self.weight_init
227
+ state_dict['sd_checkpoint'] = self.sd_checkpoint
228
+ state_dict['sd_checkpoint_name'] = self.sd_checkpoint_name
229
+ state_dict['activate_output'] = self.activate_output
230
+ state_dict['use_dropout'] = self.use_dropout
231
+ state_dict['dropout_structure'] = self.dropout_structure
232
+ state_dict['last_layer_dropout'] = (self.dropout_structure[-2] != 0) if self.dropout_structure is not None else self.last_layer_dropout
233
+ state_dict['optional_info'] = self.optional_info if self.optional_info else None
234
+
235
+ if self.optimizer_name is not None:
236
+ optimizer_saved_dict['optimizer_name'] = self.optimizer_name
237
+
238
+ torch.save(state_dict, filename)
239
+ if shared.opts.save_optimizer_state and self.optimizer_state_dict:
240
+ optimizer_saved_dict['hash'] = self.shorthash()
241
+ optimizer_saved_dict['optimizer_state_dict'] = self.optimizer_state_dict
242
+ torch.save(optimizer_saved_dict, filename + '.optim')
243
+
244
+ def load(self, filename):
245
+ self.filename = filename
246
+ if self.name is None:
247
+ self.name = os.path.splitext(os.path.basename(filename))[0]
248
+
249
+ state_dict = torch.load(filename, map_location='cpu')
250
+
251
+ self.layer_structure = state_dict.get('layer_structure', [1, 2, 1])
252
+ self.optional_info = state_dict.get('optional_info', None)
253
+ self.activation_func = state_dict.get('activation_func', None)
254
+ self.weight_init = state_dict.get('weight_initialization', 'Normal')
255
+ self.add_layer_norm = state_dict.get('is_layer_norm', False)
256
+ self.dropout_structure = state_dict.get('dropout_structure', None)
257
+ self.use_dropout = True if self.dropout_structure is not None and any(self.dropout_structure) else state_dict.get('use_dropout', False)
258
+ self.activate_output = state_dict.get('activate_output', True)
259
+ self.last_layer_dropout = state_dict.get('last_layer_dropout', False)
260
+ # Dropout structure should have same length as layer structure, Every digits should be in [0,1), and last digit must be 0.
261
+ if self.dropout_structure is None:
262
+ self.dropout_structure = parse_dropout_structure(self.layer_structure, self.use_dropout, self.last_layer_dropout)
263
+
264
+ if shared.opts.print_hypernet_extra:
265
+ if self.optional_info is not None:
266
+ print(f" INFO:\n {self.optional_info}\n")
267
+
268
+ print(f" Layer structure: {self.layer_structure}")
269
+ print(f" Activation function: {self.activation_func}")
270
+ print(f" Weight initialization: {self.weight_init}")
271
+ print(f" Layer norm: {self.add_layer_norm}")
272
+ print(f" Dropout usage: {self.use_dropout}" )
273
+ print(f" Activate last layer: {self.activate_output}")
274
+ print(f" Dropout structure: {self.dropout_structure}")
275
+
276
+ optimizer_saved_dict = torch.load(self.filename + '.optim', map_location='cpu') if os.path.exists(self.filename + '.optim') else {}
277
+
278
+ if self.shorthash() == optimizer_saved_dict.get('hash', None):
279
+ self.optimizer_state_dict = optimizer_saved_dict.get('optimizer_state_dict', None)
280
+ else:
281
+ self.optimizer_state_dict = None
282
+ if self.optimizer_state_dict:
283
+ self.optimizer_name = optimizer_saved_dict.get('optimizer_name', 'AdamW')
284
+ if shared.opts.print_hypernet_extra:
285
+ print("Loaded existing optimizer from checkpoint")
286
+ print(f"Optimizer name is {self.optimizer_name}")
287
+ else:
288
+ self.optimizer_name = "AdamW"
289
+ if shared.opts.print_hypernet_extra:
290
+ print("No saved optimizer exists in checkpoint")
291
+
292
+ for size, sd in state_dict.items():
293
+ if type(size) == int:
294
+ self.layers[size] = (
295
+ HypernetworkModule(size, sd[0], self.layer_structure, self.activation_func, self.weight_init,
296
+ self.add_layer_norm, self.activate_output, self.dropout_structure),
297
+ HypernetworkModule(size, sd[1], self.layer_structure, self.activation_func, self.weight_init,
298
+ self.add_layer_norm, self.activate_output, self.dropout_structure),
299
+ )
300
+
301
+ self.name = state_dict.get('name', self.name)
302
+ self.step = state_dict.get('step', 0)
303
+ self.sd_checkpoint = state_dict.get('sd_checkpoint', None)
304
+ self.sd_checkpoint_name = state_dict.get('sd_checkpoint_name', None)
305
+ self.eval()
306
+
307
+ def shorthash(self):
308
+ sha256 = hashes.sha256(self.filename, f'hypernet/{self.name}')
309
+
310
+ return sha256[0:10] if sha256 else None
311
+
312
+
313
+ def list_hypernetworks(path):
314
+ res = {}
315
+ for filename in sorted(glob.iglob(os.path.join(path, '**/*.pt'), recursive=True)):
316
+ name = os.path.splitext(os.path.basename(filename))[0]
317
+ # Prevent a hypothetical "None.pt" from being listed.
318
+ if name != "None":
319
+ res[name] = filename
320
+ return res
321
+
322
+
323
+ def load_hypernetwork(name):
324
+ path = shared.hypernetworks.get(name, None)
325
+
326
+ if path is None:
327
+ return None
328
+
329
+ hypernetwork = Hypernetwork()
330
+
331
+ try:
332
+ hypernetwork.load(path)
333
+ except Exception:
334
+ print(f"Error loading hypernetwork {path}", file=sys.stderr)
335
+ print(traceback.format_exc(), file=sys.stderr)
336
+ return None
337
+
338
+ return hypernetwork
339
+
340
+
341
+ def load_hypernetworks(names, multipliers=None):
342
+ already_loaded = {}
343
+
344
+ for hypernetwork in shared.loaded_hypernetworks:
345
+ if hypernetwork.name in names:
346
+ already_loaded[hypernetwork.name] = hypernetwork
347
+
348
+ shared.loaded_hypernetworks.clear()
349
+
350
+ for i, name in enumerate(names):
351
+ hypernetwork = already_loaded.get(name, None)
352
+ if hypernetwork is None:
353
+ hypernetwork = load_hypernetwork(name)
354
+
355
+ if hypernetwork is None:
356
+ continue
357
+
358
+ hypernetwork.set_multiplier(multipliers[i] if multipliers else 1.0)
359
+ shared.loaded_hypernetworks.append(hypernetwork)
360
+
361
+
362
+ def find_closest_hypernetwork_name(search: str):
363
+ if not search:
364
+ return None
365
+ search = search.lower()
366
+ applicable = [name for name in shared.hypernetworks if search in name.lower()]
367
+ if not applicable:
368
+ return None
369
+ applicable = sorted(applicable, key=lambda name: len(name))
370
+ return applicable[0]
371
+
372
+
373
+ def apply_single_hypernetwork(hypernetwork, context_k, context_v, layer=None):
374
+ hypernetwork_layers = (hypernetwork.layers if hypernetwork is not None else {}).get(context_k.shape[2], None)
375
+
376
+ if hypernetwork_layers is None:
377
+ return context_k, context_v
378
+
379
+ if layer is not None:
380
+ layer.hyper_k = hypernetwork_layers[0]
381
+ layer.hyper_v = hypernetwork_layers[1]
382
+
383
+ context_k = devices.cond_cast_unet(hypernetwork_layers[0](devices.cond_cast_float(context_k)))
384
+ context_v = devices.cond_cast_unet(hypernetwork_layers[1](devices.cond_cast_float(context_v)))
385
+ return context_k, context_v
386
+
387
+
388
+ def apply_hypernetworks(hypernetworks, context, layer=None):
389
+ context_k = context
390
+ context_v = context
391
+ for hypernetwork in hypernetworks:
392
+ context_k, context_v = apply_single_hypernetwork(hypernetwork, context_k, context_v, layer)
393
+
394
+ return context_k, context_v
395
+
396
+
397
+ def attention_CrossAttention_forward(self, x, context=None, mask=None):
398
+ h = self.heads
399
+
400
+ q = self.to_q(x)
401
+ context = default(context, x)
402
+
403
+ context_k, context_v = apply_hypernetworks(shared.loaded_hypernetworks, context, self)
404
+ k = self.to_k(context_k)
405
+ v = self.to_v(context_v)
406
+
407
+ q, k, v = map(lambda t: rearrange(t, 'b n (h d) -> (b h) n d', h=h), (q, k, v))
408
+
409
+ sim = einsum('b i d, b j d -> b i j', q, k) * self.scale
410
+
411
+ if mask is not None:
412
+ mask = rearrange(mask, 'b ... -> b (...)')
413
+ max_neg_value = -torch.finfo(sim.dtype).max
414
+ mask = repeat(mask, 'b j -> (b h) () j', h=h)
415
+ sim.masked_fill_(~mask, max_neg_value)
416
+
417
+ # attention, what we cannot get enough of
418
+ attn = sim.softmax(dim=-1)
419
+
420
+ out = einsum('b i j, b j d -> b i d', attn, v)
421
+ out = rearrange(out, '(b h) n d -> b n (h d)', h=h)
422
+ return self.to_out(out)
423
+
424
+
425
+ def stack_conds(conds):
426
+ if len(conds) == 1:
427
+ return torch.stack(conds)
428
+
429
+ # same as in reconstruct_multicond_batch
430
+ token_count = max([x.shape[0] for x in conds])
431
+ for i in range(len(conds)):
432
+ if conds[i].shape[0] != token_count:
433
+ last_vector = conds[i][-1:]
434
+ last_vector_repeated = last_vector.repeat([token_count - conds[i].shape[0], 1])
435
+ conds[i] = torch.vstack([conds[i], last_vector_repeated])
436
+
437
+ return torch.stack(conds)
438
+
439
+
440
+ def statistics(data):
441
+ if len(data) < 2:
442
+ std = 0
443
+ else:
444
+ std = stdev(data)
445
+ total_information = f"loss:{mean(data):.3f}" + u"\u00B1" + f"({std/ (len(data) ** 0.5):.3f})"
446
+ recent_data = data[-32:]
447
+ if len(recent_data) < 2:
448
+ std = 0
449
+ else:
450
+ std = stdev(recent_data)
451
+ recent_information = f"recent 32 loss:{mean(recent_data):.3f}" + u"\u00B1" + f"({std / (len(recent_data) ** 0.5):.3f})"
452
+ return total_information, recent_information
453
+
454
+
455
+ def report_statistics(loss_info:dict):
456
+ keys = sorted(loss_info.keys(), key=lambda x: sum(loss_info[x]) / len(loss_info[x]))
457
+ for key in keys:
458
+ try:
459
+ print("Loss statistics for file " + key)
460
+ info, recent = statistics(list(loss_info[key]))
461
+ print(info)
462
+ print(recent)
463
+ except Exception as e:
464
+ print(e)
465
+
466
+
467
+ def create_hypernetwork(name, enable_sizes, overwrite_old, layer_structure=None, activation_func=None, weight_init=None, add_layer_norm=False, use_dropout=False, dropout_structure=None):
468
+ # Remove illegal characters from name.
469
+ name = "".join( x for x in name if (x.isalnum() or x in "._- "))
470
+ assert name, "Name cannot be empty!"
471
+
472
+ fn = os.path.join(shared.cmd_opts.hypernetwork_dir, f"{name}.pt")
473
+ if not overwrite_old:
474
+ assert not os.path.exists(fn), f"file {fn} already exists"
475
+
476
+ if type(layer_structure) == str:
477
+ layer_structure = [float(x.strip()) for x in layer_structure.split(",")]
478
+
479
+ if use_dropout and dropout_structure and type(dropout_structure) == str:
480
+ dropout_structure = [float(x.strip()) for x in dropout_structure.split(",")]
481
+ else:
482
+ dropout_structure = [0] * len(layer_structure)
483
+
484
+ hypernet = modules.hypernetworks.hypernetwork.Hypernetwork(
485
+ name=name,
486
+ enable_sizes=[int(x) for x in enable_sizes],
487
+ layer_structure=layer_structure,
488
+ activation_func=activation_func,
489
+ weight_init=weight_init,
490
+ add_layer_norm=add_layer_norm,
491
+ use_dropout=use_dropout,
492
+ dropout_structure=dropout_structure
493
+ )
494
+ hypernet.save(fn)
495
+
496
+ shared.reload_hypernetworks()
497
+
498
+
499
+ def train_hypernetwork(id_task, hypernetwork_name, learn_rate, batch_size, gradient_step, data_root, log_directory, training_width, training_height, varsize, steps, clip_grad_mode, clip_grad_value, shuffle_tags, tag_drop_out, latent_sampling_method, use_weight, create_image_every, save_hypernetwork_every, template_filename, preview_from_txt2img, preview_prompt, preview_negative_prompt, preview_steps, preview_sampler_index, preview_cfg_scale, preview_seed, preview_width, preview_height):
500
+ # images allows training previews to have infotext. Importing it at the top causes a circular import problem.
501
+ from modules import images
502
+
503
+ save_hypernetwork_every = save_hypernetwork_every or 0
504
+ create_image_every = create_image_every or 0
505
+ template_file = textual_inversion.textual_inversion_templates.get(template_filename, None)
506
+ textual_inversion.validate_train_inputs(hypernetwork_name, learn_rate, batch_size, gradient_step, data_root, template_file, template_filename, steps, save_hypernetwork_every, create_image_every, log_directory, name="hypernetwork")
507
+ template_file = template_file.path
508
+
509
+ path = shared.hypernetworks.get(hypernetwork_name, None)
510
+ hypernetwork = Hypernetwork()
511
+ hypernetwork.load(path)
512
+ shared.loaded_hypernetworks = [hypernetwork]
513
+
514
+ shared.state.job = "train-hypernetwork"
515
+ shared.state.textinfo = "Initializing hypernetwork training..."
516
+ shared.state.job_count = steps
517
+
518
+ hypernetwork_name = hypernetwork_name.rsplit('(', 1)[0]
519
+ filename = os.path.join(shared.cmd_opts.hypernetwork_dir, f'{hypernetwork_name}.pt')
520
+
521
+ log_directory = os.path.join(log_directory, datetime.datetime.now().strftime("%Y-%m-%d"), hypernetwork_name)
522
+ unload = shared.opts.unload_models_when_training
523
+
524
+ if save_hypernetwork_every > 0:
525
+ hypernetwork_dir = os.path.join(log_directory, "hypernetworks")
526
+ os.makedirs(hypernetwork_dir, exist_ok=True)
527
+ else:
528
+ hypernetwork_dir = None
529
+
530
+ if create_image_every > 0:
531
+ images_dir = os.path.join(log_directory, "images")
532
+ os.makedirs(images_dir, exist_ok=True)
533
+ else:
534
+ images_dir = None
535
+
536
+ checkpoint = sd_models.select_checkpoint()
537
+
538
+ initial_step = hypernetwork.step or 0
539
+ if initial_step >= steps:
540
+ shared.state.textinfo = "Model has already been trained beyond specified max steps"
541
+ return hypernetwork, filename
542
+
543
+ scheduler = LearnRateScheduler(learn_rate, steps, initial_step)
544
+
545
+ clip_grad = torch.nn.utils.clip_grad_value_ if clip_grad_mode == "value" else torch.nn.utils.clip_grad_norm_ if clip_grad_mode == "norm" else None
546
+ if clip_grad:
547
+ clip_grad_sched = LearnRateScheduler(clip_grad_value, steps, initial_step, verbose=False)
548
+
549
+ if shared.opts.training_enable_tensorboard:
550
+ tensorboard_writer = textual_inversion.tensorboard_setup(log_directory)
551
+
552
+ # dataset loading may take a while, so input validations and early returns should be done before this
553
+ shared.state.textinfo = f"Preparing dataset from {html.escape(data_root)}..."
554
+
555
+ pin_memory = shared.opts.pin_memory
556
+
557
+ ds = modules.textual_inversion.dataset.PersonalizedBase(data_root=data_root, width=training_width, height=training_height, repeats=shared.opts.training_image_repeats_per_epoch, placeholder_token=hypernetwork_name, model=shared.sd_model, cond_model=shared.sd_model.cond_stage_model, device=devices.device, template_file=template_file, include_cond=True, batch_size=batch_size, gradient_step=gradient_step, shuffle_tags=shuffle_tags, tag_drop_out=tag_drop_out, latent_sampling_method=latent_sampling_method, varsize=varsize, use_weight=use_weight)
558
+
559
+ if shared.opts.save_training_settings_to_txt:
560
+ saved_params = dict(
561
+ model_name=checkpoint.model_name, model_hash=checkpoint.shorthash, num_of_dataset_images=len(ds),
562
+ **{field: getattr(hypernetwork, field) for field in ['layer_structure', 'activation_func', 'weight_init', 'add_layer_norm', 'use_dropout', ]}
563
+ )
564
+ logging.save_settings_to_file(log_directory, {**saved_params, **locals()})
565
+
566
+ latent_sampling_method = ds.latent_sampling_method
567
+
568
+ dl = modules.textual_inversion.dataset.PersonalizedDataLoader(ds, latent_sampling_method=latent_sampling_method, batch_size=ds.batch_size, pin_memory=pin_memory)
569
+
570
+ old_parallel_processing_allowed = shared.parallel_processing_allowed
571
+
572
+ if unload:
573
+ shared.parallel_processing_allowed = False
574
+ shared.sd_model.cond_stage_model.to(devices.cpu)
575
+ shared.sd_model.first_stage_model.to(devices.cpu)
576
+
577
+ weights = hypernetwork.weights()
578
+ hypernetwork.train()
579
+
580
+ # Here we use optimizer from saved HN, or we can specify as UI option.
581
+ if hypernetwork.optimizer_name in optimizer_dict:
582
+ optimizer = optimizer_dict[hypernetwork.optimizer_name](params=weights, lr=scheduler.learn_rate)
583
+ optimizer_name = hypernetwork.optimizer_name
584
+ else:
585
+ print(f"Optimizer type {hypernetwork.optimizer_name} is not defined!")
586
+ optimizer = torch.optim.AdamW(params=weights, lr=scheduler.learn_rate)
587
+ optimizer_name = 'AdamW'
588
+
589
+ if hypernetwork.optimizer_state_dict: # This line must be changed if Optimizer type can be different from saved optimizer.
590
+ try:
591
+ optimizer.load_state_dict(hypernetwork.optimizer_state_dict)
592
+ except RuntimeError as e:
593
+ print("Cannot resume from saved optimizer!")
594
+ print(e)
595
+
596
+ scaler = torch.cuda.amp.GradScaler()
597
+
598
+ batch_size = ds.batch_size
599
+ gradient_step = ds.gradient_step
600
+ # n steps = batch_size * gradient_step * n image processed
601
+ steps_per_epoch = len(ds) // batch_size // gradient_step
602
+ max_steps_per_epoch = len(ds) // batch_size - (len(ds) // batch_size) % gradient_step
603
+ loss_step = 0
604
+ _loss_step = 0 #internal
605
+ # size = len(ds.indexes)
606
+ # loss_dict = defaultdict(lambda : deque(maxlen = 1024))
607
+ loss_logging = deque(maxlen=len(ds) * 3) # this should be configurable parameter, this is 3 * epoch(dataset size)
608
+ # losses = torch.zeros((size,))
609
+ # previous_mean_losses = [0]
610
+ # previous_mean_loss = 0
611
+ # print("Mean loss of {} elements".format(size))
612
+
613
+ steps_without_grad = 0
614
+
615
+ last_saved_file = "<none>"
616
+ last_saved_image = "<none>"
617
+ forced_filename = "<none>"
618
+
619
+ pbar = tqdm.tqdm(total=steps - initial_step)
620
+ try:
621
+ sd_hijack_checkpoint.add()
622
+
623
+ for i in range((steps-initial_step) * gradient_step):
624
+ if scheduler.finished:
625
+ break
626
+ if shared.state.interrupted:
627
+ break
628
+ for j, batch in enumerate(dl):
629
+ # works as a drop_last=True for gradient accumulation
630
+ if j == max_steps_per_epoch:
631
+ break
632
+ scheduler.apply(optimizer, hypernetwork.step)
633
+ if scheduler.finished:
634
+ break
635
+ if shared.state.interrupted:
636
+ break
637
+
638
+ if clip_grad:
639
+ clip_grad_sched.step(hypernetwork.step)
640
+
641
+ with devices.autocast():
642
+ x = batch.latent_sample.to(devices.device, non_blocking=pin_memory)
643
+ if use_weight:
644
+ w = batch.weight.to(devices.device, non_blocking=pin_memory)
645
+ if tag_drop_out != 0 or shuffle_tags:
646
+ shared.sd_model.cond_stage_model.to(devices.device)
647
+ c = shared.sd_model.cond_stage_model(batch.cond_text).to(devices.device, non_blocking=pin_memory)
648
+ shared.sd_model.cond_stage_model.to(devices.cpu)
649
+ else:
650
+ c = stack_conds(batch.cond).to(devices.device, non_blocking=pin_memory)
651
+ if use_weight:
652
+ loss = shared.sd_model.weighted_forward(x, c, w)[0] / gradient_step
653
+ del w
654
+ else:
655
+ loss = shared.sd_model.forward(x, c)[0] / gradient_step
656
+ del x
657
+ del c
658
+
659
+ _loss_step += loss.item()
660
+ scaler.scale(loss).backward()
661
+
662
+ # go back until we reach gradient accumulation steps
663
+ if (j + 1) % gradient_step != 0:
664
+ continue
665
+ loss_logging.append(_loss_step)
666
+ if clip_grad:
667
+ clip_grad(weights, clip_grad_sched.learn_rate)
668
+
669
+ scaler.step(optimizer)
670
+ scaler.update()
671
+ hypernetwork.step += 1
672
+ pbar.update()
673
+ optimizer.zero_grad(set_to_none=True)
674
+ loss_step = _loss_step
675
+ _loss_step = 0
676
+
677
+ steps_done = hypernetwork.step + 1
678
+
679
+ epoch_num = hypernetwork.step // steps_per_epoch
680
+ epoch_step = hypernetwork.step % steps_per_epoch
681
+
682
+ description = f"Training hypernetwork [Epoch {epoch_num}: {epoch_step+1}/{steps_per_epoch}]loss: {loss_step:.7f}"
683
+ pbar.set_description(description)
684
+ if hypernetwork_dir is not None and steps_done % save_hypernetwork_every == 0:
685
+ # Before saving, change name to match current checkpoint.
686
+ hypernetwork_name_every = f'{hypernetwork_name}-{steps_done}'
687
+ last_saved_file = os.path.join(hypernetwork_dir, f'{hypernetwork_name_every}.pt')
688
+ hypernetwork.optimizer_name = optimizer_name
689
+ if shared.opts.save_optimizer_state:
690
+ hypernetwork.optimizer_state_dict = optimizer.state_dict()
691
+ save_hypernetwork(hypernetwork, checkpoint, hypernetwork_name, last_saved_file)
692
+ hypernetwork.optimizer_state_dict = None # dereference it after saving, to save memory.
693
+
694
+
695
+
696
+ if shared.opts.training_enable_tensorboard:
697
+ epoch_num = hypernetwork.step // len(ds)
698
+ epoch_step = hypernetwork.step - (epoch_num * len(ds)) + 1
699
+ mean_loss = sum(loss_logging) / len(loss_logging)
700
+ textual_inversion.tensorboard_add(tensorboard_writer, loss=mean_loss, global_step=hypernetwork.step, step=epoch_step, learn_rate=scheduler.learn_rate, epoch_num=epoch_num)
701
+
702
+ textual_inversion.write_loss(log_directory, "hypernetwork_loss.csv", hypernetwork.step, steps_per_epoch, {
703
+ "loss": f"{loss_step:.7f}",
704
+ "learn_rate": scheduler.learn_rate
705
+ })
706
+
707
+ if images_dir is not None and steps_done % create_image_every == 0:
708
+ forced_filename = f'{hypernetwork_name}-{steps_done}'
709
+ last_saved_image = os.path.join(images_dir, forced_filename)
710
+ hypernetwork.eval()
711
+ rng_state = torch.get_rng_state()
712
+ cuda_rng_state = None
713
+ if torch.cuda.is_available():
714
+ cuda_rng_state = torch.cuda.get_rng_state_all()
715
+ shared.sd_model.cond_stage_model.to(devices.device)
716
+ shared.sd_model.first_stage_model.to(devices.device)
717
+
718
+ p = processing.StableDiffusionProcessingTxt2Img(
719
+ sd_model=shared.sd_model,
720
+ do_not_save_grid=True,
721
+ do_not_save_samples=True,
722
+ )
723
+
724
+ p.disable_extra_networks = True
725
+
726
+ if preview_from_txt2img:
727
+ p.prompt = preview_prompt
728
+ p.negative_prompt = preview_negative_prompt
729
+ p.steps = preview_steps
730
+ p.sampler_name = sd_samplers.samplers[preview_sampler_index].name
731
+ p.cfg_scale = preview_cfg_scale
732
+ p.seed = preview_seed
733
+ p.width = preview_width
734
+ p.height = preview_height
735
+ else:
736
+ p.prompt = batch.cond_text[0]
737
+ p.steps = 20
738
+ p.width = training_width
739
+ p.height = training_height
740
+
741
+ preview_text = p.prompt
742
+
743
+ processed = processing.process_images(p)
744
+ image = processed.images[0] if len(processed.images) > 0 else None
745
+
746
+ if unload:
747
+ shared.sd_model.cond_stage_model.to(devices.cpu)
748
+ shared.sd_model.first_stage_model.to(devices.cpu)
749
+ torch.set_rng_state(rng_state)
750
+ if torch.cuda.is_available():
751
+ torch.cuda.set_rng_state_all(cuda_rng_state)
752
+ hypernetwork.train()
753
+ if image is not None:
754
+ shared.state.assign_current_image(image)
755
+ if shared.opts.training_enable_tensorboard and shared.opts.training_tensorboard_save_images:
756
+ textual_inversion.tensorboard_add_image(tensorboard_writer,
757
+ f"Validation at epoch {epoch_num}", image,
758
+ hypernetwork.step)
759
+ last_saved_image, last_text_info = images.save_image(image, images_dir, "", p.seed, p.prompt, shared.opts.samples_format, processed.infotexts[0], p=p, forced_filename=forced_filename, save_to_dirs=False)
760
+ last_saved_image += f", prompt: {preview_text}"
761
+
762
+ shared.state.job_no = hypernetwork.step
763
+
764
+ shared.state.textinfo = f"""
765
+ <p>
766
+ Loss: {loss_step:.7f}<br/>
767
+ Step: {steps_done}<br/>
768
+ Last prompt: {html.escape(batch.cond_text[0])}<br/>
769
+ Last saved hypernetwork: {html.escape(last_saved_file)}<br/>
770
+ Last saved image: {html.escape(last_saved_image)}<br/>
771
+ </p>
772
+ """
773
+ except Exception:
774
+ print(traceback.format_exc(), file=sys.stderr)
775
+ finally:
776
+ pbar.leave = False
777
+ pbar.close()
778
+ hypernetwork.eval()
779
+ #report_statistics(loss_dict)
780
+ sd_hijack_checkpoint.remove()
781
+
782
+
783
+
784
+ filename = os.path.join(shared.cmd_opts.hypernetwork_dir, f'{hypernetwork_name}.pt')
785
+ hypernetwork.optimizer_name = optimizer_name
786
+ if shared.opts.save_optimizer_state:
787
+ hypernetwork.optimizer_state_dict = optimizer.state_dict()
788
+ save_hypernetwork(hypernetwork, checkpoint, hypernetwork_name, filename)
789
+
790
+ del optimizer
791
+ hypernetwork.optimizer_state_dict = None # dereference it after saving, to save memory.
792
+ shared.sd_model.cond_stage_model.to(devices.device)
793
+ shared.sd_model.first_stage_model.to(devices.device)
794
+ shared.parallel_processing_allowed = old_parallel_processing_allowed
795
+
796
+ return hypernetwork, filename
797
+
798
+ def save_hypernetwork(hypernetwork, checkpoint, hypernetwork_name, filename):
799
+ old_hypernetwork_name = hypernetwork.name
800
+ old_sd_checkpoint = hypernetwork.sd_checkpoint if hasattr(hypernetwork, "sd_checkpoint") else None
801
+ old_sd_checkpoint_name = hypernetwork.sd_checkpoint_name if hasattr(hypernetwork, "sd_checkpoint_name") else None
802
+ try:
803
+ hypernetwork.sd_checkpoint = checkpoint.shorthash
804
+ hypernetwork.sd_checkpoint_name = checkpoint.model_name
805
+ hypernetwork.name = hypernetwork_name
806
+ hypernetwork.save(filename)
807
+ except:
808
+ hypernetwork.sd_checkpoint = old_sd_checkpoint
809
+ hypernetwork.sd_checkpoint_name = old_sd_checkpoint_name
810
+ hypernetwork.name = old_hypernetwork_name
811
+ raise
modules/hypernetworks/ui.py ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import html
2
+ import os
3
+ import re
4
+
5
+ import gradio as gr
6
+ import modules.hypernetworks.hypernetwork
7
+ from modules import devices, sd_hijack, shared
8
+
9
+ not_available = ["hardswish", "multiheadattention"]
10
+ keys = list(x for x in modules.hypernetworks.hypernetwork.HypernetworkModule.activation_dict.keys() if x not in not_available)
11
+
12
+
13
+ def create_hypernetwork(name, enable_sizes, overwrite_old, layer_structure=None, activation_func=None, weight_init=None, add_layer_norm=False, use_dropout=False, dropout_structure=None):
14
+ filename = modules.hypernetworks.hypernetwork.create_hypernetwork(name, enable_sizes, overwrite_old, layer_structure, activation_func, weight_init, add_layer_norm, use_dropout, dropout_structure)
15
+
16
+ return gr.Dropdown.update(choices=sorted([x for x in shared.hypernetworks.keys()])), f"Created: {filename}", ""
17
+
18
+
19
+ def train_hypernetwork(*args):
20
+ shared.loaded_hypernetworks = []
21
+
22
+ assert not shared.cmd_opts.lowvram, 'Training models with lowvram is not possible'
23
+
24
+ try:
25
+ sd_hijack.undo_optimizations()
26
+
27
+ hypernetwork, filename = modules.hypernetworks.hypernetwork.train_hypernetwork(*args)
28
+
29
+ res = f"""
30
+ Training {'interrupted' if shared.state.interrupted else 'finished'} at {hypernetwork.step} steps.
31
+ Hypernetwork saved to {html.escape(filename)}
32
+ """
33
+ return res, ""
34
+ except Exception:
35
+ raise
36
+ finally:
37
+ shared.sd_model.cond_stage_model.to(devices.device)
38
+ shared.sd_model.first_stage_model.to(devices.device)
39
+ sd_hijack.apply_optimizations()
40
+
modules/images.py ADDED
@@ -0,0 +1,669 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import datetime
2
+ import sys
3
+ import traceback
4
+
5
+ import pytz
6
+ import io
7
+ import math
8
+ import os
9
+ from collections import namedtuple
10
+ import re
11
+
12
+ import numpy as np
13
+ import piexif
14
+ import piexif.helper
15
+ from PIL import Image, ImageFont, ImageDraw, PngImagePlugin
16
+ from fonts.ttf import Roboto
17
+ import string
18
+ import json
19
+ import hashlib
20
+
21
+ from modules import sd_samplers, shared, script_callbacks, errors
22
+ from modules.shared import opts, cmd_opts
23
+
24
+ LANCZOS = (Image.Resampling.LANCZOS if hasattr(Image, 'Resampling') else Image.LANCZOS)
25
+
26
+
27
+ def image_grid(imgs, batch_size=1, rows=None):
28
+ if rows is None:
29
+ if opts.n_rows > 0:
30
+ rows = opts.n_rows
31
+ elif opts.n_rows == 0:
32
+ rows = batch_size
33
+ elif opts.grid_prevent_empty_spots:
34
+ rows = math.floor(math.sqrt(len(imgs)))
35
+ while len(imgs) % rows != 0:
36
+ rows -= 1
37
+ else:
38
+ rows = math.sqrt(len(imgs))
39
+ rows = round(rows)
40
+ if rows > len(imgs):
41
+ rows = len(imgs)
42
+
43
+ cols = math.ceil(len(imgs) / rows)
44
+
45
+ params = script_callbacks.ImageGridLoopParams(imgs, cols, rows)
46
+ script_callbacks.image_grid_callback(params)
47
+
48
+ w, h = imgs[0].size
49
+ grid = Image.new('RGB', size=(params.cols * w, params.rows * h), color='black')
50
+
51
+ for i, img in enumerate(params.imgs):
52
+ grid.paste(img, box=(i % params.cols * w, i // params.cols * h))
53
+
54
+ return grid
55
+
56
+
57
+ Grid = namedtuple("Grid", ["tiles", "tile_w", "tile_h", "image_w", "image_h", "overlap"])
58
+
59
+
60
+ def split_grid(image, tile_w=512, tile_h=512, overlap=64):
61
+ w = image.width
62
+ h = image.height
63
+
64
+ non_overlap_width = tile_w - overlap
65
+ non_overlap_height = tile_h - overlap
66
+
67
+ cols = math.ceil((w - overlap) / non_overlap_width)
68
+ rows = math.ceil((h - overlap) / non_overlap_height)
69
+
70
+ dx = (w - tile_w) / (cols - 1) if cols > 1 else 0
71
+ dy = (h - tile_h) / (rows - 1) if rows > 1 else 0
72
+
73
+ grid = Grid([], tile_w, tile_h, w, h, overlap)
74
+ for row in range(rows):
75
+ row_images = []
76
+
77
+ y = int(row * dy)
78
+
79
+ if y + tile_h >= h:
80
+ y = h - tile_h
81
+
82
+ for col in range(cols):
83
+ x = int(col * dx)
84
+
85
+ if x + tile_w >= w:
86
+ x = w - tile_w
87
+
88
+ tile = image.crop((x, y, x + tile_w, y + tile_h))
89
+
90
+ row_images.append([x, tile_w, tile])
91
+
92
+ grid.tiles.append([y, tile_h, row_images])
93
+
94
+ return grid
95
+
96
+
97
+ def combine_grid(grid):
98
+ def make_mask_image(r):
99
+ r = r * 255 / grid.overlap
100
+ r = r.astype(np.uint8)
101
+ return Image.fromarray(r, 'L')
102
+
103
+ mask_w = make_mask_image(np.arange(grid.overlap, dtype=np.float32).reshape((1, grid.overlap)).repeat(grid.tile_h, axis=0))
104
+ mask_h = make_mask_image(np.arange(grid.overlap, dtype=np.float32).reshape((grid.overlap, 1)).repeat(grid.image_w, axis=1))
105
+
106
+ combined_image = Image.new("RGB", (grid.image_w, grid.image_h))
107
+ for y, h, row in grid.tiles:
108
+ combined_row = Image.new("RGB", (grid.image_w, h))
109
+ for x, w, tile in row:
110
+ if x == 0:
111
+ combined_row.paste(tile, (0, 0))
112
+ continue
113
+
114
+ combined_row.paste(tile.crop((0, 0, grid.overlap, h)), (x, 0), mask=mask_w)
115
+ combined_row.paste(tile.crop((grid.overlap, 0, w, h)), (x + grid.overlap, 0))
116
+
117
+ if y == 0:
118
+ combined_image.paste(combined_row, (0, 0))
119
+ continue
120
+
121
+ combined_image.paste(combined_row.crop((0, 0, combined_row.width, grid.overlap)), (0, y), mask=mask_h)
122
+ combined_image.paste(combined_row.crop((0, grid.overlap, combined_row.width, h)), (0, y + grid.overlap))
123
+
124
+ return combined_image
125
+
126
+
127
+ class GridAnnotation:
128
+ def __init__(self, text='', is_active=True):
129
+ self.text = text
130
+ self.is_active = is_active
131
+ self.size = None
132
+
133
+
134
+ def draw_grid_annotations(im, width, height, hor_texts, ver_texts, margin=0):
135
+ def wrap(drawing, text, font, line_length):
136
+ lines = ['']
137
+ for word in text.split():
138
+ line = f'{lines[-1]} {word}'.strip()
139
+ if drawing.textlength(line, font=font) <= line_length:
140
+ lines[-1] = line
141
+ else:
142
+ lines.append(word)
143
+ return lines
144
+
145
+ def get_font(fontsize):
146
+ try:
147
+ return ImageFont.truetype(opts.font or Roboto, fontsize)
148
+ except Exception:
149
+ return ImageFont.truetype(Roboto, fontsize)
150
+
151
+ def draw_texts(drawing, draw_x, draw_y, lines, initial_fnt, initial_fontsize):
152
+ for i, line in enumerate(lines):
153
+ fnt = initial_fnt
154
+ fontsize = initial_fontsize
155
+ while drawing.multiline_textsize(line.text, font=fnt)[0] > line.allowed_width and fontsize > 0:
156
+ fontsize -= 1
157
+ fnt = get_font(fontsize)
158
+ drawing.multiline_text((draw_x, draw_y + line.size[1] / 2), line.text, font=fnt, fill=color_active if line.is_active else color_inactive, anchor="mm", align="center")
159
+
160
+ if not line.is_active:
161
+ drawing.line((draw_x - line.size[0] // 2, draw_y + line.size[1] // 2, draw_x + line.size[0] // 2, draw_y + line.size[1] // 2), fill=color_inactive, width=4)
162
+
163
+ draw_y += line.size[1] + line_spacing
164
+
165
+ fontsize = (width + height) // 25
166
+ line_spacing = fontsize // 2
167
+
168
+ fnt = get_font(fontsize)
169
+
170
+ color_active = (0, 0, 0)
171
+ color_inactive = (153, 153, 153)
172
+
173
+ pad_left = 0 if sum([sum([len(line.text) for line in lines]) for lines in ver_texts]) == 0 else width * 3 // 4
174
+
175
+ cols = im.width // width
176
+ rows = im.height // height
177
+
178
+ assert cols == len(hor_texts), f'bad number of horizontal texts: {len(hor_texts)}; must be {cols}'
179
+ assert rows == len(ver_texts), f'bad number of vertical texts: {len(ver_texts)}; must be {rows}'
180
+
181
+ calc_img = Image.new("RGB", (1, 1), "white")
182
+ calc_d = ImageDraw.Draw(calc_img)
183
+
184
+ for texts, allowed_width in zip(hor_texts + ver_texts, [width] * len(hor_texts) + [pad_left] * len(ver_texts)):
185
+ items = [] + texts
186
+ texts.clear()
187
+
188
+ for line in items:
189
+ wrapped = wrap(calc_d, line.text, fnt, allowed_width)
190
+ texts += [GridAnnotation(x, line.is_active) for x in wrapped]
191
+
192
+ for line in texts:
193
+ bbox = calc_d.multiline_textbbox((0, 0), line.text, font=fnt)
194
+ line.size = (bbox[2] - bbox[0], bbox[3] - bbox[1])
195
+ line.allowed_width = allowed_width
196
+
197
+ hor_text_heights = [sum([line.size[1] + line_spacing for line in lines]) - line_spacing for lines in hor_texts]
198
+ ver_text_heights = [sum([line.size[1] + line_spacing for line in lines]) - line_spacing * len(lines) for lines in ver_texts]
199
+
200
+ pad_top = 0 if sum(hor_text_heights) == 0 else max(hor_text_heights) + line_spacing * 2
201
+
202
+ result = Image.new("RGB", (im.width + pad_left + margin * (cols-1), im.height + pad_top + margin * (rows-1)), "white")
203
+
204
+ for row in range(rows):
205
+ for col in range(cols):
206
+ cell = im.crop((width * col, height * row, width * (col+1), height * (row+1)))
207
+ result.paste(cell, (pad_left + (width + margin) * col, pad_top + (height + margin) * row))
208
+
209
+ d = ImageDraw.Draw(result)
210
+
211
+ for col in range(cols):
212
+ x = pad_left + (width + margin) * col + width / 2
213
+ y = pad_top / 2 - hor_text_heights[col] / 2
214
+
215
+ draw_texts(d, x, y, hor_texts[col], fnt, fontsize)
216
+
217
+ for row in range(rows):
218
+ x = pad_left / 2
219
+ y = pad_top + (height + margin) * row + height / 2 - ver_text_heights[row] / 2
220
+
221
+ draw_texts(d, x, y, ver_texts[row], fnt, fontsize)
222
+
223
+ return result
224
+
225
+
226
+ def draw_prompt_matrix(im, width, height, all_prompts, margin=0):
227
+ prompts = all_prompts[1:]
228
+ boundary = math.ceil(len(prompts) / 2)
229
+
230
+ prompts_horiz = prompts[:boundary]
231
+ prompts_vert = prompts[boundary:]
232
+
233
+ hor_texts = [[GridAnnotation(x, is_active=pos & (1 << i) != 0) for i, x in enumerate(prompts_horiz)] for pos in range(1 << len(prompts_horiz))]
234
+ ver_texts = [[GridAnnotation(x, is_active=pos & (1 << i) != 0) for i, x in enumerate(prompts_vert)] for pos in range(1 << len(prompts_vert))]
235
+
236
+ return draw_grid_annotations(im, width, height, hor_texts, ver_texts, margin)
237
+
238
+
239
+ def resize_image(resize_mode, im, width, height, upscaler_name=None):
240
+ """
241
+ Resizes an image with the specified resize_mode, width, and height.
242
+
243
+ Args:
244
+ resize_mode: The mode to use when resizing the image.
245
+ 0: Resize the image to the specified width and height.
246
+ 1: Resize the image to fill the specified width and height, maintaining the aspect ratio, and then center the image within the dimensions, cropping the excess.
247
+ 2: Resize the image to fit within the specified width and height, maintaining the aspect ratio, and then center the image within the dimensions, filling empty with data from image.
248
+ im: The image to resize.
249
+ width: The width to resize the image to.
250
+ height: The height to resize the image to.
251
+ upscaler_name: The name of the upscaler to use. If not provided, defaults to opts.upscaler_for_img2img.
252
+ """
253
+
254
+ upscaler_name = upscaler_name or opts.upscaler_for_img2img
255
+
256
+ def resize(im, w, h):
257
+ if upscaler_name is None or upscaler_name == "None" or im.mode == 'L':
258
+ return im.resize((w, h), resample=LANCZOS)
259
+
260
+ scale = max(w / im.width, h / im.height)
261
+
262
+ if scale > 1.0:
263
+ upscalers = [x for x in shared.sd_upscalers if x.name == upscaler_name]
264
+ assert len(upscalers) > 0, f"could not find upscaler named {upscaler_name}"
265
+
266
+ upscaler = upscalers[0]
267
+ im = upscaler.scaler.upscale(im, scale, upscaler.data_path)
268
+
269
+ if im.width != w or im.height != h:
270
+ im = im.resize((w, h), resample=LANCZOS)
271
+
272
+ return im
273
+
274
+ if resize_mode == 0:
275
+ res = resize(im, width, height)
276
+
277
+ elif resize_mode == 1:
278
+ ratio = width / height
279
+ src_ratio = im.width / im.height
280
+
281
+ src_w = width if ratio > src_ratio else im.width * height // im.height
282
+ src_h = height if ratio <= src_ratio else im.height * width // im.width
283
+
284
+ resized = resize(im, src_w, src_h)
285
+ res = Image.new("RGB", (width, height))
286
+ res.paste(resized, box=(width // 2 - src_w // 2, height // 2 - src_h // 2))
287
+
288
+ else:
289
+ ratio = width / height
290
+ src_ratio = im.width / im.height
291
+
292
+ src_w = width if ratio < src_ratio else im.width * height // im.height
293
+ src_h = height if ratio >= src_ratio else im.height * width // im.width
294
+
295
+ resized = resize(im, src_w, src_h)
296
+ res = Image.new("RGB", (width, height))
297
+ res.paste(resized, box=(width // 2 - src_w // 2, height // 2 - src_h // 2))
298
+
299
+ if ratio < src_ratio:
300
+ fill_height = height // 2 - src_h // 2
301
+ res.paste(resized.resize((width, fill_height), box=(0, 0, width, 0)), box=(0, 0))
302
+ res.paste(resized.resize((width, fill_height), box=(0, resized.height, width, resized.height)), box=(0, fill_height + src_h))
303
+ elif ratio > src_ratio:
304
+ fill_width = width // 2 - src_w // 2
305
+ res.paste(resized.resize((fill_width, height), box=(0, 0, 0, height)), box=(0, 0))
306
+ res.paste(resized.resize((fill_width, height), box=(resized.width, 0, resized.width, height)), box=(fill_width + src_w, 0))
307
+
308
+ return res
309
+
310
+
311
+ invalid_filename_chars = '<>:"/\\|?*\n'
312
+ invalid_filename_prefix = ' '
313
+ invalid_filename_postfix = ' .'
314
+ re_nonletters = re.compile(r'[\s' + string.punctuation + ']+')
315
+ re_pattern = re.compile(r"(.*?)(?:\[([^\[\]]+)\]|$)")
316
+ re_pattern_arg = re.compile(r"(.*)<([^>]*)>$")
317
+ max_filename_part_length = 128
318
+
319
+
320
+ def sanitize_filename_part(text, replace_spaces=True):
321
+ if text is None:
322
+ return None
323
+
324
+ if replace_spaces:
325
+ text = text.replace(' ', '_')
326
+
327
+ text = text.translate({ord(x): '_' for x in invalid_filename_chars})
328
+ text = text.lstrip(invalid_filename_prefix)[:max_filename_part_length]
329
+ text = text.rstrip(invalid_filename_postfix)
330
+ return text
331
+
332
+
333
+ class FilenameGenerator:
334
+ replacements = {
335
+ 'seed': lambda self: self.seed if self.seed is not None else '',
336
+ 'steps': lambda self: self.p and self.p.steps,
337
+ 'cfg': lambda self: self.p and self.p.cfg_scale,
338
+ 'width': lambda self: self.image.width,
339
+ 'height': lambda self: self.image.height,
340
+ 'styles': lambda self: self.p and sanitize_filename_part(", ".join([style for style in self.p.styles if not style == "None"]) or "None", replace_spaces=False),
341
+ 'sampler': lambda self: self.p and sanitize_filename_part(self.p.sampler_name, replace_spaces=False),
342
+ 'model_hash': lambda self: getattr(self.p, "sd_model_hash", shared.sd_model.sd_model_hash),
343
+ 'model_name': lambda self: sanitize_filename_part(shared.sd_model.sd_checkpoint_info.model_name, replace_spaces=False),
344
+ 'date': lambda self: datetime.datetime.now().strftime('%Y-%m-%d'),
345
+ 'datetime': lambda self, *args: self.datetime(*args), # accepts formats: [datetime], [datetime<Format>], [datetime<Format><Time Zone>]
346
+ 'job_timestamp': lambda self: getattr(self.p, "job_timestamp", shared.state.job_timestamp),
347
+ 'prompt_hash': lambda self: hashlib.sha256(self.prompt.encode()).hexdigest()[0:8],
348
+ 'prompt': lambda self: sanitize_filename_part(self.prompt),
349
+ 'prompt_no_styles': lambda self: self.prompt_no_style(),
350
+ 'prompt_spaces': lambda self: sanitize_filename_part(self.prompt, replace_spaces=False),
351
+ 'prompt_words': lambda self: self.prompt_words(),
352
+ }
353
+ default_time_format = '%Y%m%d%H%M%S'
354
+
355
+ def __init__(self, p, seed, prompt, image):
356
+ self.p = p
357
+ self.seed = seed
358
+ self.prompt = prompt
359
+ self.image = image
360
+
361
+ def prompt_no_style(self):
362
+ if self.p is None or self.prompt is None:
363
+ return None
364
+
365
+ prompt_no_style = self.prompt
366
+ for style in shared.prompt_styles.get_style_prompts(self.p.styles):
367
+ if len(style) > 0:
368
+ for part in style.split("{prompt}"):
369
+ prompt_no_style = prompt_no_style.replace(part, "").replace(", ,", ",").strip().strip(',')
370
+
371
+ prompt_no_style = prompt_no_style.replace(style, "").strip().strip(',').strip()
372
+
373
+ return sanitize_filename_part(prompt_no_style, replace_spaces=False)
374
+
375
+ def prompt_words(self):
376
+ words = [x for x in re_nonletters.split(self.prompt or "") if len(x) > 0]
377
+ if len(words) == 0:
378
+ words = ["empty"]
379
+ return sanitize_filename_part(" ".join(words[0:opts.directories_max_prompt_words]), replace_spaces=False)
380
+
381
+ def datetime(self, *args):
382
+ time_datetime = datetime.datetime.now()
383
+
384
+ time_format = args[0] if len(args) > 0 and args[0] != "" else self.default_time_format
385
+ try:
386
+ time_zone = pytz.timezone(args[1]) if len(args) > 1 else None
387
+ except pytz.exceptions.UnknownTimeZoneError as _:
388
+ time_zone = None
389
+
390
+ time_zone_time = time_datetime.astimezone(time_zone)
391
+ try:
392
+ formatted_time = time_zone_time.strftime(time_format)
393
+ except (ValueError, TypeError) as _:
394
+ formatted_time = time_zone_time.strftime(self.default_time_format)
395
+
396
+ return sanitize_filename_part(formatted_time, replace_spaces=False)
397
+
398
+ def apply(self, x):
399
+ res = ''
400
+
401
+ for m in re_pattern.finditer(x):
402
+ text, pattern = m.groups()
403
+ res += text
404
+
405
+ if pattern is None:
406
+ continue
407
+
408
+ pattern_args = []
409
+ while True:
410
+ m = re_pattern_arg.match(pattern)
411
+ if m is None:
412
+ break
413
+
414
+ pattern, arg = m.groups()
415
+ pattern_args.insert(0, arg)
416
+
417
+ fun = self.replacements.get(pattern.lower())
418
+ if fun is not None:
419
+ try:
420
+ replacement = fun(self, *pattern_args)
421
+ except Exception:
422
+ replacement = None
423
+ print(f"Error adding [{pattern}] to filename", file=sys.stderr)
424
+ print(traceback.format_exc(), file=sys.stderr)
425
+
426
+ if replacement is not None:
427
+ res += str(replacement)
428
+ continue
429
+
430
+ res += f'[{pattern}]'
431
+
432
+ return res
433
+
434
+
435
+ def get_next_sequence_number(path, basename):
436
+ """
437
+ Determines and returns the next sequence number to use when saving an image in the specified directory.
438
+
439
+ The sequence starts at 0.
440
+ """
441
+ result = -1
442
+ if basename != '':
443
+ basename = basename + "-"
444
+
445
+ prefix_length = len(basename)
446
+ for p in os.listdir(path):
447
+ if p.startswith(basename):
448
+ l = os.path.splitext(p[prefix_length:])[0].split('-') # splits the filename (removing the basename first if one is defined, so the sequence number is always the first element)
449
+ try:
450
+ result = max(int(l[0]), result)
451
+ except ValueError:
452
+ pass
453
+
454
+ return result + 1
455
+
456
+
457
+ def save_image(image, path, basename, seed=None, prompt=None, extension='png', info=None, short_filename=False, no_prompt=False, grid=False, pnginfo_section_name='parameters', p=None, existing_info=None, forced_filename=None, suffix="", save_to_dirs=None):
458
+ """Save an image.
459
+
460
+ Args:
461
+ image (`PIL.Image`):
462
+ The image to be saved.
463
+ path (`str`):
464
+ The directory to save the image. Note, the option `save_to_dirs` will make the image to be saved into a sub directory.
465
+ basename (`str`):
466
+ The base filename which will be applied to `filename pattern`.
467
+ seed, prompt, short_filename,
468
+ extension (`str`):
469
+ Image file extension, default is `png`.
470
+ pngsectionname (`str`):
471
+ Specify the name of the section which `info` will be saved in.
472
+ info (`str` or `PngImagePlugin.iTXt`):
473
+ PNG info chunks.
474
+ existing_info (`dict`):
475
+ Additional PNG info. `existing_info == {pngsectionname: info, ...}`
476
+ no_prompt:
477
+ TODO I don't know its meaning.
478
+ p (`StableDiffusionProcessing`)
479
+ forced_filename (`str`):
480
+ If specified, `basename` and filename pattern will be ignored.
481
+ save_to_dirs (bool):
482
+ If true, the image will be saved into a subdirectory of `path`.
483
+
484
+ Returns: (fullfn, txt_fullfn)
485
+ fullfn (`str`):
486
+ The full path of the saved imaged.
487
+ txt_fullfn (`str` or None):
488
+ If a text file is saved for this image, this will be its full path. Otherwise None.
489
+ """
490
+ namegen = FilenameGenerator(p, seed, prompt, image)
491
+
492
+ if save_to_dirs is None:
493
+ save_to_dirs = (grid and opts.grid_save_to_dirs) or (not grid and opts.save_to_dirs and not no_prompt)
494
+
495
+ if save_to_dirs:
496
+ dirname = namegen.apply(opts.directories_filename_pattern or "[prompt_words]").lstrip(' ').rstrip('\\ /')
497
+ path = os.path.join(path, dirname)
498
+
499
+ os.makedirs(path, exist_ok=True)
500
+
501
+ if forced_filename is None:
502
+ if short_filename or seed is None:
503
+ file_decoration = ""
504
+ elif opts.save_to_dirs:
505
+ file_decoration = opts.samples_filename_pattern or "[seed]"
506
+ else:
507
+ file_decoration = opts.samples_filename_pattern or "[seed]-[prompt_spaces]"
508
+
509
+ add_number = opts.save_images_add_number or file_decoration == ''
510
+
511
+ if file_decoration != "" and add_number:
512
+ file_decoration = "-" + file_decoration
513
+
514
+ file_decoration = namegen.apply(file_decoration) + suffix
515
+
516
+ if add_number:
517
+ basecount = get_next_sequence_number(path, basename)
518
+ fullfn = None
519
+ for i in range(500):
520
+ fn = f"{basecount + i:05}" if basename == '' else f"{basename}-{basecount + i:04}"
521
+ fullfn = os.path.join(path, f"{fn}{file_decoration}.{extension}")
522
+ if not os.path.exists(fullfn):
523
+ break
524
+ else:
525
+ fullfn = os.path.join(path, f"{file_decoration}.{extension}")
526
+ else:
527
+ fullfn = os.path.join(path, f"{forced_filename}.{extension}")
528
+
529
+ pnginfo = existing_info or {}
530
+ if info is not None:
531
+ pnginfo[pnginfo_section_name] = info
532
+
533
+ params = script_callbacks.ImageSaveParams(image, p, fullfn, pnginfo)
534
+ script_callbacks.before_image_saved_callback(params)
535
+
536
+ image = params.image
537
+ fullfn = params.filename
538
+ info = params.pnginfo.get(pnginfo_section_name, None)
539
+
540
+ def _atomically_save_image(image_to_save, filename_without_extension, extension):
541
+ # save image with .tmp extension to avoid race condition when another process detects new image in the directory
542
+ temp_file_path = filename_without_extension + ".tmp"
543
+ image_format = Image.registered_extensions()[extension]
544
+
545
+ if extension.lower() == '.png':
546
+ pnginfo_data = PngImagePlugin.PngInfo()
547
+ if opts.enable_pnginfo:
548
+ for k, v in params.pnginfo.items():
549
+ pnginfo_data.add_text(k, str(v))
550
+
551
+ image_to_save.save(temp_file_path, format=image_format, quality=opts.jpeg_quality, pnginfo=pnginfo_data)
552
+
553
+ elif extension.lower() in (".jpg", ".jpeg", ".webp"):
554
+ if image_to_save.mode == 'RGBA':
555
+ image_to_save = image_to_save.convert("RGB")
556
+ elif image_to_save.mode == 'I;16':
557
+ image_to_save = image_to_save.point(lambda p: p * 0.0038910505836576).convert("RGB" if extension.lower() == ".webp" else "L")
558
+
559
+ image_to_save.save(temp_file_path, format=image_format, quality=opts.jpeg_quality)
560
+
561
+ if opts.enable_pnginfo and info is not None:
562
+ exif_bytes = piexif.dump({
563
+ "Exif": {
564
+ piexif.ExifIFD.UserComment: piexif.helper.UserComment.dump(info or "", encoding="unicode")
565
+ },
566
+ })
567
+
568
+ piexif.insert(exif_bytes, temp_file_path)
569
+ else:
570
+ image_to_save.save(temp_file_path, format=image_format, quality=opts.jpeg_quality)
571
+
572
+ # atomically rename the file with correct extension
573
+ os.replace(temp_file_path, filename_without_extension + extension)
574
+
575
+ fullfn_without_extension, extension = os.path.splitext(params.filename)
576
+ _atomically_save_image(image, fullfn_without_extension, extension)
577
+
578
+ image.already_saved_as = fullfn
579
+
580
+ oversize = image.width > opts.target_side_length or image.height > opts.target_side_length
581
+ if opts.export_for_4chan and (oversize or os.stat(fullfn).st_size > opts.img_downscale_threshold * 1024 * 1024):
582
+ ratio = image.width / image.height
583
+
584
+ if oversize and ratio > 1:
585
+ image = image.resize((round(opts.target_side_length), round(image.height * opts.target_side_length / image.width)), LANCZOS)
586
+ elif oversize:
587
+ image = image.resize((round(image.width * opts.target_side_length / image.height), round(opts.target_side_length)), LANCZOS)
588
+
589
+ try:
590
+ _atomically_save_image(image, fullfn_without_extension, ".jpg")
591
+ except Exception as e:
592
+ errors.display(e, "saving image as downscaled JPG")
593
+
594
+ if opts.save_txt and info is not None:
595
+ txt_fullfn = f"{fullfn_without_extension}.txt"
596
+ with open(txt_fullfn, "w", encoding="utf8") as file:
597
+ file.write(info + "\n")
598
+ else:
599
+ txt_fullfn = None
600
+
601
+ script_callbacks.image_saved_callback(params)
602
+
603
+ return fullfn, txt_fullfn
604
+
605
+
606
+ def read_info_from_image(image):
607
+ items = image.info or {}
608
+
609
+ geninfo = items.pop('parameters', None)
610
+
611
+ if "exif" in items:
612
+ exif = piexif.load(items["exif"])
613
+ exif_comment = (exif or {}).get("Exif", {}).get(piexif.ExifIFD.UserComment, b'')
614
+ try:
615
+ exif_comment = piexif.helper.UserComment.load(exif_comment)
616
+ except ValueError:
617
+ exif_comment = exif_comment.decode('utf8', errors="ignore")
618
+
619
+ if exif_comment:
620
+ items['exif comment'] = exif_comment
621
+ geninfo = exif_comment
622
+
623
+ for field in ['jfif', 'jfif_version', 'jfif_unit', 'jfif_density', 'dpi', 'exif',
624
+ 'loop', 'background', 'timestamp', 'duration']:
625
+ items.pop(field, None)
626
+
627
+ if items.get("Software", None) == "NovelAI":
628
+ try:
629
+ json_info = json.loads(items["Comment"])
630
+ sampler = sd_samplers.samplers_map.get(json_info["sampler"], "Euler a")
631
+
632
+ geninfo = f"""{items["Description"]}
633
+ Negative prompt: {json_info["uc"]}
634
+ Steps: {json_info["steps"]}, Sampler: {sampler}, CFG scale: {json_info["scale"]}, Seed: {json_info["seed"]}, Size: {image.width}x{image.height}, Clip skip: 2, ENSD: 31337"""
635
+ except Exception:
636
+ print("Error parsing NovelAI image generation parameters:", file=sys.stderr)
637
+ print(traceback.format_exc(), file=sys.stderr)
638
+
639
+ return geninfo, items
640
+
641
+
642
+ def image_data(data):
643
+ try:
644
+ image = Image.open(io.BytesIO(data))
645
+ textinfo, _ = read_info_from_image(image)
646
+ return textinfo, None
647
+ except Exception:
648
+ pass
649
+
650
+ try:
651
+ text = data.decode('utf8')
652
+ assert len(text) < 10000
653
+ return text, None
654
+
655
+ except Exception:
656
+ pass
657
+
658
+ return '', None
659
+
660
+
661
+ def flatten(img, bgcolor):
662
+ """replaces transparency with bgcolor (example: "#ffffff"), returning an RGB mode image with no transparency"""
663
+
664
+ if img.mode == "RGBA":
665
+ background = Image.new('RGBA', img.size, bgcolor)
666
+ background.paste(img, mask=img)
667
+ img = background
668
+
669
+ return img.convert('RGB')
modules/img2img.py ADDED
@@ -0,0 +1,184 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import math
2
+ import os
3
+ import sys
4
+ import traceback
5
+
6
+ import numpy as np
7
+ from PIL import Image, ImageOps, ImageFilter, ImageEnhance, ImageChops
8
+
9
+ from modules import devices, sd_samplers
10
+ from modules.generation_parameters_copypaste import create_override_settings_dict
11
+ from modules.processing import Processed, StableDiffusionProcessingImg2Img, process_images
12
+ from modules.shared import opts, state
13
+ import modules.shared as shared
14
+ import modules.processing as processing
15
+ from modules.ui import plaintext_to_html
16
+ import modules.images as images
17
+ import modules.scripts
18
+
19
+
20
+ def process_batch(p, input_dir, output_dir, inpaint_mask_dir, args):
21
+ processing.fix_seed(p)
22
+
23
+ images = shared.listfiles(input_dir)
24
+
25
+ is_inpaint_batch = False
26
+ if inpaint_mask_dir:
27
+ inpaint_masks = shared.listfiles(inpaint_mask_dir)
28
+ is_inpaint_batch = len(inpaint_masks) > 0
29
+ if is_inpaint_batch:
30
+ print(f"\nInpaint batch is enabled. {len(inpaint_masks)} masks found.")
31
+
32
+ print(f"Will process {len(images)} images, creating {p.n_iter * p.batch_size} new images for each.")
33
+
34
+ save_normally = output_dir == ''
35
+
36
+ p.do_not_save_grid = True
37
+ p.do_not_save_samples = not save_normally
38
+
39
+ state.job_count = len(images) * p.n_iter
40
+
41
+ for i, image in enumerate(images):
42
+ state.job = f"{i+1} out of {len(images)}"
43
+ if state.skipped:
44
+ state.skipped = False
45
+
46
+ if state.interrupted:
47
+ break
48
+
49
+ img = Image.open(image)
50
+ # Use the EXIF orientation of photos taken by smartphones.
51
+ img = ImageOps.exif_transpose(img)
52
+ p.init_images = [img] * p.batch_size
53
+
54
+ if is_inpaint_batch:
55
+ # try to find corresponding mask for an image using simple filename matching
56
+ mask_image_path = os.path.join(inpaint_mask_dir, os.path.basename(image))
57
+ # if not found use first one ("same mask for all images" use-case)
58
+ if not mask_image_path in inpaint_masks:
59
+ mask_image_path = inpaint_masks[0]
60
+ mask_image = Image.open(mask_image_path)
61
+ p.image_mask = mask_image
62
+
63
+ proc = modules.scripts.scripts_img2img.run(p, *args)
64
+ if proc is None:
65
+ proc = process_images(p)
66
+
67
+ for n, processed_image in enumerate(proc.images):
68
+ filename = os.path.basename(image)
69
+
70
+ if n > 0:
71
+ left, right = os.path.splitext(filename)
72
+ filename = f"{left}-{n}{right}"
73
+
74
+ if not save_normally:
75
+ os.makedirs(output_dir, exist_ok=True)
76
+ if processed_image.mode == 'RGBA':
77
+ processed_image = processed_image.convert("RGB")
78
+ processed_image.save(os.path.join(output_dir, filename))
79
+
80
+
81
+ def img2img(id_task: str, mode: int, prompt: str, negative_prompt: str, prompt_styles, init_img, sketch, init_img_with_mask, inpaint_color_sketch, inpaint_color_sketch_orig, init_img_inpaint, init_mask_inpaint, steps: int, sampler_index: int, mask_blur: int, mask_alpha: float, inpainting_fill: int, restore_faces: bool, tiling: bool, n_iter: int, batch_size: int, cfg_scale: float, image_cfg_scale: float, denoising_strength: float, seed: int, subseed: int, subseed_strength: float, seed_resize_from_h: int, seed_resize_from_w: int, seed_enable_extras: bool, height: int, width: int, resize_mode: int, inpaint_full_res: bool, inpaint_full_res_padding: int, inpainting_mask_invert: int, img2img_batch_input_dir: str, img2img_batch_output_dir: str, img2img_batch_inpaint_mask_dir: str, override_settings_texts, *args):
82
+ override_settings = create_override_settings_dict(override_settings_texts)
83
+
84
+ is_batch = mode == 5
85
+
86
+ if mode == 0: # img2img
87
+ image = init_img.convert("RGB")
88
+ mask = None
89
+ elif mode == 1: # img2img sketch
90
+ image = sketch.convert("RGB")
91
+ mask = None
92
+ elif mode == 2: # inpaint
93
+ image, mask = init_img_with_mask["image"], init_img_with_mask["mask"]
94
+ alpha_mask = ImageOps.invert(image.split()[-1]).convert('L').point(lambda x: 255 if x > 0 else 0, mode='1')
95
+ mask = ImageChops.lighter(alpha_mask, mask.convert('L')).convert('L')
96
+ image = image.convert("RGB")
97
+ elif mode == 3: # inpaint sketch
98
+ image = inpaint_color_sketch
99
+ orig = inpaint_color_sketch_orig or inpaint_color_sketch
100
+ pred = np.any(np.array(image) != np.array(orig), axis=-1)
101
+ mask = Image.fromarray(pred.astype(np.uint8) * 255, "L")
102
+ mask = ImageEnhance.Brightness(mask).enhance(1 - mask_alpha / 100)
103
+ blur = ImageFilter.GaussianBlur(mask_blur)
104
+ image = Image.composite(image.filter(blur), orig, mask.filter(blur))
105
+ image = image.convert("RGB")
106
+ elif mode == 4: # inpaint upload mask
107
+ image = init_img_inpaint
108
+ mask = init_mask_inpaint
109
+ else:
110
+ image = None
111
+ mask = None
112
+
113
+ # Use the EXIF orientation of photos taken by smartphones.
114
+ if image is not None:
115
+ image = ImageOps.exif_transpose(image)
116
+
117
+ assert 0. <= denoising_strength <= 1., 'can only work with strength in [0.0, 1.0]'
118
+
119
+ p = StableDiffusionProcessingImg2Img(
120
+ sd_model=shared.sd_model,
121
+ outpath_samples=opts.outdir_samples or opts.outdir_img2img_samples,
122
+ outpath_grids=opts.outdir_grids or opts.outdir_img2img_grids,
123
+ prompt=prompt,
124
+ negative_prompt=negative_prompt,
125
+ styles=prompt_styles,
126
+ seed=seed,
127
+ subseed=subseed,
128
+ subseed_strength=subseed_strength,
129
+ seed_resize_from_h=seed_resize_from_h,
130
+ seed_resize_from_w=seed_resize_from_w,
131
+ seed_enable_extras=seed_enable_extras,
132
+ sampler_name=sd_samplers.samplers_for_img2img[sampler_index].name,
133
+ batch_size=batch_size,
134
+ n_iter=n_iter,
135
+ steps=steps,
136
+ cfg_scale=cfg_scale,
137
+ width=width,
138
+ height=height,
139
+ restore_faces=restore_faces,
140
+ tiling=tiling,
141
+ init_images=[image],
142
+ mask=mask,
143
+ mask_blur=mask_blur,
144
+ inpainting_fill=inpainting_fill,
145
+ resize_mode=resize_mode,
146
+ denoising_strength=denoising_strength,
147
+ image_cfg_scale=image_cfg_scale,
148
+ inpaint_full_res=inpaint_full_res,
149
+ inpaint_full_res_padding=inpaint_full_res_padding,
150
+ inpainting_mask_invert=inpainting_mask_invert,
151
+ override_settings=override_settings,
152
+ )
153
+
154
+ p.scripts = modules.scripts.scripts_txt2img
155
+ p.script_args = args
156
+
157
+ if shared.cmd_opts.enable_console_prompts:
158
+ print(f"\nimg2img: {prompt}", file=shared.progress_print_out)
159
+
160
+ p.extra_generation_params["Mask blur"] = mask_blur
161
+
162
+ if is_batch:
163
+ assert not shared.cmd_opts.hide_ui_dir_config, "Launched with --hide-ui-dir-config, batch img2img disabled"
164
+
165
+ process_batch(p, img2img_batch_input_dir, img2img_batch_output_dir, img2img_batch_inpaint_mask_dir, args)
166
+
167
+ processed = Processed(p, [], p.seed, "")
168
+ else:
169
+ processed = modules.scripts.scripts_img2img.run(p, *args)
170
+ if processed is None:
171
+ processed = process_images(p)
172
+
173
+ p.close()
174
+
175
+ shared.total_tqdm.clear()
176
+
177
+ generation_info_js = processed.js()
178
+ if opts.samples_log_stdout:
179
+ print(generation_info_js)
180
+
181
+ if opts.do_not_show_images:
182
+ processed.images = []
183
+
184
+ return processed.images, generation_info_js, plaintext_to_html(processed.info), plaintext_to_html(processed.comments)