load image from path, branding
This commit is contained in:
+21
-25
@@ -2,7 +2,9 @@ from .controls.value_controls import FloatControl, IntControl, StringControl
|
||||
from .controls.sequence_controls import FloatSequence, IntSequence, StringSequence
|
||||
from .controls.utility_controls import FPSMonitor, SimilarityFilter, LazyCondition
|
||||
from .controls.motion_controls import MotionController, ROINode, IntegerMotionController
|
||||
from .misc_nodes import DTypeConverter, FastWebcamCapture, YOLOSimilarityCompare, TextRenderer, QuickShapeMask, MultilineText
|
||||
from .misc_nodes import DTypeConverter, FastWebcamCapture, YOLOSimilarityCompare, TextRenderer, QuickShapeMask, MultilineText, LoadImageFromPath_
|
||||
|
||||
import re
|
||||
|
||||
NODE_CLASS_MAPPINGS = {
|
||||
"FloatControl": FloatControl,
|
||||
@@ -25,32 +27,26 @@ NODE_CLASS_MAPPINGS = {
|
||||
"DTypeConverter": DTypeConverter,
|
||||
"FastWebcamCapture": FastWebcamCapture,
|
||||
"MultilineText": MultilineText,
|
||||
"LoadImageFromPath_": LoadImageFromPath_,
|
||||
}
|
||||
|
||||
NODE_DISPLAY_NAME_MAPPINGS = {
|
||||
"FloatControl": "Float Control (RyanOnTheInside)",
|
||||
"IntControl": "Int Control (RyanOnTheInside)",
|
||||
"StringControl": "String Control (RyanOnTheInside)",
|
||||
"FloatSequence": "Float Sequence (RyanOnTheInside)",
|
||||
"IntSequence": "Int Sequence (RyanOnTheInside)",
|
||||
"StringSequence": "String Sequence (RyanOnTheInside)",
|
||||
"FPSMonitor": "FPS Monitor (RyanOnTheInside)",
|
||||
"MotionController": "Float Motion Controller (RyanOnTheInside)",
|
||||
"ROINode": "ROI Node (RyanOnTheInside)",
|
||||
"IntegerMotionController": "Integer Motion Controller (RyanOnTheInside)",
|
||||
#"IntervalControl": "Interval Control (RyanOnTheInside)",
|
||||
#"DeltaControl": "Delta Control (RyanOnTheInside)",
|
||||
"QuickShapeMask": "Quick Shape Mask (RyanOnTheInside)",
|
||||
"TAESDVaeEncode": "TAESD VAE Encode (RyanOnTheInside)",
|
||||
"TAESDVaeDecode": "TAESD VAE Decode (RyanOnTheInside)",
|
||||
"DTypeConverter": "DType Converter (RyanOnTheInside)",
|
||||
"FastWebcamCapture": "Fast Webcam Capture (RyanOnTheInside)",
|
||||
"SimilarityFilter": "Similarity Filter (RyanOnTheInside)",
|
||||
"LazyCondition": "Lazy Condition (RyanOnTheInside)",
|
||||
"YOLOSimilarityCompare": "YOLO Similarity Compare (RyanOnTheInside)",
|
||||
"TextRenderer": "Text Renderer (RyanOnTheInside)",
|
||||
"MultilineText": "Multiline Text (RyanOnTheInside)",
|
||||
}
|
||||
NODE_DISPLAY_NAME_MAPPINGS = {}
|
||||
|
||||
suffix = " 🕒🅡🅣🅝"
|
||||
|
||||
for node_name in NODE_CLASS_MAPPINGS.keys():
|
||||
# Convert camelCase or snake_case to Title Case
|
||||
if node_name not in NODE_DISPLAY_NAME_MAPPINGS:
|
||||
display_name = ' '.join(word.capitalize() for word in re.findall(r'[A-Z]?[a-z]+|[A-Z]+(?=[A-Z][a-z]|\d|\W|$)|\d+', node_name))
|
||||
else:
|
||||
display_name = NODE_DISPLAY_NAME_MAPPINGS[node_name]
|
||||
|
||||
# Add the suffix if it's not already present
|
||||
if not display_name.endswith(suffix):
|
||||
display_name += suffix
|
||||
|
||||
# Assign the final display name to the mappings
|
||||
NODE_DISPLAY_NAME_MAPPINGS[node_name] = display_name
|
||||
|
||||
|
||||
WEB_DIRECTORY = "./web/js"
|
||||
|
||||
+45
-3
@@ -4,7 +4,7 @@ import numpy as np
|
||||
import base64
|
||||
import re
|
||||
from io import BytesIO
|
||||
from PIL import Image, ImageFont, ImageDraw
|
||||
from PIL import Image, ImageFont, ImageDraw, ImageOps
|
||||
import nodes
|
||||
import random
|
||||
from torchvision import transforms
|
||||
@@ -408,7 +408,7 @@ class TextRenderer:
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"any": (AlwaysEqualProxy(), {"multiline": True}), # Accept any input type and convert to string
|
||||
"any": (AlwaysEqualProxy("*"),), # Accept any input type and convert to string
|
||||
"width": ("INT", {"default": 512, "min": 64, "max": MAX_RESOLUTION, "step": 8}),
|
||||
"height": ("INT", {"default": 512, "min": 64, "max": MAX_RESOLUTION, "step": 8}),
|
||||
"font_size": ("INT", {"default": 48, "min": 1, "max": 512, "step": 1}),
|
||||
@@ -424,7 +424,7 @@ class TextRenderer:
|
||||
|
||||
RETURN_TYPES = ("IMAGE", "MASK")
|
||||
FUNCTION = "render_text"
|
||||
CATEGORY = "image"
|
||||
CATEGORY = "real-time"
|
||||
|
||||
def render_text(self, any, width, height, font_size, font_color, background_color,
|
||||
x_offset, y_offset, align, wrap_width):
|
||||
@@ -530,4 +530,46 @@ class MultilineText:
|
||||
result = '\n'.join(lines)
|
||||
|
||||
return (result,)
|
||||
|
||||
class LoadImageFromPath_:
|
||||
"""A simple node that loads an image from a given file path"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {"required": {
|
||||
"image_path": ("STRING", {
|
||||
"default": "",
|
||||
"multiline": False,
|
||||
"tooltip": "Full path to the image file to load"
|
||||
})
|
||||
}}
|
||||
|
||||
RETURN_TYPES = ("IMAGE", "MASK")
|
||||
FUNCTION = "load_image"
|
||||
CATEGORY = "image"
|
||||
|
||||
def load_image(self, image_path):
|
||||
# Open and process the image
|
||||
img = Image.open(image_path)
|
||||
img = ImageOps.exif_transpose(img)
|
||||
|
||||
# Convert to RGB if needed
|
||||
if img.mode == 'I':
|
||||
img = img.point(lambda i: i * (1 / 255))
|
||||
image = img.convert("RGB")
|
||||
|
||||
# Convert to tensor
|
||||
image = np.array(image).astype(np.float32) / 255.0
|
||||
image = torch.from_numpy(image)[None,]
|
||||
|
||||
# Create mask from alpha channel if it exists
|
||||
if 'A' in img.getbands():
|
||||
mask = np.array(img.getchannel('A')).astype(np.float32) / 255.0
|
||||
mask = 1. - torch.from_numpy(mask)
|
||||
else:
|
||||
mask = torch.zeros((64,64), dtype=torch.float32, device="cpu")
|
||||
|
||||
mask = mask.unsqueeze(0)
|
||||
|
||||
return (image, mask)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user