bizyengine 0.4.2__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.
- bizyengine/__init__.py +35 -0
- bizyengine/bizy_server/__init__.py +7 -0
- bizyengine/bizy_server/api_client.py +763 -0
- bizyengine/bizy_server/errno.py +122 -0
- bizyengine/bizy_server/error_handler.py +3 -0
- bizyengine/bizy_server/execution.py +55 -0
- bizyengine/bizy_server/resp.py +24 -0
- bizyengine/bizy_server/server.py +898 -0
- bizyengine/bizy_server/utils.py +93 -0
- bizyengine/bizyair_extras/__init__.py +24 -0
- bizyengine/bizyair_extras/nodes_advanced_refluxcontrol.py +62 -0
- bizyengine/bizyair_extras/nodes_cogview4.py +31 -0
- bizyengine/bizyair_extras/nodes_comfyui_detail_daemon.py +180 -0
- bizyengine/bizyair_extras/nodes_comfyui_instantid.py +164 -0
- bizyengine/bizyair_extras/nodes_comfyui_layerstyle_advance.py +141 -0
- bizyengine/bizyair_extras/nodes_comfyui_pulid_flux.py +88 -0
- bizyengine/bizyair_extras/nodes_controlnet.py +50 -0
- bizyengine/bizyair_extras/nodes_custom_sampler.py +130 -0
- bizyengine/bizyair_extras/nodes_dataset.py +99 -0
- bizyengine/bizyair_extras/nodes_differential_diffusion.py +16 -0
- bizyengine/bizyair_extras/nodes_flux.py +69 -0
- bizyengine/bizyair_extras/nodes_image_utils.py +93 -0
- bizyengine/bizyair_extras/nodes_ip2p.py +20 -0
- bizyengine/bizyair_extras/nodes_ipadapter_plus/__init__.py +1 -0
- bizyengine/bizyair_extras/nodes_ipadapter_plus/nodes_ipadapter_plus.py +1598 -0
- bizyengine/bizyair_extras/nodes_janus_pro.py +81 -0
- bizyengine/bizyair_extras/nodes_kolors_mz/__init__.py +86 -0
- bizyengine/bizyair_extras/nodes_model_advanced.py +62 -0
- bizyengine/bizyair_extras/nodes_sd3.py +52 -0
- bizyengine/bizyair_extras/nodes_segment_anything.py +256 -0
- bizyengine/bizyair_extras/nodes_segment_anything_utils.py +134 -0
- bizyengine/bizyair_extras/nodes_testing_utils.py +139 -0
- bizyengine/bizyair_extras/nodes_trellis.py +199 -0
- bizyengine/bizyair_extras/nodes_ultimatesdupscale.py +137 -0
- bizyengine/bizyair_extras/nodes_upscale_model.py +32 -0
- bizyengine/bizyair_extras/nodes_wan_video.py +49 -0
- bizyengine/bizyair_extras/oauth_callback/main.py +118 -0
- bizyengine/core/__init__.py +8 -0
- bizyengine/core/commands/__init__.py +1 -0
- bizyengine/core/commands/base.py +27 -0
- bizyengine/core/commands/invoker.py +4 -0
- bizyengine/core/commands/processors/model_hosting_processor.py +0 -0
- bizyengine/core/commands/processors/prompt_processor.py +123 -0
- bizyengine/core/commands/servers/model_server.py +0 -0
- bizyengine/core/commands/servers/prompt_server.py +234 -0
- bizyengine/core/common/__init__.py +8 -0
- bizyengine/core/common/caching.py +198 -0
- bizyengine/core/common/client.py +262 -0
- bizyengine/core/common/env_var.py +101 -0
- bizyengine/core/common/utils.py +93 -0
- bizyengine/core/configs/conf.py +112 -0
- bizyengine/core/configs/models.json +101 -0
- bizyengine/core/configs/models.yaml +329 -0
- bizyengine/core/data_types.py +20 -0
- bizyengine/core/image_utils.py +288 -0
- bizyengine/core/nodes_base.py +159 -0
- bizyengine/core/nodes_io.py +97 -0
- bizyengine/core/path_utils/__init__.py +9 -0
- bizyengine/core/path_utils/path_manager.py +276 -0
- bizyengine/core/path_utils/utils.py +34 -0
- bizyengine/misc/__init__.py +0 -0
- bizyengine/misc/auth.py +83 -0
- bizyengine/misc/llm.py +431 -0
- bizyengine/misc/mzkolors.py +93 -0
- bizyengine/misc/nodes.py +1208 -0
- bizyengine/misc/nodes_controlnet_aux.py +491 -0
- bizyengine/misc/nodes_controlnet_union_sdxl.py +171 -0
- bizyengine/misc/route_sam.py +60 -0
- bizyengine/misc/segment_anything.py +276 -0
- bizyengine/misc/supernode.py +182 -0
- bizyengine/misc/utils.py +218 -0
- bizyengine/version.txt +1 -0
- bizyengine-0.4.2.dist-info/METADATA +12 -0
- bizyengine-0.4.2.dist-info/RECORD +76 -0
- bizyengine-0.4.2.dist-info/WHEEL +5 -0
- bizyengine-0.4.2.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import os
|
|
3
|
+
from enum import Enum
|
|
4
|
+
|
|
5
|
+
from aiohttp import web
|
|
6
|
+
|
|
7
|
+
BIZYAIR_DEBUG = os.getenv("BIZYAIR_DEBUG", False)
|
|
8
|
+
CURRENT_DIR = os.path.dirname(os.path.abspath(__file__))
|
|
9
|
+
|
|
10
|
+
SHOW_CASES = {}
|
|
11
|
+
SAM_COORDINATE = {}
|
|
12
|
+
IS_RESET_SAM = False
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class EDIT_MODE(Enum):
|
|
16
|
+
box = 0
|
|
17
|
+
point = 1
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
from server import PromptServer
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
@PromptServer.instance.routes.post("/bizyair/postsam")
|
|
24
|
+
async def save_sam(request):
|
|
25
|
+
global IS_RESET_SAM
|
|
26
|
+
IS_RESET_SAM = False
|
|
27
|
+
post = await request.post()
|
|
28
|
+
SAM_COORDINATE["nums"] = post.get("nums")
|
|
29
|
+
SAM_COORDINATE["mode"] = json.loads(post.get("mode"))
|
|
30
|
+
if SAM_COORDINATE["mode"] == EDIT_MODE.point.value:
|
|
31
|
+
SAM_COORDINATE["point_coords"] = json.loads(post.get("coords"))
|
|
32
|
+
elif SAM_COORDINATE["mode"] == EDIT_MODE.box.value:
|
|
33
|
+
SAM_COORDINATE["box_coords"] = json.loads(post.get("coords"))
|
|
34
|
+
SAM_COORDINATE["filename"] = post.get("filename")
|
|
35
|
+
|
|
36
|
+
return web.Response(status=200)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
@PromptServer.instance.routes.get("/bizyair/getsam")
|
|
40
|
+
async def get_sam(request):
|
|
41
|
+
return web.Response(
|
|
42
|
+
text=json.dumps(SAM_COORDINATE, ensure_ascii=False),
|
|
43
|
+
content_type="application/json",
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
@PromptServer.instance.routes.get("/bizyair/resetsam")
|
|
48
|
+
async def reset_sam(request):
|
|
49
|
+
global IS_RESET_SAM
|
|
50
|
+
IS_RESET_SAM = True
|
|
51
|
+
return web.Response(status=200)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
@PromptServer.instance.routes.get("/bizyair/isresetsam")
|
|
55
|
+
async def isreset_sam(request):
|
|
56
|
+
status = {"isresetsam": IS_RESET_SAM}
|
|
57
|
+
return web.Response(
|
|
58
|
+
text=json.dumps(status),
|
|
59
|
+
content_type="application/json",
|
|
60
|
+
)
|
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
import hashlib
|
|
2
|
+
import json
|
|
3
|
+
import os
|
|
4
|
+
from enum import Enum
|
|
5
|
+
|
|
6
|
+
import folder_paths
|
|
7
|
+
import numpy as np
|
|
8
|
+
import torch
|
|
9
|
+
from bizyengine.core.common.env_var import BIZYAIR_SERVER_ADDRESS
|
|
10
|
+
from bizyengine.core.image_utils import decode_base64_to_np, encode_image_to_base64
|
|
11
|
+
from nodes import LoadImage
|
|
12
|
+
from PIL import Image, ImageOps, ImageSequence
|
|
13
|
+
|
|
14
|
+
from .route_sam import SAM_COORDINATE
|
|
15
|
+
from .utils import get_api_key, send_post_request
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class INFER_MODE(Enum):
|
|
19
|
+
auto = 0
|
|
20
|
+
text = 1
|
|
21
|
+
points_box = 2
|
|
22
|
+
batched_boxes = 3
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class EDIT_MODE(Enum):
|
|
26
|
+
box = 0
|
|
27
|
+
point = 1
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class BizyAirSegmentAnythingText:
|
|
31
|
+
API_URL = f"{BIZYAIR_SERVER_ADDRESS}/supernode/sam"
|
|
32
|
+
|
|
33
|
+
@classmethod
|
|
34
|
+
def INPUT_TYPES(s):
|
|
35
|
+
return {
|
|
36
|
+
"required": {
|
|
37
|
+
"image": ("IMAGE",),
|
|
38
|
+
"prompt": ("STRING", {}),
|
|
39
|
+
"box_threshold": (
|
|
40
|
+
"FLOAT",
|
|
41
|
+
{"default": 0.3, "min": 0, "max": 1.0, "step": 0.01},
|
|
42
|
+
),
|
|
43
|
+
"text_threshold": (
|
|
44
|
+
"FLOAT",
|
|
45
|
+
{"default": 0.3, "min": 0, "max": 1.0, "step": 0.01},
|
|
46
|
+
),
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
RETURN_TYPES = ("IMAGE", "MASK")
|
|
51
|
+
FUNCTION = "text_sam"
|
|
52
|
+
|
|
53
|
+
CATEGORY = "☁️BizyAir/segment-anything"
|
|
54
|
+
|
|
55
|
+
def text_sam(self, image, prompt, box_threshold, text_threshold):
|
|
56
|
+
API_KEY = get_api_key()
|
|
57
|
+
SIZE_LIMIT = 1536
|
|
58
|
+
device = image.device
|
|
59
|
+
_, w, h, c = image.shape
|
|
60
|
+
assert (
|
|
61
|
+
w <= SIZE_LIMIT and h <= SIZE_LIMIT
|
|
62
|
+
), f"width and height must be less than {SIZE_LIMIT}x{SIZE_LIMIT}, but got {w} and {h}"
|
|
63
|
+
|
|
64
|
+
payload = {
|
|
65
|
+
"image": None,
|
|
66
|
+
"mode": 1, # 文本分割模式
|
|
67
|
+
"params": {
|
|
68
|
+
"prompt": prompt,
|
|
69
|
+
"box_threshold": box_threshold,
|
|
70
|
+
"text_threshold": text_threshold,
|
|
71
|
+
},
|
|
72
|
+
}
|
|
73
|
+
auth = f"Bearer {API_KEY}"
|
|
74
|
+
headers = {
|
|
75
|
+
"accept": "application/json",
|
|
76
|
+
"content-type": "application/json",
|
|
77
|
+
"authorization": auth,
|
|
78
|
+
}
|
|
79
|
+
image = image.squeeze(0).numpy()
|
|
80
|
+
image_pil = Image.fromarray((image * 255).astype(np.uint8))
|
|
81
|
+
input_image = encode_image_to_base64(image_pil, format="webp")
|
|
82
|
+
payload["image"] = input_image
|
|
83
|
+
|
|
84
|
+
ret: str = send_post_request(self.API_URL, payload=payload, headers=headers)
|
|
85
|
+
ret = json.loads(ret)
|
|
86
|
+
|
|
87
|
+
try:
|
|
88
|
+
if "result" in ret:
|
|
89
|
+
ret = json.loads(ret["result"])
|
|
90
|
+
except Exception as e:
|
|
91
|
+
raise Exception(f"Unexpected response: {ret} {e=}")
|
|
92
|
+
|
|
93
|
+
if ret["status"] == "error":
|
|
94
|
+
raise Exception(ret["message"])
|
|
95
|
+
|
|
96
|
+
msg = ret["data"]
|
|
97
|
+
if msg["type"] not in ("bizyair",):
|
|
98
|
+
raise Exception(f"Unexpected response type: {msg}")
|
|
99
|
+
|
|
100
|
+
if "error" in msg:
|
|
101
|
+
raise Exception(f"Error happens: {msg}")
|
|
102
|
+
|
|
103
|
+
img = msg["image"]
|
|
104
|
+
mask_image = msg["mask_image"]
|
|
105
|
+
|
|
106
|
+
img = (
|
|
107
|
+
(torch.from_numpy(decode_base64_to_np(img)).float() / 255.0)
|
|
108
|
+
.unsqueeze(0)
|
|
109
|
+
.to(device)
|
|
110
|
+
)
|
|
111
|
+
img_mask = (
|
|
112
|
+
torch.from_numpy(decode_base64_to_np(mask_image)).float() / 255.0
|
|
113
|
+
).to(device)
|
|
114
|
+
img_mask = img_mask.mean(dim=-1)
|
|
115
|
+
img_mask = img_mask.unsqueeze(0)
|
|
116
|
+
|
|
117
|
+
return (img, img_mask)
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
class BizyAirSegmentAnythingPointBox:
|
|
121
|
+
API_URL = f"{BIZYAIR_SERVER_ADDRESS}/supernode/sam"
|
|
122
|
+
|
|
123
|
+
@classmethod
|
|
124
|
+
def INPUT_TYPES(s):
|
|
125
|
+
input_dir = folder_paths.get_input_directory()
|
|
126
|
+
files = [
|
|
127
|
+
f
|
|
128
|
+
for f in os.listdir(input_dir)
|
|
129
|
+
if os.path.isfile(os.path.join(input_dir, f))
|
|
130
|
+
]
|
|
131
|
+
return {
|
|
132
|
+
"required": {
|
|
133
|
+
"image": (sorted(files), {"image_upload": True}),
|
|
134
|
+
"is_point": ("BOOLEAN", {"default": True}),
|
|
135
|
+
},
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
RETURN_TYPES = ("IMAGE", "MASK", "IMAGE")
|
|
139
|
+
RETURN_NAMES = ("processed_image", "mask", "original_image")
|
|
140
|
+
FUNCTION = "apply"
|
|
141
|
+
|
|
142
|
+
CATEGORY = "☁️BizyAir/segment-anything"
|
|
143
|
+
|
|
144
|
+
def apply(self, image, is_point):
|
|
145
|
+
API_KEY = get_api_key()
|
|
146
|
+
SIZE_LIMIT = 1536
|
|
147
|
+
|
|
148
|
+
# 加载原始图像
|
|
149
|
+
original_image, _ = LoadImage().load_image(image)
|
|
150
|
+
# 直接克隆原始图像用于处理和透传
|
|
151
|
+
image_to_process = original_image.clone()
|
|
152
|
+
|
|
153
|
+
device = image_to_process.device
|
|
154
|
+
_, w, h, c = image_to_process.shape
|
|
155
|
+
assert (
|
|
156
|
+
w <= SIZE_LIMIT and h <= SIZE_LIMIT
|
|
157
|
+
), f"width and height must be less than {SIZE_LIMIT}x{SIZE_LIMIT}, but got {w} and {h}"
|
|
158
|
+
|
|
159
|
+
if is_point:
|
|
160
|
+
coordinates = [
|
|
161
|
+
eval(SAM_COORDINATE["point_coords"][key])
|
|
162
|
+
for key in SAM_COORDINATE["point_coords"]
|
|
163
|
+
]
|
|
164
|
+
|
|
165
|
+
input_points = [
|
|
166
|
+
[float(coord["startx"]), float(coord["starty"])]
|
|
167
|
+
for coord in coordinates
|
|
168
|
+
]
|
|
169
|
+
|
|
170
|
+
input_label = [coord["pointType"] for coord in coordinates]
|
|
171
|
+
payload = {
|
|
172
|
+
"image": None,
|
|
173
|
+
"mode": INFER_MODE.points_box.value,
|
|
174
|
+
"params": {
|
|
175
|
+
"input_points": json.dumps(input_points),
|
|
176
|
+
"input_label": json.dumps(input_label),
|
|
177
|
+
"input_boxes": None,
|
|
178
|
+
},
|
|
179
|
+
}
|
|
180
|
+
else:
|
|
181
|
+
coordinates = [
|
|
182
|
+
eval(SAM_COORDINATE["box_coords"][key])
|
|
183
|
+
for key in SAM_COORDINATE["box_coords"]
|
|
184
|
+
]
|
|
185
|
+
input_box = [
|
|
186
|
+
[
|
|
187
|
+
float(coord["startx"]),
|
|
188
|
+
float(coord["starty"]),
|
|
189
|
+
float(coord["endx"]),
|
|
190
|
+
float(coord["endy"]),
|
|
191
|
+
]
|
|
192
|
+
for coord in coordinates
|
|
193
|
+
]
|
|
194
|
+
|
|
195
|
+
payload = {
|
|
196
|
+
"image": None,
|
|
197
|
+
"mode": INFER_MODE.batched_boxes.value,
|
|
198
|
+
"params": {
|
|
199
|
+
"input_points": None,
|
|
200
|
+
"input_label": None,
|
|
201
|
+
"input_boxes": json.dumps(input_box),
|
|
202
|
+
},
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
auth = f"Bearer {API_KEY}"
|
|
206
|
+
headers = {
|
|
207
|
+
"accept": "application/json",
|
|
208
|
+
"content-type": "application/json",
|
|
209
|
+
"authorization": auth,
|
|
210
|
+
}
|
|
211
|
+
# 处理用于API的图像
|
|
212
|
+
api_image = image_to_process.squeeze(0).numpy()
|
|
213
|
+
image_pil = Image.fromarray((api_image * 255).astype(np.uint8))
|
|
214
|
+
input_image = encode_image_to_base64(image_pil, format="webp")
|
|
215
|
+
payload["image"] = input_image
|
|
216
|
+
|
|
217
|
+
ret: str = send_post_request(self.API_URL, payload=payload, headers=headers)
|
|
218
|
+
ret = json.loads(ret)
|
|
219
|
+
|
|
220
|
+
try:
|
|
221
|
+
if "result" in ret:
|
|
222
|
+
ret = json.loads(ret["result"])
|
|
223
|
+
except Exception as e:
|
|
224
|
+
raise Exception(f"Unexpected response: {ret} {e=}")
|
|
225
|
+
|
|
226
|
+
if ret["status"] == "error":
|
|
227
|
+
raise Exception(ret["message"])
|
|
228
|
+
|
|
229
|
+
msg = ret["data"]
|
|
230
|
+
if msg["type"] not in ("bizyair",):
|
|
231
|
+
raise Exception(f"Unexpected response type: {msg}")
|
|
232
|
+
|
|
233
|
+
if "error" in msg:
|
|
234
|
+
raise Exception(f"Error happens: {msg}")
|
|
235
|
+
|
|
236
|
+
img = msg["image"]
|
|
237
|
+
mask_image = msg["mask_image"]
|
|
238
|
+
|
|
239
|
+
processed_img = (
|
|
240
|
+
(torch.from_numpy(decode_base64_to_np(img)).float() / 255.0)
|
|
241
|
+
.unsqueeze(0)
|
|
242
|
+
.to(device)
|
|
243
|
+
)
|
|
244
|
+
img_mask = (
|
|
245
|
+
torch.from_numpy(decode_base64_to_np(mask_image)).float() / 255.0
|
|
246
|
+
).to(device)
|
|
247
|
+
img_mask = img_mask.mean(dim=-1)
|
|
248
|
+
img_mask = img_mask.unsqueeze(0)
|
|
249
|
+
|
|
250
|
+
# 直接返回克隆的原始图像,无需转换
|
|
251
|
+
return (processed_img, img_mask, image_to_process)
|
|
252
|
+
|
|
253
|
+
@classmethod
|
|
254
|
+
def IS_CHANGED(s, image, is_point):
|
|
255
|
+
image_path = folder_paths.get_annotated_filepath(image)
|
|
256
|
+
m = hashlib.sha256()
|
|
257
|
+
with open(image_path, "rb") as f:
|
|
258
|
+
m.update(f.read())
|
|
259
|
+
return m.digest().hex()
|
|
260
|
+
|
|
261
|
+
@classmethod
|
|
262
|
+
def VALIDATE_INPUTS(s, image, is_point):
|
|
263
|
+
if not folder_paths.exists_annotated_filepath(image):
|
|
264
|
+
return "Invalid image file: {}".format(image)
|
|
265
|
+
|
|
266
|
+
return True
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
NODE_CLASS_MAPPINGS = {
|
|
270
|
+
"BizyAirSegmentAnythingText": BizyAirSegmentAnythingText,
|
|
271
|
+
"BizyAirSegmentAnythingPointBox": BizyAirSegmentAnythingPointBox,
|
|
272
|
+
}
|
|
273
|
+
NODE_DISPLAY_NAME_MAPPINGS = {
|
|
274
|
+
"BizyAirSegmentAnythingText": "☁️BizyAir Text Guided SAM",
|
|
275
|
+
"BizyAirSegmentAnythingPointBox": "☁️BizyAir Point-Box Guided SAM",
|
|
276
|
+
}
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import hashlib
|
|
2
|
+
import json
|
|
3
|
+
import os
|
|
4
|
+
import uuid
|
|
5
|
+
from enum import Enum
|
|
6
|
+
|
|
7
|
+
import folder_paths
|
|
8
|
+
import node_helpers
|
|
9
|
+
import numpy as np
|
|
10
|
+
import torch
|
|
11
|
+
from bizyengine.core.common.env_var import BIZYAIR_SERVER_ADDRESS
|
|
12
|
+
from bizyengine.core.image_utils import (
|
|
13
|
+
decode_base64_to_np,
|
|
14
|
+
decode_data,
|
|
15
|
+
encode_data,
|
|
16
|
+
encode_image_to_base64,
|
|
17
|
+
)
|
|
18
|
+
from nodes import LoadImage
|
|
19
|
+
from PIL import Image, ImageOps, ImageSequence
|
|
20
|
+
|
|
21
|
+
from .utils import (
|
|
22
|
+
decode_and_deserialize,
|
|
23
|
+
get_api_key,
|
|
24
|
+
send_post_request,
|
|
25
|
+
serialize_and_encode,
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class RemoveBackground:
|
|
30
|
+
API_URL = f"{BIZYAIR_SERVER_ADDRESS}/supernode/removebg"
|
|
31
|
+
|
|
32
|
+
@classmethod
|
|
33
|
+
def INPUT_TYPES(s):
|
|
34
|
+
return {
|
|
35
|
+
"required": {
|
|
36
|
+
"image": ("IMAGE",),
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
RETURN_TYPES = ("IMAGE", "MASK")
|
|
41
|
+
FUNCTION = "remove_background"
|
|
42
|
+
|
|
43
|
+
CATEGORY = "☁️BizyAir"
|
|
44
|
+
|
|
45
|
+
def remove_background(self, image):
|
|
46
|
+
API_KEY = get_api_key()
|
|
47
|
+
device = image.device
|
|
48
|
+
_, h, w, _ = image.shape
|
|
49
|
+
assert (
|
|
50
|
+
w <= 1536 and h <= 1536
|
|
51
|
+
), f"width and height must be less than 1536, but got {w} and {h}"
|
|
52
|
+
|
|
53
|
+
payload = {
|
|
54
|
+
"is_compress": True,
|
|
55
|
+
"image": None,
|
|
56
|
+
}
|
|
57
|
+
auth = f"Bearer {API_KEY}"
|
|
58
|
+
headers = {
|
|
59
|
+
"accept": "application/json",
|
|
60
|
+
"content-type": "application/json",
|
|
61
|
+
"authorization": auth,
|
|
62
|
+
}
|
|
63
|
+
input_image, compress = serialize_and_encode(image, compress=True)
|
|
64
|
+
payload["image"] = input_image
|
|
65
|
+
payload["is_compress"] = compress
|
|
66
|
+
|
|
67
|
+
response: str = send_post_request(
|
|
68
|
+
self.API_URL, payload=payload, headers=headers
|
|
69
|
+
)
|
|
70
|
+
tensors = decode_and_deserialize(response)
|
|
71
|
+
t_images = tensors["images"].to(device)
|
|
72
|
+
t_mask = tensors["mask"].to(device)
|
|
73
|
+
return (t_images, t_mask)
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
class GenerateLightningImage:
|
|
77
|
+
API_URL = f"{BIZYAIR_SERVER_ADDRESS}/supernode/realvis4lightning"
|
|
78
|
+
|
|
79
|
+
@classmethod
|
|
80
|
+
def INPUT_TYPES(s):
|
|
81
|
+
return {
|
|
82
|
+
"required": {
|
|
83
|
+
"prompt": (
|
|
84
|
+
"STRING",
|
|
85
|
+
{"multiline": True, "dynamicPrompts": True, "default": "a dog"},
|
|
86
|
+
),
|
|
87
|
+
"seed": ("INT", {"default": 1, "min": 0, "max": 0xFFFFFFFFFFFFFFFF}),
|
|
88
|
+
"width": ("INT", {"default": 1024, "min": 16, "max": 1024, "step": 8}),
|
|
89
|
+
"height": ("INT", {"default": 1024, "min": 16, "max": 1024, "step": 8}),
|
|
90
|
+
"cfg": (
|
|
91
|
+
"FLOAT",
|
|
92
|
+
{
|
|
93
|
+
"default": 1.5,
|
|
94
|
+
"min": 0.0,
|
|
95
|
+
"max": 10.0,
|
|
96
|
+
"step": 0.1,
|
|
97
|
+
"round": 0.01,
|
|
98
|
+
},
|
|
99
|
+
),
|
|
100
|
+
"batch_size": ("INT", {"default": 1, "min": 1, "max": 4}),
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
RETURN_TYPES = ("IMAGE",)
|
|
105
|
+
FUNCTION = "generate_image"
|
|
106
|
+
|
|
107
|
+
CATEGORY = "☁️BizyAir"
|
|
108
|
+
|
|
109
|
+
def generate_image(self, prompt, seed, width, height, cfg, batch_size):
|
|
110
|
+
API_KEY = get_api_key()
|
|
111
|
+
assert (
|
|
112
|
+
width <= 1024 and height <= 1024
|
|
113
|
+
), f"width and height must be less than 1024, but got {width} and {height}"
|
|
114
|
+
|
|
115
|
+
payload = {
|
|
116
|
+
"batch_size": batch_size,
|
|
117
|
+
"width": width,
|
|
118
|
+
"height": height,
|
|
119
|
+
"prompt": prompt,
|
|
120
|
+
"cfg": cfg,
|
|
121
|
+
"seed": seed,
|
|
122
|
+
}
|
|
123
|
+
auth = f"Bearer {API_KEY}"
|
|
124
|
+
headers = {
|
|
125
|
+
"accept": "application/json",
|
|
126
|
+
"content-type": "application/json",
|
|
127
|
+
"authorization": auth,
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
response: str = send_post_request(
|
|
131
|
+
self.API_URL, payload=payload, headers=headers
|
|
132
|
+
)
|
|
133
|
+
tensors_np = decode_and_deserialize(response)
|
|
134
|
+
tensors = torch.from_numpy(tensors_np)
|
|
135
|
+
|
|
136
|
+
return (tensors,)
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
class ToggleServerEndpoint:
|
|
140
|
+
BIZYAIR_SERVER_ENDPOINTS = [
|
|
141
|
+
"https://bizyair-api-st.siliconflow.cn/x/v1",
|
|
142
|
+
"https://bizyair-api.siliconflow.cn/x/v1",
|
|
143
|
+
]
|
|
144
|
+
|
|
145
|
+
def __init__(self):
|
|
146
|
+
self.current_index = 0
|
|
147
|
+
|
|
148
|
+
@classmethod
|
|
149
|
+
def INPUT_TYPES(s):
|
|
150
|
+
return {
|
|
151
|
+
"required": {
|
|
152
|
+
"endpoint": (s.BIZYAIR_SERVER_ENDPOINTS,),
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
RETURN_TYPES = ()
|
|
157
|
+
FUNCTION = "toggle_endpoint"
|
|
158
|
+
OUTPUT_NODE = True
|
|
159
|
+
|
|
160
|
+
CATEGORY = "☁️BizyAir"
|
|
161
|
+
|
|
162
|
+
def toggle_endpoint(self, endpoint):
|
|
163
|
+
BIZYAIR_SERVER_ADDRESS.address = endpoint
|
|
164
|
+
from server import PromptServer
|
|
165
|
+
|
|
166
|
+
PromptServer.instance.send_sync(
|
|
167
|
+
"bizyair.server.endpoint.switch",
|
|
168
|
+
{"message": f"Switch server endpoint to {endpoint}"},
|
|
169
|
+
)
|
|
170
|
+
return ()
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
NODE_CLASS_MAPPINGS = {
|
|
174
|
+
"BizyAirRemoveBackground": RemoveBackground,
|
|
175
|
+
"BizyAirGenerateLightningImage": GenerateLightningImage,
|
|
176
|
+
"BizyAirToggleServerEndpoint": ToggleServerEndpoint,
|
|
177
|
+
}
|
|
178
|
+
NODE_DISPLAY_NAME_MAPPINGS = {
|
|
179
|
+
"BizyAirRemoveBackground": "☁️BizyAir Remove Image Background",
|
|
180
|
+
"BizyAirGenerateLightningImage": "☁️BizyAir Generate Photorealistic Images",
|
|
181
|
+
"BizyAirToggleServerEndpoint": "☁️BizyAir Switch Server Endpoint",
|
|
182
|
+
}
|