dikdimon commited on
Commit
3dabe4a
·
verified ·
1 Parent(s): c66d83d

Upload extensions using SD-Hub extension

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .gitattributes +54 -0
  2. extensions/1-sd-dynamic-thresholding/.github/FUNDING.yml +1 -0
  3. extensions/1-sd-dynamic-thresholding/.github/workflows/publish.yml +21 -0
  4. extensions/1-sd-dynamic-thresholding/.gitignore +1 -0
  5. extensions/1-sd-dynamic-thresholding/LICENSE.txt +21 -0
  6. extensions/1-sd-dynamic-thresholding/README.md +120 -0
  7. extensions/1-sd-dynamic-thresholding/__init__.py +6 -0
  8. extensions/1-sd-dynamic-thresholding/__pycache__/dynthres_core.cpython-310.pyc +0 -0
  9. extensions/1-sd-dynamic-thresholding/__pycache__/dynthres_unipc.cpython-310.pyc +0 -0
  10. extensions/1-sd-dynamic-thresholding/dynthres_comfyui.py +86 -0
  11. extensions/1-sd-dynamic-thresholding/dynthres_core.py +167 -0
  12. extensions/1-sd-dynamic-thresholding/dynthres_unipc.py +111 -0
  13. extensions/1-sd-dynamic-thresholding/github/cat_demo_1.jpg +0 -0
  14. extensions/1-sd-dynamic-thresholding/github/comfy_node.png +0 -0
  15. extensions/1-sd-dynamic-thresholding/github/grid_preview.png +0 -0
  16. extensions/1-sd-dynamic-thresholding/github/ui.png +0 -0
  17. extensions/1-sd-dynamic-thresholding/javascript/active.js +68 -0
  18. extensions/1-sd-dynamic-thresholding/pyproject.toml +13 -0
  19. extensions/1-sd-dynamic-thresholding/scripts/__pycache__/dynamic_thresholding.cpython-310.pyc +0 -0
  20. extensions/1-sd-dynamic-thresholding/scripts/dynamic_thresholding.py +270 -0
  21. extensions/4-adetailer/.github/ISSUE_TEMPLATE/bug_report.yaml +63 -0
  22. extensions/4-adetailer/.github/ISSUE_TEMPLATE/feature_request.yaml +26 -0
  23. extensions/4-adetailer/.github/workflows/lgtm.yml +23 -0
  24. extensions/4-adetailer/.github/workflows/pypi.yml +49 -0
  25. extensions/4-adetailer/.github/workflows/stale.yml +13 -0
  26. extensions/4-adetailer/.gitignore +197 -0
  27. extensions/4-adetailer/.pre-commit-config.yaml +29 -0
  28. extensions/4-adetailer/.vscode/extensions.json +9 -0
  29. extensions/4-adetailer/.vscode/settings.json +8 -0
  30. extensions/4-adetailer/CHANGELOG.md +472 -0
  31. extensions/4-adetailer/LICENSE.md +661 -0
  32. extensions/4-adetailer/README.md +118 -0
  33. extensions/4-adetailer/Taskfile.yml +32 -0
  34. extensions/4-adetailer/__pycache__/preload.cpython-310.pyc +0 -0
  35. extensions/4-adetailer/aaaaaa/__init__.py +0 -0
  36. extensions/4-adetailer/aaaaaa/__pycache__/__init__.cpython-310.pyc +0 -0
  37. extensions/4-adetailer/aaaaaa/__pycache__/conditional.cpython-310.pyc +0 -0
  38. extensions/4-adetailer/aaaaaa/__pycache__/helper.cpython-310.pyc +0 -0
  39. extensions/4-adetailer/aaaaaa/__pycache__/p_method.cpython-310.pyc +0 -0
  40. extensions/4-adetailer/aaaaaa/__pycache__/traceback.cpython-310.pyc +0 -0
  41. extensions/4-adetailer/aaaaaa/__pycache__/ui.cpython-310.pyc +0 -0
  42. extensions/4-adetailer/aaaaaa/conditional.py +21 -0
  43. extensions/4-adetailer/aaaaaa/helper.py +59 -0
  44. extensions/4-adetailer/aaaaaa/p_method.py +34 -0
  45. extensions/4-adetailer/aaaaaa/traceback.py +175 -0
  46. extensions/4-adetailer/aaaaaa/ui.py +710 -0
  47. extensions/4-adetailer/adetailer/__init__.py +18 -0
  48. extensions/4-adetailer/adetailer/__pycache__/__init__.cpython-310.pyc +0 -0
  49. extensions/4-adetailer/adetailer/__pycache__/__version__.cpython-310.pyc +0 -0
  50. extensions/4-adetailer/adetailer/__pycache__/args.cpython-310.pyc +0 -0
.gitattributes CHANGED
@@ -33,3 +33,57 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ extensions/CHECK/sd-webui-agentattention/samples/xyz_grid-2415-1-desk.png filter=lfs diff=lfs merge=lfs -text
37
+ extensions/CHECK/sd-webui-agentattention/samples/xyz_grid-2417-1-goldfinch,[[:space:]]Carduelis[[:space:]]carduelis.png filter=lfs diff=lfs merge=lfs -text
38
+ extensions/CHECK/sd-webui-agentattention/samples/xyz_grid-2418-1-bell[[:space:]]pepper.png filter=lfs diff=lfs merge=lfs -text
39
+ extensions/CHECK/sd-webui-agentattention/samples/xyz_grid-2419-1-bicycle.png filter=lfs diff=lfs merge=lfs -text
40
+ extensions/CHECK/sd-webui-agentattention/samples/xyz_grid-2428-1-desk.jpg filter=lfs diff=lfs merge=lfs -text
41
+ extensions/CHECK/sd-webui-cutoff/images/cover.jpg filter=lfs diff=lfs merge=lfs -text
42
+ extensions/CHECK/sd-webui-cutoff/images/sample-1.png filter=lfs diff=lfs merge=lfs -text
43
+ extensions/CHECK/sd-webui-cutoff/images/sample-2.png filter=lfs diff=lfs merge=lfs -text
44
+ extensions/CHECK/sd-webui-cutoff/images/sample-3.png filter=lfs diff=lfs merge=lfs -text
45
+ extensions/CHECK/sd-webui-cutoff/images/sample-4.png filter=lfs diff=lfs merge=lfs -text
46
+ extensions/CHECK/sd-webui-cutoff/images/sample-4_small.png filter=lfs diff=lfs merge=lfs -text
47
+ extensions/CHECK/sd-webui-cutoff/images/sample-5.png filter=lfs diff=lfs merge=lfs -text
48
+ extensions/CHECK/sd-webui-cutoff/images/sample-5_small.png filter=lfs diff=lfs merge=lfs -text
49
+ extensions/CHECK/sd-webui-fabric/static/example_2_default.png filter=lfs diff=lfs merge=lfs -text
50
+ extensions/CHECK/sd-webui-fabric/static/example_2_feedback.png filter=lfs diff=lfs merge=lfs -text
51
+ extensions/CHECK/sd-webui-fabric/static/example_3_10.png filter=lfs diff=lfs merge=lfs -text
52
+ extensions/CHECK/sd-webui-fabric/static/example_3_feedback.png filter=lfs diff=lfs merge=lfs -text
53
+ extensions/CHECK/sd-webui-fabric/static/fabric_demo.gif filter=lfs diff=lfs merge=lfs -text
54
+ extensions/CHECK/sd-webui-llul/images/llul_yuv420p.mp4 filter=lfs diff=lfs merge=lfs -text
55
+ extensions/CHECK/sd-webui-llul/images/mask_effect.jpg filter=lfs diff=lfs merge=lfs -text
56
+ extensions/diffusion-noise-alternatives-webui/images/ColorGrade.png filter=lfs diff=lfs merge=lfs -text
57
+ extensions/diffusion-noise-alternatives-webui/images/GrainCompare.png filter=lfs diff=lfs merge=lfs -text
58
+ extensions/sd-civitai-browser-plus/aria2/lin/aria2 filter=lfs diff=lfs merge=lfs -text
59
+ extensions/sd-civitai-browser-plus/aria2/win/aria2.exe filter=lfs diff=lfs merge=lfs -text
60
+ extensions/sd-webui-cads/samples/comparison.png filter=lfs diff=lfs merge=lfs -text
61
+ extensions/sd-webui-cads/samples/grid-7069.png filter=lfs diff=lfs merge=lfs -text
62
+ extensions/sd-webui-cads/samples/grid-7070.png filter=lfs diff=lfs merge=lfs -text
63
+ extensions/sd-webui-dycfg/images/05.png filter=lfs diff=lfs merge=lfs -text
64
+ extensions/sd-webui-dycfg/images/09.png filter=lfs diff=lfs merge=lfs -text
65
+ extensions/sd-webui-image-comparison/tab.gif filter=lfs diff=lfs merge=lfs -text
66
+ extensions/sd-webui-incantations/images/xyz_grid-0463-3.jpg filter=lfs diff=lfs merge=lfs -text
67
+ extensions/sd-webui-incantations/images/xyz_grid-0469-4.jpg filter=lfs diff=lfs merge=lfs -text
68
+ extensions/sd-webui-incantations/images/xyz_grid-2652-1419902843-cinematic[[:space:]]4K[[:space:]]photo[[:space:]]of[[:space:]]a[[:space:]]dog[[:space:]]riding[[:space:]]a[[:space:]]bus[[:space:]]and[[:space:]]eating[[:space:]]cake[[:space:]]and[[:space:]]wearing[[:space:]]headphones.png filter=lfs diff=lfs merge=lfs -text
69
+ extensions/sd-webui-incantations/images/xyz_grid-2660-1590472902-A[[:space:]]photo[[:space:]]of[[:space:]]a[[:space:]]lion[[:space:]]and[[:space:]]a[[:space:]]grizzly[[:space:]]bear[[:space:]]and[[:space:]]a[[:space:]]tiger[[:space:]]in[[:space:]]the[[:space:]]woods.jpg filter=lfs diff=lfs merge=lfs -text
70
+ extensions/sd-webui-incantations/images/xyz_grid-3040-1-a[[:space:]]puppy[[:space:]]and[[:space:]]a[[:space:]]kitten[[:space:]]on[[:space:]]the[[:space:]]moon.png filter=lfs diff=lfs merge=lfs -text
71
+ extensions/sd-webui-incantations/images/xyz_grid-3348-1590472902-A[[:space:]]photo[[:space:]]of[[:space:]]a[[:space:]]lion[[:space:]]and[[:space:]]a[[:space:]]grizzly[[:space:]]bear[[:space:]]and[[:space:]]a[[:space:]]tiger[[:space:]]in[[:space:]]the[[:space:]]woods.jpg filter=lfs diff=lfs merge=lfs -text
72
+ extensions/sd-webui-pag/images/xyz_grid-3040-1-a[[:space:]]puppy[[:space:]]and[[:space:]]a[[:space:]]kitten[[:space:]]on[[:space:]]the[[:space:]]moon.png filter=lfs diff=lfs merge=lfs -text
73
+ extensions/sd-webui-semantic-guidance/samples/comparison.png filter=lfs diff=lfs merge=lfs -text
74
+ extensions/sd-webui-semantic-guidance/samples/enhance.jpg filter=lfs diff=lfs merge=lfs -text
75
+ extensions/sd-webui-smea/sample.jpg filter=lfs diff=lfs merge=lfs -text
76
+ extensions/sd-webui-smea/sample2.jpg filter=lfs diff=lfs merge=lfs -text
77
+ extensions/sd-webui-vectorscope-cc/samples/XYZ.jpg filter=lfs diff=lfs merge=lfs -text
78
+ extensions/sd-webui-xl_vec/images/crop_top.png filter=lfs diff=lfs merge=lfs -text
79
+ extensions/sd-webui-xl_vec/images/mult.png filter=lfs diff=lfs merge=lfs -text
80
+ extensions/sd-webui-xl_vec/images/original_size.png filter=lfs diff=lfs merge=lfs -text
81
+ extensions/ssasd/images/sample.png filter=lfs diff=lfs merge=lfs -text
82
+ extensions/ssasd/images/sample2.png filter=lfs diff=lfs merge=lfs -text
83
+ extensions/ssasd/images/sample3.png filter=lfs diff=lfs merge=lfs -text
84
+ extensions/stable-diffusion-webui-composable-lora/readme/changelog_2023-04-08.png filter=lfs diff=lfs merge=lfs -text
85
+ extensions/stable-diffusion-webui-composable-lora/readme/fig11.png filter=lfs diff=lfs merge=lfs -text
86
+ extensions/stable-diffusion-webui-composable-lora/readme/fig12.png filter=lfs diff=lfs merge=lfs -text
87
+ extensions/stable-diffusion-webui-composable-lora/readme/fig13.png filter=lfs diff=lfs merge=lfs -text
88
+ extensions/stable-diffusion-webui-composable-lora/readme/fig8.png filter=lfs diff=lfs merge=lfs -text
89
+ extensions/stable-diffusion-webui-composable-lora/readme/fig9.png filter=lfs diff=lfs merge=lfs -text
extensions/1-sd-dynamic-thresholding/.github/FUNDING.yml ADDED
@@ -0,0 +1 @@
 
 
1
+ github: mcmonkey4eva
extensions/1-sd-dynamic-thresholding/.github/workflows/publish.yml ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ name: Publish to Comfy registry
2
+ on:
3
+ workflow_dispatch:
4
+ push:
5
+ branches:
6
+ - master
7
+ paths:
8
+ - "pyproject.toml"
9
+
10
+ jobs:
11
+ publish-node:
12
+ name: Publish Custom Node to registry
13
+ runs-on: ubuntu-latest
14
+ steps:
15
+ - name: Check out code
16
+ uses: actions/checkout@v4
17
+ - name: Publish Custom Node
18
+ uses: Comfy-Org/publish-node-action@main
19
+ with:
20
+ ## Add your own personal access token to your Github Repository secrets and reference it here.
21
+ personal_access_token: ${{ secrets.REGISTRY_ACCESS_TOKEN }}
extensions/1-sd-dynamic-thresholding/.gitignore ADDED
@@ -0,0 +1 @@
 
 
1
+ __pycache__/
extensions/1-sd-dynamic-thresholding/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2023 Alex "mcmonkey" Goodwin
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
extensions/1-sd-dynamic-thresholding/README.md ADDED
@@ -0,0 +1,120 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Stable Diffusion Dynamic Thresholding (CFG Scale Fix)
2
+
3
+ ### Concept
4
+
5
+ Extension for [SwarmUI](https://github.com/mcmonkeyprojects/SwarmUI), [ComfyUI](https://github.com/comfyanonymous/ComfyUI), and [AUTOMATIC1111 Stable Diffusion WebUI](https://github.com/AUTOMATIC1111/stable-diffusion-webui) that enables a way to use higher CFG Scales without color issues.
6
+
7
+ This works by clamping latents between steps. You can read more [here](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/3962) or [here](https://github.com/AUTOMATIC1111/stable-diffusion-webui/issues/3268) or [this tweet](https://twitter.com/Birchlabs/status/1582165379832348672).
8
+
9
+ --------------
10
+
11
+ ### Credit
12
+
13
+ The core functionality of this PR was originally developed by [Birch-san](https://github.com/Birch-san) and ported to the WebUI by [dtan3847](https://github.com/dtan3847), then converted to an Auto WebUI extension and given a UI by [mcmonkey4eva](https://github.com/mcmonkey4eva), further development and research done by [mcmonkey4eva](https://github.com/mcmonkey4eva) and JDMLeverton. Ported by ComfyUI by [TwoDukes](https://github.com/TwoDukes) and [mcmonkey4eva](https://github.com/mcmonkey4eva). Ported to SwarmUI by [mcmonkey4eva](https://github.com/mcmonkey4eva).
14
+
15
+ --------------
16
+
17
+ ### Examples
18
+
19
+ ![img](github/cat_demo_1.jpg)
20
+
21
+ ![img](github/ui.png)
22
+
23
+
24
+ --------------
25
+
26
+ ### Demo Grid
27
+
28
+ View at <https://sd.mcmonkey.org/dynthresh/>.
29
+
30
+ ![img](github/grid_preview.png)
31
+
32
+ (Was generated via [this YAML config](https://gist.github.com/mcmonkey4eva/fccd29172f44424dfc0217a482c824f6) for the [Infinite Grid Generator](https://github.com/mcmonkeyprojects/sd-infinity-grid-generator-script))
33
+
34
+ --------------
35
+
36
+ ### Installation and Usage
37
+
38
+ #### SwarmUI
39
+
40
+ - Supported out-of-the-box on default installations.
41
+ - If using a custom installation, just make sure the backend you use has this repo installed per the instructions specific to the backend as written below.
42
+ - It's under the "Display Advanced Options" parameter checkbox.
43
+
44
+ #### Auto WebUI
45
+
46
+ - You must have the [AUTOMATIC1111 Stable Diffusion WebUI](https://github.com/AUTOMATIC1111/stable-diffusion-webui) already installed and working. Refer to that project's readme for help with that.
47
+ - Open the WebUI, go to the `Extensions` tab
48
+ - -EITHER- Option **A**:
49
+ - go to the `Available` tab with
50
+ - click `Load from` (with the default list)
51
+ - Scroll down to find `Dynamic Thresholding (CFG Scale Fix)`, or use `CTRL+F` to find it
52
+ - -OR- Option **B**:
53
+ - Click on `Install from URL`
54
+ - Copy/paste this project's URL into the `URL for extension's git repository` textbox: `https://github.com/mcmonkeyprojects/sd-dynamic-thresholding`
55
+ - Click `Install`
56
+ - Restart or reload the WebUI
57
+ - Go to txt2img or img2img
58
+ - Check the `Enable Dynamic Thresholding (CFG Scale Fix)` box
59
+ - Read the info on-page and set the sliders where you want em.
60
+ - Click generate.
61
+
62
+
63
+ #### ComfyUI
64
+
65
+ - Must have [ComfyUI](https://github.com/comfyanonymous/ComfyUI) already installed and working. Refer to that project's readme for help with that.
66
+ - -EITHER- Option **A**: (TODO: Manager install)
67
+ - -OR- Option **B**:
68
+ - `cd ComfyUI/custom_nodes`
69
+ - `git clone https://github.com/mcmonkeyprojects/sd-dynamic-thresholding`
70
+ - restart ComfyUI
71
+ - Add node `advanced/mcmonkey/DynamicThresholdingSimple` (or `Full`)
72
+ - Link your model to the input, and then link the output model to your KSampler's input
73
+
74
+ ![img](github/comfy_node.png)
75
+
76
+ --------------
77
+
78
+ ### Supported Auto WebUI Extensions
79
+
80
+ - This can be configured within the [Infinity Grid Generator](https://github.com/mcmonkeyprojects/sd-infinity-grid-generator-script#supported-extensions) extension, see the readme of that project for details.
81
+
82
+ ### ComfyUI Compatibility
83
+
84
+ - This would work with any variant of the `KSampler` node, including custom ones, so long as they do not totally override the internal sampling function (most don't).
85
+
86
+ ----------------------
87
+
88
+ ### Licensing pre-note:
89
+
90
+ This is an open source project, provided entirely freely, for everyone to use and contribute to.
91
+
92
+ If you make any changes that could benefit the community as a whole, please contribute upstream.
93
+
94
+ ### The short of the license is:
95
+
96
+ You can do basically whatever you want, except you may not hold any developer liable for what you do with the software.
97
+
98
+ ### The long version of the license follows:
99
+
100
+ The MIT License (MIT)
101
+
102
+ Copyright (c) 2023 Alex "mcmonkey" Goodwin
103
+
104
+ Permission is hereby granted, free of charge, to any person obtaining a copy
105
+ of this software and associated documentation files (the "Software"), to deal
106
+ in the Software without restriction, including without limitation the rights
107
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
108
+ copies of the Software, and to permit persons to whom the Software is
109
+ furnished to do so, subject to the following conditions:
110
+
111
+ The above copyright notice and this permission notice shall be included in all
112
+ copies or substantial portions of the Software.
113
+
114
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
115
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
116
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
117
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
118
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
119
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
120
+ SOFTWARE.
extensions/1-sd-dynamic-thresholding/__init__.py ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ from . import dynthres_comfyui
2
+
3
+ NODE_CLASS_MAPPINGS = {
4
+ "DynamicThresholdingSimple": dynthres_comfyui.DynamicThresholdingSimpleComfyNode,
5
+ "DynamicThresholdingFull": dynthres_comfyui.DynamicThresholdingComfyNode,
6
+ }
extensions/1-sd-dynamic-thresholding/__pycache__/dynthres_core.cpython-310.pyc ADDED
Binary file (4.49 kB). View file
 
extensions/1-sd-dynamic-thresholding/__pycache__/dynthres_unipc.cpython-310.pyc ADDED
Binary file (4.92 kB). View file
 
extensions/1-sd-dynamic-thresholding/dynthres_comfyui.py ADDED
@@ -0,0 +1,86 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from .dynthres_core import DynThresh
2
+
3
+ class DynamicThresholdingComfyNode:
4
+
5
+ @classmethod
6
+ def INPUT_TYPES(s):
7
+ return {
8
+ "required": {
9
+ "model": ("MODEL",),
10
+ "mimic_scale": ("FLOAT", {"default": 7.0, "min": 0.0, "max": 100.0, "step": 0.5}),
11
+ "threshold_percentile": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.01}),
12
+ "mimic_mode": (DynThresh.Modes, ),
13
+ "mimic_scale_min": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 100.0, "step": 0.5}),
14
+ "cfg_mode": (DynThresh.Modes, ),
15
+ "cfg_scale_min": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 100.0, "step": 0.5}),
16
+ "sched_val": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 100.0, "step": 0.01}),
17
+ "separate_feature_channels": (["enable", "disable"], ),
18
+ "scaling_startpoint": (DynThresh.Startpoints, ),
19
+ "variability_measure": (DynThresh.Variabilities, ),
20
+ "interpolate_phi": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.01}),
21
+ }
22
+ }
23
+
24
+ RETURN_TYPES = ("MODEL",)
25
+ FUNCTION = "patch"
26
+ CATEGORY = "advanced/mcmonkey"
27
+
28
+ def patch(self, model, mimic_scale, threshold_percentile, mimic_mode, mimic_scale_min, cfg_mode, cfg_scale_min, sched_val, separate_feature_channels, scaling_startpoint, variability_measure, interpolate_phi):
29
+
30
+ dynamic_thresh = DynThresh(mimic_scale, threshold_percentile, mimic_mode, mimic_scale_min, cfg_mode, cfg_scale_min, sched_val, 0, 999, separate_feature_channels == "enable", scaling_startpoint, variability_measure, interpolate_phi)
31
+
32
+ def sampler_dyn_thresh(args):
33
+ input = args["input"]
34
+ cond = input - args["cond"]
35
+ uncond = input - args["uncond"]
36
+ cond_scale = args["cond_scale"]
37
+ time_step = model.model.model_sampling.timestep(args["sigma"])
38
+ time_step = time_step[0].item()
39
+ dynamic_thresh.step = 999 - time_step
40
+
41
+ if cond_scale == mimic_scale:
42
+ return input - (uncond + (cond - uncond) * cond_scale)
43
+ else:
44
+ return input - dynamic_thresh.dynthresh(cond, uncond, cond_scale, None)
45
+
46
+ m = model.clone()
47
+ m.set_model_sampler_cfg_function(sampler_dyn_thresh)
48
+ return (m, )
49
+
50
+ class DynamicThresholdingSimpleComfyNode:
51
+
52
+ @classmethod
53
+ def INPUT_TYPES(s):
54
+ return {
55
+ "required": {
56
+ "model": ("MODEL",),
57
+ "mimic_scale": ("FLOAT", {"default": 7.0, "min": 0.0, "max": 100.0, "step": 0.5}),
58
+ "threshold_percentile": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.01}),
59
+ }
60
+ }
61
+
62
+ RETURN_TYPES = ("MODEL",)
63
+ FUNCTION = "patch"
64
+ CATEGORY = "advanced/mcmonkey"
65
+
66
+ def patch(self, model, mimic_scale, threshold_percentile):
67
+
68
+ dynamic_thresh = DynThresh(mimic_scale, threshold_percentile, "CONSTANT", 0, "CONSTANT", 0, 0, 0, 999, False, "MEAN", "AD", 1)
69
+
70
+ def sampler_dyn_thresh(args):
71
+ input = args["input"]
72
+ cond = input - args["cond"]
73
+ uncond = input - args["uncond"]
74
+ cond_scale = args["cond_scale"]
75
+ time_step = model.model.model_sampling.timestep(args["sigma"])
76
+ time_step = time_step[0].item()
77
+ dynamic_thresh.step = 999 - time_step
78
+
79
+ if cond_scale == mimic_scale:
80
+ return input - (uncond + (cond - uncond) * cond_scale)
81
+ else:
82
+ return input - dynamic_thresh.dynthresh(cond, uncond, cond_scale, None)
83
+
84
+ m = model.clone()
85
+ m.set_model_sampler_cfg_function(sampler_dyn_thresh)
86
+ return (m, )
extensions/1-sd-dynamic-thresholding/dynthres_core.py ADDED
@@ -0,0 +1,167 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch, math
2
+
3
+ ######################### DynThresh Core #########################
4
+
5
+ class DynThresh:
6
+
7
+ Modes = ["Constant", "Linear Down", "Cosine Down", "Half Cosine Down", "Linear Up", "Cosine Up", "Half Cosine Up", "Power Up", "Power Down", "Linear Repeating", "Cosine Repeating", "Sawtooth"]
8
+ Startpoints = ["MEAN", "ZERO"]
9
+ Variabilities = ["AD", "STD"]
10
+
11
+ def __init__(self, mimic_scale, threshold_percentile, mimic_mode, mimic_scale_min, cfg_mode, cfg_scale_min, sched_val, experiment_mode, max_steps, separate_feature_channels, scaling_startpoint, variability_measure, interpolate_phi):
12
+ self.mimic_scale = mimic_scale
13
+ self.threshold_percentile = threshold_percentile
14
+ self.mimic_mode = mimic_mode
15
+ self.cfg_mode = cfg_mode
16
+ self.max_steps = max_steps
17
+ self.cfg_scale_min = cfg_scale_min
18
+ self.mimic_scale_min = mimic_scale_min
19
+ self.experiment_mode = experiment_mode
20
+ self.sched_val = sched_val
21
+ self.sep_feat_channels = separate_feature_channels
22
+ self.scaling_startpoint = scaling_startpoint
23
+ self.variability_measure = variability_measure
24
+ self.interpolate_phi = interpolate_phi
25
+
26
+ def interpret_scale(self, scale, mode, min):
27
+ scale -= min
28
+ max = self.max_steps - 1
29
+ frac = self.step / max
30
+ if mode == "Constant":
31
+ pass
32
+ elif mode == "Linear Down":
33
+ scale *= 1.0 - frac
34
+ elif mode == "Half Cosine Down":
35
+ scale *= math.cos(frac)
36
+ elif mode == "Cosine Down":
37
+ scale *= math.cos(frac * 1.5707)
38
+ elif mode == "Linear Up":
39
+ scale *= frac
40
+ elif mode == "Half Cosine Up":
41
+ scale *= 1.0 - math.cos(frac)
42
+ elif mode == "Cosine Up":
43
+ scale *= 1.0 - math.cos(frac * 1.5707)
44
+ elif mode == "Power Up":
45
+ scale *= math.pow(frac, self.sched_val)
46
+ elif mode == "Power Down":
47
+ scale *= 1.0 - math.pow(frac, self.sched_val)
48
+ elif mode == "Linear Repeating":
49
+ portion = (frac * self.sched_val) % 1.0
50
+ scale *= (0.5 - portion) * 2 if portion < 0.5 else (portion - 0.5) * 2
51
+ elif mode == "Cosine Repeating":
52
+ scale *= math.cos(frac * 6.28318 * self.sched_val) * 0.5 + 0.5
53
+ elif mode == "Sawtooth":
54
+ scale *= (frac * self.sched_val) % 1.0
55
+ scale += min
56
+ return scale
57
+
58
+ def dynthresh(self, cond, uncond, cfg_scale, weights):
59
+ mimic_scale = self.interpret_scale(self.mimic_scale, self.mimic_mode, self.mimic_scale_min)
60
+ cfg_scale = self.interpret_scale(cfg_scale, self.cfg_mode, self.cfg_scale_min)
61
+ # uncond shape is (batch, 4, height, width)
62
+ conds_per_batch = cond.shape[0] / uncond.shape[0]
63
+ assert conds_per_batch == int(conds_per_batch), "Expected # of conds per batch to be constant across batches"
64
+ cond_stacked = cond.reshape((-1, int(conds_per_batch)) + uncond.shape[1:])
65
+
66
+ ### Normal first part of the CFG Scale logic, basically
67
+ diff = cond_stacked - uncond.unsqueeze(1)
68
+ if weights is not None:
69
+ diff = diff * weights
70
+ relative = diff.sum(1)
71
+
72
+ ### Get the normal result for both mimic and normal scale
73
+ mim_target = uncond + relative * mimic_scale
74
+ cfg_target = uncond + relative * cfg_scale
75
+ ### If we weren't doing mimic scale, we'd just return cfg_target here
76
+
77
+ ### Now recenter the values relative to their average rather than absolute, to allow scaling from average
78
+ mim_flattened = mim_target.flatten(2)
79
+ cfg_flattened = cfg_target.flatten(2)
80
+ mim_means = mim_flattened.mean(dim=2).unsqueeze(2)
81
+ cfg_means = cfg_flattened.mean(dim=2).unsqueeze(2)
82
+ mim_centered = mim_flattened - mim_means
83
+ cfg_centered = cfg_flattened - cfg_means
84
+
85
+ if self.sep_feat_channels:
86
+ if self.variability_measure == 'STD':
87
+ mim_scaleref = mim_centered.std(dim=2).unsqueeze(2)
88
+ cfg_scaleref = cfg_centered.std(dim=2).unsqueeze(2)
89
+ else: # 'AD'
90
+ mim_scaleref = mim_centered.abs().max(dim=2).values.unsqueeze(2)
91
+ cfg_scaleref = torch.quantile(cfg_centered.abs(), self.threshold_percentile, dim=2).unsqueeze(2)
92
+
93
+ else:
94
+ if self.variability_measure == 'STD':
95
+ mim_scaleref = mim_centered.std()
96
+ cfg_scaleref = cfg_centered.std()
97
+ else: # 'AD'
98
+ mim_scaleref = mim_centered.abs().max()
99
+ cfg_scaleref = torch.quantile(cfg_centered.abs(), self.threshold_percentile)
100
+
101
+ if self.scaling_startpoint == 'ZERO':
102
+ scaling_factor = mim_scaleref / cfg_scaleref
103
+ result = cfg_flattened * scaling_factor
104
+
105
+ else: # 'MEAN'
106
+ if self.variability_measure == 'STD':
107
+ cfg_renormalized = (cfg_centered / cfg_scaleref) * mim_scaleref
108
+ else: # 'AD'
109
+ ### Get the maximum value of all datapoints (with an optional threshold percentile on the uncond)
110
+ max_scaleref = torch.maximum(mim_scaleref, cfg_scaleref)
111
+ ### Clamp to the max
112
+ cfg_clamped = cfg_centered.clamp(-max_scaleref, max_scaleref)
113
+ ### Now shrink from the max to normalize and grow to the mimic scale (instead of the CFG scale)
114
+ cfg_renormalized = (cfg_clamped / max_scaleref) * mim_scaleref
115
+
116
+ ### Now add it back onto the averages to get into real scale again and return
117
+ result = cfg_renormalized + cfg_means
118
+
119
+ actual_res = result.unflatten(2, mim_target.shape[2:])
120
+
121
+ if self.interpolate_phi != 1.0:
122
+ actual_res = actual_res * self.interpolate_phi + cfg_target * (1.0 - self.interpolate_phi)
123
+
124
+ if self.experiment_mode == 1:
125
+ num = actual_res.cpu().numpy()
126
+ for y in range(0, 64):
127
+ for x in range (0, 64):
128
+ if num[0][0][y][x] > 1.0:
129
+ num[0][1][y][x] *= 0.5
130
+ if num[0][1][y][x] > 1.0:
131
+ num[0][1][y][x] *= 0.5
132
+ if num[0][2][y][x] > 1.5:
133
+ num[0][2][y][x] *= 0.5
134
+ actual_res = torch.from_numpy(num).to(device=uncond.device)
135
+ elif self.experiment_mode == 2:
136
+ num = actual_res.cpu().numpy()
137
+ for y in range(0, 64):
138
+ for x in range (0, 64):
139
+ over_scale = False
140
+ for z in range(0, 4):
141
+ if abs(num[0][z][y][x]) > 1.5:
142
+ over_scale = True
143
+ if over_scale:
144
+ for z in range(0, 4):
145
+ num[0][z][y][x] *= 0.7
146
+ actual_res = torch.from_numpy(num).to(device=uncond.device)
147
+ elif self.experiment_mode == 3:
148
+ coefs = torch.tensor([
149
+ # R G B W
150
+ [0.298, 0.207, 0.208, 0.0], # L1
151
+ [0.187, 0.286, 0.173, 0.0], # L2
152
+ [-0.158, 0.189, 0.264, 0.0], # L3
153
+ [-0.184, -0.271, -0.473, 1.0], # L4
154
+ ], device=uncond.device)
155
+ res_rgb = torch.einsum("laxy,ab -> lbxy", actual_res, coefs)
156
+ max_r, max_g, max_b, max_w = res_rgb[0][0].max(), res_rgb[0][1].max(), res_rgb[0][2].max(), res_rgb[0][3].max()
157
+ max_rgb = max(max_r, max_g, max_b)
158
+ print(f"test max = r={max_r}, g={max_g}, b={max_b}, w={max_w}, rgb={max_rgb}")
159
+ if self.step / (self.max_steps - 1) > 0.2:
160
+ if max_rgb < 2.0 and max_w < 3.0:
161
+ res_rgb /= max_rgb / 2.4
162
+ else:
163
+ if max_rgb > 2.4 and max_w > 3.0:
164
+ res_rgb /= max_rgb / 2.4
165
+ actual_res = torch.einsum("laxy,ab -> lbxy", res_rgb, coefs.inverse())
166
+
167
+ return actual_res
extensions/1-sd-dynamic-thresholding/dynthres_unipc.py ADDED
@@ -0,0 +1,111 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import torch
3
+ import math
4
+ import traceback
5
+ from modules import shared
6
+ try:
7
+ from modules.models.diffusion import uni_pc
8
+ except Exception as e:
9
+ from modules import unipc as uni_pc
10
+
11
+ ######################### UniPC Implementation logic #########################
12
+
13
+ # The majority of this is straight from modules.models/diffusion/uni_pc/sampler.py
14
+ # Unfortunately that's not an easy middle-injection point, so, just copypasta'd it all
15
+ # It's like they designed it to intentionally be as difficult to inject into as possible :(
16
+ # (It has hooks but not in useful locations)
17
+ # I stripped the original comments for brevity.
18
+ # Some never-used code (scheduler modes, noise modes, guidance modes) have been removed as well for brevity.
19
+ # The actual impl comes down to just the last line in particular, and the `before_sample` insert to track step count.
20
+
21
+ class CustomUniPCSampler(uni_pc.sampler.UniPCSampler):
22
+ def __init__(self, model, **kwargs):
23
+ super().__init__(model, *kwargs)
24
+ @torch.no_grad()
25
+ def sample(self, S, batch_size, shape, conditioning=None, callback=None, normals_sequence=None, img_callback=None,
26
+ quantize_x0=False, eta=0., mask=None, x0=None, temperature=1., noise_dropout=0., score_corrector=None,
27
+ corrector_kwargs=None, verbose=True, x_T=None, log_every_t=100, unconditional_guidance_scale=1.,
28
+ unconditional_conditioning=None, **kwargs):
29
+ if conditioning is not None:
30
+ if isinstance(conditioning, dict):
31
+ ctmp = conditioning[list(conditioning.keys())[0]]
32
+ while isinstance(ctmp, list): ctmp = ctmp[0]
33
+ cbs = ctmp.shape[0]
34
+ if cbs != batch_size:
35
+ print(f"Warning: Got {cbs} conditionings but batch-size is {batch_size}")
36
+
37
+ elif isinstance(conditioning, list):
38
+ for ctmp in conditioning:
39
+ if ctmp.shape[0] != batch_size:
40
+ print(f"Warning: Got {cbs} conditionings but batch-size is {batch_size}")
41
+ else:
42
+ if conditioning.shape[0] != batch_size:
43
+ print(f"Warning: Got {conditioning.shape[0]} conditionings but batch-size is {batch_size}")
44
+ C, H, W = shape
45
+ size = (batch_size, C, H, W)
46
+ device = self.model.betas.device
47
+ if x_T is None:
48
+ img = torch.randn(size, device=device)
49
+ else:
50
+ img = x_T
51
+ ns = uni_pc.uni_pc.NoiseScheduleVP('discrete', alphas_cumprod=self.alphas_cumprod)
52
+ model_type = "v" if self.model.parameterization == "v" else "noise"
53
+ model_fn = CustomUniPC_model_wrapper(lambda x, t, c: self.model.apply_model(x, t, c), ns, model_type=model_type, guidance_scale=unconditional_guidance_scale, dt_data=self.main_class)
54
+ self.main_class.step = 0
55
+ def before_sample(x, t, cond, uncond):
56
+ self.main_class.step += 1
57
+ return self.before_sample(x, t, cond, uncond)
58
+ uni_pc_inst = uni_pc.uni_pc.UniPC(model_fn, ns, predict_x0=True, thresholding=False, variant=shared.opts.uni_pc_variant, condition=conditioning, unconditional_condition=unconditional_conditioning, before_sample=before_sample, after_sample=self.after_sample, after_update=self.after_update)
59
+ x = uni_pc_inst.sample(img, steps=S, skip_type=shared.opts.uni_pc_skip_type, method="multistep", order=shared.opts.uni_pc_order, lower_order_final=shared.opts.uni_pc_lower_order_final)
60
+ return x.to(device), None
61
+
62
+ def CustomUniPC_model_wrapper(model, noise_schedule, model_type="noise", model_kwargs={}, guidance_scale=1.0, dt_data=None):
63
+ def expand_dims(v, dims):
64
+ return v[(...,) + (None,)*(dims - 1)]
65
+ def get_model_input_time(t_continuous):
66
+ return (t_continuous - 1. / noise_schedule.total_N) * 1000.
67
+ def noise_pred_fn(x, t_continuous, cond=None):
68
+ if t_continuous.reshape((-1,)).shape[0] == 1:
69
+ t_continuous = t_continuous.expand((x.shape[0]))
70
+ t_input = get_model_input_time(t_continuous)
71
+ if cond is None:
72
+ output = model(x, t_input, None, **model_kwargs)
73
+ else:
74
+ output = model(x, t_input, cond, **model_kwargs)
75
+ if model_type == "noise":
76
+ return output
77
+ elif model_type == "v":
78
+ alpha_t, sigma_t = noise_schedule.marginal_alpha(t_continuous), noise_schedule.marginal_std(t_continuous)
79
+ dims = x.dim()
80
+ return expand_dims(alpha_t, dims) * output + expand_dims(sigma_t, dims) * x
81
+ def model_fn(x, t_continuous, condition, unconditional_condition):
82
+ if t_continuous.reshape((-1,)).shape[0] == 1:
83
+ t_continuous = t_continuous.expand((x.shape[0]))
84
+ if guidance_scale == 1. or unconditional_condition is None:
85
+ return noise_pred_fn(x, t_continuous, cond=condition)
86
+ else:
87
+ x_in = torch.cat([x] * 2)
88
+ t_in = torch.cat([t_continuous] * 2)
89
+ if isinstance(condition, dict):
90
+ assert isinstance(unconditional_condition, dict)
91
+ c_in = dict()
92
+ for k in condition:
93
+ if isinstance(condition[k], list):
94
+ c_in[k] = [torch.cat([
95
+ unconditional_condition[k][i],
96
+ condition[k][i]]) for i in range(len(condition[k]))]
97
+ else:
98
+ c_in[k] = torch.cat([
99
+ unconditional_condition[k],
100
+ condition[k]])
101
+ elif isinstance(condition, list):
102
+ c_in = list()
103
+ assert isinstance(unconditional_condition, list)
104
+ for i in range(len(condition)):
105
+ c_in.append(torch.cat([unconditional_condition[i], condition[i]]))
106
+ else:
107
+ c_in = torch.cat([unconditional_condition, condition])
108
+ noise_uncond, noise = noise_pred_fn(x_in, t_in, cond=c_in).chunk(2)
109
+ #return noise_uncond + guidance_scale * (noise - noise_uncond)
110
+ return dt_data.dynthresh(noise, noise_uncond, guidance_scale, None)
111
+ return model_fn
extensions/1-sd-dynamic-thresholding/github/cat_demo_1.jpg ADDED
extensions/1-sd-dynamic-thresholding/github/comfy_node.png ADDED
extensions/1-sd-dynamic-thresholding/github/grid_preview.png ADDED
extensions/1-sd-dynamic-thresholding/github/ui.png ADDED
extensions/1-sd-dynamic-thresholding/javascript/active.js ADDED
@@ -0,0 +1,68 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ let dynthres_update_enabled = function() {
2
+ return Array.from(arguments);
3
+ };
4
+
5
+ (function(){
6
+ let accordions = {};
7
+ let enabled = {};
8
+ onUiUpdate(() => {
9
+ let accordion_id_prefix = "#dynthres_";
10
+ let extension_checkbox_class = ".dynthres-enabled";
11
+
12
+ dynthres_update_enabled = function() {
13
+ let res = Array.from(arguments);
14
+ let tabname = res[1] ? "img2img" : "txt2img";
15
+
16
+ let checkbox = accordions[tabname]?.querySelector(extension_checkbox_class + ' input');
17
+ checkbox?.dispatchEvent(new Event('change'));
18
+
19
+ return res;
20
+ };
21
+
22
+ function attachEnabledButtonListener(checkbox, accordion) {
23
+ let span = accordion.querySelector('.label-wrap span');
24
+ let badge = document.createElement('input');
25
+ badge.type = "checkbox";
26
+ badge.checked = checkbox.checked;
27
+ badge.addEventListener('click', (e) => {
28
+ checkbox.checked = !checkbox.checked;
29
+ badge.checked = checkbox.checked;
30
+ checkbox.dispatchEvent(new Event('change'));
31
+ e.stopPropagation();
32
+ });
33
+
34
+ badge.className = checkbox.className;
35
+ badge.classList.add('primary');
36
+ span.insertBefore(badge, span.firstChild);
37
+ let space = document.createElement('span');
38
+ space.innerHTML = "&nbsp;";
39
+ span.insertBefore(space, badge.nextSibling);
40
+
41
+ checkbox.addEventListener('change', () => {
42
+ let badge = accordion.querySelector('.label-wrap span input');
43
+ badge.checked = checkbox.checked;
44
+ });
45
+ checkbox.parentNode.style.display = "none";
46
+ }
47
+
48
+ if (Object.keys(accordions).length < 2) {
49
+ let accordion = gradioApp().querySelector(accordion_id_prefix + 'txt2img');
50
+ if (accordion) {
51
+ accordions.txt2img = accordion;
52
+ }
53
+ accordion = gradioApp().querySelector(accordion_id_prefix + 'img2img');
54
+ if (accordion) {
55
+ accordions.img2img = accordion;
56
+ }
57
+ }
58
+
59
+ if (Object.keys(accordions).length > 0 && accordions.txt2img && !enabled.txt2img) {
60
+ enabled.txt2img = accordions.txt2img.querySelector(extension_checkbox_class + ' input');
61
+ attachEnabledButtonListener(enabled.txt2img, accordions.txt2img);
62
+ }
63
+ if (Object.keys(accordions).length > 0 && accordions.img2img && !enabled.img2img) {
64
+ enabled.img2img = accordions.img2img.querySelector(extension_checkbox_class + ' input');
65
+ attachEnabledButtonListener(enabled.img2img, accordions.img2img);
66
+ }
67
+ });
68
+ })();
extensions/1-sd-dynamic-thresholding/pyproject.toml ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [project]
2
+ name = "sd-dynamic-thresholding"
3
+ description = "Adds nodes for Dynamic Thresholding, CFG scheduling, and related techniques"
4
+ version = "1.0.1"
5
+ license = { file = "LICENSE.txt" }
6
+
7
+ [project.urls]
8
+ Repository = "https://github.com/mcmonkeyprojects/sd-dynamic-thresholding"
9
+
10
+ [tool.comfy]
11
+ PublisherId = "mcmonkey"
12
+ DisplayName = "Dynamic Thresholding"
13
+ Icon = ""
extensions/1-sd-dynamic-thresholding/scripts/__pycache__/dynamic_thresholding.cpython-310.pyc ADDED
Binary file (12.7 kB). View file
 
extensions/1-sd-dynamic-thresholding/scripts/dynamic_thresholding.py ADDED
@@ -0,0 +1,270 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ##################
2
+ # Stable Diffusion Dynamic Thresholding (CFG Scale Fix)
3
+ #
4
+ # Author: Alex 'mcmonkey' Goodwin
5
+ # GitHub URL: https://github.com/mcmonkeyprojects/sd-dynamic-thresholding
6
+ # Created: 2022/01/26
7
+ # Last updated: 2023/01/30
8
+ #
9
+ # For usage help, view the README.md file in the extension root, or via the GitHub page.
10
+ #
11
+ ##################
12
+
13
+ import gradio as gr
14
+ import torch, traceback
15
+ import dynthres_core
16
+ from modules import scripts, script_callbacks, sd_samplers, sd_samplers_compvis, sd_samplers_common
17
+ try:
18
+ import dynthres_unipc
19
+ except Exception as e:
20
+ print(f"\n\n======\nError! UniPC sampler support failed to load! Is your WebUI up to date?\n(Error: {e})\n======")
21
+ try:
22
+ from modules.sd_samplers_kdiffusion import CFGDenoiserKDiffusion as cfgdenoisekdiff
23
+ IS_AUTO_16 = True
24
+ except Exception as e:
25
+ print(f"\n\n======\nWarning! Using legacy KDiff version! Is your WebUI up to date?\n======")
26
+ from modules.sd_samplers_kdiffusion import CFGDenoiser as cfgdenoisekdiff
27
+ IS_AUTO_16 = False
28
+
29
+ DISABLE_VISIBILITY = True
30
+
31
+ ######################### Data values #########################
32
+ MODES_WITH_VALUE = ["Power Up", "Power Down", "Linear Repeating", "Cosine Repeating", "Sawtooth"]
33
+
34
+ ######################### Script class entrypoint #########################
35
+ class Script(scripts.Script):
36
+
37
+ def title(self):
38
+ return "Dynamic Thresholding (CFG Scale Fix)"
39
+
40
+ def show(self, is_img2img):
41
+ return scripts.AlwaysVisible
42
+
43
+ def ui(self, is_img2img):
44
+ def vis_change(is_vis):
45
+ return {"visible": is_vis, "__type__": "update"}
46
+ # "Dynamic Thresholding (CFG Scale Fix)"
47
+ dtrue = gr.Checkbox(value=True, visible=False)
48
+ dfalse = gr.Checkbox(value=False, visible=False)
49
+ with gr.Accordion("Dynamic Thresholding (CFG Scale Fix)", open=False, elem_id="dynthres_" + ("img2img" if is_img2img else "txt2img")):
50
+ with gr.Row():
51
+ enabled = gr.Checkbox(value=False, label="Enable Dynamic Thresholding (CFG Scale Fix)", elem_classes=["dynthres-enabled"], elem_id='dynthres_enabled')
52
+ with gr.Group():
53
+ gr.HTML(value=f"View <a style=\"border-bottom: 1px #00ffff dotted;\" href=\"https://github.com/mcmonkeyprojects/sd-dynamic-thresholding/wiki/Usage-Tips\">the wiki for usage tips.</a><br><br>", elem_id='dynthres_wiki_link')
54
+ mimic_scale = gr.Slider(minimum=1.0, maximum=30.0, step=0.5, label='Mimic CFG Scale', value=7.0, elem_id='dynthres_mimic_scale')
55
+ with gr.Accordion("Advanced Options", open=False, elem_id='dynthres_advanced_opts'):
56
+ with gr.Row():
57
+ threshold_percentile = gr.Slider(minimum=90.0, value=100.0, maximum=100.0, step=0.05, label='Top percentile of latents to clamp', elem_id='dynthres_threshold_percentile')
58
+ interpolate_phi = gr.Slider(minimum=0.0, maximum=1.0, step=0.01, label="Interpolate Phi", value=1.0, elem_id='dynthres_interpolate_phi')
59
+ with gr.Row():
60
+ mimic_mode = gr.Dropdown(dynthres_core.DynThresh.Modes, value="Constant", label="Mimic Scale Scheduler", elem_id='dynthres_mimic_mode')
61
+ cfg_mode = gr.Dropdown(dynthres_core.DynThresh.Modes, value="Constant", label="CFG Scale Scheduler", elem_id='dynthres_cfg_mode')
62
+ mimic_scale_min = gr.Slider(minimum=0.0, maximum=30.0, step=0.5, visible=DISABLE_VISIBILITY, label="Minimum value of the Mimic Scale Scheduler", elem_id='dynthres_mimic_scale_min')
63
+ cfg_scale_min = gr.Slider(minimum=0.0, maximum=30.0, step=0.5, visible=DISABLE_VISIBILITY, label="Minimum value of the CFG Scale Scheduler", elem_id='dynthres_cfg_scale_min')
64
+ sched_val = gr.Slider(minimum=0.0, maximum=40.0, step=0.5, value=4.0, visible=DISABLE_VISIBILITY, label="Scheduler Value", info="Value unique to the scheduler mode - for Power Up/Down, this is the power. For Linear/Cosine Repeating, this is the number of repeats per image.", elem_id='dynthres_sched_val')
65
+ with gr.Row():
66
+ separate_feature_channels = gr.Checkbox(value=True, label="Separate Feature Channels", elem_id='dynthres_separate_feature_channels')
67
+ scaling_startpoint = gr.Radio(["ZERO", "MEAN"], value="MEAN", label="Scaling Startpoint")
68
+ variability_measure = gr.Radio(["STD", "AD"], value="AD", label="Variability Measure")
69
+ def should_show_scheduler_value(cfg_mode, mimic_mode):
70
+ sched_vis = cfg_mode in MODES_WITH_VALUE or mimic_mode in MODES_WITH_VALUE or DISABLE_VISIBILITY
71
+ return vis_change(sched_vis), vis_change(mimic_mode != "Constant" or DISABLE_VISIBILITY), vis_change(cfg_mode != "Constant" or DISABLE_VISIBILITY)
72
+ cfg_mode.change(should_show_scheduler_value, inputs=[cfg_mode, mimic_mode], outputs=[sched_val, mimic_scale_min, cfg_scale_min])
73
+ mimic_mode.change(should_show_scheduler_value, inputs=[cfg_mode, mimic_mode], outputs=[sched_val, mimic_scale_min, cfg_scale_min])
74
+ enabled.change(
75
+ _js="dynthres_update_enabled",
76
+ fn=None,
77
+ inputs=[enabled, dtrue if is_img2img else dfalse],
78
+ show_progress = False)
79
+ self.infotext_fields = (
80
+ (enabled, lambda d: gr.Checkbox.update(value="Dynamic thresholding enabled" in d)),
81
+ (mimic_scale, "Mimic scale"),
82
+ (separate_feature_channels, "Separate Feature Channels"),
83
+ (scaling_startpoint, lambda d: gr.Radio.update(value=d.get("Scaling Startpoint", "MEAN"))),
84
+ (variability_measure, lambda d: gr.Radio.update(value=d.get("Variability Measure", "AD"))),
85
+ (interpolate_phi, "Interpolate Phi"),
86
+ (threshold_percentile, "Threshold percentile"),
87
+ (mimic_scale_min, "Mimic scale minimum"),
88
+ (mimic_mode, lambda d: gr.Dropdown.update(value=d.get("Mimic mode", "Constant"))),
89
+ (cfg_mode, lambda d: gr.Dropdown.update(value=d.get("CFG mode", "Constant"))),
90
+ (cfg_scale_min, "CFG scale minimum"),
91
+ (sched_val, "Scheduler value"))
92
+ return [enabled, mimic_scale, threshold_percentile, mimic_mode, mimic_scale_min, cfg_mode, cfg_scale_min, sched_val, separate_feature_channels, scaling_startpoint, variability_measure, interpolate_phi]
93
+
94
+ last_id = 0
95
+
96
+ def process_batch(self, p, enabled, mimic_scale, threshold_percentile, mimic_mode, mimic_scale_min, cfg_mode, cfg_scale_min, sched_val, separate_feature_channels, scaling_startpoint, variability_measure, interpolate_phi, batch_number, prompts, seeds, subseeds):
97
+ enabled = getattr(p, 'dynthres_enabled', enabled)
98
+ if not enabled:
99
+ return
100
+ orig_sampler_name = p.sampler_name
101
+ orig_latent_sampler_name = getattr(p, 'latent_sampler', None)
102
+ if orig_sampler_name in ["DDIM", "PLMS"]:
103
+ raise RuntimeError(f"Cannot use sampler {orig_sampler_name} with Dynamic Thresholding")
104
+ if orig_latent_sampler_name in ["DDIM", "PLMS"]:
105
+ raise RuntimeError(f"Cannot use secondary sampler {orig_latent_sampler_name} with Dynamic Thresholding")
106
+ if 'UniPC' in (orig_sampler_name, orig_latent_sampler_name) and p.enable_hr:
107
+ raise RuntimeError(f"UniPC does not support Hires Fix. Auto WebUI silently swaps to DDIM for this, which DynThresh does not support. Please swap to a sampler capable of img2img processing for HR Fix to work.")
108
+ mimic_scale = getattr(p, 'dynthres_mimic_scale', mimic_scale)
109
+ separate_feature_channels = getattr(p, 'dynthres_separate_feature_channels', separate_feature_channels)
110
+ scaling_startpoint = getattr(p, 'dynthres_scaling_startpoint', scaling_startpoint)
111
+ variability_measure = getattr(p, 'dynthres_variability_measure', variability_measure)
112
+ interpolate_phi = getattr(p, 'dynthres_interpolate_phi', interpolate_phi)
113
+ threshold_percentile = getattr(p, 'dynthres_threshold_percentile', threshold_percentile)
114
+ mimic_mode = getattr(p, 'dynthres_mimic_mode', mimic_mode)
115
+ mimic_scale_min = getattr(p, 'dynthres_mimic_scale_min', mimic_scale_min)
116
+ cfg_mode = getattr(p, 'dynthres_cfg_mode', cfg_mode)
117
+ cfg_scale_min = getattr(p, 'dynthres_cfg_scale_min', cfg_scale_min)
118
+ experiment_mode = getattr(p, 'dynthres_experiment_mode', 0)
119
+ sched_val = getattr(p, 'dynthres_scheduler_val', sched_val)
120
+ p.extra_generation_params["Dynamic thresholding enabled"] = True
121
+ p.extra_generation_params["Mimic scale"] = mimic_scale
122
+ p.extra_generation_params["Separate Feature Channels"] = separate_feature_channels
123
+ p.extra_generation_params["Scaling Startpoint"] = scaling_startpoint
124
+ p.extra_generation_params["Variability Measure"] = variability_measure
125
+ p.extra_generation_params["Interpolate Phi"] = interpolate_phi
126
+ p.extra_generation_params["Threshold percentile"] = threshold_percentile
127
+ p.extra_generation_params["Sampler"] = orig_sampler_name
128
+ if mimic_mode != "Constant":
129
+ p.extra_generation_params["Mimic mode"] = mimic_mode
130
+ p.extra_generation_params["Mimic scale minimum"] = mimic_scale_min
131
+ if cfg_mode != "Constant":
132
+ p.extra_generation_params["CFG mode"] = cfg_mode
133
+ p.extra_generation_params["CFG scale minimum"] = cfg_scale_min
134
+ if cfg_mode in MODES_WITH_VALUE or mimic_mode in MODES_WITH_VALUE:
135
+ p.extra_generation_params["Scheduler value"] = sched_val
136
+ # Note: the ID number is to protect the edge case of multiple simultaneous runs with different settings
137
+ Script.last_id += 1
138
+ # Percentage to portion
139
+ threshold_percentile *= 0.01
140
+
141
+ def make_sampler(orig_sampler_name):
142
+ fixed_sampler_name = f"{orig_sampler_name}_dynthres{Script.last_id}"
143
+
144
+ # Make a placeholder sampler
145
+ sampler = sd_samplers.all_samplers_map[orig_sampler_name]
146
+ dt_data = dynthres_core.DynThresh(mimic_scale, threshold_percentile, mimic_mode, mimic_scale_min, cfg_mode, cfg_scale_min, sched_val, experiment_mode, p.steps, separate_feature_channels, scaling_startpoint, variability_measure, interpolate_phi)
147
+ if orig_sampler_name == "UniPC":
148
+ def unipc_constructor(model):
149
+ return CustomVanillaSDSampler(dynthres_unipc.CustomUniPCSampler, model, dt_data)
150
+ new_sampler = sd_samplers_common.SamplerData(fixed_sampler_name, unipc_constructor, sampler.aliases, sampler.options)
151
+ else:
152
+ def new_constructor(model):
153
+ result = sampler.constructor(model)
154
+ cfg = CustomCFGDenoiser(result if IS_AUTO_16 else result.model_wrap_cfg.inner_model, dt_data)
155
+ result.model_wrap_cfg = cfg
156
+ return result
157
+ new_sampler = sd_samplers_common.SamplerData(fixed_sampler_name, new_constructor, sampler.aliases, sampler.options)
158
+ return fixed_sampler_name, new_sampler
159
+
160
+ # Apply for usage
161
+ p.orig_sampler_name = orig_sampler_name
162
+ p.orig_latent_sampler_name = orig_latent_sampler_name
163
+ p.fixed_samplers = []
164
+
165
+ if orig_latent_sampler_name:
166
+ latent_sampler_name, latent_sampler = make_sampler(orig_latent_sampler_name)
167
+ sd_samplers.all_samplers_map[latent_sampler_name] = latent_sampler
168
+ p.fixed_samplers.append(latent_sampler_name)
169
+ p.latent_sampler = latent_sampler_name
170
+
171
+ if orig_sampler_name != orig_latent_sampler_name:
172
+ p.sampler_name, new_sampler = make_sampler(orig_sampler_name)
173
+ sd_samplers.all_samplers_map[p.sampler_name] = new_sampler
174
+ p.fixed_samplers.append(p.sampler_name)
175
+ else:
176
+ p.sampler_name = p.latent_sampler
177
+
178
+ if p.sampler is not None:
179
+ p.sampler = sd_samplers.create_sampler(p.sampler_name, p.sd_model)
180
+
181
+ def postprocess_batch(self, p, enabled, mimic_scale, threshold_percentile, mimic_mode, mimic_scale_min, cfg_mode, cfg_scale_min, sched_val, separate_feature_channels, scaling_startpoint, variability_measure, interpolate_phi, batch_number, images):
182
+ if not enabled or not hasattr(p, 'orig_sampler_name'):
183
+ return
184
+ p.sampler_name = p.orig_sampler_name
185
+ if p.orig_latent_sampler_name:
186
+ p.latent_sampler = p.orig_latent_sampler_name
187
+ for added_sampler in p.fixed_samplers:
188
+ del sd_samplers.all_samplers_map[added_sampler]
189
+ del p.fixed_samplers
190
+ del p.orig_sampler_name
191
+ del p.orig_latent_sampler_name
192
+
193
+ ######################### CompVis Implementation logic #########################
194
+
195
+ class CustomVanillaSDSampler(sd_samplers_compvis.VanillaStableDiffusionSampler):
196
+ def __init__(self, constructor, sd_model, dt_data):
197
+ super().__init__(constructor, sd_model)
198
+ self.sampler.main_class = dt_data
199
+
200
+ ######################### K-Diffusion Implementation logic #########################
201
+
202
+ class CustomCFGDenoiser(cfgdenoisekdiff):
203
+ def __init__(self, model, dt_data):
204
+ super().__init__(model)
205
+ self.main_class = dt_data
206
+
207
+ def combine_denoised(self, x_out, conds_list, uncond, cond_scale):
208
+ if isinstance(uncond, dict) and 'crossattn' in uncond:
209
+ uncond = uncond['crossattn']
210
+ denoised_uncond = x_out[-uncond.shape[0]:]
211
+ # conds_list shape is (batch, cond, 2)
212
+ weights = torch.tensor(conds_list, device=uncond.device).select(2, 1)
213
+ weights = weights.reshape(*weights.shape, 1, 1, 1)
214
+ self.main_class.step = self.step
215
+ if hasattr(self, 'total_steps'):
216
+ self.main_class.max_steps = self.total_steps
217
+
218
+ if self.main_class.experiment_mode >= 4 and self.main_class.experiment_mode <= 5:
219
+ # https://arxiv.org/pdf/2305.08891.pdf "Rescale CFG". It's not good, but if you want to test it, just set experiment_mode = 4 + phi.
220
+ denoised = torch.clone(denoised_uncond)
221
+ fi = self.main_class.experiment_mode - 4.0
222
+ for i, conds in enumerate(conds_list):
223
+ for cond_index, weight in conds:
224
+ xcfg = (denoised_uncond[i] + (x_out[cond_index] - denoised_uncond[i]) * (cond_scale * weight))
225
+ xrescaled = xcfg * (torch.std(x_out[cond_index]) / torch.std(xcfg))
226
+ xfinal = fi * xrescaled + (1.0 - fi) * xcfg
227
+ denoised[i] = xfinal
228
+ return denoised
229
+
230
+ return self.main_class.dynthresh(x_out[:-uncond.shape[0]], denoised_uncond, cond_scale, weights)
231
+
232
+ ######################### XYZ Plot Script Support logic #########################
233
+
234
+ def make_axis_options():
235
+ xyz_grid = [x for x in scripts.scripts_data if x.script_class.__module__ in ("xyz_grid.py", "scripts.xyz_grid")][0].module
236
+ def apply_mimic_scale(p, x, xs):
237
+ if x != 0:
238
+ setattr(p, "dynthres_enabled", True)
239
+ setattr(p, "dynthres_mimic_scale", x)
240
+ else:
241
+ setattr(p, "dynthres_enabled", False)
242
+ def confirm_scheduler(p, xs):
243
+ for x in xs:
244
+ if x not in dynthres_core.DynThresh.Modes:
245
+ raise RuntimeError(f"Unknown Scheduler: {x}")
246
+ extra_axis_options = [
247
+ xyz_grid.AxisOption("[DynThres] Mimic Scale", float, apply_mimic_scale),
248
+ xyz_grid.AxisOption("[DynThres] Separate Feature Channels", int,
249
+ xyz_grid.apply_field("dynthres_separate_feature_channels")),
250
+ xyz_grid.AxisOption("[DynThres] Scaling Startpoint", str, xyz_grid.apply_field("dynthres_scaling_startpoint"), choices=lambda:['ZERO', 'MEAN']),
251
+ xyz_grid.AxisOption("[DynThres] Variability Measure", str, xyz_grid.apply_field("dynthres_variability_measure"), choices=lambda:['STD', 'AD']),
252
+ xyz_grid.AxisOption("[DynThres] Interpolate Phi", float, xyz_grid.apply_field("dynthres_interpolate_phi")),
253
+ xyz_grid.AxisOption("[DynThres] Threshold Percentile", float, xyz_grid.apply_field("dynthres_threshold_percentile")),
254
+ xyz_grid.AxisOption("[DynThres] Mimic Scheduler", str, xyz_grid.apply_field("dynthres_mimic_mode"), confirm=confirm_scheduler, choices=lambda: dynthres_core.DynThresh.Modes),
255
+ xyz_grid.AxisOption("[DynThres] Mimic minimum", float, xyz_grid.apply_field("dynthres_mimic_scale_min")),
256
+ xyz_grid.AxisOption("[DynThres] CFG Scheduler", str, xyz_grid.apply_field("dynthres_cfg_mode"), confirm=confirm_scheduler, choices=lambda: dynthres_core.DynThresh.Modes),
257
+ xyz_grid.AxisOption("[DynThres] CFG minimum", float, xyz_grid.apply_field("dynthres_cfg_scale_min")),
258
+ xyz_grid.AxisOption("[DynThres] Scheduler value", float, xyz_grid.apply_field("dynthres_scheduler_val"))
259
+ ]
260
+ if not any("[DynThres]" in x.label for x in xyz_grid.axis_options):
261
+ xyz_grid.axis_options.extend(extra_axis_options)
262
+
263
+ def callback_before_ui():
264
+ try:
265
+ make_axis_options()
266
+ except Exception as e:
267
+ traceback.print_exc()
268
+ print(f"Failed to add support for X/Y/Z Plot Script because: {e}")
269
+
270
+ script_callbacks.on_before_ui(callback_before_ui)
extensions/4-adetailer/.github/ISSUE_TEMPLATE/bug_report.yaml ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ name: Bug report
2
+ description: Create a report
3
+ title: "[Bug]: "
4
+ labels:
5
+ - bug
6
+
7
+ body:
8
+ - type: textarea
9
+ attributes:
10
+ label: Describe the bug
11
+ description: A clear and concise description of what the bug is.
12
+ placeholder: |
13
+ Any language accepted
14
+ 아무 언어 사용가능
15
+ すべての言語に対応
16
+ 接受所有语言
17
+ Se aceptan todos los idiomas
18
+ Alle Sprachen werden akzeptiert
19
+ Toutes les langues sont acceptées
20
+ Принимаются все языки
21
+ validations:
22
+ required: true
23
+
24
+ - type: textarea
25
+ attributes:
26
+ label: Steps to reproduce
27
+ description: |
28
+ Description of how we can reproduce this issue.
29
+ validations:
30
+ required: true
31
+
32
+ - type: textarea
33
+ attributes:
34
+ label: Screenshots
35
+ description: Screenshots related to the issue.
36
+
37
+ - type: textarea
38
+ attributes:
39
+ label: Console logs, from start to end.
40
+ description: |
41
+ The full console log of your terminal.
42
+ placeholder: |
43
+ Python ...
44
+ Version: ...
45
+ Commit hash: ...
46
+ Installing requirements
47
+ ...
48
+
49
+ Launching Web UI with arguments: ...
50
+ [-] ADetailer initialized. version: ...
51
+ ...
52
+ ...
53
+
54
+ Traceback (most recent call last):
55
+ ...
56
+ ...
57
+ render: Shell
58
+ validations:
59
+ required: true
60
+
61
+ - type: textarea
62
+ attributes:
63
+ label: List of installed extensions
extensions/4-adetailer/.github/ISSUE_TEMPLATE/feature_request.yaml ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ name: Feature request
2
+ description: Suggest an idea for this project
3
+ title: "[Feature Request]: "
4
+ labels:
5
+ - enhancement
6
+
7
+ body:
8
+ - type: textarea
9
+ attributes:
10
+ label: Is your feature request related to a problem? Please describe.
11
+ description: A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12
+
13
+ - type: textarea
14
+ attributes:
15
+ label: Describe the solution you'd like
16
+ description: A clear and concise description of what you want to happen.
17
+
18
+ - type: textarea
19
+ attributes:
20
+ label: Describe alternatives you've considered
21
+ description: A clear and concise description of any alternative solutions or features you've considered.
22
+
23
+ - type: textarea
24
+ attributes:
25
+ label: Additional context
26
+ description: Add any other context or screenshots about the feature request here.
extensions/4-adetailer/.github/workflows/lgtm.yml ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ name: Empirical Implementation of JDD
2
+
3
+ on:
4
+ pull_request:
5
+ types:
6
+ - opened
7
+
8
+ jobs:
9
+ lint:
10
+ permissions:
11
+ issues: write
12
+ pull-requests: write
13
+ runs-on: ubuntu-latest
14
+
15
+ steps:
16
+ - uses: peter-evans/create-or-update-comment@v4
17
+ with:
18
+ issue-number: ${{ github.event.pull_request.number }}
19
+ body: |
20
+ ![Imgur](https://i.imgur.com/ESow3BL.png)
21
+
22
+ LGTM
23
+ reactions: hooray
extensions/4-adetailer/.github/workflows/pypi.yml ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ name: Publish to PyPI
2
+ on:
3
+ push:
4
+ tags:
5
+ - "v*"
6
+
7
+ jobs:
8
+ test:
9
+ name: test
10
+ runs-on: macos-14
11
+ strategy:
12
+ matrix:
13
+ python-version:
14
+ - "3.10"
15
+ - "3.11"
16
+ - "3.12"
17
+
18
+ steps:
19
+ - uses: actions/checkout@v4
20
+
21
+ - name: Set up Python ${{ matrix.python-version }}
22
+ uses: actions/setup-python@v5
23
+ with:
24
+ python-version: ${{ matrix.python-version }}
25
+
26
+ - uses: yezz123/setup-uv@v4
27
+
28
+ - name: Install dependencies
29
+ run: |
30
+ uv pip install --system . pytest
31
+
32
+ - name: Run tests
33
+ run: pytest -v
34
+
35
+ build:
36
+ name: build
37
+ runs-on: ubuntu-latest
38
+ permissions:
39
+ id-token: write
40
+ needs: [test]
41
+
42
+ steps:
43
+ - uses: actions/checkout@v4
44
+
45
+ - name: Build wheel
46
+ run: pipx run build
47
+
48
+ - name: Publish to PyPI
49
+ uses: pypa/gh-action-pypi-publish@release/v1
extensions/4-adetailer/.github/workflows/stale.yml ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ name: Close stale issues and PRs
2
+ on:
3
+ schedule:
4
+ - cron: "30 1 * * *"
5
+
6
+ jobs:
7
+ stale:
8
+ runs-on: ubuntu-latest
9
+ steps:
10
+ - uses: actions/stale@v9
11
+ with:
12
+ days-before-stale: 17
13
+ days-before-close: 3
extensions/4-adetailer/.gitignore ADDED
@@ -0,0 +1,197 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Created by https://www.toptal.com/developers/gitignore/api/python,visualstudiocode
2
+ # Edit at https://www.toptal.com/developers/gitignore?templates=python,visualstudiocode
3
+
4
+ ### Python ###
5
+ # Byte-compiled / optimized / DLL files
6
+ __pycache__/
7
+ *.py[cod]
8
+ *$py.class
9
+
10
+ # C extensions
11
+ *.so
12
+
13
+ # Distribution / packaging
14
+ .Python
15
+ build/
16
+ develop-eggs/
17
+ dist/
18
+ downloads/
19
+ eggs/
20
+ .eggs/
21
+ lib/
22
+ lib64/
23
+ parts/
24
+ sdist/
25
+ var/
26
+ wheels/
27
+ share/python-wheels/
28
+ *.egg-info/
29
+ .installed.cfg
30
+ *.egg
31
+ MANIFEST
32
+
33
+ # PyInstaller
34
+ # Usually these files are written by a python script from a template
35
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
36
+ *.manifest
37
+ *.spec
38
+
39
+ # Installer logs
40
+ pip-log.txt
41
+ pip-delete-this-directory.txt
42
+
43
+ # Unit test / coverage reports
44
+ htmlcov/
45
+ .tox/
46
+ .nox/
47
+ .coverage
48
+ .coverage.*
49
+ .cache
50
+ nosetests.xml
51
+ coverage.xml
52
+ *.cover
53
+ *.py,cover
54
+ .hypothesis/
55
+ .pytest_cache/
56
+ cover/
57
+
58
+ # Translations
59
+ *.mo
60
+ *.pot
61
+
62
+ # Django stuff:
63
+ *.log
64
+ local_settings.py
65
+ db.sqlite3
66
+ db.sqlite3-journal
67
+
68
+ # Flask stuff:
69
+ instance/
70
+ .webassets-cache
71
+
72
+ # Scrapy stuff:
73
+ .scrapy
74
+
75
+ # Sphinx documentation
76
+ docs/_build/
77
+
78
+ # PyBuilder
79
+ .pybuilder/
80
+ target/
81
+
82
+ # Jupyter Notebook
83
+ .ipynb_checkpoints
84
+
85
+ # IPython
86
+ profile_default/
87
+ ipython_config.py
88
+
89
+ # pyenv
90
+ # For a library or package, you might want to ignore these files since the code is
91
+ # intended to run in multiple environments; otherwise, check them in:
92
+ # .python-version
93
+
94
+ # pipenv
95
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
96
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
97
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
98
+ # install all needed dependencies.
99
+ #Pipfile.lock
100
+
101
+ # poetry
102
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
103
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
104
+ # commonly ignored for libraries.
105
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
106
+ #poetry.lock
107
+
108
+ # pdm
109
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
110
+ #pdm.lock
111
+ # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
112
+ # in version control.
113
+ # https://pdm.fming.dev/#use-with-ide
114
+ .pdm.toml
115
+
116
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
117
+ __pypackages__/
118
+
119
+ # Celery stuff
120
+ celerybeat-schedule
121
+ celerybeat.pid
122
+
123
+ # SageMath parsed files
124
+ *.sage.py
125
+
126
+ # Environments
127
+ .env
128
+ .venv
129
+ env/
130
+ venv/
131
+ ENV/
132
+ env.bak/
133
+ venv.bak/
134
+
135
+ # Spyder project settings
136
+ .spyderproject
137
+ .spyproject
138
+
139
+ # Rope project settings
140
+ .ropeproject
141
+
142
+ # mkdocs documentation
143
+ /site
144
+
145
+ # mypy
146
+ .mypy_cache/
147
+ .dmypy.json
148
+ dmypy.json
149
+
150
+ # Pyre type checker
151
+ .pyre/
152
+
153
+ # pytype static type analyzer
154
+ .pytype/
155
+
156
+ # Cython debug symbols
157
+ cython_debug/
158
+
159
+ # PyCharm
160
+ # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
161
+ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
162
+ # and can be added to the global gitignore or merged into this file. For a more nuclear
163
+ # option (not recommended) you can uncomment the following to ignore the entire idea folder.
164
+ #.idea/
165
+
166
+ ### Python Patch ###
167
+ # Poetry local configuration file - https://python-poetry.org/docs/configuration/#local-configuration
168
+ poetry.toml
169
+
170
+ # ruff
171
+ .ruff_cache/
172
+
173
+ # LSP config files
174
+ pyrightconfig.json
175
+
176
+ ### VisualStudioCode ###
177
+ .vscode/*
178
+ !.vscode/settings.json
179
+ !.vscode/tasks.json
180
+ !.vscode/launch.json
181
+ !.vscode/extensions.json
182
+ !.vscode/*.code-snippets
183
+
184
+ # Local History for Visual Studio Code
185
+ .history/
186
+
187
+ # Built Visual Studio Code Extensions
188
+ *.vsix
189
+
190
+ ### VisualStudioCode Patch ###
191
+ # Ignore all local history of files
192
+ .history
193
+ .ionide
194
+
195
+ # End of https://www.toptal.com/developers/gitignore/api/python,visualstudiocode
196
+ *.ipynb
197
+ node_modules
extensions/4-adetailer/.pre-commit-config.yaml ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ci:
2
+ autoupdate_branch: "dev"
3
+
4
+ repos:
5
+ - repo: https://github.com/pre-commit/pre-commit-hooks
6
+ rev: v4.6.0
7
+ hooks:
8
+ - id: check-added-large-files
9
+ args: [--maxkb=100]
10
+ - id: check-merge-conflict
11
+ - id: check-case-conflict
12
+ - id: check-ast
13
+ - id: check-yaml
14
+ - id: trailing-whitespace
15
+ args: [--markdown-linebreak-ext=md]
16
+ - id: end-of-file-fixer
17
+ - id: mixed-line-ending
18
+
19
+ - repo: https://github.com/rbubley/mirrors-prettier
20
+ rev: v3.3.3
21
+ hooks:
22
+ - id: prettier
23
+
24
+ - repo: https://github.com/astral-sh/ruff-pre-commit
25
+ rev: v0.5.6
26
+ hooks:
27
+ - id: ruff
28
+ args: [--fix, --exit-non-zero-on-fix]
29
+ - id: ruff-format
extensions/4-adetailer/.vscode/extensions.json ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "recommendations": [
3
+ "ms-python.vscode-pylance",
4
+ "ms-python.black-formatter",
5
+ "kevinrose.vsc-python-indent",
6
+ "charliermarsh.ruff",
7
+ "shardulm94.trailing-spaces"
8
+ ]
9
+ }
extensions/4-adetailer/.vscode/settings.json ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "explorer.fileNesting.enabled": true,
3
+ "explorer.fileNesting.patterns": {
4
+ "pyproject.toml": ".env, .gitignore, .pre-commit-config.yaml, Taskfile.yml",
5
+ "README.md": "LICENSE.md, CHANGELOG.md",
6
+ "install.py": "preload.py"
7
+ }
8
+ }
extensions/4-adetailer/CHANGELOG.md ADDED
@@ -0,0 +1,472 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Changelog
2
+
3
+ ## 2024-08-03
4
+
5
+ - v24.8.0
6
+ - 샘플러 선택칸에 Use same sampler 옵션 추가
7
+ - 컨트롤넷 유니온 모델을 선택할 수 있게 함
8
+
9
+ - webui 1.9.0이상에서 기본 스케줄러가 설정되지 않던 문제 수정
10
+ - issus #656의 문제 해결을 위해 v24.4.0에 적용되었던 프롬프트 표시 기능을 되돌림
11
+ - mediapipe에서 에러가 발생하면 추론이 실패한 것으로 처리하고 조용히 넘어감
12
+
13
+ ## 2024-06-16
14
+
15
+ - v24.6.0
16
+ - webui 1.6.0 미만 버전을 위한 기능들을 제거하고, 최소 버전을 1.6.0으로 올림
17
+ - 허깅페이스 연결을 체크하는데 1초만 소요되도록 함
18
+ - 허깅페이스 미러 (hf-mirror.com)도 체크함 (합쳐서 2초)
19
+ - InputAccordion을 적용함
20
+
21
+ ## 2024-05-20
22
+
23
+ - v24.5.1
24
+ - uv를 사용하지 않게 함
25
+ - 모든 허깅페이스 모델을 동시에 다운로드 시도함
26
+ - 기본 탭 수를 2에서 4로 변경
27
+
28
+ ## 2024-05-19
29
+
30
+ - v24.5.0
31
+ - 개별 탭 활성화/비활성화 체크박스 추가
32
+ - ad_extra_model_dir 옵션에 |로 구분된 여러 디렉토리를 추가할 수 있게 함 (PR #596)
33
+ - `hypertile` 빌트인 확장이 지원되도록 함
34
+ - 항상 cond 캐시를 비움
35
+ - 설치 스크립트에 uv를 사용함
36
+ - mediapipe 최소 버전을 올려 protobuf 버전 4를 사용하게 함
37
+
38
+ ## 2024-04-17
39
+
40
+ - v24.4.2
41
+ - `params.txt` 파일이 없을 때 에러가 발생하지 않도록 수정
42
+ - 파이썬 3.9 이하에서 유니온 타입 에러 방지
43
+
44
+ ## 2024-04-14
45
+
46
+ - v24.4.1
47
+ - webui 1.9.0에서 발생한 에러 수정
48
+ - extra generation params에 callable이 들어와서 생긴 문제
49
+ - assign_current_image에 None이 들어갈 수 있던 문제
50
+ - webui 1.9.0에서 변경된 scheduler 지원
51
+ - 컨트롤넷 모델을 찾을 때, 대소문자 구분을 하지 않음 (PR #577)
52
+ - 몇몇 기능을 스크립트에서 분리하여 별도 파일로 빼냄
53
+
54
+ ## 2024-04-10
55
+
56
+ - v24.4.0
57
+ - txt2img에서 hires를 설정했을 때, 이미지의 exif에서 Denoising Strength가 adetailer의 denoisiog stregnth로 덮어 쓰이는 문제 수정
58
+ - ad prompt, ad negative prompt에 프롬프트를 변경하는 기능을 적용했을 때(와일드카드 등), 적용된 프롬프트가 이미지의 exif에 제대로 표시됨
59
+
60
+ ## 2024-03-29
61
+
62
+ - v24.3.5
63
+ - 알 수 없는 이유로 인페인팅을 확인하는 과정에서 Txt2Img 인스턴스가 들어오는 문제에 대한 임시 해결
64
+
65
+ ## 2024-03-28
66
+
67
+ - v24.3.4
68
+ - 인페인트에서, 이미지 해상도가 16의 배수가 아닐 때 사이즈 불일치로 인한 opencv 에러 방지
69
+
70
+ ## 2024-03-25
71
+
72
+ - v24.3.3
73
+ - webui 1.6.0 미만 버전에서 create_binary_mask 함수에 대해 ImportError가 발생하는 것 수정
74
+
75
+ ## 2024-03-21
76
+
77
+ - v24.3.2
78
+ - UI를 거치지 않은 입력에 대해, image_mask를 입력했을 때 opencv 에러가 발생하는 것 수정
79
+ - img2img inpaint에서 skip img2img 옵션을 활성화할 경우, adetailer를 비활성화함
80
+ - 마스크 크기에 대해 해결하기 힘든 문제가 있음
81
+
82
+ ## 2024-03-16
83
+
84
+ - v24.3.1
85
+ - YOLO World v2, YOLO9 지원가능한 버전으로 ultralytics 업데이트
86
+ - inpaint full res인 경우 인페인트 모드에서 동작하게 변경
87
+ - inpaint full res가 아닌 경우, 사용자가 입력한 마스크와 교차점이 있는 마스크만 선택하여 사용함
88
+
89
+ ## 2024-03-01
90
+
91
+ - v24.3.0
92
+ - YOLO World 모델 추가: 가장 큰 yolov8x-world.pt 모델만 기본적으로 선택할 수 있게 함.
93
+ - lllyasviel/stable-diffusion-webui-forge에서 컨트롤넷을 사용가능하게 함 (PR #517)
94
+ - 기본 스크립트 목록에 soft_inpainting 추가 (https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/14208)
95
+
96
+ - 기존에 설치한 사람에게 소급적용되지는 않음
97
+
98
+ - 감지모델에 대한 간단한 pytest 추가함
99
+ - xyz grid 컨트롤넷 모델 옵션에 `Passthrough` 추가함
100
+
101
+ ## 2024-01-23
102
+
103
+ - v24.1.2
104
+ - controlnet 모델에 `Passthrough` 옵션 추가. 입력으로 들어온 컨트롤넷 옵션을 그대로 사용
105
+ - fastapi 엔드포인트 추가
106
+
107
+ ## 2024-01-10
108
+
109
+ - v24.1.1
110
+ - SDNext 호환 업데이트 (issue #466)
111
+ - 설정 값 state에 초기값 추가
112
+ - 위젯 값을 변경할 때마다 state도 변경되게 함 (기존에는 생성 버튼을 누를 때 적용되었음)
113
+ - `inpaint_depth_hand` 컨트롤넷 모델이 depth 모델로 인식되게 함 (issue #463)
114
+
115
+ ## 2024-01-04
116
+
117
+ - v24.1.0
118
+ - `depth_hand_refiner` ControlNet 추가 (PR #460)
119
+
120
+ ## 2023-12-30
121
+
122
+ - v23.12.0
123
+ - 파일을 인자로 추가하는 몇몇 스크립트에 대해 deepcopy의 에러를 피하기 위해 script_args 복사 방법을 변경함
124
+ - skip img2img 기능을 사용할 때 너비, 높이를 128로 고정하여 스킵 과정이 조금 더 나아짐
125
+ - img2img inpainting 모드에서 adetailer 자동 비활성화
126
+ - 처음 생성된 params.txt 파일을 항상 유지하도록 변경함
127
+
128
+ ## 2023-11-19
129
+
130
+ - v23.11.1
131
+ - 기본 스크립트 목록에 negpip 추가
132
+ - 기존에 설치한 사람에게 소급적용되지는 않��
133
+ - skip img2img 옵션이 2스텝 이상일 때, 제대로 적용되지 않는 문제 수정
134
+ - SD.Next에서 이미지가 np.ndarray로 입력되는 경우 수정
135
+ - 컨트롤넷 경로를 sys.path에 추가하여 --data-dir등을 지정한 경우에도 임포트 에러가 일어나지 않게 함.
136
+
137
+ ## 2023-10-30
138
+
139
+ - v23.11.0
140
+ - 이미지의 인덱스 계산방법 변경
141
+ - webui 1.1.0 미만에서 adetailer 실행 불가능하게 함
142
+ - 컨트롤넷 preprocessor 선택지 늘림
143
+ - 추가 yolo 모델 디렉터리를 설정할 수 있는 옵션 추가
144
+ - infotext에 `/`가 있는 항목이 exif에서 복원되지 않는 문제 수정
145
+ - 이전 버전에 생성된 이미지는 여전히 복원안됨
146
+ - 같은 탭에서 항상 같은 시드를 적용하게 하는 옵션 추가
147
+ - 컨트롤넷 1.1.411 (f2aafcf2beb99a03cbdf7db73852228ccd6bd1d6) 버전을 사용중일 경우,
148
+ webui 버전 1.6.0 미만에서 사용할 수 없다는 메세지 출력
149
+
150
+ ## 2023-10-15
151
+
152
+ - v23.10.1
153
+ - xyz grid에 prompt S/R 추가
154
+ - img2img에서 steps가 1일때 에러가 발생하는 샘플러의 처리를 위해 샘플러 이름도 변경하게 수정
155
+
156
+ ## 2023-10-07
157
+
158
+ - v23.10.0
159
+ - 허깅페이스 모델을 다운로드 실패했을 때, 계속 다운로드를 시도하지 않음
160
+ - img2img에서 img2img단계를 건너뛰는 기능 추가
161
+ - live preview에서 감지 단계를 보여줌 (PR #352)
162
+
163
+ ## 2023-09-20
164
+
165
+ - v23.9.3
166
+ - ultralytics 버전 8.0.181로 업데이트 (https://github.com/ultralytics/ultralytics/pull/4891)
167
+ - mediapipe와 ultralytics의 lazy import
168
+
169
+ ## 2023-09-10
170
+
171
+ - v23.9.2
172
+ - (실험적) VAE 선택 기능
173
+
174
+ ## 2023-09-01
175
+
176
+ - v23.9.1
177
+ - webui 1.6.0에 추가된 인자를 사용해서 생긴 하위 호환 문제 수정
178
+
179
+ ## 2023-08-31
180
+
181
+ - v23.9.0
182
+ - (실험적) 체크포인트 선택기능
183
+ - 버그가 있어 리프레시 버튼은 구현에서 빠짐
184
+ - 1.6.0 업데이트에 따라 img2img에서 사용불가능한 샘플러를 선택했을 때 더이상 Euler로 변경하지 않음
185
+ - 유효하지 않은 인자가 전달되었을 때, 에러를 일으키지 않고 대신 adetailer를 비활성화함
186
+
187
+ ## 2023-08-25
188
+
189
+ - v23.8.1
190
+ - xyz grid에서 model을 `None`으로 설정한 이후에 adetailer가 비활성화 되는 문제 수정
191
+ - skip을 눌렀을 때 진행을 멈춤
192
+ - `--medvram-sdxl`을 설정했을 때에도 cpu를 사용하게 함
193
+
194
+ ## 2023-08-14
195
+
196
+ - v23.8.0
197
+ - `[PROMPT]` 키워드 추가. `ad_prompt` 또는 `ad_negative_prompt`에 사용하면 입력 프롬프트로 대체됨 (PR #243)
198
+ - Only top k largest 옵션 추가 (PR #264)
199
+ - ultralytics 버전 업데이트
200
+
201
+ ## 2023-07-31
202
+
203
+ - v23.7.11
204
+ - separate clip skip 옵션 추가
205
+ - install requirements 정리 (ultralytics 새 버전, mediapipe~=3.20)
206
+
207
+ ## 2023-07-28
208
+
209
+ - v23.7.10
210
+ - ultralytics, mediapipe import문 정리
211
+ - traceback에서 컬러를 없앰 (api 때문), 라이브러리 버전도 보여주게 설정.
212
+ - huggingface_hub, pydantic을 install.py에서 없앰
213
+ - 안쓰는 컨트롤넷 관련 코드 삭제
214
+
215
+ ## 2023-07-23
216
+
217
+ - v23.7.9
218
+ - `ultralytics.utils` ModuleNotFoundError 해결 (https://github.com/ultralytics/ultralytics/issues/3856)
219
+ - `pydantic` 2.0 이상 버전 설치안되도록 함
220
+ - `controlnet_dir` cmd args 문제 수정 (PR #107)
221
+
222
+ ## 2023-07-20
223
+
224
+ - v23.7.8
225
+ - `paste_field_names` 추가했던 것을 되돌림
226
+
227
+ ## 2023-07-19
228
+
229
+ - v23.7.7
230
+ - 인페인팅 단계에서 별도의 샘플러를 선택할 수 있게 옵션을 추가함 (xyz그리드에도 추가)
231
+ - webui 1.0.0-pre 이하 버전에서 batch index 문제 수정
232
+ - 스크립트에 `paste_field_names`을 추가함. 사용되는지는 모르겠음
233
+
234
+ ## 2023-07-16
235
+
236
+ - v23.7.6
237
+ - `ultralytics 8.0.135`에 추가된 cpuinfo 기능을 위해 `py-cpuinfo`를 미리 설치하게 함. (미리 설치 안하면 cpu나 mps사용할 때 재시작해야함)
238
+ - init_image가 RGB 모드가 아닐 때 RGB로 변경.
239
+
240
+ ## 2023-07-07
241
+
242
+ - v23.7.4
243
+ - batch count > 1일때 프롬프트의 인덱스 문제 수정
244
+
245
+ - v23.7.5
246
+ - i2i의 `cached_uc`와 `cached_c`가 p의 `cached_uc`와 `cached_c`가 다른 인스턴스가 되도록 수정
247
+
248
+ ## 2023-07-05
249
+
250
+ - v23.7.3
251
+ - 버그 수정
252
+ - `object()`가 json 직렬화 안되는 문제
253
+ - `process`를 호출함에 따라 배치 카운트가 2이상일 때, all_prompts가 고정되는 문제
254
+ - `ad-before`와 `ad-preview` 이미지 파일명이 실제 파일명과 다른 문제
255
+ - pydantic 2.0 호환성 문제
256
+
257
+ ## 2023-07-04
258
+
259
+ - v23.7.2
260
+ - `mediapipe_face_mesh_eyes_only` 모델 추가: `mediapipe_face_mesh`로 감지한 뒤 눈만 사용함.
261
+ - 매 배치 시작 전에 `scripts.postprocess`를, 후에 `scripts.process`를 호출함.
262
+ - 컨트롤넷을 사용하면 소요 시간이 조금 늘어나지만 몇몇 문제 해결에 도움이 됨.
263
+ - `lora_block_weight`를 스크립트 화이트리스트에 추가함.
264
+ - 한번이라도 ADetailer를 사용한 사람은 수동으로 추가해야함.
265
+
266
+ ## 2023-07-03
267
+
268
+ - v23.7.1
269
+ - `process_images`를 진행한 뒤 `StableDiffusionProcessing` 오브젝트의 close를 호출함
270
+ - api 호출로 사용했는지 확인하는 속성 추가
271
+ - `NansException`이 발생했을 때 중지하지 않고 남은 과정 계속 진행함
272
+
273
+ ## 2023-07-02
274
+
275
+ - v23.7.0
276
+ - `NansException`이 발생하면 로그에 표시하고 원본 이미지를 반환하게 설정
277
+ - `rich`를 사용한 에러 트레이싱
278
+ - install.py에 `rich` 추가
279
+ - 생성 중에 컴포넌트의 값을 변경하면 args의 값도 함께 변경되는 문제 수정 (issue #180)
280
+ - 터미널 로그로 ad_prompt와 ad_negative_prompt에 적용된 실제 프롬프트 확인할 수 있음 (입력과 다를 경우에만)
281
+
282
+ ## 2023-06-28
283
+
284
+ - v23.6.4
285
+ - 최대 모델 수 5 -> 10개
286
+ - ad_prompt와 ad_negative_prompt에 빈칸으로 놔두면 입력 프롬프트가 사용된다는 문구 추가
287
+ - huggingface 모델 다운로드 실패시 로깅
288
+ - 1st 모델이 `None`일 경우 나머지 입력을 무시하던 문제 수정
289
+ - `--use-cpu` 에 `adetailer` 입력 시 cpu로 yolo모델을 사용함
290
+
291
+ ## 2023-06-20
292
+
293
+ - v23.6.3
294
+ - 컨트롤넷 inpaint 모델에 대해, 3가지 모듈을 사용할 수 있도록 함
295
+ - Noise Multiplier 옵션 추가 (PR #149)
296
+ - pydantic 최소 버전 1.10.8로 설정 (Issue #146)
297
+
298
+ ## 2023-06-05
299
+
300
+ - v23.6.2
301
+ - xyz_grid에서 ADetailer를 사용할 수 있게함.
302
+ - 8가지 옵션만 1st 탭에 적용되도록 함.
303
+
304
+ ## 2023-06-01
305
+
306
+ - v23.6.1
307
+ - `inpaint, scribble, lineart, openpose, tile` 5가지 컨트롤넷 모델 지원 (PR #107)
308
+ - controlnet guidance start, end 인자 추가 (PR #107)
309
+ - `modules.extensions`를 사용하여 컨트롤넷 확장을 불러오고 경로를 알아내로록 변경
310
+ - ui에서 컨트롤넷을 별도 함수로 분리
311
+
312
+ ## 2023-05-30
313
+
314
+ - v23.6.0
315
+ - 스크립트의 이름을 `After Detailer`에서 `ADetailer`로 변경
316
+ - API 사용자는 변경 필요함
317
+ - 몇몇 설정 변경
318
+ - `ad_conf` → `ad_confidence`. 0~100 사이의 int → 0.0~1.0 사이의 float
319
+ - `ad_inpaint_full_res` → `ad_inpaint_only_masked`
320
+ - `ad_inpaint_full_res_padding` → `ad_inpaint_only_masked_padding`
321
+ - mediapipe face mesh 모델 추가
322
+
323
+ - mediapipe 최소 버전 `0.10.0`
324
+
325
+ - rich traceback 제거함
326
+ - huggingface 다운로드 실패할 때 에러가 나지 않게 하고 해당 모델을 제거함
327
+
328
+ ## 2023-05-26
329
+
330
+ - v23.5.19
331
+ - 1번째 탭에도 `None` 옵션을 추가함
332
+ - api로 ad controlnet model에 inpaint가 아닌 다른 컨트롤넷 모델을 사용하지 못하도록 막음
333
+ - adetailer 진행중에 total tqdm 진행바 업데이트를 멈춤
334
+ - state.inturrupted 상태에서 adetailer 과정을 중지함
335
+ - 컨트롤넷 process를 각 batch가 끝난 순간에만 호출하도록 변경
336
+
337
+ ### 2023-05-25
338
+
339
+ - v23.5.18
340
+ - 컨트롤넷 관련 수정
341
+ - unit의 `input_mode`를 `SIMPLE`로 모두 변경
342
+ - 컨트롤넷 유넷 훅과 하이잭 함수들을 adetailer를 실행할 때에만 되돌리는 기능 추가
343
+ - adetailer 처리가 끝난 뒤 컨트롤넷 스크립트의 process를 다시 진행함. (batch count 2 이상일때의 문제 해결)
344
+ - 기본 활성 스크립트 목록에서 컨트롤넷을 뺌
345
+
346
+ ### 2023-05-22
347
+
348
+ - v23.5.17
349
+ - 컨트롤넷 확장이 있으면 컨트롤넷 스크립트를 활성화함. (컨트롤넷 관련 문제 해결)
350
+ - 모든 컴포넌트에 elem_id 설정
351
+ - ui에 버전을 표시함
352
+
353
+ ### 2023-05-19
354
+
355
+ - v23.5.16
356
+ - 추가한 옵션
357
+ - Mask min/max ratio
358
+ - Mask merge mode
359
+ - Restore faces after ADetailer
360
+ - 옵션들을 Accordion으로 묶음
361
+
362
+ ### 2023-05-18
363
+
364
+ - v23.5.15
365
+ - 필요한 것만 임포트하도록 변경 (vae 로딩 오류 없어짐. 로딩 속도 빨라짐)
366
+
367
+ ### 2023-05-17
368
+
369
+ - v23.5.14
370
+ - `[SKIP]`으로 ad prompt 일부를 건너뛰는 기능 추가
371
+ - bbox 정렬 옵션 추가
372
+ - sd_webui 타입힌트를 만들어냄
373
+ - enable checker와 관련된 api 오류 수정?
374
+
375
+ ### 2023-05-15
376
+
377
+ - v23.5.13
378
+ - `[SEP]`으로 ad prompt를 분리하여 적용하는 기능 추가
379
+ - enable checker를 다시 pydantic으로 변경함
380
+ - ui 관련 함수를 adetailer.ui 폴더로 분리함
381
+ - controlnet을 사용할 때 모든 controlnet unit 비활성화
382
+ - adetailer 폴더가 없으면 만들게 함
383
+
384
+ ### 2023-05-13
385
+
386
+ - v23.5.12
387
+ - `ad_enable`을 제외한 입력이 dict타입으로 들어오도록 변경
388
+ - web api로 사용할 때에 특히 사용하기 쉬움
389
+ - web api breaking change
390
+ - `mask_preprocess` 인자를 넣지 않았던 오류 수정 (PR #47)
391
+ - huggingface에서 모델을 다운로드하지 않는 옵션 추가 `--ad-no-huggingface`
392
+
393
+ ### 2023-05-12
394
+
395
+ - v23.5.11
396
+ - `ultralytics` 알람 제거
397
+ - 필요없는 exif 인자 더 제거함
398
+ - `use separate steps` 옵션 추가
399
+ - ui 배치를 조정함
400
+
401
+ ### 2023-05-09
402
+
403
+ - v23.5.10
404
+ - 선택한 스크립트만 ADetailer에 적용하는 옵션 추가, 기본값 `True`. 설정 탭에서 지정가능.
405
+ - 기본값: `dynamic_prompting,dynamic_thresholding,wildcards,wildcard_recursive`
406
+ - `person_yolov8s-seg.pt` 모델 추가
407
+ - `ultralytics`의 최소 버전을 `8.0.97`로 설정 (C:\\ 문제 해결된 버전)
408
+
409
+ ### 2023-05-08
410
+
411
+ - v23.5.9
412
+ - 2가지 이상의 모델을 사용할 수 있음. 기본값: 2, 최대: 5
413
+ - segment 모델을 사용할 수 있게 함. `person_yolov8n-seg.pt` 추가
414
+
415
+ ### 2023-05-07
416
+
417
+ - v23.5.8
418
+ - 프롬프트와 네거티브 프롬프트에 방향키 지원 (PR #24)
419
+ - `mask_preprocess`를 추가함. 이전 버전과 시드값이 달라질 가능성 있음!
420
+ - 이미지 처리가 일어났을 때에만 before이미지를 저장함
421
+ - 설정창의 레이블을 ADetailer 대신 더 적절하게 수정함
422
+
423
+ ### 2023-05-06
424
+
425
+ - v23.5.7
426
+ - `ad_use_cfg_scale` 옵션 추가. cfg 스케일을 따로 사용할지 말지 결정함.
427
+ - `ad_enable` 기본값을 `True`에서 `False`로 변경
428
+ - `ad_model`의 기본값을 `None`에서 첫번째 모델로 변경
429
+ - 최소 2개의 입력(ad_enable, ad_model)만 들어오면 작동하게 변경.
430
+
431
+ - v23.5.7.post0
432
+ - `init_controlnet_ext`을 controlnet_exists == True일때에만 실행
433
+ - webui를 C드라이브 바로 밑에 설치한 사람들에게 `ultralytics` 경고 표시
434
+
435
+ ### 2023-05-05 (어린이날)
436
+
437
+ - v23.5.5
438
+ - `Save images before ADetailer` 옵션 추가
439
+ - 입력으로 들어온 인자와 ALL_ARGS의 길이가 다르면 에러메세지
440
+ - README.md에 설치방법 추가
441
+
442
+ - v23.5.6
443
+ - get_args에서 IndexError가 발생하면 자세한 에러메세지를 볼 수 있음
444
+ - AdetailerArgs에 extra_params 내장
445
+ - scripts_args를 딥카피함
446
+ - postprocess_image를 약간 분리함
447
+
448
+ - v23.5.6.post0
449
+ - `init_controlnet_ext`에서 에러메세지를 자세히 볼 수 있음
450
+
451
+ ### 2023-05-04
452
+
453
+ - v23.5.4
454
+ - use pydantic for arguments validation
455
+ - revert: ad_model to `None` as default
456
+ - revert: `__future__` imports
457
+ - lazily import yolo and mediapipe
458
+
459
+ ### 2023-05-03
460
+
461
+ - v23.5.3.post0
462
+ - remove `__future__` imports
463
+ - change to copy scripts and scripts args
464
+
465
+ - v23.5.3.post1
466
+ - change default ad_model from `None`
467
+
468
+ ### 2023-05-02
469
+
470
+ - v23.5.3
471
+ - Remove `None` from model list and add `Enable ADetailer` checkbox.
472
+ - install.py `skip_install` fix.
extensions/4-adetailer/LICENSE.md ADDED
@@ -0,0 +1,661 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ GNU AFFERO GENERAL PUBLIC LICENSE
2
+ Version 3, 19 November 2007
3
+
4
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
5
+ Everyone is permitted to copy and distribute verbatim copies
6
+ of this license document, but changing it is not allowed.
7
+
8
+ Preamble
9
+
10
+ The GNU Affero General Public License is a free, copyleft license for
11
+ software and other kinds of works, specifically designed to ensure
12
+ cooperation with the community in the case of network server software.
13
+
14
+ The licenses for most software and other practical works are designed
15
+ to take away your freedom to share and change the works. By contrast,
16
+ our General Public Licenses are intended to guarantee your freedom to
17
+ share and change all versions of a program--to make sure it remains free
18
+ software for all its users.
19
+
20
+ When we speak of free software, we are referring to freedom, not
21
+ price. Our General Public Licenses are designed to make sure that you
22
+ have the freedom to distribute copies of free software (and charge for
23
+ them if you wish), that you receive source code or can get it if you
24
+ want it, that you can change the software or use pieces of it in new
25
+ free programs, and that you know you can do these things.
26
+
27
+ Developers that use our General Public Licenses protect your rights
28
+ with two steps: (1) assert copyright on the software, and (2) offer
29
+ you this License which gives you legal permission to copy, distribute
30
+ and/or modify the software.
31
+
32
+ A secondary benefit of defending all users' freedom is that
33
+ improvements made in alternate versions of the program, if they
34
+ receive widespread use, become available for other developers to
35
+ incorporate. Many developers of free software are heartened and
36
+ encouraged by the resulting cooperation. However, in the case of
37
+ software used on network servers, this result may fail to come about.
38
+ The GNU General Public License permits making a modified version and
39
+ letting the public access it on a server without ever releasing its
40
+ source code to the public.
41
+
42
+ The GNU Affero General Public License is designed specifically to
43
+ ensure that, in such cases, the modified source code becomes available
44
+ to the community. It requires the operator of a network server to
45
+ provide the source code of the modified version running there to the
46
+ users of that server. Therefore, public use of a modified version, on
47
+ a publicly accessible server, gives the public access to the source
48
+ code of the modified version.
49
+
50
+ An older license, called the Affero General Public License and
51
+ published by Affero, was designed to accomplish similar goals. This is
52
+ a different license, not a version of the Affero GPL, but Affero has
53
+ released a new version of the Affero GPL which permits relicensing under
54
+ this license.
55
+
56
+ The precise terms and conditions for copying, distribution and
57
+ modification follow.
58
+
59
+ TERMS AND CONDITIONS
60
+
61
+ 0. Definitions.
62
+
63
+ "This License" refers to version 3 of the GNU Affero General Public License.
64
+
65
+ "Copyright" also means copyright-like laws that apply to other kinds of
66
+ works, such as semiconductor masks.
67
+
68
+ "The Program" refers to any copyrightable work licensed under this
69
+ License. Each licensee is addressed as "you". "Licensees" and
70
+ "recipients" may be individuals or organizations.
71
+
72
+ To "modify" a work means to copy from or adapt all or part of the work
73
+ in a fashion requiring copyright permission, other than the making of an
74
+ exact copy. The resulting work is called a "modified version" of the
75
+ earlier work or a work "based on" the earlier work.
76
+
77
+ A "covered work" means either the unmodified Program or a work based
78
+ on the Program.
79
+
80
+ To "propagate" a work means to do anything with it that, without
81
+ permission, would make you directly or secondarily liable for
82
+ infringement under applicable copyright law, except executing it on a
83
+ computer or modifying a private copy. Propagation includes copying,
84
+ distribution (with or without modification), making available to the
85
+ public, and in some countries other activities as well.
86
+
87
+ To "convey" a work means any kind of propagation that enables other
88
+ parties to make or receive copies. Mere interaction with a user through
89
+ a computer network, with no transfer of a copy, is not conveying.
90
+
91
+ An interactive user interface displays "Appropriate Legal Notices"
92
+ to the extent that it includes a convenient and prominently visible
93
+ feature that (1) displays an appropriate copyright notice, and (2)
94
+ tells the user that there is no warranty for the work (except to the
95
+ extent that warranties are provided), that licensees may convey the
96
+ work under this License, and how to view a copy of this License. If
97
+ the interface presents a list of user commands or options, such as a
98
+ menu, a prominent item in the list meets this criterion.
99
+
100
+ 1. Source Code.
101
+
102
+ The "source code" for a work means the preferred form of the work
103
+ for making modifications to it. "Object code" means any non-source
104
+ form of a work.
105
+
106
+ A "Standard Interface" means an interface that either is an official
107
+ standard defined by a recognized standards body, or, in the case of
108
+ interfaces specified for a particular programming language, one that
109
+ is widely used among developers working in that language.
110
+
111
+ The "System Libraries" of an executable work include anything, other
112
+ than the work as a whole, that (a) is included in the normal form of
113
+ packaging a Major Component, but which is not part of that Major
114
+ Component, and (b) serves only to enable use of the work with that
115
+ Major Component, or to implement a Standard Interface for which an
116
+ implementation is available to the public in source code form. A
117
+ "Major Component", in this context, means a major essential component
118
+ (kernel, window system, and so on) of the specific operating system
119
+ (if any) on which the executable work runs, or a compiler used to
120
+ produce the work, or an object code interpreter used to run it.
121
+
122
+ The "Corresponding Source" for a work in object code form means all
123
+ the source code needed to generate, install, and (for an executable
124
+ work) run the object code and to modify the work, including scripts to
125
+ control those activities. However, it does not include the work's
126
+ System Libraries, or general-purpose tools or generally available free
127
+ programs which are used unmodified in performing those activities but
128
+ which are not part of the work. For example, Corresponding Source
129
+ includes interface definition files associated with source files for
130
+ the work, and the source code for shared libraries and dynamically
131
+ linked subprograms that the work is specifically designed to require,
132
+ such as by intimate data communication or control flow between those
133
+ subprograms and other parts of the work.
134
+
135
+ The Corresponding Source need not include anything that users
136
+ can regenerate automatically from other parts of the Corresponding
137
+ Source.
138
+
139
+ The Corresponding Source for a work in source code form is that
140
+ same work.
141
+
142
+ 2. Basic Permissions.
143
+
144
+ All rights granted under this License are granted for the term of
145
+ copyright on the Program, and are irrevocable provided the stated
146
+ conditions are met. This License explicitly affirms your unlimited
147
+ permission to run the unmodified Program. The output from running a
148
+ covered work is covered by this License only if the output, given its
149
+ content, constitutes a covered work. This License acknowledges your
150
+ rights of fair use or other equivalent, as provided by copyright law.
151
+
152
+ You may make, run and propagate covered works that you do not
153
+ convey, without conditions so long as your license otherwise remains
154
+ in force. You may convey covered works to others for the sole purpose
155
+ of having them make modifications exclusively for you, or provide you
156
+ with facilities for running those works, provided that you comply with
157
+ the terms of this License in conveying all material for which you do
158
+ not control copyright. Those thus making or running the covered works
159
+ for you must do so exclusively on your behalf, under your direction
160
+ and control, on terms that prohibit them from making any copies of
161
+ your copyrighted material outside their relationship with you.
162
+
163
+ Conveying under any other circumstances is permitted solely under
164
+ the conditions stated below. Sublicensing is not allowed; section 10
165
+ makes it unnecessary.
166
+
167
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
168
+
169
+ No covered work shall be deemed part of an effective technological
170
+ measure under any applicable law fulfilling obligations under article
171
+ 11 of the WIPO copyright treaty adopted on 20 December 1996, or
172
+ similar laws prohibiting or restricting circumvention of such
173
+ measures.
174
+
175
+ When you convey a covered work, you waive any legal power to forbid
176
+ circumvention of technological measures to the extent such circumvention
177
+ is effected by exercising rights under this License with respect to
178
+ the covered work, and you disclaim any intention to limit operation or
179
+ modification of the work as a means of enforcing, against the work's
180
+ users, your or third parties' legal rights to forbid circumvention of
181
+ technological measures.
182
+
183
+ 4. Conveying Verbatim Copies.
184
+
185
+ You may convey verbatim copies of the Program's source code as you
186
+ receive it, in any medium, provided that you conspicuously and
187
+ appropriately publish on each copy an appropriate copyright notice;
188
+ keep intact all notices stating that this License and any
189
+ non-permissive terms added in accord with section 7 apply to the code;
190
+ keep intact all notices of the absence of any warranty; and give all
191
+ recipients a copy of this License along with the Program.
192
+
193
+ You may charge any price or no price for each copy that you convey,
194
+ and you may offer support or warranty protection for a fee.
195
+
196
+ 5. Conveying Modified Source Versions.
197
+
198
+ You may convey a work based on the Program, or the modifications to
199
+ produce it from the Program, in the form of source code under the
200
+ terms of section 4, provided that you also meet all of these conditions:
201
+
202
+ a) The work must carry prominent notices stating that you modified
203
+ it, and giving a relevant date.
204
+
205
+ b) The work must carry prominent notices stating that it is
206
+ released under this License and any conditions added under section
207
+ 7. This requirement modifies the requirement in section 4 to
208
+ "keep intact all notices".
209
+
210
+ c) You must license the entire work, as a whole, under this
211
+ License to anyone who comes into possession of a copy. This
212
+ License will therefore apply, along with any applicable section 7
213
+ additional terms, to the whole of the work, and all its parts,
214
+ regardless of how they are packaged. This License gives no
215
+ permission to license the work in any other way, but it does not
216
+ invalidate such permission if you have separately received it.
217
+
218
+ d) If the work has interactive user interfaces, each must display
219
+ Appropriate Legal Notices; however, if the Program has interactive
220
+ interfaces that do not display Appropriate Legal Notices, your
221
+ work need not make them do so.
222
+
223
+ A compilation of a covered work with other separate and independent
224
+ works, which are not by their nature extensions of the covered work,
225
+ and which are not combined with it such as to form a larger program,
226
+ in or on a volume of a storage or distribution medium, is called an
227
+ "aggregate" if the compilation and its resulting copyright are not
228
+ used to limit the access or legal rights of the compilation's users
229
+ beyond what the individual works permit. Inclusion of a covered work
230
+ in an aggregate does not cause this License to apply to the other
231
+ parts of the aggregate.
232
+
233
+ 6. Conveying Non-Source Forms.
234
+
235
+ You may convey a covered work in object code form under the terms
236
+ of sections 4 and 5, provided that you also convey the
237
+ machine-readable Corresponding Source under the terms of this License,
238
+ in one of these ways:
239
+
240
+ a) Convey the object code in, or embodied in, a physical product
241
+ (including a physical distribution medium), accompanied by the
242
+ Corresponding Source fixed on a durable physical medium
243
+ customarily used for software interchange.
244
+
245
+ b) Convey the object code in, or embodied in, a physical product
246
+ (including a physical distribution medium), accompanied by a
247
+ written offer, valid for at least three years and valid for as
248
+ long as you offer spare parts or customer support for that product
249
+ model, to give anyone who possesses the object code either (1) a
250
+ copy of the Corresponding Source for all the software in the
251
+ product that is covered by this License, on a durable physical
252
+ medium customarily used for software interchange, for a price no
253
+ more than your reasonable cost of physically performing this
254
+ conveying of source, or (2) access to copy the
255
+ Corresponding Source from a network server at no charge.
256
+
257
+ c) Convey individual copies of the object code with a copy of the
258
+ written offer to provide the Corresponding Source. This
259
+ alternative is allowed only occasionally and noncommercially, and
260
+ only if you received the object code with such an offer, in accord
261
+ with subsection 6b.
262
+
263
+ d) Convey the object code by offering access from a designated
264
+ place (gratis or for a charge), and offer equivalent access to the
265
+ Corresponding Source in the same way through the same place at no
266
+ further charge. You need not require recipients to copy the
267
+ Corresponding Source along with the object code. If the place to
268
+ copy the object code is a network server, the Corresponding Source
269
+ may be on a different server (operated by you or a third party)
270
+ that supports equivalent copying facilities, provided you maintain
271
+ clear directions next to the object code saying where to find the
272
+ Corresponding Source. Regardless of what server hosts the
273
+ Corresponding Source, you remain obligated to ensure that it is
274
+ available for as long as needed to satisfy these requirements.
275
+
276
+ e) Convey the object code using peer-to-peer transmission, provided
277
+ you inform other peers where the object code and Corresponding
278
+ Source of the work are being offered to the general public at no
279
+ charge under subsection 6d.
280
+
281
+ A separable portion of the object code, whose source code is excluded
282
+ from the Corresponding Source as a System Library, need not be
283
+ included in conveying the object code work.
284
+
285
+ A "User Product" is either (1) a "consumer product", which means any
286
+ tangible personal property which is normally used for personal, family,
287
+ or household purposes, or (2) anything designed or sold for incorporation
288
+ into a dwelling. In determining whether a product is a consumer product,
289
+ doubtful cases shall be resolved in favor of coverage. For a particular
290
+ product received by a particular user, "normally used" refers to a
291
+ typical or common use of that class of product, regardless of the status
292
+ of the particular user or of the way in which the particular user
293
+ actually uses, or expects or is expected to use, the product. A product
294
+ is a consumer product regardless of whether the product has substantial
295
+ commercial, industrial or non-consumer uses, unless such uses represent
296
+ the only significant mode of use of the product.
297
+
298
+ "Installation Information" for a User Product means any methods,
299
+ procedures, authorization keys, or other information required to install
300
+ and execute modified versions of a covered work in that User Product from
301
+ a modified version of its Corresponding Source. The information must
302
+ suffice to ensure that the continued functioning of the modified object
303
+ code is in no case prevented or interfered with solely because
304
+ modification has been made.
305
+
306
+ If you convey an object code work under this section in, or with, or
307
+ specifically for use in, a User Product, and the conveying occurs as
308
+ part of a transaction in which the right of possession and use of the
309
+ User Product is transferred to the recipient in perpetuity or for a
310
+ fixed term (regardless of how the transaction is characterized), the
311
+ Corresponding Source conveyed under this section must be accompanied
312
+ by the Installation Information. But this requirement does not apply
313
+ if neither you nor any third party retains the ability to install
314
+ modified object code on the User Product (for example, the work has
315
+ been installed in ROM).
316
+
317
+ The requirement to provide Installation Information does not include a
318
+ requirement to continue to provide support service, warranty, or updates
319
+ for a work that has been modified or installed by the recipient, or for
320
+ the User Product in which it has been modified or installed. Access to a
321
+ network may be denied when the modification itself materially and
322
+ adversely affects the operation of the network or violates the rules and
323
+ protocols for communication across the network.
324
+
325
+ Corresponding Source conveyed, and Installation Information provided,
326
+ in accord with this section must be in a format that is publicly
327
+ documented (and with an implementation available to the public in
328
+ source code form), and must require no special password or key for
329
+ unpacking, reading or copying.
330
+
331
+ 7. Additional Terms.
332
+
333
+ "Additional permissions" are terms that supplement the terms of this
334
+ License by making exceptions from one or more of its conditions.
335
+ Additional permissions that are applicable to the entire Program shall
336
+ be treated as though they were included in this License, to the extent
337
+ that they are valid under applicable law. If additional permissions
338
+ apply only to part of the Program, that part may be used separately
339
+ under those permissions, but the entire Program remains governed by
340
+ this License without regard to the additional permissions.
341
+
342
+ When you convey a copy of a covered work, you may at your option
343
+ remove any additional permissions from that copy, or from any part of
344
+ it. (Additional permissions may be written to require their own
345
+ removal in certain cases when you modify the work.) You may place
346
+ additional permissions on material, added by you to a covered work,
347
+ for which you have or can give appropriate copyright permission.
348
+
349
+ Notwithstanding any other provision of this License, for material you
350
+ add to a covered work, you may (if authorized by the copyright holders of
351
+ that material) supplement the terms of this License with terms:
352
+
353
+ a) Disclaiming warranty or limiting liability differently from the
354
+ terms of sections 15 and 16 of this License; or
355
+
356
+ b) Requiring preservation of specified reasonable legal notices or
357
+ author attributions in that material or in the Appropriate Legal
358
+ Notices displayed by works containing it; or
359
+
360
+ c) Prohibiting misrepresentation of the origin of that material, or
361
+ requiring that modified versions of such material be marked in
362
+ reasonable ways as different from the original version; or
363
+
364
+ d) Limiting the use for publicity purposes of names of licensors or
365
+ authors of the material; or
366
+
367
+ e) Declining to grant rights under trademark law for use of some
368
+ trade names, trademarks, or service marks; or
369
+
370
+ f) Requiring indemnification of licensors and authors of that
371
+ material by anyone who conveys the material (or modified versions of
372
+ it) with contractual assumptions of liability to the recipient, for
373
+ any liability that these contractual assumptions directly impose on
374
+ those licensors and authors.
375
+
376
+ All other non-permissive additional terms are considered "further
377
+ restrictions" within the meaning of section 10. If the Program as you
378
+ received it, or any part of it, contains a notice stating that it is
379
+ governed by this License along with a term that is a further
380
+ restriction, you may remove that term. If a license document contains
381
+ a further restriction but permits relicensing or conveying under this
382
+ License, you may add to a covered work material governed by the terms
383
+ of that license document, provided that the further restriction does
384
+ not survive such relicensing or conveying.
385
+
386
+ If you add terms to a covered work in accord with this section, you
387
+ must place, in the relevant source files, a statement of the
388
+ additional terms that apply to those files, or a notice indicating
389
+ where to find the applicable terms.
390
+
391
+ Additional terms, permissive or non-permissive, may be stated in the
392
+ form of a separately written license, or stated as exceptions;
393
+ the above requirements apply either way.
394
+
395
+ 8. Termination.
396
+
397
+ You may not propagate or modify a covered work except as expressly
398
+ provided under this License. Any attempt otherwise to propagate or
399
+ modify it is void, and will automatically terminate your rights under
400
+ this License (including any patent licenses granted under the third
401
+ paragraph of section 11).
402
+
403
+ However, if you cease all violation of this License, then your
404
+ license from a particular copyright holder is reinstated (a)
405
+ provisionally, unless and until the copyright holder explicitly and
406
+ finally terminates your license, and (b) permanently, if the copyright
407
+ holder fails to notify you of the violation by some reasonable means
408
+ prior to 60 days after the cessation.
409
+
410
+ Moreover, your license from a particular copyright holder is
411
+ reinstated permanently if the copyright holder notifies you of the
412
+ violation by some reasonable means, this is the first time you have
413
+ received notice of violation of this License (for any work) from that
414
+ copyright holder, and you cure the violation prior to 30 days after
415
+ your receipt of the notice.
416
+
417
+ Termination of your rights under this section does not terminate the
418
+ licenses of parties who have received copies or rights from you under
419
+ this License. If your rights have been terminated and not permanently
420
+ reinstated, you do not qualify to receive new licenses for the same
421
+ material under section 10.
422
+
423
+ 9. Acceptance Not Required for Having Copies.
424
+
425
+ You are not required to accept this License in order to receive or
426
+ run a copy of the Program. Ancillary propagation of a covered work
427
+ occurring solely as a consequence of using peer-to-peer transmission
428
+ to receive a copy likewise does not require acceptance. However,
429
+ nothing other than this License grants you permission to propagate or
430
+ modify any covered work. These actions infringe copyright if you do
431
+ not accept this License. Therefore, by modifying or propagating a
432
+ covered work, you indicate your acceptance of this License to do so.
433
+
434
+ 10. Automatic Licensing of Downstream Recipients.
435
+
436
+ Each time you convey a covered work, the recipient automatically
437
+ receives a license from the original licensors, to run, modify and
438
+ propagate that work, subject to this License. You are not responsible
439
+ for enforcing compliance by third parties with this License.
440
+
441
+ An "entity transaction" is a transaction transferring control of an
442
+ organization, or substantially all assets of one, or subdividing an
443
+ organization, or merging organizations. If propagation of a covered
444
+ work results from an entity transaction, each party to that
445
+ transaction who receives a copy of the work also receives whatever
446
+ licenses to the work the party's predecessor in interest had or could
447
+ give under the previous paragraph, plus a right to possession of the
448
+ Corresponding Source of the work from the predecessor in interest, if
449
+ the predecessor has it or can get it with reasonable efforts.
450
+
451
+ You may not impose any further restrictions on the exercise of the
452
+ rights granted or affirmed under this License. For example, you may
453
+ not impose a license fee, royalty, or other charge for exercise of
454
+ rights granted under this License, and you may not initiate litigation
455
+ (including a cross-claim or counterclaim in a lawsuit) alleging that
456
+ any patent claim is infringed by making, using, selling, offering for
457
+ sale, or importing the Program or any portion of it.
458
+
459
+ 11. Patents.
460
+
461
+ A "contributor" is a copyright holder who authorizes use under this
462
+ License of the Program or a work on which the Program is based. The
463
+ work thus licensed is called the contributor's "contributor version".
464
+
465
+ A contributor's "essential patent claims" are all patent claims
466
+ owned or controlled by the contributor, whether already acquired or
467
+ hereafter acquired, that would be infringed by some manner, permitted
468
+ by this License, of making, using, or selling its contributor version,
469
+ but do not include claims that would be infringed only as a
470
+ consequence of further modification of the contributor version. For
471
+ purposes of this definition, "control" includes the right to grant
472
+ patent sublicenses in a manner consistent with the requirements of
473
+ this License.
474
+
475
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
476
+ patent license under the contributor's essential patent claims, to
477
+ make, use, sell, offer for sale, import and otherwise run, modify and
478
+ propagate the contents of its contributor version.
479
+
480
+ In the following three paragraphs, a "patent license" is any express
481
+ agreement or commitment, however denominated, not to enforce a patent
482
+ (such as an express permission to practice a patent or covenant not to
483
+ sue for patent infringement). To "grant" such a patent license to a
484
+ party means to make such an agreement or commitment not to enforce a
485
+ patent against the party.
486
+
487
+ If you convey a covered work, knowingly relying on a patent license,
488
+ and the Corresponding Source of the work is not available for anyone
489
+ to copy, free of charge and under the terms of this License, through a
490
+ publicly available network server or other readily accessible means,
491
+ then you must either (1) cause the Corresponding Source to be so
492
+ available, or (2) arrange to deprive yourself of the benefit of the
493
+ patent license for this particular work, or (3) arrange, in a manner
494
+ consistent with the requirements of this License, to extend the patent
495
+ license to downstream recipients. "Knowingly relying" means you have
496
+ actual knowledge that, but for the patent license, your conveying the
497
+ covered work in a country, or your recipient's use of the covered work
498
+ in a country, would infringe one or more identifiable patents in that
499
+ country that you have reason to believe are valid.
500
+
501
+ If, pursuant to or in connection with a single transaction or
502
+ arrangement, you convey, or propagate by procuring conveyance of, a
503
+ covered work, and grant a patent license to some of the parties
504
+ receiving the covered work authorizing them to use, propagate, modify
505
+ or convey a specific copy of the covered work, then the patent license
506
+ you grant is automatically extended to all recipients of the covered
507
+ work and works based on it.
508
+
509
+ A patent license is "discriminatory" if it does not include within
510
+ the scope of its coverage, prohibits the exercise of, or is
511
+ conditioned on the non-exercise of one or more of the rights that are
512
+ specifically granted under this License. You may not convey a covered
513
+ work if you are a party to an arrangement with a third party that is
514
+ in the business of distributing software, under which you make payment
515
+ to the third party based on the extent of your activity of conveying
516
+ the work, and under which the third party grants, to any of the
517
+ parties who would receive the covered work from you, a discriminatory
518
+ patent license (a) in connection with copies of the covered work
519
+ conveyed by you (or copies made from those copies), or (b) primarily
520
+ for and in connection with specific products or compilations that
521
+ contain the covered work, unless you entered into that arrangement,
522
+ or that patent license was granted, prior to 28 March 2007.
523
+
524
+ Nothing in this License shall be construed as excluding or limiting
525
+ any implied license or other defenses to infringement that may
526
+ otherwise be available to you under applicable patent law.
527
+
528
+ 12. No Surrender of Others' Freedom.
529
+
530
+ If conditions are imposed on you (whether by court order, agreement or
531
+ otherwise) that contradict the conditions of this License, they do not
532
+ excuse you from the conditions of this License. If you cannot convey a
533
+ covered work so as to satisfy simultaneously your obligations under this
534
+ License and any other pertinent obligations, then as a consequence you may
535
+ not convey it at all. For example, if you agree to terms that obligate you
536
+ to collect a royalty for further conveying from those to whom you convey
537
+ the Program, the only way you could satisfy both those terms and this
538
+ License would be to refrain entirely from conveying the Program.
539
+
540
+ 13. Remote Network Interaction; Use with the GNU General Public License.
541
+
542
+ Notwithstanding any other provision of this License, if you modify the
543
+ Program, your modified version must prominently offer all users
544
+ interacting with it remotely through a computer network (if your version
545
+ supports such interaction) an opportunity to receive the Corresponding
546
+ Source of your version by providing access to the Corresponding Source
547
+ from a network server at no charge, through some standard or customary
548
+ means of facilitating copying of software. This Corresponding Source
549
+ shall include the Corresponding Source for any work covered by version 3
550
+ of the GNU General Public License that is incorporated pursuant to the
551
+ following paragraph.
552
+
553
+ Notwithstanding any other provision of this License, you have
554
+ permission to link or combine any covered work with a work licensed
555
+ under version 3 of the GNU General Public License into a single
556
+ combined work, and to convey the resulting work. The terms of this
557
+ License will continue to apply to the part which is the covered work,
558
+ but the work with which it is combined will remain governed by version
559
+ 3 of the GNU General Public License.
560
+
561
+ 14. Revised Versions of this License.
562
+
563
+ The Free Software Foundation may publish revised and/or new versions of
564
+ the GNU Affero General Public License from time to time. Such new versions
565
+ will be similar in spirit to the present version, but may differ in detail to
566
+ address new problems or concerns.
567
+
568
+ Each version is given a distinguishing version number. If the
569
+ Program specifies that a certain numbered version of the GNU Affero General
570
+ Public License "or any later version" applies to it, you have the
571
+ option of following the terms and conditions either of that numbered
572
+ version or of any later version published by the Free Software
573
+ Foundation. If the Program does not specify a version number of the
574
+ GNU Affero General Public License, you may choose any version ever published
575
+ by the Free Software Foundation.
576
+
577
+ If the Program specifies that a proxy can decide which future
578
+ versions of the GNU Affero General Public License can be used, that proxy's
579
+ public statement of acceptance of a version permanently authorizes you
580
+ to choose that version for the Program.
581
+
582
+ Later license versions may give you additional or different
583
+ permissions. However, no additional obligations are imposed on any
584
+ author or copyright holder as a result of your choosing to follow a
585
+ later version.
586
+
587
+ 15. Disclaimer of Warranty.
588
+
589
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
590
+ APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
591
+ HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
592
+ OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
593
+ THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
594
+ PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
595
+ IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
596
+ ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
597
+
598
+ 16. Limitation of Liability.
599
+
600
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
601
+ WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
602
+ THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
603
+ GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
604
+ USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
605
+ DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
606
+ PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
607
+ EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
608
+ SUCH DAMAGES.
609
+
610
+ 17. Interpretation of Sections 15 and 16.
611
+
612
+ If the disclaimer of warranty and limitation of liability provided
613
+ above cannot be given local legal effect according to their terms,
614
+ reviewing courts shall apply local law that most closely approximates
615
+ an absolute waiver of all civil liability in connection with the
616
+ Program, unless a warranty or assumption of liability accompanies a
617
+ copy of the Program in return for a fee.
618
+
619
+ END OF TERMS AND CONDITIONS
620
+
621
+ How to Apply These Terms to Your New Programs
622
+
623
+ If you develop a new program, and you want it to be of the greatest
624
+ possible use to the public, the best way to achieve this is to make it
625
+ free software which everyone can redistribute and change under these terms.
626
+
627
+ To do so, attach the following notices to the program. It is safest
628
+ to attach them to the start of each source file to most effectively
629
+ state the exclusion of warranty; and each file should have at least
630
+ the "copyright" line and a pointer to where the full notice is found.
631
+
632
+ <one line to give the program's name and a brief idea of what it does.>
633
+ Copyright (C) <year> <name of author>
634
+
635
+ This program is free software: you can redistribute it and/or modify
636
+ it under the terms of the GNU Affero General Public License as published
637
+ by the Free Software Foundation, either version 3 of the License, or
638
+ (at your option) any later version.
639
+
640
+ This program is distributed in the hope that it will be useful,
641
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
642
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
643
+ GNU Affero General Public License for more details.
644
+
645
+ You should have received a copy of the GNU Affero General Public License
646
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
647
+
648
+ Also add information on how to contact you by electronic and paper mail.
649
+
650
+ If your software can interact with users remotely through a computer
651
+ network, you should also make sure that it provides a way for users to
652
+ get its source. For example, if your program is a web application, its
653
+ interface could display a "Source" link that leads users to an archive
654
+ of the code. There are many ways you could offer source, and different
655
+ solutions will be better for different programs; see section 13 for the
656
+ specific requirements.
657
+
658
+ You should also get your employer (if you work as a programmer) or school,
659
+ if any, to sign a "copyright disclaimer" for the program, if necessary.
660
+ For more information on this, and how to apply and follow the GNU AGPL, see
661
+ <http://www.gnu.org/licenses/>.
extensions/4-adetailer/README.md ADDED
@@ -0,0 +1,118 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # ADetailer
2
+
3
+ ADetailer is an extension for the stable diffusion webui that does automatic masking and inpainting. It is similar to the Detection Detailer.
4
+
5
+ ## Install
6
+
7
+ You can install it directly from the Extensions tab.
8
+
9
+ ![image](https://i.imgur.com/qaXtoI6.png)
10
+
11
+ Or
12
+
13
+ (from Mikubill/sd-webui-controlnet)
14
+
15
+ 1. Open "Extensions" tab.
16
+ 2. Open "Install from URL" tab in the tab.
17
+ 3. Enter `https://github.com/Bing-su/adetailer.git` to "URL for extension's git repository".
18
+ 4. Press "Install" button.
19
+ 5. Wait 5 seconds, and you will see the message "Installed into stable-diffusion-webui\extensions\adetailer. Use Installed tab to restart".
20
+ 6. Go to "Installed" tab, click "Check for updates", and then click "Apply and restart UI". (The next time you can also use this method to update extensions.)
21
+ 7. Completely restart A1111 webui including your terminal. (If you do not know what is a "terminal", you can reboot your computer: turn your computer off and turn it on again.)
22
+
23
+ ## Options
24
+
25
+ | Model, Prompts | | |
26
+ | --------------------------------- | ---------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
27
+ | ADetailer model | Determine what to detect. | `None` = disable |
28
+ | ADetailer model classes | Comma separated class names to detect. only available when using YOLO World models | If blank, use default values.<br/>default = [COCO 80 classes](https://github.com/ultralytics/ultralytics/blob/main/ultralytics/cfg/datasets/coco.yaml) |
29
+ | ADetailer prompt, negative prompt | Prompts and negative prompts to apply | If left blank, it will use the same as the input. |
30
+ | Skip img2img | Skip img2img. In practice, this works by changing the step count of img2img to 1. | img2img only |
31
+
32
+ | Detection | | |
33
+ | ------------------------------------ | -------------------------------------------------------------------------------------------- | ------------ |
34
+ | Detection model confidence threshold | Only objects with a detection model confidence above this threshold are used for inpainting. | |
35
+ | Mask min/max ratio | Only use masks whose area is between those ratios for the area of the entire image. | |
36
+ | Mask only the top k largest | Only use the k objects with the largest area of the bbox. | 0 to disable |
37
+
38
+ If you want to exclude objects in the background, try setting the min ratio to around `0.01`.
39
+
40
+ | Mask Preprocessing | | |
41
+ | ------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------- |
42
+ | Mask x, y offset | Moves the mask horizontally and vertically by | |
43
+ | Mask erosion (-) / dilation (+) | Enlarge or reduce the detected mask. | [opencv example](https://docs.opencv.org/4.7.0/db/df6/tutorial_erosion_dilatation.html) |
44
+ | Mask merge mode | `None`: Inpaint each mask<br/>`Merge`: Merge all masks and inpaint<br/>`Merge and Invert`: Merge all masks and Invert, then inpaint | |
45
+
46
+ Applied in this order: x, y offset → erosion/dilation → merge/invert.
47
+
48
+ #### Inpainting
49
+
50
+ Each option corresponds to a corresponding option on the inpaint tab. Therefore, please refer to the inpaint tab for usage details on how to use each option.
51
+
52
+ ## ControlNet Inpainting
53
+
54
+ You can use the ControlNet extension if you have ControlNet installed and ControlNet models.
55
+
56
+ Support `inpaint, scribble, lineart, openpose, tile, depth` controlnet models. Once you choose a model, the preprocessor is set automatically. It works separately from the model set by the Controlnet extension.
57
+
58
+ If you select `Passthrough`, the controlnet settings you set outside of ADetailer will be used.
59
+
60
+ ## Advanced Options
61
+
62
+ API request example: [wiki/REST-API](https://github.com/Bing-su/adetailer/wiki/REST-API)
63
+
64
+ `[SEP], [SKIP], [PROMPT]` tokens: [wiki/Advanced](https://github.com/Bing-su/adetailer/wiki/Advanced)
65
+
66
+ ## Media
67
+
68
+ - 🎥 [どこよりも詳しい After Detailer (adetailer)の使い方 ① 【Stable Diffusion】](https://youtu.be/sF3POwPUWCE)
69
+ - 🎥 [どこよりも詳しい After Detailer (adetailer)の使い方 ② 【Stable Diffusion】](https://youtu.be/urNISRdbIEg)
70
+
71
+ - 📜 [ADetailer Installation and 5 Usage Methods](https://kindanai.com/en/manual-adetailer/)
72
+
73
+ ## Model
74
+
75
+ | Model | Target | mAP 50 | mAP 50-95 |
76
+ | --------------------- | --------------------- | ----------------------------- | ----------------------------- |
77
+ | face_yolov8n.pt | 2D / realistic face | 0.660 | 0.366 |
78
+ | face_yolov8s.pt | 2D / realistic face | 0.713 | 0.404 |
79
+ | hand_yolov8n.pt | 2D / realistic hand | 0.767 | 0.505 |
80
+ | person_yolov8n-seg.pt | 2D / realistic person | 0.782 (bbox)<br/>0.761 (mask) | 0.555 (bbox)<br/>0.460 (mask) |
81
+ | person_yolov8s-seg.pt | 2D / realistic person | 0.824 (bbox)<br/>0.809 (mask) | 0.605 (bbox)<br/>0.508 (mask) |
82
+ | mediapipe_face_full | realistic face | - | - |
83
+ | mediapipe_face_short | realistic face | - | - |
84
+ | mediapipe_face_mesh | realistic face | - | - |
85
+
86
+ The YOLO models can be found on huggingface [Bingsu/adetailer](https://huggingface.co/Bingsu/adetailer).
87
+
88
+ For a detailed description of the YOLO8 model, see: https://docs.ultralytics.com/models/yolov8/#overview
89
+
90
+ YOLO World model: https://docs.ultralytics.com/models/yolo-world/
91
+
92
+ ### Additional Model
93
+
94
+ Put your [ultralytics](https://github.com/ultralytics/ultralytics) yolo model in `models/adetailer`. The model name should end with `.pt`.
95
+
96
+ It must be a bbox detection or segment model and use all label.
97
+
98
+ ## How it works
99
+
100
+ ADetailer works in three simple steps.
101
+
102
+ 1. Create an image.
103
+ 2. Detect object with a detection model and create a mask image.
104
+ 3. Inpaint using the image from 1 and the mask from 2.
105
+
106
+ ## Development
107
+
108
+ ADetailer is developed and tested using the stable-diffusion 1.5 model, for the latest version of [AUTOMATIC1111/stable-diffusion-webui](https://github.com/AUTOMATIC1111/stable-diffusion-webui) repository only.
109
+
110
+ ## License
111
+
112
+ ADetailer is a derivative work that uses two AGPL-licensed works (stable-diffusion-webui, ultralytics) and is therefore distributed under the AGPL license.
113
+
114
+ ## See Also
115
+
116
+ - https://github.com/ototadana/sd-face-editor
117
+ - https://github.com/continue-revolution/sd-webui-segment-anything
118
+ - https://github.com/portu-sim/sd-webui-bmab
extensions/4-adetailer/Taskfile.yml ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # https://taskfile.dev
2
+
3
+ version: "3"
4
+
5
+ dotenv:
6
+ - .env
7
+
8
+ tasks:
9
+ default:
10
+ cmds:
11
+ - echo "$PYTHON"
12
+ - echo "$WEBUI"
13
+ - echo "$UV_PYTHON"
14
+ silent: true
15
+
16
+ launch:
17
+ dir: "{{.WEBUI}}"
18
+ cmds:
19
+ - "{{.PYTHON}} launch.py --xformers --api"
20
+ silent: true
21
+
22
+ lint:
23
+ cmds:
24
+ - pre-commit run -a
25
+
26
+ update:
27
+ cmds:
28
+ - "{{.PYTHON}} -m uv pip install -U ultralytics mediapipe ruff pre-commit black devtools pytest"
29
+
30
+ update-torch:
31
+ cmds:
32
+ - "{{.PYTHON}} -m uv pip install -U torch torchvision torchaudio -f https://download.pytorch.org/whl/torch_stable.html"
extensions/4-adetailer/__pycache__/preload.cpython-310.pyc ADDED
Binary file (437 Bytes). View file
 
extensions/4-adetailer/aaaaaa/__init__.py ADDED
File without changes
extensions/4-adetailer/aaaaaa/__pycache__/__init__.cpython-310.pyc ADDED
Binary file (160 Bytes). View file
 
extensions/4-adetailer/aaaaaa/__pycache__/conditional.cpython-310.pyc ADDED
Binary file (625 Bytes). View file
 
extensions/4-adetailer/aaaaaa/__pycache__/helper.cpython-310.pyc ADDED
Binary file (1.7 kB). View file
 
extensions/4-adetailer/aaaaaa/__pycache__/p_method.cpython-310.pyc ADDED
Binary file (1.23 kB). View file
 
extensions/4-adetailer/aaaaaa/__pycache__/traceback.cpython-310.pyc ADDED
Binary file (4.34 kB). View file
 
extensions/4-adetailer/aaaaaa/__pycache__/ui.cpython-310.pyc ADDED
Binary file (15.7 kB). View file
 
extensions/4-adetailer/aaaaaa/conditional.py ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ msg = "[-] ADetailer: WebUI versions below 1.6.0 are not supported."
4
+
5
+ try:
6
+ from modules.processing import create_binary_mask # noqa: F401
7
+ except ImportError as e:
8
+ raise RuntimeError(msg) from e
9
+
10
+
11
+ try:
12
+ from modules.ui_components import InputAccordion # noqa: F401
13
+ except ImportError as e:
14
+ raise RuntimeError(msg) from e
15
+
16
+
17
+ try:
18
+ from modules.sd_schedulers import schedulers
19
+ except ImportError:
20
+ # webui < 1.9.0
21
+ schedulers = []
extensions/4-adetailer/aaaaaa/helper.py ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ from contextlib import contextmanager
4
+ from copy import copy
5
+ from typing import TYPE_CHECKING, Any, Union
6
+
7
+ import torch
8
+
9
+ from modules import safe
10
+ from modules.shared import opts
11
+
12
+ if TYPE_CHECKING:
13
+ # 타입 체커가 빨간 줄을 긋지 않게 하는 편법
14
+ from types import SimpleNamespace
15
+
16
+ StableDiffusionProcessingTxt2Img = SimpleNamespace
17
+ StableDiffusionProcessingImg2Img = SimpleNamespace
18
+ else:
19
+ from modules.processing import (
20
+ StableDiffusionProcessingImg2Img,
21
+ StableDiffusionProcessingTxt2Img,
22
+ )
23
+
24
+ PT = Union[StableDiffusionProcessingTxt2Img, StableDiffusionProcessingImg2Img]
25
+
26
+
27
+ @contextmanager
28
+ def change_torch_load():
29
+ orig = torch.load
30
+ try:
31
+ torch.load = safe.unsafe_torch_load
32
+ yield
33
+ finally:
34
+ torch.load = orig
35
+
36
+
37
+ @contextmanager
38
+ def pause_total_tqdm():
39
+ orig = opts.data.get("multiple_tqdm", True)
40
+ try:
41
+ opts.data["multiple_tqdm"] = False
42
+ yield
43
+ finally:
44
+ opts.data["multiple_tqdm"] = orig
45
+
46
+
47
+ @contextmanager
48
+ def preserve_prompts(p: PT):
49
+ all_pt = copy(p.all_prompts)
50
+ all_ng = copy(p.all_negative_prompts)
51
+ try:
52
+ yield
53
+ finally:
54
+ p.all_prompts = all_pt
55
+ p.all_negative_prompts = all_ng
56
+
57
+
58
+ def copy_extra_params(extra_params: dict[str, Any]) -> dict[str, Any]:
59
+ return {k: v for k, v in extra_params.items() if not callable(v)}
extensions/4-adetailer/aaaaaa/p_method.py ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+
4
+ def need_call_process(p) -> bool:
5
+ if p.scripts is None:
6
+ return False
7
+ i = p.batch_index
8
+ bs = p.batch_size
9
+ return i == bs - 1
10
+
11
+
12
+ def need_call_postprocess(p) -> bool:
13
+ if p.scripts is None:
14
+ return False
15
+ return p.batch_index == 0
16
+
17
+
18
+ def is_img2img_inpaint(p) -> bool:
19
+ return hasattr(p, "image_mask") and p.image_mask is not None
20
+
21
+
22
+ def is_inpaint_only_masked(p) -> bool:
23
+ return hasattr(p, "inpaint_full_res") and p.inpaint_full_res
24
+
25
+
26
+ def get_i(p) -> int:
27
+ it = p.iteration
28
+ bs = p.batch_size
29
+ i = p.batch_index
30
+ return it * bs + i
31
+
32
+
33
+ def is_skip_img2img(p) -> bool:
34
+ return getattr(p, "_ad_skip_img2img", False)
extensions/4-adetailer/aaaaaa/traceback.py ADDED
@@ -0,0 +1,175 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ import io
4
+ import platform
5
+ import sys
6
+ from collections.abc import Callable
7
+ from importlib.metadata import version
8
+ from typing import Any, TypeVar
9
+
10
+ from rich.console import Console, Group
11
+ from rich.panel import Panel
12
+ from rich.table import Table
13
+ from rich.traceback import Traceback
14
+ from typing_extensions import ParamSpec
15
+
16
+ from adetailer.__version__ import __version__
17
+ from adetailer.args import ADetailerArgs
18
+
19
+
20
+ def processing(*args: Any) -> dict[str, Any]:
21
+ try:
22
+ from modules.processing import (
23
+ StableDiffusionProcessingImg2Img,
24
+ StableDiffusionProcessingTxt2Img,
25
+ )
26
+ except ImportError:
27
+ return {}
28
+
29
+ p = None
30
+ for arg in args:
31
+ if isinstance(
32
+ arg, (StableDiffusionProcessingTxt2Img, StableDiffusionProcessingImg2Img)
33
+ ):
34
+ p = arg
35
+ break
36
+
37
+ if p is None:
38
+ return {}
39
+
40
+ info = {
41
+ "prompt": p.prompt,
42
+ "negative_prompt": p.negative_prompt,
43
+ "n_iter": p.n_iter,
44
+ "batch_size": p.batch_size,
45
+ "width": p.width,
46
+ "height": p.height,
47
+ "sampler_name": p.sampler_name,
48
+ "enable_hr": getattr(p, "enable_hr", False),
49
+ "hr_upscaler": getattr(p, "hr_upscaler", ""),
50
+ }
51
+
52
+ info.update(sd_models())
53
+ return info
54
+
55
+
56
+ def sd_models() -> dict[str, str]:
57
+ try:
58
+ from modules import shared
59
+
60
+ opts = shared.opts
61
+ except Exception:
62
+ return {}
63
+
64
+ return {
65
+ "checkpoint": getattr(opts, "sd_model_checkpoint", "------"),
66
+ "vae": getattr(opts, "sd_vae", "------"),
67
+ "unet": getattr(opts, "sd_unet", "------"),
68
+ }
69
+
70
+
71
+ def ad_args(*args: Any) -> dict[str, Any]:
72
+ ad_args = []
73
+ for arg in args:
74
+ if not isinstance(arg, dict):
75
+ continue
76
+
77
+ try:
78
+ a = ADetailerArgs(**arg)
79
+ except ValueError:
80
+ continue
81
+
82
+ if not a.need_skip():
83
+ ad_args.append(a)
84
+
85
+ if not ad_args:
86
+ return {}
87
+
88
+ arg0 = ad_args[0]
89
+ return {
90
+ "version": __version__,
91
+ "ad_model": arg0.ad_model,
92
+ "ad_prompt": arg0.ad_prompt,
93
+ "ad_negative_prompt": arg0.ad_negative_prompt,
94
+ "ad_controlnet_model": arg0.ad_controlnet_model,
95
+ "is_api": arg0.is_api,
96
+ }
97
+
98
+
99
+ def library_version():
100
+ libraries = ["torch", "torchvision", "ultralytics", "mediapipe"]
101
+ d = {}
102
+ for lib in libraries:
103
+ try:
104
+ d[lib] = version(lib)
105
+ except Exception: # noqa: PERF203
106
+ d[lib] = "Unknown"
107
+ return d
108
+
109
+
110
+ def sys_info() -> dict[str, Any]:
111
+ try:
112
+ import launch
113
+
114
+ version = launch.git_tag()
115
+ commit = launch.commit_hash()
116
+ except Exception:
117
+ version = "Unknown (too old or vladmandic)"
118
+ commit = "Unknown"
119
+
120
+ return {
121
+ "Platform": platform.platform(),
122
+ "Python": sys.version,
123
+ "Version": version,
124
+ "Commit": commit,
125
+ "Commandline": sys.argv,
126
+ "Libraries": library_version(),
127
+ }
128
+
129
+
130
+ def get_table(title: str, data: dict[str, Any]) -> Table:
131
+ table = Table(title=title, highlight=True)
132
+ table.add_column(" ", justify="right", style="dim")
133
+ table.add_column("Value")
134
+ for key, value in data.items():
135
+ if not isinstance(value, str):
136
+ value = repr(value)
137
+ table.add_row(key, value)
138
+
139
+ return table
140
+
141
+
142
+ P = ParamSpec("P")
143
+ T = TypeVar("T")
144
+
145
+
146
+ def rich_traceback(func: Callable[P, T]) -> Callable[P, T]:
147
+ def wrapper(*args, **kwargs):
148
+ string = io.StringIO()
149
+ width = Console().width
150
+ width = width - 4 if width > 4 else None
151
+ console = Console(file=string, width=width)
152
+ try:
153
+ return func(*args, **kwargs)
154
+ except Exception as e:
155
+ tables = [
156
+ get_table(title, data)
157
+ for title, data in [
158
+ ("System info", sys_info()),
159
+ ("Inputs", processing(*args)),
160
+ ("ADetailer", ad_args(*args)),
161
+ ]
162
+ if data
163
+ ]
164
+ tables.append(Traceback(extra_lines=1))
165
+
166
+ console.print(Panel(Group(*tables)))
167
+ output = "\n" + string.getvalue()
168
+
169
+ try:
170
+ error = e.__class__(output)
171
+ except Exception:
172
+ error = RuntimeError(output)
173
+ raise error from None
174
+
175
+ return wrapper
extensions/4-adetailer/aaaaaa/ui.py ADDED
@@ -0,0 +1,710 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import dataclass
4
+ from functools import partial
5
+ from itertools import chain
6
+ from types import SimpleNamespace
7
+ from typing import Any
8
+
9
+ import gradio as gr
10
+
11
+ from aaaaaa.conditional import InputAccordion
12
+ from adetailer import ADETAILER, __version__
13
+ from adetailer.args import ALL_ARGS, MASK_MERGE_INVERT
14
+ from controlnet_ext import controlnet_exists, controlnet_type, get_cn_models
15
+
16
+ if controlnet_type == "forge":
17
+ from lib_controlnet import global_state
18
+
19
+ cn_module_choices = {
20
+ "inpaint": list(global_state.get_filtered_preprocessors("Inpaint")),
21
+ "lineart": list(global_state.get_filtered_preprocessors("Lineart")),
22
+ "openpose": list(global_state.get_filtered_preprocessors("OpenPose")),
23
+ "tile": list(global_state.get_filtered_preprocessors("Tile")),
24
+ "scribble": list(global_state.get_filtered_preprocessors("Scribble")),
25
+ "depth": list(global_state.get_filtered_preprocessors("Depth")),
26
+ }
27
+ else:
28
+ cn_module_choices = {
29
+ "inpaint": [
30
+ "inpaint_global_harmonious",
31
+ "inpaint_only",
32
+ "inpaint_only+lama",
33
+ ],
34
+ "lineart": [
35
+ "lineart_coarse",
36
+ "lineart_realistic",
37
+ "lineart_anime",
38
+ "lineart_anime_denoise",
39
+ ],
40
+ "openpose": ["openpose_full", "dw_openpose_full"],
41
+ "tile": ["tile_resample", "tile_colorfix", "tile_colorfix+sharp"],
42
+ "scribble": ["t2ia_sketch_pidi"],
43
+ "depth": ["depth_midas", "depth_hand_refiner"],
44
+ }
45
+
46
+ union = list(chain.from_iterable(cn_module_choices.values()))
47
+ cn_module_choices["union"] = union
48
+
49
+
50
+ class Widgets(SimpleNamespace):
51
+ def tolist(self):
52
+ return [getattr(self, attr) for attr in ALL_ARGS.attrs]
53
+
54
+
55
+ @dataclass
56
+ class WebuiInfo:
57
+ ad_model_list: list[str]
58
+ sampler_names: list[str]
59
+ scheduler_names: list[str]
60
+ t2i_button: gr.Button
61
+ i2i_button: gr.Button
62
+ checkpoints_list: list[str]
63
+ vae_list: list[str]
64
+
65
+
66
+ def gr_interactive(value: bool = True):
67
+ return gr.update(interactive=value)
68
+
69
+
70
+ def ordinal(n: int) -> str:
71
+ d = {1: "st", 2: "nd", 3: "rd"}
72
+ return str(n) + ("th" if 11 <= n % 100 <= 13 else d.get(n % 10, "th"))
73
+
74
+
75
+ def suffix(n: int, c: str = " ") -> str:
76
+ return "" if n == 0 else c + ordinal(n + 1)
77
+
78
+
79
+ def on_widget_change(state: dict, value: Any, *, attr: str):
80
+ if "is_api" in state:
81
+ state = state.copy()
82
+ state.pop("is_api")
83
+ state[attr] = value
84
+ return state
85
+
86
+
87
+ def on_generate_click(state: dict, *values: Any):
88
+ for attr, value in zip(ALL_ARGS.attrs, values):
89
+ state[attr] = value # noqa: PERF403
90
+ state["is_api"] = ()
91
+ return state
92
+
93
+
94
+ def on_ad_model_update(model: str):
95
+ if "-world" in model:
96
+ return gr.update(
97
+ visible=True,
98
+ placeholder="Comma separated class names to detect, ex: 'person,cat'. default: COCO 80 classes",
99
+ )
100
+ return gr.update(visible=False, placeholder="")
101
+
102
+
103
+ def on_cn_model_update(cn_model_name: str):
104
+ cn_model_name = cn_model_name.replace("inpaint_depth", "depth")
105
+ for t in cn_module_choices:
106
+ if t in cn_model_name:
107
+ choices = cn_module_choices[t]
108
+ return gr.update(visible=True, choices=choices, value=choices[0])
109
+ return gr.update(visible=False, choices=["None"], value="None")
110
+
111
+
112
+ def elem_id(item_id: str, n: int, is_img2img: bool) -> str:
113
+ tab = "img2img" if is_img2img else "txt2img"
114
+ suf = suffix(n, "_")
115
+ return f"script_{tab}_adetailer_{item_id}{suf}"
116
+
117
+
118
+ def state_init(w: Widgets) -> dict[str, Any]:
119
+ return {attr: getattr(w, attr).value for attr in ALL_ARGS.attrs}
120
+
121
+
122
+ def adui(
123
+ num_models: int,
124
+ is_img2img: bool,
125
+ webui_info: WebuiInfo,
126
+ ):
127
+ states = []
128
+ infotext_fields = []
129
+ eid = partial(elem_id, n=0, is_img2img=is_img2img)
130
+
131
+ with InputAccordion(
132
+ value=False,
133
+ elem_id=eid("ad_main_accordion"),
134
+ label=ADETAILER,
135
+ visible=True,
136
+ ) as ad_enable:
137
+ with gr.Row():
138
+ with gr.Column(scale=8):
139
+ ad_skip_img2img = gr.Checkbox(
140
+ label="Skip img2img",
141
+ value=False,
142
+ visible=is_img2img,
143
+ elem_id=eid("ad_skip_img2img"),
144
+ )
145
+
146
+ with gr.Column(scale=1, min_width=180):
147
+ gr.Markdown(
148
+ f"v{__version__}",
149
+ elem_id=eid("ad_version"),
150
+ )
151
+
152
+ infotext_fields.append((ad_enable, "ADetailer enable"))
153
+ infotext_fields.append((ad_skip_img2img, "ADetailer skip img2img"))
154
+
155
+ with gr.Group(), gr.Tabs():
156
+ for n in range(num_models):
157
+ with gr.Tab(ordinal(n + 1)):
158
+ state, infofields = one_ui_group(
159
+ n=n,
160
+ is_img2img=is_img2img,
161
+ webui_info=webui_info,
162
+ )
163
+
164
+ states.append(state)
165
+ infotext_fields.extend(infofields)
166
+
167
+ # components: [bool, bool, dict, dict, ...]
168
+ components = [ad_enable, ad_skip_img2img, *states]
169
+ return components, infotext_fields
170
+
171
+
172
+ def one_ui_group(n: int, is_img2img: bool, webui_info: WebuiInfo):
173
+ w = Widgets()
174
+ eid = partial(elem_id, n=n, is_img2img=is_img2img)
175
+
176
+ model_choices = (
177
+ [*webui_info.ad_model_list, "None"]
178
+ if n == 0
179
+ else ["None", *webui_info.ad_model_list]
180
+ )
181
+
182
+ with gr.Group():
183
+ with gr.Row(variant="compact"):
184
+ w.ad_tab_enable = gr.Checkbox(
185
+ label=f"Enable this tab ({ordinal(n + 1)})",
186
+ value=True,
187
+ visible=True,
188
+ elem_id=eid("ad_tab_enable"),
189
+ )
190
+
191
+ with gr.Row():
192
+ w.ad_model = gr.Dropdown(
193
+ label="ADetailer detector" + suffix(n),
194
+ choices=model_choices,
195
+ value=model_choices[0],
196
+ visible=True,
197
+ type="value",
198
+ elem_id=eid("ad_model"),
199
+ info="Select a model to use for detection.",
200
+ )
201
+
202
+ with gr.Row():
203
+ w.ad_model_classes = gr.Textbox(
204
+ label="ADetailer detector classes" + suffix(n),
205
+ value="",
206
+ visible=False,
207
+ elem_id=eid("ad_classes"),
208
+ )
209
+
210
+ w.ad_model.change(
211
+ on_ad_model_update,
212
+ inputs=w.ad_model,
213
+ outputs=w.ad_model_classes,
214
+ queue=False,
215
+ )
216
+
217
+ gr.HTML("<br>")
218
+
219
+ with gr.Group():
220
+ with gr.Row(elem_id=eid("ad_toprow_prompt")):
221
+ w.ad_prompt = gr.Textbox(
222
+ label="ad_prompt" + suffix(n),
223
+ show_label=False,
224
+ lines=3,
225
+ placeholder="ADetailer prompt"
226
+ + suffix(n)
227
+ + "\nIf blank, the main prompt is used.",
228
+ elem_id=eid("ad_prompt"),
229
+ )
230
+
231
+ with gr.Row(elem_id=eid("ad_toprow_negative_prompt")):
232
+ w.ad_negative_prompt = gr.Textbox(
233
+ label="ad_negative_prompt" + suffix(n),
234
+ show_label=False,
235
+ lines=2,
236
+ placeholder="ADetailer negative prompt"
237
+ + suffix(n)
238
+ + "\nIf blank, the main negative prompt is used.",
239
+ elem_id=eid("ad_negative_prompt"),
240
+ )
241
+
242
+ with gr.Group():
243
+ with gr.Accordion(
244
+ "Detection", open=False, elem_id=eid("ad_detection_accordion")
245
+ ):
246
+ detection(w, n, is_img2img)
247
+
248
+ with gr.Accordion(
249
+ "Mask Preprocessing",
250
+ open=False,
251
+ elem_id=eid("ad_mask_preprocessing_accordion"),
252
+ ):
253
+ mask_preprocessing(w, n, is_img2img)
254
+
255
+ with gr.Accordion(
256
+ "Inpainting", open=False, elem_id=eid("ad_inpainting_accordion")
257
+ ):
258
+ inpainting(w, n, is_img2img, webui_info)
259
+
260
+ with gr.Group():
261
+ controlnet(w, n, is_img2img)
262
+
263
+ state = gr.State(lambda: state_init(w))
264
+
265
+ for attr in ALL_ARGS.attrs:
266
+ widget = getattr(w, attr)
267
+ on_change = partial(on_widget_change, attr=attr)
268
+ widget.change(fn=on_change, inputs=[state, widget], outputs=state, queue=False)
269
+
270
+ all_inputs = [state, *w.tolist()]
271
+ target_button = webui_info.i2i_button if is_img2img else webui_info.t2i_button
272
+ target_button.click(
273
+ fn=on_generate_click, inputs=all_inputs, outputs=state, queue=False
274
+ )
275
+
276
+ infotext_fields = [(getattr(w, attr), name + suffix(n)) for attr, name in ALL_ARGS]
277
+
278
+ return state, infotext_fields
279
+
280
+
281
+ def detection(w: Widgets, n: int, is_img2img: bool):
282
+ eid = partial(elem_id, n=n, is_img2img=is_img2img)
283
+
284
+ with gr.Row():
285
+ with gr.Column(variant="compact"):
286
+ w.ad_confidence = gr.Slider(
287
+ label="Detection model confidence threshold" + suffix(n),
288
+ minimum=0.0,
289
+ maximum=1.0,
290
+ step=0.01,
291
+ value=0.3,
292
+ visible=True,
293
+ elem_id=eid("ad_confidence"),
294
+ )
295
+ w.ad_mask_k_largest = gr.Slider(
296
+ label="Mask only the top k largest (0 to disable)" + suffix(n),
297
+ minimum=0,
298
+ maximum=10,
299
+ step=1,
300
+ value=0,
301
+ visible=True,
302
+ elem_id=eid("ad_mask_k_largest"),
303
+ )
304
+
305
+ with gr.Column(variant="compact"):
306
+ w.ad_mask_min_ratio = gr.Slider(
307
+ label="Mask min area ratio" + suffix(n),
308
+ minimum=0.0,
309
+ maximum=1.0,
310
+ step=0.001,
311
+ value=0.0,
312
+ visible=True,
313
+ elem_id=eid("ad_mask_min_ratio"),
314
+ )
315
+ w.ad_mask_max_ratio = gr.Slider(
316
+ label="Mask max area ratio" + suffix(n),
317
+ minimum=0.0,
318
+ maximum=1.0,
319
+ step=0.001,
320
+ value=1.0,
321
+ visible=True,
322
+ elem_id=eid("ad_mask_max_ratio"),
323
+ )
324
+
325
+
326
+ def mask_preprocessing(w: Widgets, n: int, is_img2img: bool):
327
+ eid = partial(elem_id, n=n, is_img2img=is_img2img)
328
+
329
+ with gr.Group():
330
+ with gr.Row():
331
+ with gr.Column(variant="compact"):
332
+ w.ad_x_offset = gr.Slider(
333
+ label="Mask x(→) offset" + suffix(n),
334
+ minimum=-200,
335
+ maximum=200,
336
+ step=1,
337
+ value=0,
338
+ visible=True,
339
+ elem_id=eid("ad_x_offset"),
340
+ )
341
+ w.ad_y_offset = gr.Slider(
342
+ label="Mask y(↑) offset" + suffix(n),
343
+ minimum=-200,
344
+ maximum=200,
345
+ step=1,
346
+ value=0,
347
+ visible=True,
348
+ elem_id=eid("ad_y_offset"),
349
+ )
350
+
351
+ with gr.Column(variant="compact"):
352
+ w.ad_dilate_erode = gr.Slider(
353
+ label="Mask erosion (-) / dilation (+)" + suffix(n),
354
+ minimum=-128,
355
+ maximum=128,
356
+ step=4,
357
+ value=4,
358
+ visible=True,
359
+ elem_id=eid("ad_dilate_erode"),
360
+ )
361
+
362
+ with gr.Row():
363
+ w.ad_mask_merge_invert = gr.Radio(
364
+ label="Mask merge mode" + suffix(n),
365
+ choices=MASK_MERGE_INVERT,
366
+ value="None",
367
+ elem_id=eid("ad_mask_merge_invert"),
368
+ info="None: do nothing, Merge: merge masks, Merge and Invert: merge all masks and invert",
369
+ )
370
+
371
+
372
+ def inpainting(w: Widgets, n: int, is_img2img: bool, webui_info: WebuiInfo):
373
+ eid = partial(elem_id, n=n, is_img2img=is_img2img)
374
+
375
+ with gr.Group():
376
+ with gr.Row():
377
+ w.ad_mask_blur = gr.Slider(
378
+ label="Inpaint mask blur" + suffix(n),
379
+ minimum=0,
380
+ maximum=64,
381
+ step=1,
382
+ value=4,
383
+ visible=True,
384
+ elem_id=eid("ad_mask_blur"),
385
+ )
386
+
387
+ w.ad_denoising_strength = gr.Slider(
388
+ label="Inpaint denoising strength" + suffix(n),
389
+ minimum=0.0,
390
+ maximum=1.0,
391
+ step=0.01,
392
+ value=0.4,
393
+ visible=True,
394
+ elem_id=eid("ad_denoising_strength"),
395
+ )
396
+
397
+ with gr.Row():
398
+ with gr.Column(variant="compact"):
399
+ w.ad_inpaint_only_masked = gr.Checkbox(
400
+ label="Inpaint only masked" + suffix(n),
401
+ value=True,
402
+ visible=True,
403
+ elem_id=eid("ad_inpaint_only_masked"),
404
+ )
405
+ w.ad_inpaint_only_masked_padding = gr.Slider(
406
+ label="Inpaint only masked padding, pixels" + suffix(n),
407
+ minimum=0,
408
+ maximum=256,
409
+ step=4,
410
+ value=32,
411
+ visible=True,
412
+ elem_id=eid("ad_inpaint_only_masked_padding"),
413
+ )
414
+
415
+ w.ad_inpaint_only_masked.change(
416
+ gr_interactive,
417
+ inputs=w.ad_inpaint_only_masked,
418
+ outputs=w.ad_inpaint_only_masked_padding,
419
+ queue=False,
420
+ )
421
+
422
+ with gr.Column(variant="compact"):
423
+ w.ad_use_inpaint_width_height = gr.Checkbox(
424
+ label="Use separate width/height" + suffix(n),
425
+ value=False,
426
+ visible=True,
427
+ elem_id=eid("ad_use_inpaint_width_height"),
428
+ )
429
+
430
+ w.ad_inpaint_width = gr.Slider(
431
+ label="inpaint width" + suffix(n),
432
+ minimum=64,
433
+ maximum=2048,
434
+ step=4,
435
+ value=512,
436
+ visible=True,
437
+ elem_id=eid("ad_inpaint_width"),
438
+ )
439
+
440
+ w.ad_inpaint_height = gr.Slider(
441
+ label="inpaint height" + suffix(n),
442
+ minimum=64,
443
+ maximum=2048,
444
+ step=4,
445
+ value=512,
446
+ visible=True,
447
+ elem_id=eid("ad_inpaint_height"),
448
+ )
449
+
450
+ w.ad_use_inpaint_width_height.change(
451
+ lambda value: (gr_interactive(value), gr_interactive(value)),
452
+ inputs=w.ad_use_inpaint_width_height,
453
+ outputs=[w.ad_inpaint_width, w.ad_inpaint_height],
454
+ queue=False,
455
+ )
456
+
457
+ with gr.Row():
458
+ with gr.Column(variant="compact"):
459
+ w.ad_use_steps = gr.Checkbox(
460
+ label="Use separate steps" + suffix(n),
461
+ value=False,
462
+ visible=True,
463
+ elem_id=eid("ad_use_steps"),
464
+ )
465
+
466
+ w.ad_steps = gr.Slider(
467
+ label="ADetailer steps" + suffix(n),
468
+ minimum=1,
469
+ maximum=150,
470
+ step=1,
471
+ value=28,
472
+ visible=True,
473
+ elem_id=eid("ad_steps"),
474
+ )
475
+
476
+ w.ad_use_steps.change(
477
+ gr_interactive,
478
+ inputs=w.ad_use_steps,
479
+ outputs=w.ad_steps,
480
+ queue=False,
481
+ )
482
+
483
+ with gr.Column(variant="compact"):
484
+ w.ad_use_cfg_scale = gr.Checkbox(
485
+ label="Use separate CFG scale" + suffix(n),
486
+ value=False,
487
+ visible=True,
488
+ elem_id=eid("ad_use_cfg_scale"),
489
+ )
490
+
491
+ w.ad_cfg_scale = gr.Slider(
492
+ label="ADetailer CFG scale" + suffix(n),
493
+ minimum=0.0,
494
+ maximum=30.0,
495
+ step=0.5,
496
+ value=7.0,
497
+ visible=True,
498
+ elem_id=eid("ad_cfg_scale"),
499
+ )
500
+
501
+ w.ad_use_cfg_scale.change(
502
+ gr_interactive,
503
+ inputs=w.ad_use_cfg_scale,
504
+ outputs=w.ad_cfg_scale,
505
+ queue=False,
506
+ )
507
+
508
+ with gr.Row():
509
+ with gr.Column(variant="compact"):
510
+ w.ad_use_checkpoint = gr.Checkbox(
511
+ label="Use separate checkpoint" + suffix(n),
512
+ value=False,
513
+ visible=True,
514
+ elem_id=eid("ad_use_checkpoint"),
515
+ )
516
+
517
+ ckpts = ["Use same checkpoint", *webui_info.checkpoints_list]
518
+
519
+ w.ad_checkpoint = gr.Dropdown(
520
+ label="ADetailer checkpoint" + suffix(n),
521
+ choices=ckpts,
522
+ value=ckpts[0],
523
+ visible=True,
524
+ elem_id=eid("ad_checkpoint"),
525
+ )
526
+
527
+ with gr.Column(variant="compact"):
528
+ w.ad_use_vae = gr.Checkbox(
529
+ label="Use separate VAE" + suffix(n),
530
+ value=False,
531
+ visible=True,
532
+ elem_id=eid("ad_use_vae"),
533
+ )
534
+
535
+ vaes = ["Use same VAE", *webui_info.vae_list]
536
+
537
+ w.ad_vae = gr.Dropdown(
538
+ label="ADetailer VAE" + suffix(n),
539
+ choices=vaes,
540
+ value=vaes[0],
541
+ visible=True,
542
+ elem_id=eid("ad_vae"),
543
+ )
544
+
545
+ with gr.Row(), gr.Column(variant="compact"):
546
+ w.ad_use_sampler = gr.Checkbox(
547
+ label="Use separate sampler" + suffix(n),
548
+ value=False,
549
+ visible=True,
550
+ elem_id=eid("ad_use_sampler"),
551
+ )
552
+
553
+ sampler_names = [
554
+ "Use same sampler",
555
+ *webui_info.sampler_names,
556
+ ]
557
+
558
+ with gr.Row():
559
+ w.ad_sampler = gr.Dropdown(
560
+ label="ADetailer sampler" + suffix(n),
561
+ choices=sampler_names,
562
+ value=sampler_names[1],
563
+ visible=True,
564
+ elem_id=eid("ad_sampler"),
565
+ )
566
+
567
+ scheduler_names = [
568
+ "Use same scheduler",
569
+ *webui_info.scheduler_names,
570
+ ]
571
+ w.ad_scheduler = gr.Dropdown(
572
+ label="ADetailer scheduler" + suffix(n),
573
+ choices=scheduler_names,
574
+ value=scheduler_names[0],
575
+ visible=len(scheduler_names) > 1,
576
+ elem_id=eid("ad_scheduler"),
577
+ )
578
+
579
+ w.ad_use_sampler.change(
580
+ lambda value: (gr_interactive(value), gr_interactive(value)),
581
+ inputs=w.ad_use_sampler,
582
+ outputs=[w.ad_sampler, w.ad_scheduler],
583
+ queue=False,
584
+ )
585
+
586
+ with gr.Row():
587
+ with gr.Column(variant="compact"):
588
+ w.ad_use_noise_multiplier = gr.Checkbox(
589
+ label="Use separate noise multiplier" + suffix(n),
590
+ value=False,
591
+ visible=True,
592
+ elem_id=eid("ad_use_noise_multiplier"),
593
+ )
594
+
595
+ w.ad_noise_multiplier = gr.Slider(
596
+ label="Noise multiplier for img2img" + suffix(n),
597
+ minimum=0.5,
598
+ maximum=1.5,
599
+ step=0.01,
600
+ value=1.0,
601
+ visible=True,
602
+ elem_id=eid("ad_noise_multiplier"),
603
+ )
604
+
605
+ w.ad_use_noise_multiplier.change(
606
+ gr_interactive,
607
+ inputs=w.ad_use_noise_multiplier,
608
+ outputs=w.ad_noise_multiplier,
609
+ queue=False,
610
+ )
611
+
612
+ with gr.Column(variant="compact"):
613
+ w.ad_use_clip_skip = gr.Checkbox(
614
+ label="Use separate CLIP skip" + suffix(n),
615
+ value=False,
616
+ visible=True,
617
+ elem_id=eid("ad_use_clip_skip"),
618
+ )
619
+
620
+ w.ad_clip_skip = gr.Slider(
621
+ label="ADetailer CLIP skip" + suffix(n),
622
+ minimum=1,
623
+ maximum=12,
624
+ step=1,
625
+ value=1,
626
+ visible=True,
627
+ elem_id=eid("ad_clip_skip"),
628
+ )
629
+
630
+ w.ad_use_clip_skip.change(
631
+ gr_interactive,
632
+ inputs=w.ad_use_clip_skip,
633
+ outputs=w.ad_clip_skip,
634
+ queue=False,
635
+ )
636
+
637
+ with gr.Row(), gr.Column(variant="compact"):
638
+ w.ad_restore_face = gr.Checkbox(
639
+ label="Restore faces after ADetailer" + suffix(n),
640
+ value=False,
641
+ elem_id=eid("ad_restore_face"),
642
+ )
643
+
644
+
645
+ def controlnet(w: Widgets, n: int, is_img2img: bool):
646
+ eid = partial(elem_id, n=n, is_img2img=is_img2img)
647
+ cn_models = ["None", "Passthrough", *get_cn_models()]
648
+
649
+ with gr.Row(variant="panel"):
650
+ with gr.Column(variant="compact"):
651
+ w.ad_controlnet_model = gr.Dropdown(
652
+ label="ControlNet model" + suffix(n),
653
+ choices=cn_models,
654
+ value="None",
655
+ visible=True,
656
+ type="value",
657
+ interactive=controlnet_exists,
658
+ elem_id=eid("ad_controlnet_model"),
659
+ )
660
+
661
+ w.ad_controlnet_module = gr.Dropdown(
662
+ label="ControlNet module" + suffix(n),
663
+ choices=["None"],
664
+ value="None",
665
+ visible=False,
666
+ type="value",
667
+ interactive=controlnet_exists,
668
+ elem_id=eid("ad_controlnet_module"),
669
+ )
670
+
671
+ w.ad_controlnet_weight = gr.Slider(
672
+ label="ControlNet weight" + suffix(n),
673
+ minimum=0.0,
674
+ maximum=1.0,
675
+ step=0.01,
676
+ value=1.0,
677
+ visible=True,
678
+ interactive=controlnet_exists,
679
+ elem_id=eid("ad_controlnet_weight"),
680
+ )
681
+
682
+ w.ad_controlnet_model.change(
683
+ on_cn_model_update,
684
+ inputs=w.ad_controlnet_model,
685
+ outputs=w.ad_controlnet_module,
686
+ queue=False,
687
+ )
688
+
689
+ with gr.Column(variant="compact"):
690
+ w.ad_controlnet_guidance_start = gr.Slider(
691
+ label="ControlNet guidance start" + suffix(n),
692
+ minimum=0.0,
693
+ maximum=1.0,
694
+ step=0.01,
695
+ value=0.0,
696
+ visible=True,
697
+ interactive=controlnet_exists,
698
+ elem_id=eid("ad_controlnet_guidance_start"),
699
+ )
700
+
701
+ w.ad_controlnet_guidance_end = gr.Slider(
702
+ label="ControlNet guidance end" + suffix(n),
703
+ minimum=0.0,
704
+ maximum=1.0,
705
+ step=0.01,
706
+ value=1.0,
707
+ visible=True,
708
+ interactive=controlnet_exists,
709
+ elem_id=eid("ad_controlnet_guidance_end"),
710
+ )
extensions/4-adetailer/adetailer/__init__.py ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from .__version__ import __version__
2
+ from .args import ALL_ARGS, ADetailerArgs
3
+ from .common import PredictOutput, get_models
4
+ from .mediapipe import mediapipe_predict
5
+ from .ultralytics import ultralytics_predict
6
+
7
+ ADETAILER = "ADetailer"
8
+
9
+ __all__ = [
10
+ "__version__",
11
+ "ADetailerArgs",
12
+ "ADETAILER",
13
+ "ALL_ARGS",
14
+ "PredictOutput",
15
+ "get_models",
16
+ "mediapipe_predict",
17
+ "ultralytics_predict",
18
+ ]
extensions/4-adetailer/adetailer/__pycache__/__init__.cpython-310.pyc ADDED
Binary file (518 Bytes). View file
 
extensions/4-adetailer/adetailer/__pycache__/__version__.cpython-310.pyc ADDED
Binary file (188 Bytes). View file
 
extensions/4-adetailer/adetailer/__pycache__/args.cpython-310.pyc ADDED
Binary file (8.2 kB). View file