load image from path, branding

This commit is contained in:
RyanOnTheInside
2025-01-29 16:29:03 -05:00
parent 4a7676f687
commit 172f191b45
2 changed files with 66 additions and 28 deletions
+21 -25
View File
@@ -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
View File
@@ -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)