comfy-ui-api-workflow 0.0.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (176) hide show
  1. comfy_ui_api_workflow/__about__.py +1 -0
  2. comfy_ui_api_workflow/__init__.py +9 -0
  3. comfy_ui_api_workflow/_impl/__init__.py +0 -0
  4. comfy_ui_api_workflow/_impl/data_structure.py +182 -0
  5. comfy_ui_api_workflow/_impl/enums.py +13 -0
  6. comfy_ui_api_workflow/_impl/errors/__init__.py +3 -0
  7. comfy_ui_api_workflow/_impl/errors/data_structure.py +34 -0
  8. comfy_ui_api_workflow/_impl/errors/node.py +63 -0
  9. comfy_ui_api_workflow/_impl/errors/output.py +5 -0
  10. comfy_ui_api_workflow/_impl/errors/pipeline.py +14 -0
  11. comfy_ui_api_workflow/_impl/errors/workflow.py +13 -0
  12. comfy_ui_api_workflow/_impl/exceptions.py +22 -0
  13. comfy_ui_api_workflow/_impl/lazy.py +71 -0
  14. comfy_ui_api_workflow/_impl/nodes/__init__.py +3 -0
  15. comfy_ui_api_workflow/_impl/nodes/advanced/__init__.py +3 -0
  16. comfy_ui_api_workflow/_impl/nodes/advanced/debug.py +103 -0
  17. comfy_ui_api_workflow/_impl/nodes/advanced/guidance.py +281 -0
  18. comfy_ui_api_workflow/_impl/nodes/advanced/hooks/__init__.py +29 -0
  19. comfy_ui_api_workflow/_impl/nodes/advanced/hooks/clip.py +35 -0
  20. comfy_ui_api_workflow/_impl/nodes/advanced/hooks/combine.py +108 -0
  21. comfy_ui_api_workflow/_impl/nodes/advanced/hooks/cond_pair.py +203 -0
  22. comfy_ui_api_workflow/_impl/nodes/advanced/hooks/cond_single.py +143 -0
  23. comfy_ui_api_workflow/_impl/nodes/advanced/hooks/create.py +130 -0
  24. comfy_ui_api_workflow/_impl/nodes/advanced/hooks/scheduling.py +167 -0
  25. comfy_ui_api_workflow/_impl/nodes/advanced/multigpu.py +78 -0
  26. comfy_ui_api_workflow/_impl/nodes/audio.py +260 -0
  27. comfy_ui_api_workflow/_impl/nodes/base.py +214 -0
  28. comfy_ui_api_workflow/_impl/nodes/experimental/__init__.py +283 -0
  29. comfy_ui_api_workflow/_impl/nodes/experimental/attention_experiments.py +156 -0
  30. comfy_ui_api_workflow/_impl/nodes/experimental/stable_cascade.py +16 -0
  31. comfy_ui_api_workflow/_impl/nodes/image/__init__.py +601 -0
  32. comfy_ui_api_workflow/_impl/nodes/image/adjustments.py +46 -0
  33. comfy_ui_api_workflow/_impl/nodes/image/background_removal.py +16 -0
  34. comfy_ui_api_workflow/_impl/nodes/image/batch.py +236 -0
  35. comfy_ui_api_workflow/_impl/nodes/image/color.py +104 -0
  36. comfy_ui_api_workflow/_impl/nodes/image/compositing.py +128 -0
  37. comfy_ui_api_workflow/_impl/nodes/image/detection.py +689 -0
  38. comfy_ui_api_workflow/_impl/nodes/image/filters.py +215 -0
  39. comfy_ui_api_workflow/_impl/nodes/image/geometry_estimation.py +307 -0
  40. comfy_ui_api_workflow/_impl/nodes/image/mask.py +291 -0
  41. comfy_ui_api_workflow/_impl/nodes/image/post_processors.py +45 -0
  42. comfy_ui_api_workflow/_impl/nodes/image/pre_processors.py +13 -0
  43. comfy_ui_api_workflow/_impl/nodes/image/transform.py +385 -0
  44. comfy_ui_api_workflow/_impl/nodes/image/upscaling.py +188 -0
  45. comfy_ui_api_workflow/_impl/nodes/image/video.py +66 -0
  46. comfy_ui_api_workflow/_impl/nodes/model/__init__.py +3 -0
  47. comfy_ui_api_workflow/_impl/nodes/model/conditioning/__init__.py +395 -0
  48. comfy_ui_api_workflow/_impl/nodes/model/conditioning/ace.py +232 -0
  49. comfy_ui_api_workflow/_impl/nodes/model/conditioning/autoregressive.py +53 -0
  50. comfy_ui_api_workflow/_impl/nodes/model/conditioning/controlnet.py +153 -0
  51. comfy_ui_api_workflow/_impl/nodes/model/conditioning/cosmos.py +108 -0
  52. comfy_ui_api_workflow/_impl/nodes/model/conditioning/flux.py +121 -0
  53. comfy_ui_api_workflow/_impl/nodes/model/conditioning/gligen.py +57 -0
  54. comfy_ui_api_workflow/_impl/nodes/model/conditioning/hidream.py +31 -0
  55. comfy_ui_api_workflow/_impl/nodes/model/conditioning/hunyuan_3d.py +44 -0
  56. comfy_ui_api_workflow/_impl/nodes/model/conditioning/hunyuan_image.py +21 -0
  57. comfy_ui_api_workflow/_impl/nodes/model/conditioning/hunyuan_video.py +243 -0
  58. comfy_ui_api_workflow/_impl/nodes/model/conditioning/instructpix2pix.py +28 -0
  59. comfy_ui_api_workflow/_impl/nodes/model/conditioning/kandinsky.py +78 -0
  60. comfy_ui_api_workflow/_impl/nodes/model/conditioning/lotus.py +8 -0
  61. comfy_ui_api_workflow/_impl/nodes/model/conditioning/ltxv.py +504 -0
  62. comfy_ui_api_workflow/_impl/nodes/model/conditioning/lumina.py +39 -0
  63. comfy_ui_api_workflow/_impl/nodes/model/conditioning/minimax.py +110 -0
  64. comfy_ui_api_workflow/_impl/nodes/model/conditioning/minimax_music.py +53 -0
  65. comfy_ui_api_workflow/_impl/nodes/model/conditioning/photomaker.py +28 -0
  66. comfy_ui_api_workflow/_impl/nodes/model/conditioning/pixart.py +34 -0
  67. comfy_ui_api_workflow/_impl/nodes/model/conditioning/qwen_image.py +101 -0
  68. comfy_ui_api_workflow/_impl/nodes/model/conditioning/stable_audio.py +34 -0
  69. comfy_ui_api_workflow/_impl/nodes/model/conditioning/stable_cascade.py +16 -0
  70. comfy_ui_api_workflow/_impl/nodes/model/conditioning/stable_diffusion.py +141 -0
  71. comfy_ui_api_workflow/_impl/nodes/model/conditioning/stable_diffusion_upscaler.py +37 -0
  72. comfy_ui_api_workflow/_impl/nodes/model/conditioning/stable_video.py +63 -0
  73. comfy_ui_api_workflow/_impl/nodes/model/conditioning/stable_video_3d.py +53 -0
  74. comfy_ui_api_workflow/_impl/nodes/model/conditioning/stable_zero123.py +128 -0
  75. comfy_ui_api_workflow/_impl/nodes/model/conditioning/transform.py +341 -0
  76. comfy_ui_api_workflow/_impl/nodes/model/conditioning/trellis.py +168 -0
  77. comfy_ui_api_workflow/_impl/nodes/model/conditioning/triposplat.py +54 -0
  78. comfy_ui_api_workflow/_impl/nodes/model/conditioning/void.py +61 -0
  79. comfy_ui_api_workflow/_impl/nodes/model/conditioning/wan/__init__.py +184 -0
  80. comfy_ui_api_workflow/_impl/nodes/model/conditioning/wan/animate.py +255 -0
  81. comfy_ui_api_workflow/_impl/nodes/model/conditioning/wan/camera.py +150 -0
  82. comfy_ui_api_workflow/_impl/nodes/model/conditioning/wan/dancer.py +102 -0
  83. comfy_ui_api_workflow/_impl/nodes/model/conditioning/wan/fun_control.py +129 -0
  84. comfy_ui_api_workflow/_impl/nodes/model/conditioning/wan/fun_inpaint.py +68 -0
  85. comfy_ui_api_workflow/_impl/nodes/model/conditioning/wan/humo.py +63 -0
  86. comfy_ui_api_workflow/_impl/nodes/model/conditioning/wan/move.py +332 -0
  87. comfy_ui_api_workflow/_impl/nodes/model/conditioning/wan/phantom_subject.py +58 -0
  88. comfy_ui_api_workflow/_impl/nodes/model/conditioning/wan/scail.py +161 -0
  89. comfy_ui_api_workflow/_impl/nodes/model/conditioning/wan/sound.py +128 -0
  90. comfy_ui_api_workflow/_impl/nodes/model/conditioning/wan/vace.py +73 -0
  91. comfy_ui_api_workflow/_impl/nodes/model/conditioning/yue2.py +189 -0
  92. comfy_ui_api_workflow/_impl/nodes/model/conditioning/z_image.py +59 -0
  93. comfy_ui_api_workflow/_impl/nodes/model/latent/__init__.py +510 -0
  94. comfy_ui_api_workflow/_impl/nodes/model/latent/ace.py +49 -0
  95. comfy_ui_api_workflow/_impl/nodes/model/latent/advanced/__init__.py +210 -0
  96. comfy_ui_api_workflow/_impl/nodes/model/latent/advanced/operations.py +113 -0
  97. comfy_ui_api_workflow/_impl/nodes/model/latent/autoregressive.py +36 -0
  98. comfy_ui_api_workflow/_impl/nodes/model/latent/batch.py +93 -0
  99. comfy_ui_api_workflow/_impl/nodes/model/latent/chroma_radiance.py +28 -0
  100. comfy_ui_api_workflow/_impl/nodes/model/latent/cosmos.py +36 -0
  101. comfy_ui_api_workflow/_impl/nodes/model/latent/flux.py +28 -0
  102. comfy_ui_api_workflow/_impl/nodes/model/latent/hidream.py +28 -0
  103. comfy_ui_api_workflow/_impl/nodes/model/latent/hunyuan_3d.py +57 -0
  104. comfy_ui_api_workflow/_impl/nodes/model/latent/hunyuan_image.py +28 -0
  105. comfy_ui_api_workflow/_impl/nodes/model/latent/hunyuan_video.py +130 -0
  106. comfy_ui_api_workflow/_impl/nodes/model/latent/ltxv.py +162 -0
  107. comfy_ui_api_workflow/_impl/nodes/model/latent/minimax.py +28 -0
  108. comfy_ui_api_workflow/_impl/nodes/model/latent/minimax_music.py +25 -0
  109. comfy_ui_api_workflow/_impl/nodes/model/latent/mochi.py +36 -0
  110. comfy_ui_api_workflow/_impl/nodes/model/latent/qwen.py +36 -0
  111. comfy_ui_api_workflow/_impl/nodes/model/latent/seedvr.py +16 -0
  112. comfy_ui_api_workflow/_impl/nodes/model/latent/stable_cascade.py +60 -0
  113. comfy_ui_api_workflow/_impl/nodes/model/latent/stable_diffusion.py +28 -0
  114. comfy_ui_api_workflow/_impl/nodes/model/latent/transform.py +92 -0
  115. comfy_ui_api_workflow/_impl/nodes/model/latent/trellis.py +91 -0
  116. comfy_ui_api_workflow/_impl/nodes/model/latent/triposplat.py +86 -0
  117. comfy_ui_api_workflow/_impl/nodes/model/latent/void.py +54 -0
  118. comfy_ui_api_workflow/_impl/nodes/model/latent/yue2.py +25 -0
  119. comfy_ui_api_workflow/_impl/nodes/model/loaders.py +820 -0
  120. comfy_ui_api_workflow/_impl/nodes/model/merging/__init__.py +290 -0
  121. comfy_ui_api_workflow/_impl/nodes/model/merging/model_specific.py +4370 -0
  122. comfy_ui_api_workflow/_impl/nodes/model/patch/__init__.py +463 -0
  123. comfy_ui_api_workflow/_impl/nodes/model/patch/anima.py +53 -0
  124. comfy_ui_api_workflow/_impl/nodes/model/patch/chroma_radiance.py +50 -0
  125. comfy_ui_api_workflow/_impl/nodes/model/patch/flux.py +63 -0
  126. comfy_ui_api_workflow/_impl/nodes/model/patch/hidream.py +72 -0
  127. comfy_ui_api_workflow/_impl/nodes/model/patch/ltxv.py +125 -0
  128. comfy_ui_api_workflow/_impl/nodes/model/patch/minimax.py +92 -0
  129. comfy_ui_api_workflow/_impl/nodes/model/patch/qwen.py +57 -0
  130. comfy_ui_api_workflow/_impl/nodes/model/patch/sensenova.py +21 -0
  131. comfy_ui_api_workflow/_impl/nodes/model/patch/stable_cascade.py +21 -0
  132. comfy_ui_api_workflow/_impl/nodes/model/patch/stable_diffusion.py +21 -0
  133. comfy_ui_api_workflow/_impl/nodes/model/patch/supir.py +57 -0
  134. comfy_ui_api_workflow/_impl/nodes/model/patch/unet.py +281 -0
  135. comfy_ui_api_workflow/_impl/nodes/model/patch/wan.py +143 -0
  136. comfy_ui_api_workflow/_impl/nodes/model/sampling/__init__.py +228 -0
  137. comfy_ui_api_workflow/_impl/nodes/model/sampling/custom.py +123 -0
  138. comfy_ui_api_workflow/_impl/nodes/model/sampling/guiders.py +252 -0
  139. comfy_ui_api_workflow/_impl/nodes/model/sampling/noise.py +52 -0
  140. comfy_ui_api_workflow/_impl/nodes/model/sampling/samplers.py +531 -0
  141. comfy_ui_api_workflow/_impl/nodes/model/sampling/schedulers.py +462 -0
  142. comfy_ui_api_workflow/_impl/nodes/model/sampling/sigmas.py +163 -0
  143. comfy_ui_api_workflow/_impl/nodes/model/training.py +249 -0
  144. comfy_ui_api_workflow/_impl/nodes/partner/__init__.py +3 -0
  145. comfy_ui_api_workflow/_impl/nodes/partner/audio/__init__.py +3 -0
  146. comfy_ui_api_workflow/_impl/nodes/partner/audio/elevenlabs.py +47 -0
  147. comfy_ui_api_workflow/_impl/nodes/partner/image/__init__.py +3 -0
  148. comfy_ui_api_workflow/_impl/nodes/partner/image/bytedance.py +16 -0
  149. comfy_ui_api_workflow/_impl/nodes/partner/image/krea.py +31 -0
  150. comfy_ui_api_workflow/_impl/nodes/partner/image/luma.py +27 -0
  151. comfy_ui_api_workflow/_impl/nodes/partner/image/recraft.py +220 -0
  152. comfy_ui_api_workflow/_impl/nodes/partner/text/__init__.py +3 -0
  153. comfy_ui_api_workflow/_impl/nodes/partner/text/gemini.py +25 -0
  154. comfy_ui_api_workflow/_impl/nodes/partner/text/openai.py +77 -0
  155. comfy_ui_api_workflow/_impl/nodes/partner/video/__init__.py +3 -0
  156. comfy_ui_api_workflow/_impl/nodes/partner/video/bytedance.py +16 -0
  157. comfy_ui_api_workflow/_impl/nodes/partner/video/pixverse.py +27 -0
  158. comfy_ui_api_workflow/_impl/nodes/text.py +506 -0
  159. comfy_ui_api_workflow/_impl/nodes/three_d/__init__.py +563 -0
  160. comfy_ui_api_workflow/_impl/nodes/three_d/mesh.py +183 -0
  161. comfy_ui_api_workflow/_impl/nodes/three_d/splat.py +262 -0
  162. comfy_ui_api_workflow/_impl/nodes/three_d/texturing.py +254 -0
  163. comfy_ui_api_workflow/_impl/nodes/utilities/__init__.py +404 -0
  164. comfy_ui_api_workflow/_impl/nodes/utilities/logic.py +44 -0
  165. comfy_ui_api_workflow/_impl/nodes/utilities/primitive.py +107 -0
  166. comfy_ui_api_workflow/_impl/nodes/validation.py +126 -0
  167. comfy_ui_api_workflow/_impl/nodes/video/__init__.py +440 -0
  168. comfy_ui_api_workflow/_impl/nodes/video/batch.py +45 -0
  169. comfy_ui_api_workflow/_impl/nodes/video/preprocessors.py +24 -0
  170. comfy_ui_api_workflow/_impl/nodes/video/transform.py +52 -0
  171. comfy_ui_api_workflow/_impl/pipeline.py +67 -0
  172. comfy_ui_api_workflow/_impl/workflow.py +539 -0
  173. comfy_ui_api_workflow-0.0.1.dist-info/METADATA +123 -0
  174. comfy_ui_api_workflow-0.0.1.dist-info/RECORD +176 -0
  175. comfy_ui_api_workflow-0.0.1.dist-info/WHEEL +4 -0
  176. comfy_ui_api_workflow-0.0.1.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,689 @@
1
+ from typing import Literal, get_args
2
+
3
+ from ..base import BaseNode
4
+ from ..validation import (
5
+ validate_bool,
6
+ validate_choice,
7
+ validate_not_empty,
8
+ validate_range,
9
+ )
10
+
11
+
12
+ class SDPoseKeypointExtractor(BaseNode):
13
+ __slots__ = ("model", "vae", "image", "batch_size", "bboxes")
14
+ CATEGORY = "image/detection"
15
+ OUTPUTS = {"keypoints": 0}
16
+ RETURN_TYPES = ("POSE_KEYPOINT",)
17
+ INPUT_SOCKET_TYPES = {
18
+ "model": "MODEL",
19
+ "vae": "VAE",
20
+ "image": "IMAGE",
21
+ "batch_size": "INT",
22
+ "bboxes": "BOUNDING_BOX",
23
+ }
24
+
25
+ def __init__(
26
+ self,
27
+ node_id: str,
28
+ model: tuple[str, int],
29
+ vae: tuple[str, int],
30
+ image: tuple[str, int],
31
+ batch_size: int | tuple[str, int] = 16,
32
+ bboxes: tuple[str, int] | None = None,
33
+ ) -> None:
34
+ super().__init__(node_id=node_id)
35
+ self.model = model
36
+ self.vae = vae
37
+ self.image = image
38
+ self.batch_size = batch_size
39
+ if bboxes is not None:
40
+ self.bboxes = bboxes
41
+ self.__validate()
42
+
43
+ def __validate(self) -> None:
44
+ validate_range("batch_size", self.batch_size, 1, 10_000)
45
+
46
+
47
+ class SDPoseDrawKeypoints(BaseNode):
48
+ __slots__ = (
49
+ "keypoints",
50
+ "draw_body",
51
+ "draw_hands",
52
+ "draw_face",
53
+ "draw_feet",
54
+ "stick_width",
55
+ "face_point_size",
56
+ "score_threshold",
57
+ "draw_head",
58
+ )
59
+ CATEGORY = "image/detection"
60
+ OUTPUTS = {"IMAGE": 0}
61
+ RETURN_TYPES = ("IMAGE",)
62
+ INPUT_SOCKET_TYPES = {
63
+ "keypoints": "POSE_KEYPOINT",
64
+ "draw_body": "BOOLEAN",
65
+ "draw_hands": "BOOLEAN",
66
+ "draw_face": "BOOLEAN",
67
+ "draw_feet": "BOOLEAN",
68
+ "stick_width": "INT",
69
+ "face_point_size": "INT",
70
+ "score_threshold": "FLOAT",
71
+ "draw_head": "BOOLEAN",
72
+ }
73
+
74
+ def __init__(
75
+ self,
76
+ node_id: str,
77
+ keypoints: tuple[str, int],
78
+ draw_body: bool | tuple[str, int] = True,
79
+ draw_hands: bool | tuple[str, int] = True,
80
+ draw_face: bool | tuple[str, int] = True,
81
+ draw_feet: bool | tuple[str, int] = False,
82
+ stick_width: int | tuple[str, int] = 4,
83
+ face_point_size: int | tuple[str, int] = 3,
84
+ score_threshold: float | tuple[str, int] = 0.3,
85
+ draw_head: bool | tuple[str, int] = True,
86
+ ) -> None:
87
+ super().__init__(node_id=node_id)
88
+ self.keypoints = keypoints
89
+ self.draw_body = draw_body
90
+ self.draw_hands = draw_hands
91
+ self.draw_face = draw_face
92
+ self.draw_feet = draw_feet
93
+ self.stick_width = stick_width
94
+ self.face_point_size = face_point_size
95
+ self.score_threshold = score_threshold
96
+ self.draw_head = draw_head
97
+ self.__validate()
98
+
99
+ def __validate(self) -> None:
100
+ validate_bool("draw_body", self.draw_body)
101
+ validate_bool("draw_hands", self.draw_hands)
102
+ validate_bool("draw_face", self.draw_face)
103
+ validate_bool("draw_feet", self.draw_feet)
104
+ validate_range("stick_width", self.stick_width, 1, 10)
105
+ validate_range("face_point_size", self.face_point_size, 1, 10)
106
+ validate_range("score_threshold", self.score_threshold, 0.0, 1.0)
107
+ validate_bool("draw_head", self.draw_head)
108
+
109
+
110
+ class SDPoseFaceBBoxes(BaseNode):
111
+ __slots__ = ("keypoints", "scale", "force_square")
112
+ CATEGORY = "image/detection"
113
+ OUTPUTS = {"bboxes": 0}
114
+ RETURN_TYPES = ("BOUNDING_BOX",)
115
+ INPUT_SOCKET_TYPES = {
116
+ "keypoints": "POSE_KEYPOINT",
117
+ "scale": "FLOAT",
118
+ "force_square": "BOOLEAN",
119
+ }
120
+
121
+ def __init__(
122
+ self,
123
+ node_id: str,
124
+ keypoints: tuple[str, int],
125
+ scale: float | tuple[str, int] = 1.5,
126
+ force_square: bool | tuple[str, int] = True,
127
+ ) -> None:
128
+ super().__init__(node_id=node_id)
129
+ self.keypoints = keypoints
130
+ self.scale = scale
131
+ self.force_square = force_square
132
+ self.__validate()
133
+
134
+ def __validate(self) -> None:
135
+ validate_range("scale", self.scale, 1.0, 10.0)
136
+ validate_bool("force_square", self.force_square)
137
+
138
+
139
+ RTDETR_detect_Class_Names = Literal[
140
+ "all",
141
+ "person",
142
+ "bicycle",
143
+ "car",
144
+ "motorcycle",
145
+ "airplane",
146
+ "bus",
147
+ "train",
148
+ "truck",
149
+ "boat",
150
+ "traffic light",
151
+ "fire hydrant",
152
+ "stop sign",
153
+ "parking meter",
154
+ "bench",
155
+ "bird",
156
+ "cat",
157
+ "dog",
158
+ "horse",
159
+ "sheep",
160
+ "cow",
161
+ "elephant",
162
+ "bear",
163
+ "zebra",
164
+ "giraffe",
165
+ "backpack",
166
+ "umbrella",
167
+ "handbag",
168
+ "tie",
169
+ "suitcase",
170
+ "frisbee",
171
+ "skis",
172
+ "snowboard",
173
+ "sports ball",
174
+ "kite",
175
+ "baseball bat",
176
+ "baseball glove",
177
+ "skateboard",
178
+ "surfboard",
179
+ "tennis racket",
180
+ "bottle",
181
+ "wine glass",
182
+ "cup",
183
+ "fork",
184
+ "knife",
185
+ "spoon",
186
+ "bowl",
187
+ "banana",
188
+ "apple",
189
+ "sandwich",
190
+ "orange",
191
+ "broccoli",
192
+ "carrot",
193
+ "hot dog",
194
+ "pizza",
195
+ "donut",
196
+ "cake",
197
+ "chair",
198
+ "couch",
199
+ "potted plant",
200
+ "bed",
201
+ "dining table",
202
+ "toilet",
203
+ "tv",
204
+ "laptop",
205
+ "mouse",
206
+ "remote",
207
+ "keyboard",
208
+ "cell phone",
209
+ "microwave",
210
+ "oven",
211
+ "toaster",
212
+ "sink",
213
+ "refrigerator",
214
+ "book",
215
+ "clock",
216
+ "vase",
217
+ "scissors",
218
+ "teddy bear",
219
+ "hair drier",
220
+ "toothbrush",
221
+ ]
222
+ RTDETR_DETECT_CLASS_NAMES = frozenset(get_args(RTDETR_detect_Class_Names))
223
+
224
+
225
+ class RTDETR_detect(BaseNode):
226
+ __slots__ = ("model", "image", "threshold", "class_name", "max_detections")
227
+ CATEGORY = "image/detection"
228
+ OUTPUTS = {"bboxes": 0}
229
+ RETURN_TYPES = ("BOUNDING_BOX",)
230
+ INPUT_SOCKET_TYPES = {
231
+ "model": "MODEL",
232
+ "image": "IMAGE",
233
+ "threshold": "FLOAT",
234
+ "class_name": "COMBO",
235
+ "max_detections": "INT",
236
+ }
237
+
238
+ def __init__(
239
+ self,
240
+ node_id: str,
241
+ model: tuple[str, int],
242
+ image: tuple[str, int],
243
+ threshold: float | tuple[str, int] = 0.5,
244
+ class_name: RTDETR_detect_Class_Names | tuple[str, int] = "all",
245
+ max_detections: int | tuple[str, int] = 100,
246
+ ) -> None:
247
+ super().__init__(node_id=node_id)
248
+ self.model = model
249
+ self.image = image
250
+ self.threshold = threshold
251
+ self.class_name = class_name
252
+ self.max_detections = max_detections
253
+ self.__validate()
254
+
255
+ def __validate(self) -> None:
256
+ validate_range("threshold", self.threshold)
257
+ validate_choice("class_name", self.class_name, RTDETR_DETECT_CLASS_NAMES)
258
+ validate_range("max_detections", self.max_detections)
259
+
260
+
261
+ class DrawBBoxes(BaseNode):
262
+ __slots__ = ("bboxes", "image")
263
+ CATEGORY = "image/detection"
264
+ OUTPUTS = {"out_image": 0}
265
+ RETURN_TYPES = ("IMAGE",)
266
+ INPUT_SOCKET_TYPES = {"bboxes": "BOUNDING_BOX", "image": "IMAGE"}
267
+
268
+ def __init__(
269
+ self,
270
+ node_id: str,
271
+ bboxes: tuple[str, int],
272
+ image: tuple[str, int] | None = None,
273
+ ) -> None:
274
+ super().__init__(node_id=node_id)
275
+ self.bboxes = bboxes
276
+ if image is not None:
277
+ self.image = image
278
+
279
+
280
+ class SAM3_Detect(BaseNode):
281
+ __slots__ = (
282
+ "model",
283
+ "image",
284
+ "threshold",
285
+ "refine_iterations",
286
+ "individual_masks",
287
+ "conditioning",
288
+ "bboxes",
289
+ "positive_coords",
290
+ "negative_coords",
291
+ )
292
+ CATEGORY = "image/detection"
293
+ OUTPUTS = {"masks": 0, "bboxes": 1}
294
+ RETURN_TYPES = ("MASK", "BOUNDING_BOX")
295
+ INPUT_SOCKET_TYPES = {
296
+ "model": "MODEL",
297
+ "image": "IMAGE",
298
+ "threshold": "FLOAT",
299
+ "refine_iterations": "INT",
300
+ "individual_masks": "BOOLEAN",
301
+ "conditioning": "CONDITIONING",
302
+ "bboxes": "BOUNDING_BOX",
303
+ "positive_coords": "STRING",
304
+ "negative_coords": "STRING",
305
+ }
306
+
307
+ def __init__(
308
+ self,
309
+ node_id: str,
310
+ model: tuple[str, int],
311
+ image: tuple[str, int],
312
+ threshold: float | tuple[str, int] = 0.5,
313
+ refine_iterations: int | tuple[str, int] = 2,
314
+ individual_masks: bool | tuple[str, int] = False,
315
+ conditioning: tuple[str, int] | None = None,
316
+ bboxes: tuple[str, int] | None = None,
317
+ positive_coords: tuple[str, int] | None = None,
318
+ negative_coords: tuple[str, int] | None = None,
319
+ ) -> None:
320
+ super().__init__(node_id=node_id)
321
+ self.model = model
322
+ self.image = image
323
+ self.threshold = threshold
324
+ self.refine_iterations = refine_iterations
325
+ self.individual_masks = individual_masks
326
+ if conditioning is not None:
327
+ self.conditioning = conditioning
328
+ if bboxes is not None:
329
+ self.bboxes = bboxes
330
+ if positive_coords is not None:
331
+ self.positive_coords = positive_coords
332
+ if negative_coords is not None:
333
+ self.negative_coords = negative_coords
334
+ self.__validate()
335
+
336
+ def __validate(self) -> None:
337
+ validate_range("threshold", self.threshold, 0.0, 1.0)
338
+ validate_range("refine_iterations", self.refine_iterations, 0, 5)
339
+ validate_bool("individual_masks", self.individual_masks)
340
+
341
+
342
+ class SAM3_VideoTrack(BaseNode):
343
+ __slots__ = (
344
+ "images",
345
+ "model",
346
+ "detection_threshold",
347
+ "max_objects",
348
+ "detect_interval",
349
+ "initial_mask",
350
+ "conditioning",
351
+ )
352
+ CATEGORY = "image/detection"
353
+ OUTPUTS = {"track_data": 0}
354
+ RETURN_TYPES = ("SAM3_TRACK_DATA",)
355
+ INPUT_SOCKET_TYPES = {
356
+ "images": "IMAGE",
357
+ "model": "MODEL",
358
+ "detection_threshold": "FLOAT",
359
+ "max_objects": "INT",
360
+ "detect_interval": "INT",
361
+ "initial_mask": "MASK",
362
+ "conditioning": "CONDITIONING",
363
+ }
364
+
365
+ def __init__(
366
+ self,
367
+ node_id: str,
368
+ images: tuple[str, int],
369
+ model: tuple[str, int],
370
+ detection_threshold: float | tuple[str, int] = 0.5,
371
+ max_objects: int | tuple[str, int] = 4,
372
+ detect_interval: int | tuple[str, int] = 1,
373
+ initial_mask: tuple[str, int] | None = None,
374
+ conditioning: tuple[str, int] | None = None,
375
+ ) -> None:
376
+ super().__init__(node_id=node_id)
377
+ self.images = images
378
+ self.model = model
379
+ self.detection_threshold = detection_threshold
380
+ self.max_objects = max_objects
381
+ self.detect_interval = detect_interval
382
+ if initial_mask is not None:
383
+ self.initial_mask = initial_mask
384
+ if conditioning is not None:
385
+ self.conditioning = conditioning
386
+ self.__validate()
387
+
388
+ def __validate(self) -> None:
389
+ validate_range("detection_threshold", self.detection_threshold, 0.0, 1.0)
390
+ validate_range("max_objects", self.max_objects, 0, 64)
391
+ validate_range("detect_interval", self.detect_interval, 1)
392
+
393
+
394
+ class SAM3_TrackPreview(BaseNode):
395
+ __slots__ = ("track_data", "opacity", "fps", "images")
396
+ CATEGORY = "image/detection"
397
+ INPUT_SOCKET_TYPES = {
398
+ "track_data": "SAM3_TRACK_DATA",
399
+ "opacity": "FLOAT",
400
+ "fps": "FLOAT",
401
+ "images": "IMAGE",
402
+ }
403
+
404
+ def __init__(
405
+ self,
406
+ node_id: str,
407
+ track_data: tuple[str, int],
408
+ opacity: float | tuple[str, int] = 0.5,
409
+ fps: float | tuple[str, int] = 24.0,
410
+ images: tuple[str, int] | None = None,
411
+ ) -> None:
412
+ super().__init__(node_id=node_id)
413
+ self.track_data = track_data
414
+ self.opacity = opacity
415
+ self.fps = fps
416
+ if images is not None:
417
+ self.images = images
418
+ self.__validate()
419
+
420
+ def __validate(self) -> None:
421
+ validate_range("opacity", self.opacity, 0.0, 1.0)
422
+ validate_range("fps", self.fps, 1.0, 120.0)
423
+
424
+
425
+ class SAM3_TrackToMask(BaseNode):
426
+ __slots__ = ("track_data", "object_indices")
427
+ CATEGORY = "image/detection"
428
+ OUTPUTS = {"masks": 0}
429
+ RETURN_TYPES = ("MASK",)
430
+ INPUT_SOCKET_TYPES = {"track_data": "SAM3_TRACK_DATA", "object_indices": "STRING"}
431
+
432
+ def __init__(
433
+ self,
434
+ node_id: str,
435
+ track_data: tuple[str, int],
436
+ object_indices: str | tuple[str, int] = "",
437
+ ) -> None:
438
+ super().__init__(node_id=node_id)
439
+ self.track_data = track_data
440
+ self.object_indices = object_indices
441
+
442
+
443
+ MediaPipeFaceLandmarker_Detector_Variants = Literal["short", "full", "both"]
444
+ MediaPipeFaceLandmarker_Missing_Frame_Fallbacks = Literal[
445
+ "empty", "previous", "interpolate"
446
+ ]
447
+ MEDIAPIPEFACELANDMARKER_DETECTOR_VARIANTS = frozenset(
448
+ get_args(MediaPipeFaceLandmarker_Detector_Variants)
449
+ )
450
+ MEDIAPIPEFACELANDMARKER_MISSING_FRAME_FALLBACKS = frozenset(
451
+ get_args(MediaPipeFaceLandmarker_Missing_Frame_Fallbacks)
452
+ )
453
+
454
+
455
+ class MediaPipeFaceLandmarker(BaseNode):
456
+ __slots__ = (
457
+ "face_detection_model",
458
+ "image",
459
+ "detector_variant",
460
+ "num_faces",
461
+ "min_confidence",
462
+ "missing_frame_fallback",
463
+ )
464
+ CATEGORY = "image/detection"
465
+ OUTPUTS = {"face_landmarks": 0, "bboxes": 1}
466
+ RETURN_TYPES = ("FACE_LANDMARKS", "BOUNDING_BOX")
467
+ INPUT_SOCKET_TYPES = {
468
+ "face_detection_model": "FACE_DETECTION_MODEL",
469
+ "image": "IMAGE",
470
+ "detector_variant": "COMBO",
471
+ "num_faces": "INT",
472
+ "min_confidence": "FLOAT",
473
+ "missing_frame_fallback": "COMBO",
474
+ }
475
+
476
+ def __init__(
477
+ self,
478
+ node_id: str,
479
+ face_detection_model: tuple[str, int],
480
+ image: tuple[str, int],
481
+ detector_variant: (
482
+ MediaPipeFaceLandmarker_Detector_Variants | tuple[str, int]
483
+ ) = "short",
484
+ num_faces: int | tuple[str, int] = 1,
485
+ min_confidence: float | tuple[str, int] = 0.5,
486
+ missing_frame_fallback: (
487
+ MediaPipeFaceLandmarker_Missing_Frame_Fallbacks | tuple[str, int]
488
+ ) = "empty",
489
+ ) -> None:
490
+ super().__init__(node_id=node_id)
491
+ self.face_detection_model = face_detection_model
492
+ self.image = image
493
+ self.detector_variant = detector_variant
494
+ self.num_faces = num_faces
495
+ self.min_confidence = min_confidence
496
+ self.missing_frame_fallback = missing_frame_fallback
497
+ self.__validate()
498
+
499
+ def __validate(self) -> None:
500
+ validate_choice(
501
+ "detector_variant",
502
+ self.detector_variant,
503
+ MEDIAPIPEFACELANDMARKER_DETECTOR_VARIANTS,
504
+ )
505
+ validate_range("num_faces", self.num_faces, 0, 16)
506
+ validate_range("min_confidence", self.min_confidence, 0.0, 1.0)
507
+ validate_choice(
508
+ "missing_frame_fallback",
509
+ self.missing_frame_fallback,
510
+ MEDIAPIPEFACELANDMARKER_MISSING_FRAME_FALLBACKS,
511
+ )
512
+
513
+
514
+ class SAM3DBody_Loader(BaseNode):
515
+ __slots__ = ("model_file",)
516
+ CATEGORY = "image/detection"
517
+ OUTPUTS = {"sam3d_body_model": 0}
518
+ RETURN_TYPES = ("SAM3D_BODY_MODEL",)
519
+ INPUT_SOCKET_TYPES = {"model_file": "COMBO"}
520
+
521
+ def __init__(self, node_id: str, model_file: str | tuple[str, int]) -> None:
522
+ super().__init__(node_id=node_id)
523
+ self.model_file = model_file
524
+ self.__validate()
525
+
526
+ def __validate(self) -> None:
527
+ validate_not_empty("model_file", self.model_file)
528
+
529
+
530
+ class SAM3DBody_Predict(BaseNode):
531
+ __slots__ = (
532
+ "sam3d_body_model",
533
+ "image",
534
+ "fov",
535
+ "run_hand_refinement",
536
+ "batch_size",
537
+ "track_data",
538
+ "bboxes",
539
+ )
540
+ CATEGORY = "image/detection"
541
+ OUTPUTS = {"mhr_pose_data": 0}
542
+ RETURN_TYPES = ("MHR_POSE_DATA",)
543
+ INPUT_SOCKET_TYPES = {
544
+ "sam3d_body_model": "SAM3D_BODY_MODEL",
545
+ "image": "IMAGE",
546
+ "run_hand_refinement": "BOOLEAN",
547
+ "fov": "FLOAT",
548
+ "batch_size": "INT",
549
+ "track_data": "SAM3_TRACK_DATA",
550
+ "bboxes": "BOUNDING_BOX",
551
+ }
552
+
553
+ def __init__(
554
+ self,
555
+ node_id: str,
556
+ sam3d_body_model: tuple[str, int],
557
+ image: tuple[str, int],
558
+ fov: float | tuple[str, int],
559
+ run_hand_refinement: bool | tuple[str, int] = True,
560
+ batch_size: int | tuple[str, int] = 64,
561
+ track_data: tuple[str, int] | None = None,
562
+ bboxes: tuple[str, int] | None = None,
563
+ ) -> None:
564
+ super().__init__(node_id=node_id)
565
+ self.sam3d_body_model = sam3d_body_model
566
+ self.image = image
567
+ self.fov = fov
568
+ self.run_hand_refinement = run_hand_refinement
569
+ self.batch_size = batch_size
570
+ if track_data is not None:
571
+ self.track_data = track_data
572
+ if bboxes is not None:
573
+ self.bboxes = bboxes
574
+ self.__validate()
575
+
576
+ def __validate(self) -> None:
577
+ validate_range("fov", self.fov)
578
+ validate_bool("run_hand_refinement", self.run_hand_refinement)
579
+ validate_range("batch_size", self.batch_size, 1, 512)
580
+
581
+
582
+ class SAM3DBody_FaceExpression(BaseNode):
583
+ __slots__ = (
584
+ "sam3d_body_model",
585
+ "mhr_pose_data",
586
+ "image",
587
+ "strength",
588
+ "mouth_strength",
589
+ "eye_strength",
590
+ "brow_strength",
591
+ "input_threshold",
592
+ "blendshape_smooth_window",
593
+ )
594
+ CATEGORY = "image/detection"
595
+ OUTPUTS = {"mhr_pose_data": 0}
596
+ RETURN_TYPES = ("MHR_POSE_DATA",)
597
+ INPUT_SOCKET_TYPES = {
598
+ "sam3d_body_model": "SAM3D_BODY_MODEL",
599
+ "mhr_pose_data": "MHR_POSE_DATA",
600
+ "image": "IMAGE",
601
+ "strength": "FLOAT",
602
+ "mouth_strength": "FLOAT",
603
+ "eye_strength": "FLOAT",
604
+ "brow_strength": "FLOAT",
605
+ "input_threshold": "FLOAT",
606
+ "blendshape_smooth_window": "INT",
607
+ }
608
+
609
+ def __init__(
610
+ self,
611
+ node_id: str,
612
+ sam3d_body_model: tuple[str, int],
613
+ mhr_pose_data: tuple[str, int],
614
+ image: tuple[str, int],
615
+ strength: float | tuple[str, int] = 1.0,
616
+ mouth_strength: float | tuple[str, int] = 1.0,
617
+ eye_strength: float | tuple[str, int] = 2.0,
618
+ brow_strength: float | tuple[str, int] = 2.0,
619
+ input_threshold: float | tuple[str, int] = 0.02,
620
+ blendshape_smooth_window: int | tuple[str, int] = 7,
621
+ ) -> None:
622
+ super().__init__(node_id=node_id)
623
+ self.sam3d_body_model = sam3d_body_model
624
+ self.mhr_pose_data = mhr_pose_data
625
+ self.image = image
626
+ self.strength = strength
627
+ self.mouth_strength = mouth_strength
628
+ self.eye_strength = eye_strength
629
+ self.brow_strength = brow_strength
630
+ self.input_threshold = input_threshold
631
+ self.blendshape_smooth_window = blendshape_smooth_window
632
+ self.__validate()
633
+
634
+ def __validate(self) -> None:
635
+ validate_range("strength", self.strength, 0.0, 4.0)
636
+ validate_range("mouth_strength", self.mouth_strength, 0.0, 4.0)
637
+ validate_range("eye_strength", self.eye_strength, 0.0, 4.0)
638
+ validate_range("brow_strength", self.brow_strength, 0.0, 4.0)
639
+ validate_range("input_threshold", self.input_threshold, 0.0, 0.5)
640
+ validate_range("blendshape_smooth_window", self.blendshape_smooth_window, 1, 31)
641
+
642
+
643
+ SAM3DBody_Smooth_Methods = Literal["gaussian", "savgol"]
644
+ SAM3DBODY_SMOOTH_METHODS = frozenset(get_args(SAM3DBody_Smooth_Methods))
645
+
646
+
647
+ class SAM3DBody_Smooth(BaseNode):
648
+ __slots__ = (
649
+ "mhr_pose_data",
650
+ "strength",
651
+ "method",
652
+ "window",
653
+ "rotation_threshold_degrees",
654
+ )
655
+ CATEGORY = "image/detection"
656
+ OUTPUTS = {"mhr_pose_data": 0}
657
+ RETURN_TYPES = ("MHR_POSE_DATA",)
658
+ INPUT_SOCKET_TYPES = {
659
+ "mhr_pose_data": "MHR_POSE_DATA",
660
+ "strength": "FLOAT",
661
+ "method": "COMBO",
662
+ "window": "INT",
663
+ "rotation_threshold_degrees": "FLOAT",
664
+ }
665
+
666
+ def __init__(
667
+ self,
668
+ node_id: str,
669
+ mhr_pose_data: tuple[str, int],
670
+ strength: float | tuple[str, int] = 1.0,
671
+ method: SAM3DBody_Smooth_Methods | tuple[str, int] = "savgol",
672
+ window: int | tuple[str, int] = 7,
673
+ rotation_threshold_degrees: float | tuple[str, int] = 30.0,
674
+ ) -> None:
675
+ super().__init__(node_id=node_id)
676
+ self.mhr_pose_data = mhr_pose_data
677
+ self.strength = strength
678
+ self.method = method
679
+ self.window = window
680
+ self.rotation_threshold_degrees = rotation_threshold_degrees
681
+ self.__validate()
682
+
683
+ def __validate(self) -> None:
684
+ validate_range("strength", self.strength, 0.0, 1.0)
685
+ validate_choice("method", self.method, SAM3DBODY_SMOOTH_METHODS)
686
+ validate_range("window", self.window, 1, 51)
687
+ validate_range(
688
+ "rotation_threshold_degrees", self.rotation_threshold_degrees, 0.0, 90.0
689
+ )