Merge pull request #6 from qingyuan18/main
added nova canvas&reel and textract node
This commit is contained in:
Generated
+3
@@ -0,0 +1,3 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$" />
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
Generated
+6
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectRootManager">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
</project>
|
||||
Generated
+8
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/comfyui-llm-node-for-amazon-bedrock.iml" filepath="$PROJECT_DIR$/.idea/comfyui-llm-node-for-amazon-bedrock.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
Generated
+6
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
@@ -143,6 +143,14 @@ Here are models ready for use, more models are coming soon.
|
||||
- [X] Claude Instant (1.x)
|
||||
|
||||
- Amazon:
|
||||
- Nova Canvas
|
||||
- [X] text to image
|
||||
- [X] variation
|
||||
- [X] background replacement(with prompt)
|
||||
|
||||
- Nova Reel
|
||||
- [X] text to video
|
||||
- [X] image to video
|
||||
|
||||
- Titan Image Generator G1 (1.x)
|
||||
- [X] text to image
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 664 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 392 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 164 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 14 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 63 KiB |
+126
-1
@@ -20,6 +20,129 @@ CLAUDE3_MAX_SIZE = 1568
|
||||
bedrock_runtime_client = get_client(service_name="bedrock-runtime")
|
||||
|
||||
|
||||
|
||||
class BedrockNovaMultimodal:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"prompt": ("STRING", {"multiline": True}),
|
||||
"model_id": (
|
||||
[
|
||||
"amazon.nova-pro-v1:0",
|
||||
"amazon.nova-lite-v1:0",
|
||||
],
|
||||
),
|
||||
"maxTokens": (
|
||||
"INT",
|
||||
{
|
||||
"default": 2048,
|
||||
"min": 0, # Minimum value
|
||||
"max": 4096, # Maximum value
|
||||
"step": 1, # Slider's step
|
||||
"display": "number", # Cosmetic only: display as "number" or "slider"
|
||||
},
|
||||
),
|
||||
"temperature": (
|
||||
"FLOAT",
|
||||
{
|
||||
"default": 0.5,
|
||||
"min": 0.0,
|
||||
"max": 1.0,
|
||||
"step": 0.1,
|
||||
"round": 0.001, # The value represeting the precision to round to, will be set to the step value by default. Can be set to False to disable rounding.
|
||||
"display": "slider",
|
||||
},
|
||||
),
|
||||
"topP": (
|
||||
"FLOAT",
|
||||
{
|
||||
"default": 1.0,
|
||||
"min": 0.0,
|
||||
"max": 1.0,
|
||||
"step": 0.1,
|
||||
"round": 0.001, # The value represeting the precision to round to, will be set to the step value by default. Can be set to False to disable rounding.
|
||||
"display": "slider",
|
||||
},
|
||||
)
|
||||
},
|
||||
"optional": {
|
||||
"image": ("IMAGE",{"default": None}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("STRING",)
|
||||
FUNCTION = "forward"
|
||||
CATEGORY = "aws"
|
||||
|
||||
@retry(tries=MAX_RETRY)
|
||||
def forward(
|
||||
self,
|
||||
**kwargs
|
||||
):
|
||||
|
||||
prompt = kwargs.get('prompt')
|
||||
model_id = kwargs.get('model_id')
|
||||
maxTokens = kwargs.get('maxTokens')
|
||||
temperature = kwargs.get('temperature')
|
||||
topP = kwargs.get('topP')
|
||||
image = kwargs.get('image')
|
||||
|
||||
content = []
|
||||
content.append({
|
||||
"text": prompt,
|
||||
})
|
||||
|
||||
if image is not None:
|
||||
image = image[0] * 255.0
|
||||
image = Image.fromarray(image.clamp(0, 255).numpy().round().astype(np.uint8))
|
||||
|
||||
width, height = image.size
|
||||
max_size = max(width, height)
|
||||
if max_size > CLAUDE3_MAX_SIZE:
|
||||
width = round(width * CLAUDE3_MAX_SIZE / max_size)
|
||||
height = round(height * CLAUDE3_MAX_SIZE / max_size)
|
||||
image = image.resize((width, height))
|
||||
|
||||
buffer = BytesIO()
|
||||
image.save(buffer, format="png", quality=80)
|
||||
image_data = buffer.getvalue()
|
||||
|
||||
image_base64 = base64.b64encode(image_data).decode("utf-8")
|
||||
content.append( {
|
||||
"image": {
|
||||
"format": "png",
|
||||
"source": {"bytes": image_base64},
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
inf_params = {"max_new_tokens": maxTokens, "top_p": topP, "temperature": temperature}
|
||||
|
||||
|
||||
body = json.dumps(
|
||||
{
|
||||
"schemaVersion": "messages-v1",
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": content,
|
||||
}
|
||||
],
|
||||
"inferenceConfig": inf_params,
|
||||
},
|
||||
ensure_ascii=False,
|
||||
)
|
||||
|
||||
response = bedrock_runtime_client.invoke_model(
|
||||
body=body,
|
||||
modelId=model_id,
|
||||
)
|
||||
|
||||
message = json.loads(response.get("body").read())['output']['message']['content'][0]['text']
|
||||
print("here1===",message)
|
||||
return (message,)
|
||||
|
||||
class BedrockClaudeMultimodal:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
@@ -252,7 +375,7 @@ class BedrockClaude:
|
||||
# The different model providers have individual request and response formats.
|
||||
# For the format, ranges, and default values for Anthropic Claude, refer to:
|
||||
# https://docs.aws.amazon.com/bedrock/latest/userguide/model-parameters-anthropic-claude-messages.html
|
||||
|
||||
print("prompt input:",prompt)
|
||||
body = json.dumps(
|
||||
{
|
||||
"anthropic_version": "bedrock-2023-05-31",
|
||||
@@ -280,6 +403,7 @@ class BedrockClaude:
|
||||
modelId=model_id,
|
||||
)
|
||||
message = json.loads(response.get("body").read())["content"][0]["text"]
|
||||
print("output message:",message)
|
||||
|
||||
return (message,)
|
||||
|
||||
@@ -450,4 +574,5 @@ NODE_CLASS_MAPPINGS = {
|
||||
"Bedrock - Claude": BedrockClaude,
|
||||
"Bedrock - Claude Multimodal": BedrockClaudeMultimodal,
|
||||
"Bedrock - SDXL": BedrockSDXL,
|
||||
"Bedrock - Nova": BedrockNovaMultimodal
|
||||
}
|
||||
|
||||
@@ -0,0 +1,454 @@
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import base64
|
||||
from io import BytesIO
|
||||
from random import randint
|
||||
import logging
|
||||
from datetime import datetime
|
||||
import requests
|
||||
from retry import retry
|
||||
from PIL import Image
|
||||
import numpy as np
|
||||
import torch
|
||||
from .session import get_client
|
||||
import boto3
|
||||
|
||||
MAX_RETRY = 3
|
||||
|
||||
def generate_images(
|
||||
inference_params,
|
||||
model_id="amazon.nova-canvas-v1:0",
|
||||
region_name="us-east-1",
|
||||
endpoint_url=None,
|
||||
output_directory="~/ComfyUI/output",
|
||||
):
|
||||
|
||||
os.makedirs(output_directory, exist_ok=True)
|
||||
|
||||
image_count = 1
|
||||
if "imageGenerationConfig" in inference_params:
|
||||
if "numberOfImages" in inference_params["imageGenerationConfig"]:
|
||||
image_count = inference_params["imageGenerationConfig"]["numberOfImages"]
|
||||
|
||||
print(f"Generating {image_count} image(s) with {model_id}")
|
||||
|
||||
# Display the seed value if one is being used.
|
||||
if "imageGenerationConfig" in inference_params:
|
||||
if "seed" in inference_params["imageGenerationConfig"]:
|
||||
print(
|
||||
f"Using seed: {inference_params['imageGenerationConfig']['seed']}"
|
||||
)
|
||||
|
||||
bedrock_client_optional_args = (
|
||||
{} if endpoint_url is None else {"endpoint_url": endpoint_url}
|
||||
)
|
||||
bedrock = boto3.client(
|
||||
service_name="bedrock-runtime",
|
||||
#region_name=region_name,
|
||||
**bedrock_client_optional_args,
|
||||
)
|
||||
|
||||
body_json = json.dumps(inference_params, indent=2)
|
||||
#print("here1===",body_json)
|
||||
|
||||
# Write request body to JSON file.
|
||||
request_file_path = os.path.join(output_directory, "request.json")
|
||||
with open(request_file_path, "w") as f:
|
||||
f.write(body_json)
|
||||
|
||||
try:
|
||||
response = bedrock.invoke_model(
|
||||
body=body_json,
|
||||
modelId=model_id,
|
||||
accept="application/json",
|
||||
contentType="application/json",
|
||||
)
|
||||
|
||||
response_metadata = response.get("ResponseMetadata")
|
||||
# WRite response metadata to JSON file.
|
||||
response_metadata_file_path = os.path.join(
|
||||
output_directory, "response_metadata.json"
|
||||
)
|
||||
with open(response_metadata_file_path, "w") as f:
|
||||
json.dump(response_metadata, f, indent=2)
|
||||
|
||||
response_body = json.loads(response.get("body").read())
|
||||
|
||||
# Write response body to JSON file.
|
||||
response_file_path = os.path.join(output_directory, "response_body.json")
|
||||
with open(response_file_path, "w") as f:
|
||||
json.dump(response_body, f, indent=2)
|
||||
|
||||
# Log the request ID.
|
||||
print(f"Request ID: {response['ResponseMetadata']['RequestId']}")
|
||||
|
||||
# Check for non-exception errors.
|
||||
if "error" in response_body:
|
||||
if response_body["error"] == "":
|
||||
print(
|
||||
"""Response included 'error' of "" (empty string). This indicates a bug with the Bedrock API."""
|
||||
)
|
||||
else:
|
||||
printf("Error: {response_body['error']}")
|
||||
|
||||
return response_body
|
||||
|
||||
except Exception as e:
|
||||
# If e has "response", write it to disk as JSON.
|
||||
if hasattr(e, "response"):
|
||||
error_response = e.response
|
||||
error_response_file_path = os.path.join(
|
||||
output_directory, "error_response.json"
|
||||
)
|
||||
with open(error_response_file_path, "w") as f:
|
||||
json.dump(error_response, f, indent=2)
|
||||
|
||||
print(e)
|
||||
raise e
|
||||
|
||||
|
||||
bedrock_runtime_client = get_client(service_name="bedrock-runtime")
|
||||
output_directory = "/home/ubuntu/ComfyUI/output/"
|
||||
class BedrockNovaTextImage:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"prompt": ("STRING", {"multiline": True}),
|
||||
"num_images": (
|
||||
"INT",
|
||||
{
|
||||
"default": 1,
|
||||
"min": 1,
|
||||
"max": 5,
|
||||
"step": 1,
|
||||
"round": 1, # The value represeting the precision to round to, will be set to the step value by default. Can be set to False to disable rounding.
|
||||
"display": "number",
|
||||
},
|
||||
),
|
||||
"quality": (
|
||||
[
|
||||
"standard",
|
||||
"premium",
|
||||
],
|
||||
),
|
||||
"resolution": (
|
||||
[
|
||||
"1024 x 1024",
|
||||
"768 x 768",
|
||||
"512 x 512",
|
||||
"1152 x 768",
|
||||
"576 x 384",
|
||||
"768 x 1280",
|
||||
"384 x 640",
|
||||
"1280 x 768"
|
||||
],
|
||||
),
|
||||
"cfg_scale": (
|
||||
"FLOAT",
|
||||
{
|
||||
"default": 7.0,
|
||||
"min": 0.0,
|
||||
"max": 35.0,
|
||||
"step": 0.1,
|
||||
"round": 0.001, # The value represeting the precision to round to, will be set to the step value by default. Can be set to False to disable rounding.
|
||||
"display": "slider",
|
||||
},
|
||||
),
|
||||
"seed": (
|
||||
"INT",
|
||||
{
|
||||
"default": 0,
|
||||
"min": 0,
|
||||
"max": 2147483646,
|
||||
"step": 1,
|
||||
"round": 1, # The value represeting the precision to round to, will be set to the step value by default. Can be set to False to disable rounding.
|
||||
"display": "number",
|
||||
},
|
||||
),
|
||||
},
|
||||
"optional": {
|
||||
"negative_prompt":("STRING", {"multiline": True}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("IMAGE",)
|
||||
FUNCTION = "forward"
|
||||
CATEGORY = "aws"
|
||||
|
||||
@retry(tries=MAX_RETRY)
|
||||
def forward(self, prompt, negative_prompt,num_images, quality, resolution, cfg_scale, seed):
|
||||
|
||||
height, width = map(int, re.findall(r"\d+", resolution))
|
||||
|
||||
inference_params ={
|
||||
"taskType": "TEXT_IMAGE",
|
||||
"textToImageParams": {"text": prompt,
|
||||
"negativeText":negative_prompt},
|
||||
"imageGenerationConfig": {
|
||||
"numberOfImages": num_images,
|
||||
"quality": quality,
|
||||
"cfgScale": cfg_scale,
|
||||
"height": height,
|
||||
"width": width,
|
||||
"seed": seed,
|
||||
},
|
||||
}
|
||||
|
||||
# Define an output directory with a unique name.
|
||||
generation_id = datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
|
||||
output_directory = f"output/{generation_id}"
|
||||
|
||||
# Generate the image(s).
|
||||
response_body = generate_images(
|
||||
inference_params=inference_params,
|
||||
model_id="amazon.nova-canvas-v1:0",
|
||||
output_directory=output_directory
|
||||
)
|
||||
|
||||
# response_body = json.loads(response["body"].read())
|
||||
# base64_image_data = response_body["images"][0]
|
||||
images = [
|
||||
np.array(Image.open(BytesIO(base64.b64decode(base64_image))))
|
||||
for base64_image in response_body.get("images")
|
||||
]
|
||||
images = [
|
||||
torch.from_numpy(np.array(image).astype(np.float32) / 255.0).unsqueeze(0)
|
||||
for image in images
|
||||
]
|
||||
if len(images) == 1:
|
||||
images = images[0]
|
||||
else:
|
||||
images = torch.cat(images, 0)
|
||||
return (images,)
|
||||
|
||||
|
||||
class BedrockNovaIpAdatper:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"image": ("IMAGE",),
|
||||
"prompt": ("STRING", {"multiline": True}),
|
||||
"negative_prompt": ("STRING", {"multiline": True}),
|
||||
"similarity_strength": (
|
||||
"FLOAT",
|
||||
{
|
||||
"default": 0.9,
|
||||
"min": 0.2,
|
||||
"max": 1.0,
|
||||
"step": 0.1,
|
||||
"round": 0.01, # The value represeting the precision to round to, will be set to the step value by default. Can be set to False to disable rounding.
|
||||
"display": "slider",
|
||||
},
|
||||
),
|
||||
"num_images": (
|
||||
"INT",
|
||||
{
|
||||
"default": 1,
|
||||
"min": 1,
|
||||
"max": 5,
|
||||
"step": 1,
|
||||
"round": 1, # The value represeting the precision to round to, will be set to the step value by default. Can be set to False to disable rounding.
|
||||
"display": "number",
|
||||
},
|
||||
),
|
||||
"cfg_scale": (
|
||||
"FLOAT",
|
||||
{
|
||||
"default": 8.0,
|
||||
"min": 1.1,
|
||||
"max": 10.0,
|
||||
"step": 0.1,
|
||||
"round": 0.001, # The value represeting the precision to round to, will be set to the step value by default. Can be set to False to disable rounding.
|
||||
"display": "slider",
|
||||
},
|
||||
),
|
||||
"resolution": (
|
||||
[
|
||||
"1024 x 1024",
|
||||
"1024 x 1024",
|
||||
"768 x 768",
|
||||
"512 x 512",
|
||||
"1152 x 768",
|
||||
"576 x 384",
|
||||
"768 x 1280"
|
||||
],
|
||||
),
|
||||
"seed": (
|
||||
"INT",
|
||||
{
|
||||
"default": 0,
|
||||
"min": 0,
|
||||
"max": 2147483646,
|
||||
"step": 1,
|
||||
"round": 1, # The value represeting the precision to round to, will be set to the step value by default. Can be set to False to disable rounding.
|
||||
"display": "number",
|
||||
},
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("IMAGE",)
|
||||
FUNCTION = "forward"
|
||||
CATEGORY = "aws"
|
||||
|
||||
@retry(tries=MAX_RETRY)
|
||||
def forward(self, image, prompt, negative_prompt, similarity_strength, num_images, cfg_scale, resolution,seed):
|
||||
|
||||
image = image[0] * 255.0
|
||||
image = Image.fromarray(image.clamp(0, 255).numpy().round().astype(np.uint8))
|
||||
|
||||
height, width = map(int, re.findall(r"\d+", resolution))
|
||||
|
||||
buffer = BytesIO()
|
||||
image.save(buffer, format="PNG")
|
||||
|
||||
image_data = buffer.getvalue()
|
||||
|
||||
image_base64 = base64.b64encode(image_data).decode("utf-8")
|
||||
|
||||
inference_params = {
|
||||
"taskType": "IMAGE_VARIATION",
|
||||
"imageVariationParams": {
|
||||
"images": [image_base64],
|
||||
"text": prompt,
|
||||
"negativeText": negative_prompt,
|
||||
"similarityStrength": similarity_strength,
|
||||
},
|
||||
"imageGenerationConfig": {
|
||||
"numberOfImages": num_images,
|
||||
"quality": "premium",
|
||||
"height": height,
|
||||
"width": width,
|
||||
"cfgScale": cfg_scale,
|
||||
"seed": seed
|
||||
}
|
||||
}
|
||||
|
||||
response_body = generate_images(
|
||||
inference_params=inference_params,
|
||||
model_id="amazon.nova-canvas-v1:0",
|
||||
output_directory=output_directory
|
||||
)
|
||||
|
||||
images = [
|
||||
np.array(Image.open(BytesIO(base64.b64decode(base64_image))))
|
||||
for base64_image in response_body.get("images")
|
||||
]
|
||||
images = [
|
||||
torch.from_numpy(np.array(image).astype(np.float32) / 255.0).unsqueeze(0)
|
||||
for image in images
|
||||
]
|
||||
if len(images) == 1:
|
||||
images = images[0]
|
||||
else:
|
||||
images = torch.cat(images, 0)
|
||||
return (images,)
|
||||
|
||||
|
||||
class BedrockNovaBackgroundPEReplace:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"image": ("IMAGE",),
|
||||
"prompt": ("STRING", {"multiline": True}),
|
||||
"mask_prompt": ("STRING", {"multiline": True}),
|
||||
"num_images": (
|
||||
"INT",
|
||||
{
|
||||
"default": 1,
|
||||
"min": 1,
|
||||
"max": 5,
|
||||
"step": 1,
|
||||
"round": 1, # The value represeting the precision to round to, will be set to the step value by default. Can be set to False to disable rounding.
|
||||
"display": "number",
|
||||
},
|
||||
),
|
||||
"cfg_scale": (
|
||||
"FLOAT",
|
||||
{
|
||||
"default": 8.0,
|
||||
"min": 1.1,
|
||||
"max": 10.0,
|
||||
"step": 0.1,
|
||||
"round": 0.001, # The value represeting the precision to round to, will be set to the step value by default. Can be set to False to disable rounding.
|
||||
"display": "slider",
|
||||
},
|
||||
),
|
||||
"seed": (
|
||||
"INT",
|
||||
{
|
||||
"default": 0,
|
||||
"min": 0,
|
||||
"max": 2147483646,
|
||||
"step": 1,
|
||||
"round": 1, # The value represeting the precision to round to, will be set to the step value by default. Can be set to False to disable rounding.
|
||||
"display": "number",
|
||||
},
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("IMAGE",)
|
||||
FUNCTION = "forward"
|
||||
CATEGORY = "aws"
|
||||
|
||||
@retry(tries=MAX_RETRY)
|
||||
def forward(self, image, prompt, mask_prompt, num_images, cfg_scale,seed):
|
||||
image = image[0] * 255.0
|
||||
image = Image.fromarray(image.clamp(0, 255).numpy().round().astype(np.uint8))
|
||||
|
||||
|
||||
buffer = BytesIO()
|
||||
image.save(buffer, format="PNG")
|
||||
|
||||
image_data = buffer.getvalue()
|
||||
|
||||
image_base64 = base64.b64encode(image_data).decode("utf-8")
|
||||
|
||||
inference_params = {
|
||||
"taskType": "OUTPAINTING",
|
||||
"outPaintingParams": {
|
||||
"image": image_base64,
|
||||
"text": prompt,
|
||||
"maskPrompt": mask_prompt,
|
||||
"outPaintingMode": "PRECISE",
|
||||
},
|
||||
"imageGenerationConfig": {
|
||||
"numberOfImages": num_images,
|
||||
"quality": "premium",
|
||||
"cfgScale": cfg_scale,
|
||||
"seed": seed
|
||||
}
|
||||
}
|
||||
|
||||
response_body = generate_images(
|
||||
inference_params=inference_params,
|
||||
model_id="amazon.nova-canvas-v1:0",
|
||||
output_directory=output_directory
|
||||
)
|
||||
|
||||
images = [
|
||||
np.array(Image.open(BytesIO(base64.b64decode(base64_image))))
|
||||
for base64_image in response_body.get("images")
|
||||
]
|
||||
images = [
|
||||
torch.from_numpy(np.array(image).astype(np.float32) / 255.0).unsqueeze(0)
|
||||
for image in images
|
||||
]
|
||||
if len(images) == 1:
|
||||
images = images[0]
|
||||
else:
|
||||
images = torch.cat(images, 0)
|
||||
return (images,)
|
||||
|
||||
|
||||
|
||||
NODE_CLASS_MAPPINGS = {
|
||||
"Bedrock - Nova Text to Image": BedrockNovaTextImage,
|
||||
"Bedrock - Nova IpAdapter": BedrockNovaIpAdatper,
|
||||
"Bedrock - Nova Background Prompt Replace": BedrockNovaBackgroundPEReplace,
|
||||
}
|
||||
@@ -0,0 +1,227 @@
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import base64
|
||||
from io import BytesIO
|
||||
from random import randint
|
||||
import logging
|
||||
from datetime import datetime
|
||||
import requests
|
||||
from retry import retry
|
||||
from PIL import Image
|
||||
import numpy as np
|
||||
import torch
|
||||
from .session import get_client
|
||||
import time
|
||||
import boto3
|
||||
|
||||
MAX_RETRY = 3
|
||||
def get_default_region():
|
||||
"""获取默认的 AWS 区域"""
|
||||
session = boto3.Session()
|
||||
return session.region_name
|
||||
|
||||
def get_account_id():
|
||||
"""获取当前 AWS 账户 ID"""
|
||||
sts_client = boto3.client('sts')
|
||||
return sts_client.get_caller_identity().get('Account')
|
||||
|
||||
def is_video_downloaded_for_invocation_job(invocation_job, output_folder="output"):
|
||||
"""
|
||||
This function checks if the video file for the given invocation job has been downloaded.
|
||||
"""
|
||||
invocation_arn = invocation_job["invocationArn"]
|
||||
invocation_id = invocation_arn.split("/")[-1]
|
||||
folder_name = get_folder_name_for_job(invocation_job)
|
||||
output_folder = os.path.abspath(f"{output_folder}/{folder_name}")
|
||||
file_name = f"{invocation_id}.mp4"
|
||||
local_file_path = os.path.join(output_folder, file_name)
|
||||
return os.path.exists(local_file_path)
|
||||
|
||||
def get_folder_name_for_job(invocation_job):
|
||||
invocation_arn = invocation_job["invocationArn"]
|
||||
invocation_id = invocation_arn.split("/")[-1]
|
||||
submit_time = invocation_job["submitTime"]
|
||||
timestamp = submit_time.astimezone().strftime("%Y-%m-%d_%H-%M-%S")
|
||||
folder_name = f"{timestamp}_{invocation_id}"
|
||||
return folder_name
|
||||
|
||||
def download_video_for_invocation_arn(invocation_arn, bucket_name, destination_folder):
|
||||
"""
|
||||
This function downloads the video file for the given invocation ARN.
|
||||
"""
|
||||
invocation_id = invocation_arn.split("/")[-1]
|
||||
|
||||
# Create the local file path
|
||||
file_name = f"{invocation_id}.mp4"
|
||||
import os
|
||||
|
||||
output_folder = os.path.abspath(destination_folder)
|
||||
local_file_path = os.path.join(output_folder, file_name)
|
||||
|
||||
# Ensure the output folder exists
|
||||
os.makedirs(output_folder, exist_ok=True)
|
||||
|
||||
# Create an S3 client
|
||||
s3 = boto3.client("s3")
|
||||
|
||||
# List objects in the specified folder
|
||||
response = s3.list_objects_v2(Bucket=bucket_name, Prefix=invocation_id)
|
||||
|
||||
# Find the first MP4 file and download it.
|
||||
for obj in response.get("Contents", []):
|
||||
object_key = obj["Key"]
|
||||
if object_key.endswith(".mp4"):
|
||||
print(f"""Downloading "{object_key}"...""")
|
||||
s3.download_file(bucket_name, object_key, local_file_path)
|
||||
print(f"Downloaded to {local_file_path}")
|
||||
return local_file_path
|
||||
|
||||
# If we reach this point, no MP4 file was found.
|
||||
print(f"Problem: No MP4 file was found in S3 at {bucket_name}/{invocation_id}")
|
||||
|
||||
def get_job_id_from_arn(invocation_arn):
|
||||
return invocation_arn.split("/")[-1]
|
||||
|
||||
def save_completed_job(job, output_folder="output"):
|
||||
job_id = get_job_id_from_arn(job["invocationArn"])
|
||||
|
||||
output_folder_abs = os.path.abspath(
|
||||
f"{output_folder}/{get_folder_name_for_job(job)}"
|
||||
)
|
||||
|
||||
# Ensure the output folder exists
|
||||
os.makedirs(output_folder_abs, exist_ok=True)
|
||||
|
||||
status_file = os.path.join(output_folder_abs, "completed.json")
|
||||
|
||||
if is_video_downloaded_for_invocation_job(job, output_folder=output_folder):
|
||||
print(f"Skipping completed job {job_id}, video already downloaded.")
|
||||
return
|
||||
|
||||
s3_bucket_name = (
|
||||
job["outputDataConfig"]["s3OutputDataConfig"]["s3Uri"]
|
||||
.split("//")[1]
|
||||
.split("/")[0]
|
||||
)
|
||||
|
||||
localPath = download_video_for_invocation_arn(
|
||||
job["invocationArn"], s3_bucket_name, output_folder_abs
|
||||
)
|
||||
return localPath
|
||||
|
||||
|
||||
bedrock_runtime_client = get_client(service_name="bedrock-runtime")
|
||||
region = get_default_region()
|
||||
account_id = get_account_id()
|
||||
s3_destination_bucket = f"sagemaker-{region}-{account_id}"
|
||||
|
||||
class BedrockNovaVideo:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"prompt": ("STRING", {"multiline": True}),
|
||||
"dimension": (
|
||||
[
|
||||
"1280x720"
|
||||
],
|
||||
),
|
||||
"seed": (
|
||||
"INT",
|
||||
{
|
||||
"default": 0,
|
||||
"min": 0,
|
||||
"max": 2147483646,
|
||||
"step": 1,
|
||||
"round": 1, # The value represeting the precision to round to, will be set to the step value by default. Can be set to False to disable rounding.
|
||||
"display": "number",
|
||||
},
|
||||
),
|
||||
},
|
||||
"optional": {
|
||||
"image": ("IMAGE",),
|
||||
},
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("STRING",)
|
||||
FUNCTION = "forward"
|
||||
CATEGORY = "aws"
|
||||
|
||||
@retry(tries=MAX_RETRY)
|
||||
def forward(self, **kwargs):
|
||||
prompt = kwargs.get('prompt')
|
||||
dimension = kwargs.get('dimension')
|
||||
seed = kwargs.get('seed')
|
||||
image = kwargs.get('image')
|
||||
|
||||
|
||||
input_image_base64=None
|
||||
if image is not None:
|
||||
image = image[0] * 255.0
|
||||
image = Image.fromarray(image.clamp(0, 255).numpy().round().astype(np.uint8))
|
||||
buffer = BytesIO()
|
||||
image.save(buffer, format="PNG")
|
||||
|
||||
image_data = buffer.getvalue()
|
||||
input_image_base64 = base64.b64encode(image_data).decode("utf-8")
|
||||
|
||||
textToVideoParams={ "text": prompt}
|
||||
if input_image_base64 is not None:
|
||||
textToVideoParams["images"] = [
|
||||
{
|
||||
"format": "png", # May be "png" or "jpeg"
|
||||
"source": {
|
||||
"bytes": input_image_base64
|
||||
}
|
||||
}
|
||||
]
|
||||
model_input = {
|
||||
"taskType": "TEXT_VIDEO",
|
||||
"textToVideoParams": textToVideoParams,
|
||||
"videoGenerationConfig": {
|
||||
"durationSeconds": 6, # 6 is the only supported value currently.
|
||||
"fps": 24, # 24 is the only supported value currently.
|
||||
"dimension": dimension, # "1280x720" is the only supported value currently.
|
||||
"seed": seed # A random seed guarantees we'll get a different result each time this code runs.
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
invocation = bedrock_runtime_client.start_async_invoke(
|
||||
modelId="amazon.nova-reel-v1:0",
|
||||
modelInput=model_input,
|
||||
outputDataConfig={"s3OutputDataConfig": {"s3Uri": f"s3://{s3_destination_bucket}"}},
|
||||
)
|
||||
|
||||
invocation_arn = invocation["invocationArn"]
|
||||
print("\nResponse:")
|
||||
print(json.dumps(invocation, indent=2, default=str))
|
||||
|
||||
save_local_path = ""
|
||||
|
||||
# Save the invocation details for later reference. Helpful for debugging and reporting feedback.
|
||||
while True:
|
||||
job_update = bedrock_runtime_client.get_async_invoke(invocationArn=invocation_arn)
|
||||
status = job_update["status"]
|
||||
start_time = time.time()
|
||||
|
||||
if status == "Completed":
|
||||
save_local_path = save_completed_job(job_update, output_folder="/home/ubuntu/ComfyUI/output/")
|
||||
break
|
||||
else:
|
||||
elapsed_time = time.time() - start_time
|
||||
if elapsed_time > 600:
|
||||
print("Job timed out after 60 seconds.")
|
||||
break
|
||||
else:
|
||||
time.sleep(5)
|
||||
return (save_local_path,)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
NODE_CLASS_MAPPINGS = {
|
||||
"Bedrock - Nova Video": BedrockNovaVideo
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
import base64
|
||||
import io
|
||||
import os
|
||||
from datetime import datetime
|
||||
|
||||
from PIL import Image
|
||||
|
||||
|
||||
def save_base64_image(base64_image, output_directory, base_name="image", suffix="_1"):
|
||||
"""
|
||||
Saves a base64 encoded image to a specified output directory with a timestamp and a suffix.
|
||||
|
||||
Args:
|
||||
base64_image (str): The base64 encoded image string.
|
||||
output_directory (str): The directory where the image will be saved.
|
||||
suffix (str, optional): A suffix to be added to the filename. Defaults to "_1".
|
||||
Returns:
|
||||
PIL.Image.Image: The Pillow Image object representing the saved image.
|
||||
"""
|
||||
image_bytes = base64.b64decode(base64_image)
|
||||
image = Image.open(io.BytesIO(image_bytes))
|
||||
save_image(image, output_directory, base_name, suffix)
|
||||
return image
|
||||
|
||||
|
||||
def save_image(image, output_directory, base_name="image", suffix="_1"):
|
||||
"""
|
||||
Saves a Pillow Image object to a specified output directory with a timestamp and a suffix.
|
||||
|
||||
Args:
|
||||
image (PIL.Image.Image): The Pillow Image object to be saved.
|
||||
output_directory (str): The directory where the image will be saved.
|
||||
suffix (str, optional): A suffix to be added to the filename. Defaults to "_1".
|
||||
Returns:
|
||||
None
|
||||
"""
|
||||
if not os.path.exists(output_directory):
|
||||
os.makedirs(output_directory)
|
||||
|
||||
file_name = f"{base_name}{suffix}.png"
|
||||
file_path = os.path.join(output_directory, file_name)
|
||||
image.save(file_path)
|
||||
|
||||
|
||||
def save_base64_images(base64_images, output_directory, base_name="image"):
|
||||
"""
|
||||
Saves a list of base64 encoded images to a specified output directory.
|
||||
|
||||
Args:
|
||||
base64_images (list): A list of base64 encoded image strings.
|
||||
output_directory (str): The directory where the images will be saved.
|
||||
Returns:
|
||||
An array of Pillow Image objects representing the saved images.
|
||||
"""
|
||||
images = []
|
||||
for i, base64_image in enumerate(base64_images):
|
||||
image = save_base64_image(
|
||||
base64_image, output_directory, base_name=base_name, suffix=f"_{i+1}"
|
||||
)
|
||||
images.append(image)
|
||||
|
||||
return images
|
||||
@@ -18,6 +18,7 @@ class PromptTemplate:
|
||||
|
||||
def forward(self, prompt, prompt_template):
|
||||
output = prompt_template.replace("{prompt}", prompt).replace("[prompt]", prompt)
|
||||
#print("output prompt:",output)
|
||||
return (output,)
|
||||
|
||||
class PromptTemplateTwoInput:
|
||||
|
||||
@@ -0,0 +1,423 @@
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import base64
|
||||
from io import BytesIO
|
||||
import io
|
||||
import requests
|
||||
from retry import retry
|
||||
import boto3
|
||||
from PIL import Image
|
||||
import numpy as np
|
||||
import torch
|
||||
import cv2
|
||||
import folder_paths
|
||||
from .session import get_client
|
||||
import torch
|
||||
from torchvision import transforms
|
||||
from paddleocr import PaddleOCR, draw_ocr
|
||||
from paddleocr import PPStructure,draw_structure_result
|
||||
import tempfile
|
||||
|
||||
|
||||
current_directory = os.path.dirname(os.path.abspath(__file__))
|
||||
temp_img_path = os.path.join(current_directory, "temp_dir", "AnyText_manual_mask_pos_img.png")
|
||||
textract = get_client(service_name="textract")
|
||||
MAX_RETRY = 3
|
||||
|
||||
|
||||
class ImageOCRByTextract:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"image": ("IMAGE",)
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("STRING","INT","INT","INT","INT","IMAGE")
|
||||
RETURN_NAMES = ("Text","Left","Top","Width","Height","Mask Image")
|
||||
FUNCTION = "forward"
|
||||
CATEGORY = "aws"
|
||||
OUTPUT_NODE = True
|
||||
|
||||
def ocr_by_textract(self,image_input):
|
||||
numpy_image = (image_input[0] * 255.0).clamp(0, 255).numpy()
|
||||
image = image_input[0] * 255.0
|
||||
image = Image.fromarray(image.clamp(0, 255).numpy().round().astype(np.uint8))
|
||||
# Get the original dimensions of the image
|
||||
img_width, img_height = image.size
|
||||
|
||||
## Call Textract DetectDocumentText function
|
||||
byte_stream = io.BytesIO()
|
||||
image.save(byte_stream, format='PNG')
|
||||
byte_image = byte_stream.getvalue()
|
||||
response = textract.detect_document_text(Document={'Bytes': byte_image})
|
||||
|
||||
#initial the scan result
|
||||
result = []
|
||||
# Create a black mask image of the same size as the original image
|
||||
mask = np.zeros_like(numpy_image)
|
||||
all_text=""
|
||||
|
||||
|
||||
# Extract text and bounding box information
|
||||
for item in response['Blocks']:
|
||||
if item['BlockType'] == 'LINE':
|
||||
text = item['Text']
|
||||
box = item['Geometry']['BoundingBox']
|
||||
left = int(box['Left'] * img_width)
|
||||
top = int(box['Top'] * img_height)
|
||||
width = int(box['Width'] * img_width)
|
||||
height = int(box['Height']* img_height)
|
||||
|
||||
##Add information to the result list
|
||||
result.append({
|
||||
'Text': text,
|
||||
'Left': left,
|
||||
'Top': top,
|
||||
'Width': width,
|
||||
'Height': height
|
||||
|
||||
})
|
||||
all_text=all_text+text
|
||||
#Draw mask for each text information box
|
||||
#Specify the coordinates of the top-left and bottom-right corners of the rectangle
|
||||
temp_mask = np.zeros_like(numpy_image)
|
||||
x1, y1 = int(left), int(top)
|
||||
x2, y2 = int(left + width), int(top + height)
|
||||
# Draw white rectangular boxes on the mask image
|
||||
cv2.rectangle(temp_mask, (x1, y1), (x2, y2), (255, 255, 255), -1)
|
||||
mask = cv2.bitwise_or(mask, temp_mask)
|
||||
|
||||
# Perform bitwise operation between the mask image and the original image to generate the masked image
|
||||
masked_img = cv2.bitwise_and(numpy_image, mask)
|
||||
masked_img = torch.from_numpy(np.array(masked_img).astype(np.float32) / 255.0).unsqueeze(0)
|
||||
|
||||
print("result",result)
|
||||
|
||||
return all_text,result[0]['Left'],result[0]['Top'],result[0]['Width'],result[0]['Height'],masked_img
|
||||
|
||||
|
||||
@retry(tries=MAX_RETRY)
|
||||
def forward(self, image):
|
||||
return self.ocr_by_textract(image)
|
||||
|
||||
|
||||
### for anyText Nodes
|
||||
class ImageOCRByTextractV2:
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
input_dir = folder_paths.get_input_directory()
|
||||
files = [f for f in os.listdir(input_dir) if os.path.isfile(os.path.join(input_dir, f))]
|
||||
return {"required":
|
||||
{
|
||||
"image": (sorted(files), {"image_upload": True}),
|
||||
},
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("STRING","STRING","STRING","IMAGE")
|
||||
RETURN_NAMES = ("Texts","Original Image Path","Mask Image Path","AnyText Mask Image")
|
||||
FUNCTION = "forward"
|
||||
CATEGORY = "aws"
|
||||
OUTPUT_NODE = True
|
||||
|
||||
def ocr_by_textract(self,image_input):
|
||||
ori_image_path = folder_paths.get_annotated_filepath(image_input)
|
||||
pos_img_path = os.path.join(temp_img_path)
|
||||
|
||||
## Convert orignal image to tensor
|
||||
pil_image = Image.open(ori_image_path)
|
||||
transform = transforms.Compose([
|
||||
transforms.ToTensor(), # Convert PIL Image to tensor and normalize pixel values to [0, 1]
|
||||
])
|
||||
image_input = transform(pil_image)
|
||||
|
||||
## The image input is already in the standard ComfyUI image tensor format
|
||||
numpy_image = (image_input[0] * 255.0).clamp(0, 255).numpy()
|
||||
image = image_input[0] * 255.0
|
||||
image = Image.fromarray(image.clamp(0, 255).numpy().round().astype(np.uint8))
|
||||
# Get the original dimensions of the image
|
||||
img_width, img_height = image.size
|
||||
|
||||
# Call the Textract DetectDocumentText function
|
||||
byte_stream = io.BytesIO()
|
||||
image.save(byte_stream, format='PNG')
|
||||
byte_image = byte_stream.getvalue()
|
||||
response = textract.detect_document_text(Document={'Bytes': byte_image})
|
||||
|
||||
# Initialize the results list
|
||||
result = []
|
||||
# Create a black mask image with the same size as the original image
|
||||
#mask = np.zeros_like(numpy_image)
|
||||
mask = np.ones_like(numpy_image) * 255
|
||||
all_text=""
|
||||
|
||||
|
||||
# Extract text and bounding box information
|
||||
for item in response['Blocks']:
|
||||
if item['BlockType'] == 'LINE':
|
||||
text = item['Text']
|
||||
box = item['Geometry']['BoundingBox']
|
||||
left = int(box['Left'] * img_width)
|
||||
top = int(box['Top'] * img_height)
|
||||
width = int(box['Width'] * img_width)
|
||||
height = int(box['Height']* img_height)
|
||||
|
||||
# Add the information to the result list
|
||||
result.append(text)
|
||||
# Draw mask for each text information box
|
||||
# Specify the coordinates of the top-left and bottom-right corners of the rectangle
|
||||
temp_mask = np.zeros_like(numpy_image)
|
||||
x1, y1 = int(left), int(top)
|
||||
x2, y2 = int(left + width), int(top + height)
|
||||
# Draw black rectangular boxes on the mask image
|
||||
#cv2.rectangle(temp_mask, (x1, y1), (x2, y2), (0, 0, 0), -1)
|
||||
#mask = cv2.bitwise_or(mask, temp_mask)
|
||||
|
||||
cv2.rectangle(mask, (left, top), (left + width, top + height), (0, 0, 0), -1)
|
||||
|
||||
# Perform bitwise operation between the mask image and the original image to generate the masked image
|
||||
masked_img = np.where(mask == 0, 0, numpy_image)
|
||||
#masked_img = cv2.bitwise_and(numpy_image, mask)
|
||||
masked_img = torch.from_numpy(np.array(masked_img).astype(np.float32) / 255.0).unsqueeze(0)
|
||||
#masked_img.save(temp_img_path)
|
||||
# Convert PyTorch tensor to PIL image
|
||||
to_pil = transforms.ToPILImage()
|
||||
pil_image = to_pil(masked_img.squeeze(0))
|
||||
# save PIL image
|
||||
pil_image.save(temp_img_path)
|
||||
|
||||
all_text="|".join(result)
|
||||
print("result",result)
|
||||
|
||||
return all_text ,ori_image_path,temp_img_path, masked_img
|
||||
|
||||
|
||||
|
||||
@retry(tries=MAX_RETRY)
|
||||
def forward(self, image):
|
||||
return self.ocr_by_textract(image)
|
||||
|
||||
|
||||
## for layer style nodes
|
||||
class ImageOCRByTextractV4:
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
input_dir = folder_paths.get_input_directory()
|
||||
files = [f for f in os.listdir(input_dir) if os.path.isfile(os.path.join(input_dir, f))]
|
||||
return {"required":{
|
||||
"image": ("IMAGE",),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("STRING","STRING","STRING","STRING","STRING","STRING","STRING","IMAGE","IMAGE")
|
||||
RETURN_NAMES = ("Texts","x_offsets","y_offsets","widths","heights","img_width","img_height","Mask Image","Original Image")
|
||||
FUNCTION = "forward"
|
||||
CATEGORY = "aws"
|
||||
OUTPUT_NODE = True
|
||||
|
||||
def convert_to_xywh(self,coordinates):
|
||||
# Extract all x and y coordinates
|
||||
x_coords = [coord[0] for coord in coordinates]
|
||||
y_coords = [coord[1] for coord in coordinates]
|
||||
|
||||
# Calculate x offset and y offset
|
||||
x_offset = min(x_coords)
|
||||
y_offset = min(y_coords)
|
||||
|
||||
# Calculate width and height
|
||||
width = max(x_coords) - x_offset
|
||||
height = max(y_coords) - y_offset
|
||||
|
||||
print(x_offset,y_offset,width,height)
|
||||
return int(x_offset), int(y_offset), int(width), int(height)
|
||||
|
||||
def ocr_by_paddleocr(self,image_input):
|
||||
|
||||
image = image_input[0] * 255.0
|
||||
image = Image.fromarray(image.clamp(0, 255).numpy().round().astype(np.uint8))
|
||||
numpy_image = (image_input[0] * 255.0).clamp(0, 255).numpy()
|
||||
|
||||
img_width, img_height = image.size
|
||||
|
||||
|
||||
# Create temporary file
|
||||
with tempfile.NamedTemporaryFile(delete=False, suffix='.png', dir='/tmp/') as temp_file:
|
||||
temp_filename = temp_file.name
|
||||
|
||||
# Save numpy_image as a temporary file
|
||||
cv2.imwrite(temp_filename, cv2.cvtColor(numpy_image, cv2.COLOR_RGB2BGR))
|
||||
|
||||
ocr = PaddleOCR(
|
||||
det_model_dir='/home/ubuntu/ComfyUI/models/checkpoints/PaddleOCR/det',
|
||||
rec_model_dir='/home/ubuntu/ComfyUI/models/checkpoints/PaddleOCR/rec',
|
||||
det_limit_side_len=2048,
|
||||
use_angle_cls=True,
|
||||
#use_gpu=False,
|
||||
)
|
||||
|
||||
ocr_results = ocr.ocr(temp_filename, cls=True)[0]
|
||||
|
||||
# Create a mask image with the same size as the original image
|
||||
result = []
|
||||
masked_img = numpy_image.copy()
|
||||
all_text=""
|
||||
x_offsets=[]
|
||||
y_offsets=[]
|
||||
widths=[]
|
||||
heights=[]
|
||||
|
||||
|
||||
# Extract text and bounding box information
|
||||
for line in ocr_results:
|
||||
if not isinstance(line, list):
|
||||
continue
|
||||
boxes = line[0]
|
||||
x_offset,y_offset,width,height = self.convert_to_xywh(boxes)
|
||||
x_offsets.append(str(x_offset))
|
||||
y_offsets.append(str(y_offset))
|
||||
widths.append(str(width))
|
||||
heights.append(str(height))
|
||||
|
||||
text = line[1][0]
|
||||
print("text")
|
||||
print(text)
|
||||
result.append(text)
|
||||
|
||||
# Draw mask for each text information box
|
||||
# Specify the coordinates of the top-left and bottom-right corners of the rectangle
|
||||
x1, y1 = int(x_offset), int(y_offset)
|
||||
x2, y2 = int(x_offset + width), int(y_offset + height)
|
||||
# Draw a black rectangle on the mask image
|
||||
cv2.rectangle(masked_img, (x1, y1), (x2, y2), (0, 0, 0), -1)
|
||||
|
||||
masked_img = torch.from_numpy(np.array(masked_img).astype(np.float32) / 255.0).unsqueeze(0)
|
||||
|
||||
all_text="|".join(result)
|
||||
x_offsets="|".join(x_offsets)
|
||||
y_offsets="|".join(y_offsets)
|
||||
widths="|".join(widths)
|
||||
heights="|".join(heights)
|
||||
|
||||
print("result",result)
|
||||
|
||||
# Add original image output
|
||||
original_img = image_input
|
||||
# delete temp files
|
||||
os.unlink(temp_filename)
|
||||
|
||||
return all_text ,x_offsets,y_offsets,widths,heights,img_width,img_height, masked_img,original_img
|
||||
|
||||
|
||||
|
||||
@retry(tries=MAX_RETRY)
|
||||
def forward(self, image):
|
||||
return self.ocr_by_paddleocr(image)
|
||||
|
||||
|
||||
## for layer style nodes
|
||||
class ImageOCRByTextractV3:
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
input_dir = folder_paths.get_input_directory()
|
||||
files = [f for f in os.listdir(input_dir) if os.path.isfile(os.path.join(input_dir, f))]
|
||||
return {"required":{
|
||||
"image": ("IMAGE",),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("STRING","STRING","STRING","STRING","STRING","STRING","STRING","IMAGE","IMAGE")
|
||||
RETURN_NAMES = ("Texts","x_offsets","y_offsets","widths","heights","img_width","img_height","Mask Image","Original Image")
|
||||
FUNCTION = "forward"
|
||||
CATEGORY = "aws"
|
||||
OUTPUT_NODE = True
|
||||
|
||||
def ocr_by_textract(self,image_input):
|
||||
|
||||
|
||||
image = image_input[0] * 255.0
|
||||
image = Image.fromarray(image.clamp(0, 255).numpy().round().astype(np.uint8))
|
||||
numpy_image = (image_input[0] * 255.0).clamp(0, 255).numpy()
|
||||
|
||||
|
||||
img_width, img_height = image.size
|
||||
|
||||
|
||||
byte_stream = io.BytesIO()
|
||||
image.save(byte_stream, format='PNG')
|
||||
byte_image = byte_stream.getvalue()
|
||||
response = textract.detect_document_text(Document={'Bytes': byte_image})
|
||||
|
||||
|
||||
result = []
|
||||
|
||||
masked_img = numpy_image.copy()
|
||||
all_text=""
|
||||
x_offsets=[]
|
||||
y_offsets=[]
|
||||
widths=[]
|
||||
heights=[]
|
||||
|
||||
|
||||
|
||||
for item in response['Blocks']:
|
||||
if item['BlockType'] == 'LINE':
|
||||
text = item['Text']
|
||||
box = item['Geometry']['BoundingBox']
|
||||
|
||||
left = int(box['Left'] * img_width)
|
||||
x_offsets.append(str(left))
|
||||
|
||||
top = int(box['Top'] * img_height)
|
||||
y_offsets.append(str(top))
|
||||
|
||||
width = int(box['Width'] * img_width)
|
||||
widths.append(str(width))
|
||||
|
||||
height = int(box['Height']* img_height)
|
||||
heights.append(str(height))
|
||||
|
||||
|
||||
result.append(text)
|
||||
# Draw mask for each text information box
|
||||
# Specify the coordinates of the top-left and bottom-right corners of the rectangle
|
||||
x1, y1 = int(left), int(top)
|
||||
x2, y2 = int(left + width), int(top + height)
|
||||
# Draw black rectangular boxes on the mask image
|
||||
cv2.rectangle(masked_img, (x1, y1), (x2, y2), (0, 0, 0), -1)
|
||||
|
||||
|
||||
#masked_img = torch.from_numpy(np.array(masked_img).astype(np.float32) / 255.0).unsqueeze(0)
|
||||
masked_img = torch.from_numpy(np.array(masked_img).astype(np.float32) / 255.0).unsqueeze(0)
|
||||
###summary the output
|
||||
all_text="|".join(result)
|
||||
x_offsets="|".join(x_offsets)
|
||||
y_offsets="|".join(y_offsets)
|
||||
widths="|".join(widths)
|
||||
heights="|".join(heights)
|
||||
|
||||
print("result",result)
|
||||
|
||||
# Add original image output
|
||||
original_img = image_input
|
||||
|
||||
return all_text ,x_offsets,y_offsets,widths,heights,img_width,img_height, masked_img,original_img
|
||||
|
||||
|
||||
|
||||
@retry(tries=MAX_RETRY)
|
||||
def forward(self, image):
|
||||
return self.ocr_by_textract(image)
|
||||
|
||||
|
||||
NODE_CLASS_MAPPINGS = {
|
||||
"Image OCR By Textract": ImageOCRByTextract,
|
||||
"Image OCR By Textract V2":ImageOCRByTextractV2,
|
||||
"Image OCR By Textract V3":ImageOCRByTextractV3,
|
||||
"Image OCR by PaddleOCR": ImageOCRByTextractV4
|
||||
}
|
||||
|
||||
@@ -1,186 +0,0 @@
|
||||
{
|
||||
"last_node_id": 5,
|
||||
"last_link_id": 3,
|
||||
"nodes": [
|
||||
{
|
||||
"id": 1,
|
||||
"type": "Image From URL",
|
||||
"pos": [
|
||||
68,
|
||||
283
|
||||
],
|
||||
"size": {
|
||||
"0": 315,
|
||||
"1": 58
|
||||
},
|
||||
"flags": {},
|
||||
"order": 0,
|
||||
"mode": 0,
|
||||
"outputs": [
|
||||
{
|
||||
"name": "IMAGE",
|
||||
"type": "IMAGE",
|
||||
"links": [
|
||||
1,
|
||||
2
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 0
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "Image From URL"
|
||||
},
|
||||
"widgets_values": [
|
||||
"https://upload.wikimedia.org/wikipedia/commons/a/a7/Camponotus_flavomarginatus_ant.jpg"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"type": "Bedrock - Claude Multimodal",
|
||||
"pos": [
|
||||
461,
|
||||
123
|
||||
],
|
||||
"size": {
|
||||
"0": 400,
|
||||
"1": 200
|
||||
},
|
||||
"flags": {},
|
||||
"order": 2,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "image",
|
||||
"type": "IMAGE",
|
||||
"link": 2
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "STRING",
|
||||
"type": "STRING",
|
||||
"links": [
|
||||
3
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 0
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "Bedrock - Claude Multimodal"
|
||||
},
|
||||
"widgets_values": [
|
||||
"Describe this image.",
|
||||
"anthropic.claude-3-haiku-20240307-v1:0",
|
||||
2048,
|
||||
0.5,
|
||||
1,
|
||||
250
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"type": "PreviewImage",
|
||||
"pos": [
|
||||
484,
|
||||
400
|
||||
],
|
||||
"size": [
|
||||
266.63671875,
|
||||
246
|
||||
],
|
||||
"flags": {},
|
||||
"order": 1,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "images",
|
||||
"type": "IMAGE",
|
||||
"link": 1
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "PreviewImage"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"type": "ShowText|pysssss",
|
||||
"pos": [
|
||||
916,
|
||||
154
|
||||
],
|
||||
"size": [
|
||||
323.16015625,
|
||||
179.2890625
|
||||
],
|
||||
"flags": {},
|
||||
"order": 3,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "text",
|
||||
"type": "STRING",
|
||||
"link": 3,
|
||||
"widget": {
|
||||
"name": "text"
|
||||
}
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "STRING",
|
||||
"type": "STRING",
|
||||
"links": null,
|
||||
"shape": 6
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "ShowText|pysssss"
|
||||
},
|
||||
"widgets_values": [
|
||||
"",
|
||||
"The image shows a close-up view of a black ant on a textured surface. The ant appears to be in a crouched or alert position, with its legs and antennae extended. The lighting and focus create a dramatic, almost cinematic effect, highlighting the intricate details of the ant's body and the rough texture of the surface it is standing on."
|
||||
]
|
||||
}
|
||||
],
|
||||
"links": [
|
||||
[
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
2,
|
||||
0,
|
||||
"IMAGE"
|
||||
],
|
||||
[
|
||||
2,
|
||||
1,
|
||||
0,
|
||||
3,
|
||||
0,
|
||||
"IMAGE"
|
||||
],
|
||||
[
|
||||
3,
|
||||
3,
|
||||
0,
|
||||
5,
|
||||
0,
|
||||
"STRING"
|
||||
]
|
||||
],
|
||||
"groups": [],
|
||||
"config": {},
|
||||
"extra": {
|
||||
"ds": {
|
||||
"scale": 1,
|
||||
"offset": [
|
||||
-0.125,
|
||||
0.2421875
|
||||
]
|
||||
}
|
||||
},
|
||||
"version": 0.4
|
||||
}
|
||||
@@ -0,0 +1,788 @@
|
||||
{
|
||||
"last_node_id": 35,
|
||||
"last_link_id": 71,
|
||||
"nodes": [
|
||||
{
|
||||
"id": 15,
|
||||
"type": "PreviewImage",
|
||||
"pos": [
|
||||
1680,
|
||||
650
|
||||
],
|
||||
"size": {
|
||||
"0": 295.9647216796875,
|
||||
"1": 320.621337890625
|
||||
},
|
||||
"flags": {},
|
||||
"order": 11,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "images",
|
||||
"type": "IMAGE",
|
||||
"link": 23
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "PreviewImage"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 29,
|
||||
"type": "PreviewImage",
|
||||
"pos": [
|
||||
1680,
|
||||
1040
|
||||
],
|
||||
"size": {
|
||||
"0": 295.9647216796875,
|
||||
"1": 320.621337890625
|
||||
},
|
||||
"flags": {},
|
||||
"order": 12,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "images",
|
||||
"type": "IMAGE",
|
||||
"link": 62
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "PreviewImage"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 8,
|
||||
"type": "PreviewImage",
|
||||
"pos": [
|
||||
1680,
|
||||
230
|
||||
],
|
||||
"size": {
|
||||
"0": 299.51416015625,
|
||||
"1": 327.3353271484375
|
||||
},
|
||||
"flags": {},
|
||||
"order": 10,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "images",
|
||||
"type": "IMAGE",
|
||||
"link": 8
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "PreviewImage"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 31,
|
||||
"type": "PreviewImage",
|
||||
"pos": [
|
||||
2410,
|
||||
240
|
||||
],
|
||||
"size": {
|
||||
"0": 299.51416015625,
|
||||
"1": 327.3353271484375
|
||||
},
|
||||
"flags": {},
|
||||
"order": 13,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "images",
|
||||
"type": "IMAGE",
|
||||
"link": 65
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "PreviewImage"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 33,
|
||||
"type": "PreviewImage",
|
||||
"pos": [
|
||||
2410,
|
||||
630
|
||||
],
|
||||
"size": {
|
||||
"0": 299.51416015625,
|
||||
"1": 327.3353271484375
|
||||
},
|
||||
"flags": {},
|
||||
"order": 14,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "images",
|
||||
"type": "IMAGE",
|
||||
"link": 68
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "PreviewImage"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 35,
|
||||
"type": "PreviewImage",
|
||||
"pos": [
|
||||
2420,
|
||||
1020
|
||||
],
|
||||
"size": {
|
||||
"0": 299.51416015625,
|
||||
"1": 327.3353271484375
|
||||
},
|
||||
"flags": {},
|
||||
"order": 15,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "images",
|
||||
"type": "IMAGE",
|
||||
"link": 71
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "PreviewImage"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 25,
|
||||
"type": "Reroute",
|
||||
"pos": [
|
||||
1132,
|
||||
727
|
||||
],
|
||||
"size": [
|
||||
75,
|
||||
26
|
||||
],
|
||||
"flags": {},
|
||||
"order": 3,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "*",
|
||||
"link": 54
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "MASK",
|
||||
"links": [
|
||||
58,
|
||||
59,
|
||||
61,
|
||||
64,
|
||||
67,
|
||||
70
|
||||
],
|
||||
"slot_index": 0
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"showOutputText": false,
|
||||
"horizontal": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 27,
|
||||
"type": "Reroute",
|
||||
"pos": [
|
||||
1129,
|
||||
439
|
||||
],
|
||||
"size": [
|
||||
75,
|
||||
26
|
||||
],
|
||||
"flags": {},
|
||||
"order": 2,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "*",
|
||||
"link": 55
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "IMAGE",
|
||||
"links": [
|
||||
56,
|
||||
57,
|
||||
60,
|
||||
63,
|
||||
66,
|
||||
69
|
||||
],
|
||||
"slot_index": 0
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"showOutputText": false,
|
||||
"horizontal": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 24,
|
||||
"type": "LayerMask: RemBgUltra",
|
||||
"pos": [
|
||||
785,
|
||||
772
|
||||
],
|
||||
"size": {
|
||||
"0": 315,
|
||||
"1": 150
|
||||
},
|
||||
"flags": {},
|
||||
"order": 1,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "image",
|
||||
"type": "IMAGE",
|
||||
"link": 36
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "image",
|
||||
"type": "IMAGE",
|
||||
"links": null,
|
||||
"shape": 3
|
||||
},
|
||||
{
|
||||
"name": "mask",
|
||||
"type": "MASK",
|
||||
"links": [
|
||||
54
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 1
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "LayerMask: RemBgUltra"
|
||||
},
|
||||
"widgets_values": [
|
||||
8,
|
||||
0.01,
|
||||
0.99,
|
||||
false
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"type": "LoadImage",
|
||||
"pos": [
|
||||
431,
|
||||
439
|
||||
],
|
||||
"size": {
|
||||
"0": 323.62158203125,
|
||||
"1": 420.20391845703125
|
||||
},
|
||||
"flags": {},
|
||||
"order": 0,
|
||||
"mode": 0,
|
||||
"outputs": [
|
||||
{
|
||||
"name": "IMAGE",
|
||||
"type": "IMAGE",
|
||||
"links": [
|
||||
36,
|
||||
55
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 0
|
||||
},
|
||||
{
|
||||
"name": "MASK",
|
||||
"type": "MASK",
|
||||
"links": null,
|
||||
"shape": 3
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "LoadImage"
|
||||
},
|
||||
"widgets_values": [
|
||||
"512x512with_background (24).png",
|
||||
"image"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 7,
|
||||
"type": "LayerUtility: LaMa",
|
||||
"pos": [
|
||||
1300,
|
||||
320
|
||||
],
|
||||
"size": {
|
||||
"0": 315,
|
||||
"1": 174
|
||||
},
|
||||
"flags": {},
|
||||
"order": 4,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "image",
|
||||
"type": "IMAGE",
|
||||
"link": 56
|
||||
},
|
||||
{
|
||||
"name": "mask",
|
||||
"type": "MASK",
|
||||
"link": 58
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "image",
|
||||
"type": "IMAGE",
|
||||
"links": [
|
||||
8
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 0
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "LayerUtility: LaMa"
|
||||
},
|
||||
"widgets_values": [
|
||||
"lama",
|
||||
"cuda",
|
||||
false,
|
||||
25,
|
||||
6
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 14,
|
||||
"type": "LayerUtility: LaMa",
|
||||
"pos": [
|
||||
1300,
|
||||
710
|
||||
],
|
||||
"size": {
|
||||
"0": 315,
|
||||
"1": 174
|
||||
},
|
||||
"flags": {},
|
||||
"order": 5,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "image",
|
||||
"type": "IMAGE",
|
||||
"link": 57
|
||||
},
|
||||
{
|
||||
"name": "mask",
|
||||
"type": "MASK",
|
||||
"link": 59
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "image",
|
||||
"type": "IMAGE",
|
||||
"links": [
|
||||
23
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 0
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "LayerUtility: LaMa"
|
||||
},
|
||||
"widgets_values": [
|
||||
"ldm",
|
||||
"cuda",
|
||||
false,
|
||||
25,
|
||||
6
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 28,
|
||||
"type": "LayerUtility: LaMa",
|
||||
"pos": [
|
||||
1290,
|
||||
1030
|
||||
],
|
||||
"size": {
|
||||
"0": 315,
|
||||
"1": 174
|
||||
},
|
||||
"flags": {},
|
||||
"order": 6,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "image",
|
||||
"type": "IMAGE",
|
||||
"link": 60
|
||||
},
|
||||
{
|
||||
"name": "mask",
|
||||
"type": "MASK",
|
||||
"link": 61
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "image",
|
||||
"type": "IMAGE",
|
||||
"links": [
|
||||
62
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 0
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "LayerUtility: LaMa"
|
||||
},
|
||||
"widgets_values": [
|
||||
"zits",
|
||||
"cuda",
|
||||
false,
|
||||
25,
|
||||
6
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 30,
|
||||
"type": "LayerUtility: LaMa",
|
||||
"pos": [
|
||||
2036,
|
||||
314
|
||||
],
|
||||
"size": {
|
||||
"0": 315,
|
||||
"1": 174
|
||||
},
|
||||
"flags": {},
|
||||
"order": 7,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "image",
|
||||
"type": "IMAGE",
|
||||
"link": 63
|
||||
},
|
||||
{
|
||||
"name": "mask",
|
||||
"type": "MASK",
|
||||
"link": 64
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "image",
|
||||
"type": "IMAGE",
|
||||
"links": [
|
||||
65
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 0
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "LayerUtility: LaMa"
|
||||
},
|
||||
"widgets_values": [
|
||||
"mat",
|
||||
"cuda",
|
||||
false,
|
||||
25,
|
||||
6
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 32,
|
||||
"type": "LayerUtility: LaMa",
|
||||
"pos": [
|
||||
2037,
|
||||
724
|
||||
],
|
||||
"size": {
|
||||
"0": 315,
|
||||
"1": 174
|
||||
},
|
||||
"flags": {},
|
||||
"order": 8,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "image",
|
||||
"type": "IMAGE",
|
||||
"link": 66
|
||||
},
|
||||
{
|
||||
"name": "mask",
|
||||
"type": "MASK",
|
||||
"link": 67
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "image",
|
||||
"type": "IMAGE",
|
||||
"links": [
|
||||
68
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 0
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "LayerUtility: LaMa"
|
||||
},
|
||||
"widgets_values": [
|
||||
"fcf",
|
||||
"cuda",
|
||||
false,
|
||||
25,
|
||||
6
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 34,
|
||||
"type": "LayerUtility: LaMa",
|
||||
"pos": [
|
||||
2043,
|
||||
1042
|
||||
],
|
||||
"size": {
|
||||
"0": 315,
|
||||
"1": 174
|
||||
},
|
||||
"flags": {},
|
||||
"order": 9,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "image",
|
||||
"type": "IMAGE",
|
||||
"link": 69
|
||||
},
|
||||
{
|
||||
"name": "mask",
|
||||
"type": "MASK",
|
||||
"link": 70
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "image",
|
||||
"type": "IMAGE",
|
||||
"links": [
|
||||
71
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 0
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "LayerUtility: LaMa"
|
||||
},
|
||||
"widgets_values": [
|
||||
"spread",
|
||||
"cuda",
|
||||
false,
|
||||
25,
|
||||
6
|
||||
]
|
||||
}
|
||||
],
|
||||
"links": [
|
||||
[
|
||||
8,
|
||||
7,
|
||||
0,
|
||||
8,
|
||||
0,
|
||||
"IMAGE"
|
||||
],
|
||||
[
|
||||
23,
|
||||
14,
|
||||
0,
|
||||
15,
|
||||
0,
|
||||
"IMAGE"
|
||||
],
|
||||
[
|
||||
36,
|
||||
2,
|
||||
0,
|
||||
24,
|
||||
0,
|
||||
"IMAGE"
|
||||
],
|
||||
[
|
||||
54,
|
||||
24,
|
||||
1,
|
||||
25,
|
||||
0,
|
||||
"*"
|
||||
],
|
||||
[
|
||||
55,
|
||||
2,
|
||||
0,
|
||||
27,
|
||||
0,
|
||||
"*"
|
||||
],
|
||||
[
|
||||
56,
|
||||
27,
|
||||
0,
|
||||
7,
|
||||
0,
|
||||
"IMAGE"
|
||||
],
|
||||
[
|
||||
57,
|
||||
27,
|
||||
0,
|
||||
14,
|
||||
0,
|
||||
"IMAGE"
|
||||
],
|
||||
[
|
||||
58,
|
||||
25,
|
||||
0,
|
||||
7,
|
||||
1,
|
||||
"MASK"
|
||||
],
|
||||
[
|
||||
59,
|
||||
25,
|
||||
0,
|
||||
14,
|
||||
1,
|
||||
"MASK"
|
||||
],
|
||||
[
|
||||
60,
|
||||
27,
|
||||
0,
|
||||
28,
|
||||
0,
|
||||
"IMAGE"
|
||||
],
|
||||
[
|
||||
61,
|
||||
25,
|
||||
0,
|
||||
28,
|
||||
1,
|
||||
"MASK"
|
||||
],
|
||||
[
|
||||
62,
|
||||
28,
|
||||
0,
|
||||
29,
|
||||
0,
|
||||
"IMAGE"
|
||||
],
|
||||
[
|
||||
63,
|
||||
27,
|
||||
0,
|
||||
30,
|
||||
0,
|
||||
"IMAGE"
|
||||
],
|
||||
[
|
||||
64,
|
||||
25,
|
||||
0,
|
||||
30,
|
||||
1,
|
||||
"MASK"
|
||||
],
|
||||
[
|
||||
65,
|
||||
30,
|
||||
0,
|
||||
31,
|
||||
0,
|
||||
"IMAGE"
|
||||
],
|
||||
[
|
||||
66,
|
||||
27,
|
||||
0,
|
||||
32,
|
||||
0,
|
||||
"IMAGE"
|
||||
],
|
||||
[
|
||||
67,
|
||||
25,
|
||||
0,
|
||||
32,
|
||||
1,
|
||||
"MASK"
|
||||
],
|
||||
[
|
||||
68,
|
||||
32,
|
||||
0,
|
||||
33,
|
||||
0,
|
||||
"IMAGE"
|
||||
],
|
||||
[
|
||||
69,
|
||||
27,
|
||||
0,
|
||||
34,
|
||||
0,
|
||||
"IMAGE"
|
||||
],
|
||||
[
|
||||
70,
|
||||
25,
|
||||
0,
|
||||
34,
|
||||
1,
|
||||
"MASK"
|
||||
],
|
||||
[
|
||||
71,
|
||||
34,
|
||||
0,
|
||||
35,
|
||||
0,
|
||||
"IMAGE"
|
||||
]
|
||||
],
|
||||
"groups": [],
|
||||
"config": {},
|
||||
"extra": {},
|
||||
"version": 0.4
|
||||
}
|
||||
@@ -0,0 +1,701 @@
|
||||
{
|
||||
"last_node_id": 52,
|
||||
"last_link_id": 83,
|
||||
"nodes": [
|
||||
{
|
||||
"id": 25,
|
||||
"type": "PreviewImage",
|
||||
"pos": [
|
||||
1789,
|
||||
644
|
||||
],
|
||||
"size": {
|
||||
"0": 210,
|
||||
"1": 246
|
||||
},
|
||||
"flags": {},
|
||||
"order": 13,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "images",
|
||||
"type": "IMAGE",
|
||||
"link": 47
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "PreviewImage"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 23,
|
||||
"type": "Image OCR By Textract",
|
||||
"pos": [
|
||||
-654,
|
||||
420
|
||||
],
|
||||
"size": {
|
||||
"0": 210,
|
||||
"1": 126
|
||||
},
|
||||
"flags": {},
|
||||
"order": 4,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "image",
|
||||
"type": "IMAGE",
|
||||
"link": 36
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "Text",
|
||||
"type": "STRING",
|
||||
"links": [
|
||||
38
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 0
|
||||
},
|
||||
{
|
||||
"name": "Left",
|
||||
"type": "INT",
|
||||
"links": [],
|
||||
"shape": 3,
|
||||
"slot_index": 1
|
||||
},
|
||||
{
|
||||
"name": "Top",
|
||||
"type": "INT",
|
||||
"links": [],
|
||||
"shape": 3,
|
||||
"slot_index": 2
|
||||
},
|
||||
{
|
||||
"name": "Width",
|
||||
"type": "INT",
|
||||
"links": [],
|
||||
"shape": 3,
|
||||
"slot_index": 3
|
||||
},
|
||||
{
|
||||
"name": "Height",
|
||||
"type": "INT",
|
||||
"links": [],
|
||||
"shape": 3,
|
||||
"slot_index": 4
|
||||
},
|
||||
{
|
||||
"name": "Mask Image",
|
||||
"type": "IMAGE",
|
||||
"links": [
|
||||
49
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 5
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "Image OCR By Textract"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 15,
|
||||
"type": "Bedrock - Claude",
|
||||
"pos": [
|
||||
-322,
|
||||
948
|
||||
],
|
||||
"size": {
|
||||
"0": 400,
|
||||
"1": 200
|
||||
},
|
||||
"flags": {},
|
||||
"order": 8,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "prompt",
|
||||
"type": "STRING",
|
||||
"link": 30,
|
||||
"widget": {
|
||||
"name": "prompt"
|
||||
}
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "STRING",
|
||||
"type": "STRING",
|
||||
"links": [
|
||||
59
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 0
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "Bedrock - Claude"
|
||||
},
|
||||
"widgets_values": [
|
||||
"",
|
||||
"anthropic.claude-3-haiku-20240307-v1:0",
|
||||
2048,
|
||||
1,
|
||||
1,
|
||||
71
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 40,
|
||||
"type": "String",
|
||||
"pos": [
|
||||
347,
|
||||
1165
|
||||
],
|
||||
"size": {
|
||||
"0": 315,
|
||||
"1": 58
|
||||
},
|
||||
"flags": {},
|
||||
"order": 0,
|
||||
"mode": 0,
|
||||
"outputs": [
|
||||
{
|
||||
"name": "STRING",
|
||||
"type": "STRING",
|
||||
"links": [
|
||||
58
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 0
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "String"
|
||||
},
|
||||
"widgets_values": [
|
||||
"Yes"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 48,
|
||||
"type": "MaskPreview+",
|
||||
"pos": [
|
||||
756,
|
||||
302
|
||||
],
|
||||
"size": {
|
||||
"0": 210,
|
||||
"1": 246
|
||||
},
|
||||
"flags": {},
|
||||
"order": 3,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "mask",
|
||||
"type": "MASK",
|
||||
"link": 69
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "MaskPreview+"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 39,
|
||||
"type": "Compare",
|
||||
"pos": [
|
||||
757,
|
||||
1079
|
||||
],
|
||||
"size": {
|
||||
"0": 315,
|
||||
"1": 78
|
||||
},
|
||||
"flags": {},
|
||||
"order": 10,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "a",
|
||||
"type": "*",
|
||||
"link": 59
|
||||
},
|
||||
{
|
||||
"name": "b",
|
||||
"type": "*",
|
||||
"link": 58
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "B",
|
||||
"type": "BOOLEAN",
|
||||
"links": [
|
||||
78
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 0
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "Compare"
|
||||
},
|
||||
"widgets_values": [
|
||||
"a == b"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 32,
|
||||
"type": "ImageToMask",
|
||||
"pos": [
|
||||
-296,
|
||||
518
|
||||
],
|
||||
"size": {
|
||||
"0": 315,
|
||||
"1": 58
|
||||
},
|
||||
"flags": {},
|
||||
"order": 7,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "image",
|
||||
"type": "IMAGE",
|
||||
"link": 49
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "MASK",
|
||||
"type": "MASK",
|
||||
"links": [
|
||||
50,
|
||||
79
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 0
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "ImageToMask"
|
||||
},
|
||||
"widgets_values": [
|
||||
"green"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 51,
|
||||
"type": "If ANY execute A else B",
|
||||
"pos": [
|
||||
947,
|
||||
648
|
||||
],
|
||||
"size": {
|
||||
"0": 210,
|
||||
"1": 66
|
||||
},
|
||||
"flags": {},
|
||||
"order": 11,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "ANY",
|
||||
"type": "*",
|
||||
"link": 78
|
||||
},
|
||||
{
|
||||
"name": "IF_TRUE",
|
||||
"type": "*",
|
||||
"link": 79
|
||||
},
|
||||
{
|
||||
"name": "IF_FALSE",
|
||||
"type": "*",
|
||||
"link": 80
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "?",
|
||||
"type": "*",
|
||||
"links": [
|
||||
81
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 0
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "If ANY execute A else B"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 24,
|
||||
"type": "LayerUtility: LaMa",
|
||||
"pos": [
|
||||
1384,
|
||||
959
|
||||
],
|
||||
"size": {
|
||||
"0": 315,
|
||||
"1": 174
|
||||
},
|
||||
"flags": {},
|
||||
"order": 12,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "image",
|
||||
"type": "IMAGE",
|
||||
"link": 83
|
||||
},
|
||||
{
|
||||
"name": "mask",
|
||||
"type": "MASK",
|
||||
"link": 81,
|
||||
"slot_index": 1
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "image",
|
||||
"type": "IMAGE",
|
||||
"links": [
|
||||
47
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 0
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "LayerUtility: LaMa"
|
||||
},
|
||||
"widgets_values": [
|
||||
"lama",
|
||||
"cuda",
|
||||
false,
|
||||
25,
|
||||
6
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 47,
|
||||
"type": "SolidMask",
|
||||
"pos": [
|
||||
-312,
|
||||
227
|
||||
],
|
||||
"size": {
|
||||
"0": 315,
|
||||
"1": 106
|
||||
},
|
||||
"flags": {},
|
||||
"order": 1,
|
||||
"mode": 0,
|
||||
"outputs": [
|
||||
{
|
||||
"name": "MASK",
|
||||
"type": "MASK",
|
||||
"links": [
|
||||
69,
|
||||
80
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 0
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "SolidMask"
|
||||
},
|
||||
"widgets_values": [
|
||||
0,
|
||||
1000,
|
||||
662
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 33,
|
||||
"type": "MaskPreview+",
|
||||
"pos": [
|
||||
511,
|
||||
394
|
||||
],
|
||||
"size": {
|
||||
"0": 210,
|
||||
"1": 246
|
||||
},
|
||||
"flags": {},
|
||||
"order": 9,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "mask",
|
||||
"type": "MASK",
|
||||
"link": 50
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "MaskPreview+"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 17,
|
||||
"type": "Prompt Template",
|
||||
"pos": [
|
||||
-400,
|
||||
648
|
||||
],
|
||||
"size": {
|
||||
"0": 521.4636840820312,
|
||||
"1": 208.76742553710938
|
||||
},
|
||||
"flags": {},
|
||||
"order": 6,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "prompt",
|
||||
"type": "STRING",
|
||||
"link": 38,
|
||||
"widget": {
|
||||
"name": "prompt"
|
||||
}
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "STRING",
|
||||
"type": "STRING",
|
||||
"links": [
|
||||
30
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 0
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "Prompt Template"
|
||||
},
|
||||
"widgets_values": [
|
||||
"",
|
||||
"判断如下文本中是否包含暴力,恐怖,色情,政治的内容\n[prompt]\n如果包含,返回\"Yes\", 否则返回\"No\"\n直接返回结果,不要包含其他任务内容"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"type": "LoadImage",
|
||||
"pos": [
|
||||
-1091,
|
||||
346
|
||||
],
|
||||
"size": {
|
||||
"0": 315,
|
||||
"1": 314
|
||||
},
|
||||
"flags": {},
|
||||
"order": 2,
|
||||
"mode": 0,
|
||||
"outputs": [
|
||||
{
|
||||
"name": "IMAGE",
|
||||
"type": "IMAGE",
|
||||
"links": [
|
||||
36,
|
||||
82
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 0
|
||||
},
|
||||
{
|
||||
"name": "MASK",
|
||||
"type": "MASK",
|
||||
"links": [],
|
||||
"shape": 3,
|
||||
"slot_index": 1
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "LoadImage"
|
||||
},
|
||||
"widgets_values": [
|
||||
"textract_demo005 (1).png",
|
||||
"image"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 52,
|
||||
"type": "Reroute",
|
||||
"pos": [
|
||||
726.544712798572,
|
||||
819.4428242873535
|
||||
],
|
||||
"size": [
|
||||
75,
|
||||
26
|
||||
],
|
||||
"flags": {},
|
||||
"order": 5,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "*",
|
||||
"link": 82
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "IMAGE",
|
||||
"links": [
|
||||
83
|
||||
],
|
||||
"slot_index": 0
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"showOutputText": false,
|
||||
"horizontal": false
|
||||
}
|
||||
}
|
||||
],
|
||||
"links": [
|
||||
[
|
||||
30,
|
||||
17,
|
||||
0,
|
||||
15,
|
||||
0,
|
||||
"STRING"
|
||||
],
|
||||
[
|
||||
36,
|
||||
4,
|
||||
0,
|
||||
23,
|
||||
0,
|
||||
"IMAGE"
|
||||
],
|
||||
[
|
||||
38,
|
||||
23,
|
||||
0,
|
||||
17,
|
||||
0,
|
||||
"STRING"
|
||||
],
|
||||
[
|
||||
47,
|
||||
24,
|
||||
0,
|
||||
25,
|
||||
0,
|
||||
"IMAGE"
|
||||
],
|
||||
[
|
||||
49,
|
||||
23,
|
||||
5,
|
||||
32,
|
||||
0,
|
||||
"IMAGE"
|
||||
],
|
||||
[
|
||||
50,
|
||||
32,
|
||||
0,
|
||||
33,
|
||||
0,
|
||||
"MASK"
|
||||
],
|
||||
[
|
||||
58,
|
||||
40,
|
||||
0,
|
||||
39,
|
||||
1,
|
||||
"*"
|
||||
],
|
||||
[
|
||||
59,
|
||||
15,
|
||||
0,
|
||||
39,
|
||||
0,
|
||||
"*"
|
||||
],
|
||||
[
|
||||
69,
|
||||
47,
|
||||
0,
|
||||
48,
|
||||
0,
|
||||
"MASK"
|
||||
],
|
||||
[
|
||||
78,
|
||||
39,
|
||||
0,
|
||||
51,
|
||||
0,
|
||||
"*"
|
||||
],
|
||||
[
|
||||
79,
|
||||
32,
|
||||
0,
|
||||
51,
|
||||
1,
|
||||
"*"
|
||||
],
|
||||
[
|
||||
80,
|
||||
47,
|
||||
0,
|
||||
51,
|
||||
2,
|
||||
"*"
|
||||
],
|
||||
[
|
||||
81,
|
||||
51,
|
||||
0,
|
||||
24,
|
||||
1,
|
||||
"MASK"
|
||||
],
|
||||
[
|
||||
82,
|
||||
4,
|
||||
0,
|
||||
52,
|
||||
0,
|
||||
"*"
|
||||
],
|
||||
[
|
||||
83,
|
||||
52,
|
||||
0,
|
||||
24,
|
||||
0,
|
||||
"IMAGE"
|
||||
]
|
||||
],
|
||||
"groups": [],
|
||||
"config": {},
|
||||
"extra": {
|
||||
"ds": {
|
||||
"scale": 0.7513148009015782,
|
||||
"offset": {
|
||||
"0": -256.5145409235732,
|
||||
"1": -365.5770235061039
|
||||
}
|
||||
}
|
||||
},
|
||||
"version": 0.4
|
||||
}
|
||||
@@ -0,0 +1,777 @@
|
||||
{
|
||||
"last_node_id": 41,
|
||||
"last_link_id": 58,
|
||||
"nodes": [
|
||||
{
|
||||
"id": 11,
|
||||
"type": "LayerStyle: DropShadow",
|
||||
"pos": [
|
||||
1364,
|
||||
274
|
||||
],
|
||||
"size": {
|
||||
"0": 315,
|
||||
"1": 266
|
||||
},
|
||||
"flags": {},
|
||||
"order": 11,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "background_image",
|
||||
"type": "IMAGE",
|
||||
"link": 46
|
||||
},
|
||||
{
|
||||
"name": "layer_image",
|
||||
"type": "IMAGE",
|
||||
"link": 28
|
||||
},
|
||||
{
|
||||
"name": "layer_mask",
|
||||
"type": "MASK",
|
||||
"link": null
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "image",
|
||||
"type": "IMAGE",
|
||||
"links": [
|
||||
20
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 0
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "LayerStyle: DropShadow"
|
||||
},
|
||||
"widgets_values": [
|
||||
true,
|
||||
"normal",
|
||||
75,
|
||||
8,
|
||||
8,
|
||||
2,
|
||||
8,
|
||||
"#000000"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 24,
|
||||
"type": "LayerUtility: LaMa",
|
||||
"pos": [
|
||||
833,
|
||||
102
|
||||
],
|
||||
"size": {
|
||||
"0": 315,
|
||||
"1": 174
|
||||
},
|
||||
"flags": {},
|
||||
"order": 8,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "image",
|
||||
"type": "IMAGE",
|
||||
"link": 44
|
||||
},
|
||||
{
|
||||
"name": "mask",
|
||||
"type": "MASK",
|
||||
"link": 56
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "image",
|
||||
"type": "IMAGE",
|
||||
"links": [
|
||||
45,
|
||||
46,
|
||||
47
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 0
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "LayerUtility: LaMa"
|
||||
},
|
||||
"widgets_values": [
|
||||
"lama",
|
||||
"cuda",
|
||||
false,
|
||||
25,
|
||||
6
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 32,
|
||||
"type": "ImageToMask",
|
||||
"pos": [
|
||||
-25.47701164649243,
|
||||
402.810252108054
|
||||
],
|
||||
"size": {
|
||||
"0": 315,
|
||||
"1": 58
|
||||
},
|
||||
"flags": {},
|
||||
"order": 4,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "image",
|
||||
"type": "IMAGE",
|
||||
"link": 49
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "MASK",
|
||||
"type": "MASK",
|
||||
"links": [
|
||||
50,
|
||||
56
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 0
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "ImageToMask"
|
||||
},
|
||||
"widgets_values": [
|
||||
"green"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 33,
|
||||
"type": "MaskPreview+",
|
||||
"pos": [
|
||||
601,
|
||||
267
|
||||
],
|
||||
"size": {
|
||||
"0": 210,
|
||||
"1": 246
|
||||
},
|
||||
"flags": {},
|
||||
"order": 7,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "mask",
|
||||
"type": "MASK",
|
||||
"link": 50
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "MaskPreview+"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 25,
|
||||
"type": "PreviewImage",
|
||||
"pos": [
|
||||
1452,
|
||||
-35
|
||||
],
|
||||
"size": {
|
||||
"0": 210,
|
||||
"1": 246
|
||||
},
|
||||
"flags": {},
|
||||
"order": 10,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "images",
|
||||
"type": "IMAGE",
|
||||
"link": 47
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "PreviewImage"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"type": "PreviewImage",
|
||||
"pos": [
|
||||
1904,
|
||||
273
|
||||
],
|
||||
"size": {
|
||||
"0": 714.4351806640625,
|
||||
"1": 444.59918212890625
|
||||
},
|
||||
"flags": {},
|
||||
"order": 12,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "images",
|
||||
"type": "IMAGE",
|
||||
"link": 20
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "PreviewImage"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 23,
|
||||
"type": "Image OCR By Textract",
|
||||
"pos": [
|
||||
-654,
|
||||
420
|
||||
],
|
||||
"size": {
|
||||
"0": 210,
|
||||
"1": 126
|
||||
},
|
||||
"flags": {},
|
||||
"order": 2,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "image",
|
||||
"type": "IMAGE",
|
||||
"link": 36
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "Text",
|
||||
"type": "STRING",
|
||||
"links": [
|
||||
38
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 0
|
||||
},
|
||||
{
|
||||
"name": "Left",
|
||||
"type": "INT",
|
||||
"links": [
|
||||
39
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 1
|
||||
},
|
||||
{
|
||||
"name": "Top",
|
||||
"type": "INT",
|
||||
"links": [
|
||||
40
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 2
|
||||
},
|
||||
{
|
||||
"name": "Width",
|
||||
"type": "INT",
|
||||
"links": [
|
||||
41
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 3
|
||||
},
|
||||
{
|
||||
"name": "Height",
|
||||
"type": "INT",
|
||||
"links": [
|
||||
42
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 4
|
||||
},
|
||||
{
|
||||
"name": "Mask Image",
|
||||
"type": "IMAGE",
|
||||
"links": [
|
||||
49
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 5
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "Image OCR By Textract"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 15,
|
||||
"type": "Bedrock - Claude",
|
||||
"pos": [
|
||||
305,
|
||||
811
|
||||
],
|
||||
"size": {
|
||||
"0": 400,
|
||||
"1": 200
|
||||
},
|
||||
"flags": {},
|
||||
"order": 5,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "prompt",
|
||||
"type": "STRING",
|
||||
"link": 30,
|
||||
"widget": {
|
||||
"name": "prompt"
|
||||
}
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "STRING",
|
||||
"type": "STRING",
|
||||
"links": [
|
||||
29
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 0
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "Bedrock - Claude"
|
||||
},
|
||||
"widgets_values": [
|
||||
"",
|
||||
"anthropic.claude-3-haiku-20240307-v1:0",
|
||||
2048,
|
||||
1,
|
||||
1,
|
||||
71
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 9,
|
||||
"type": "LayerUtility: SimpleTextImage",
|
||||
"pos": [
|
||||
1316,
|
||||
619
|
||||
],
|
||||
"size": {
|
||||
"0": 392.5400695800781,
|
||||
"1": 406.2833557128906
|
||||
},
|
||||
"flags": {},
|
||||
"order": 9,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "size_as",
|
||||
"type": "*",
|
||||
"link": 45
|
||||
},
|
||||
{
|
||||
"name": "text",
|
||||
"type": "STRING",
|
||||
"link": 29,
|
||||
"widget": {
|
||||
"name": "text"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "x_offset",
|
||||
"type": "INT",
|
||||
"link": 39,
|
||||
"widget": {
|
||||
"name": "x_offset"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "y_offset",
|
||||
"type": "INT",
|
||||
"link": 40,
|
||||
"widget": {
|
||||
"name": "y_offset"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "width",
|
||||
"type": "INT",
|
||||
"link": 41,
|
||||
"widget": {
|
||||
"name": "width"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "height",
|
||||
"type": "INT",
|
||||
"link": 42,
|
||||
"widget": {
|
||||
"name": "height"
|
||||
}
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "image",
|
||||
"type": "IMAGE",
|
||||
"links": [
|
||||
28
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 0
|
||||
},
|
||||
{
|
||||
"name": "mask",
|
||||
"type": "MASK",
|
||||
"links": null,
|
||||
"shape": 3
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "LayerUtility: SimpleTextImage"
|
||||
},
|
||||
"widgets_values": [
|
||||
"Are you going to Scarborough Fair?\nParsley, sage, rosemary, and thyme.\nRemember me to one who lives there,\nShe once was the true love of mine.",
|
||||
"Alibaba-PuHuiTi-Heavy.ttf",
|
||||
"left",
|
||||
80,
|
||||
8,
|
||||
50,
|
||||
"#FFFFFF",
|
||||
0,
|
||||
"#FF8000",
|
||||
0,
|
||||
300,
|
||||
512,
|
||||
512
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 40,
|
||||
"type": "String",
|
||||
"pos": [
|
||||
-99.1735806485697,
|
||||
1134.5376124549446
|
||||
],
|
||||
"size": {
|
||||
"0": 315,
|
||||
"1": 58
|
||||
},
|
||||
"flags": {},
|
||||
"order": 0,
|
||||
"mode": 0,
|
||||
"outputs": [
|
||||
{
|
||||
"name": "STRING",
|
||||
"type": "STRING",
|
||||
"links": [
|
||||
58
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 0
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "String"
|
||||
},
|
||||
"widgets_values": [
|
||||
"浪人"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 39,
|
||||
"type": "Compare",
|
||||
"pos": [
|
||||
306,
|
||||
1091
|
||||
],
|
||||
"size": {
|
||||
"0": 315,
|
||||
"1": 78
|
||||
},
|
||||
"flags": {},
|
||||
"order": 6,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "a",
|
||||
"type": "*",
|
||||
"link": 57
|
||||
},
|
||||
{
|
||||
"name": "b",
|
||||
"type": "*",
|
||||
"link": 58
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "B",
|
||||
"type": "BOOLEAN",
|
||||
"links": null,
|
||||
"shape": 3,
|
||||
"slot_index": 0
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "Compare"
|
||||
},
|
||||
"widgets_values": [
|
||||
"a == b"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"type": "LoadImage",
|
||||
"pos": [
|
||||
-1091,
|
||||
346
|
||||
],
|
||||
"size": {
|
||||
"0": 315,
|
||||
"1": 314
|
||||
},
|
||||
"flags": {},
|
||||
"order": 1,
|
||||
"mode": 0,
|
||||
"outputs": [
|
||||
{
|
||||
"name": "IMAGE",
|
||||
"type": "IMAGE",
|
||||
"links": [
|
||||
36,
|
||||
44
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 0
|
||||
},
|
||||
{
|
||||
"name": "MASK",
|
||||
"type": "MASK",
|
||||
"links": [],
|
||||
"shape": 3,
|
||||
"slot_index": 1
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "LoadImage"
|
||||
},
|
||||
"widgets_values": [
|
||||
"textract_demo005.png",
|
||||
"image"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 17,
|
||||
"type": "Prompt Template",
|
||||
"pos": [
|
||||
-398,
|
||||
661
|
||||
],
|
||||
"size": {
|
||||
"0": 521.4636840820312,
|
||||
"1": 208.76742553710938
|
||||
},
|
||||
"flags": {},
|
||||
"order": 3,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "prompt",
|
||||
"type": "STRING",
|
||||
"link": 38,
|
||||
"widget": {
|
||||
"name": "prompt"
|
||||
}
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "STRING",
|
||||
"type": "STRING",
|
||||
"links": [
|
||||
30,
|
||||
57
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 0
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "Prompt Template"
|
||||
},
|
||||
"widgets_values": [
|
||||
"",
|
||||
"翻译如下英文为日语\n[prompt]\n直接返回翻译后文本"
|
||||
]
|
||||
}
|
||||
],
|
||||
"links": [
|
||||
[
|
||||
20,
|
||||
11,
|
||||
0,
|
||||
2,
|
||||
0,
|
||||
"IMAGE"
|
||||
],
|
||||
[
|
||||
28,
|
||||
9,
|
||||
0,
|
||||
11,
|
||||
1,
|
||||
"IMAGE"
|
||||
],
|
||||
[
|
||||
29,
|
||||
15,
|
||||
0,
|
||||
9,
|
||||
1,
|
||||
"STRING"
|
||||
],
|
||||
[
|
||||
30,
|
||||
17,
|
||||
0,
|
||||
15,
|
||||
0,
|
||||
"STRING"
|
||||
],
|
||||
[
|
||||
36,
|
||||
4,
|
||||
0,
|
||||
23,
|
||||
0,
|
||||
"IMAGE"
|
||||
],
|
||||
[
|
||||
38,
|
||||
23,
|
||||
0,
|
||||
17,
|
||||
0,
|
||||
"STRING"
|
||||
],
|
||||
[
|
||||
39,
|
||||
23,
|
||||
1,
|
||||
9,
|
||||
2,
|
||||
"INT"
|
||||
],
|
||||
[
|
||||
40,
|
||||
23,
|
||||
2,
|
||||
9,
|
||||
3,
|
||||
"INT"
|
||||
],
|
||||
[
|
||||
41,
|
||||
23,
|
||||
3,
|
||||
9,
|
||||
4,
|
||||
"INT"
|
||||
],
|
||||
[
|
||||
42,
|
||||
23,
|
||||
4,
|
||||
9,
|
||||
5,
|
||||
"INT"
|
||||
],
|
||||
[
|
||||
44,
|
||||
4,
|
||||
0,
|
||||
24,
|
||||
0,
|
||||
"IMAGE"
|
||||
],
|
||||
[
|
||||
45,
|
||||
24,
|
||||
0,
|
||||
9,
|
||||
0,
|
||||
"*"
|
||||
],
|
||||
[
|
||||
46,
|
||||
24,
|
||||
0,
|
||||
11,
|
||||
0,
|
||||
"IMAGE"
|
||||
],
|
||||
[
|
||||
47,
|
||||
24,
|
||||
0,
|
||||
25,
|
||||
0,
|
||||
"IMAGE"
|
||||
],
|
||||
[
|
||||
49,
|
||||
23,
|
||||
5,
|
||||
32,
|
||||
0,
|
||||
"IMAGE"
|
||||
],
|
||||
[
|
||||
50,
|
||||
32,
|
||||
0,
|
||||
33,
|
||||
0,
|
||||
"MASK"
|
||||
],
|
||||
[
|
||||
56,
|
||||
32,
|
||||
0,
|
||||
24,
|
||||
1,
|
||||
"MASK"
|
||||
],
|
||||
[
|
||||
57,
|
||||
17,
|
||||
0,
|
||||
39,
|
||||
0,
|
||||
"*"
|
||||
],
|
||||
[
|
||||
58,
|
||||
40,
|
||||
0,
|
||||
39,
|
||||
1,
|
||||
"*"
|
||||
]
|
||||
],
|
||||
"groups": [],
|
||||
"config": {},
|
||||
"extra": {
|
||||
"ds": {
|
||||
"scale": 1.1000000000000005,
|
||||
"offset": {
|
||||
"0": 986.1125011031153,
|
||||
"1": -372.55607836403607
|
||||
}
|
||||
}
|
||||
},
|
||||
"version": 0.4
|
||||
}
|
||||
Reference in New Issue
Block a user