mirror of
https://github.com/tusharbhutt/Endless-Nodes.git
synced 2026-03-24 21:52:12 -03:00
Add files via upload
This commit is contained in:
@@ -195,4 +195,3 @@ These nodes may or may not be maintained. They work on my system but may not on
|
|||||||
+[Mikey nodes](https://github.com/bash-j/mikey_nodes )to grab code snippet to pass scoring metadata to image
|
+[Mikey nodes](https://github.com/bash-j/mikey_nodes )to grab code snippet to pass scoring metadata to image
|
||||||
|
|
||||||
# Took some base code from the [WAS save image node](https://github.com/WASasquatch/was-node-suite-comfyui) to repurpose it
|
# Took some base code from the [WAS save image node](https://github.com/WASasquatch/was-node-suite-comfyui) to repurpose it
|
||||||
|
|
||||||
|
|||||||
29
__init__.py
29
__init__.py
@@ -1,8 +1,8 @@
|
|||||||
"""
|
"""
|
||||||
@author: BiffMunky
|
@author: BiffMunky
|
||||||
@title: 🌌 An Endless Sea of Stars Nodes 🌌
|
@title: Endless ️🌊🌠 Node 🌌
|
||||||
@nickname: 🌌 Endless Nodes 🌌
|
@nickname: ♾️🌊🌠
|
||||||
@description: A small set of nodes I created for various numerical and text inputs. Features switches for text and numbers, parameter collection nodes, and two aesthetic scoring modwls.
|
@description: A small set of nodes I created for various numerical and text inputs. Features switches for text and numbers, parameter collection nodes, and two aesthetic scoring models.
|
||||||
"""
|
"""
|
||||||
from .endless_nodes import *
|
from .endless_nodes import *
|
||||||
|
|
||||||
@@ -15,16 +15,27 @@ NODE_CLASS_MAPPINGS = {
|
|||||||
"Endless Nodes Parameterizer & Prompts": EndlessNode_XLParameterizerPrompt,
|
"Endless Nodes Parameterizer & Prompts": EndlessNode_XLParameterizerPrompt,
|
||||||
"Endless Nodes Combo Parameterizer": EndlessNode_ComboXLParameterizer,
|
"Endless Nodes Combo Parameterizer": EndlessNode_ComboXLParameterizer,
|
||||||
"Endless Nodes Combo Parameterizer & Prompts": EndlessNode_ComboXLParameterizerPrompt,
|
"Endless Nodes Combo Parameterizer & Prompts": EndlessNode_ComboXLParameterizerPrompt,
|
||||||
#"Endless Nodes Image Save with Text File": EndlessNode_ImageSaver,
|
"Endless Nodes Image Save with Text File": EndlessNode_ImageSaver,
|
||||||
# "Endless Nodes Display String": EndlessNode_DisplayString,
|
|
||||||
# "Endless Nodes Display Number": EndlessNode_DisplayNumber,
|
|
||||||
# "Endless Nodes Display Integer": EndlessNode_DisplayInt,
|
|
||||||
# "Endless Nodes Display Float": EndlessNode_DisplayFloat,
|
|
||||||
"Endless Nodes Aesthetic Scoring": EndlessNode_Scoring,
|
"Endless Nodes Aesthetic Scoring": EndlessNode_Scoring,
|
||||||
|
"Endless Nodes Aesthetic Scoring Auto": EndlessNode_ScoringAutoScore,
|
||||||
"Endless Nodes Image Reward": EndlessNode_ImageReward,
|
"Endless Nodes Image Reward": EndlessNode_ImageReward,
|
||||||
|
"Endless Nodes Image Reward Auto": EndlessNode_ImageRewardAutoScore,
|
||||||
|
"Endless Nodes Float to Integer": EndlessNode_FloattoInt,
|
||||||
|
"Endless Nodes Float to Number": EndlessNode_FloattoNum,
|
||||||
|
"Endless Nodes Float to String": EndlessNode_FloattoString,
|
||||||
|
"Endless Nodes Number to Float": EndlessNode_NumtoFloat,
|
||||||
|
"Endless Nodes Number to Integer": EndlessNode_NumtoInt,
|
||||||
|
"Endless Nodes Number to String": EndlessNode_NumtoString,
|
||||||
|
"Endless Nodes Integer to Float": EndlessNode_InttoFloat,
|
||||||
|
"Endless Nodes Integer to Number": EndlessNode_InttoNum,
|
||||||
|
"Endless Nodes Integer to String": EndlessNode_InttoString,
|
||||||
|
"Endless Nodes Float to X": EndlessNode_FloattoX,
|
||||||
|
"Endless Nodes Integer to X": EndlessNode_InttoX,
|
||||||
|
"Endless Nodes Number to X": EndlessNode_NumtoX,
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
__all__ = ['NODE_CLASS_MAPPINGS']
|
__all__ = ['NODE_CLASS_MAPPINGS']
|
||||||
|
|
||||||
print("\033[36m 🌌 An Endless Sea of Stars Custom Nodes 🌌 V0.24 \033[34m: \033[92mLoaded\033[0m")
|
print("\033[36m 🌌 An Endless Sea of Stars Custom Nodes 🌌 \033[33mreV0.28 \033[34m: \033[92mLoaded\033[0m")
|
||||||
@@ -1,3 +1,8 @@
|
|||||||
|
Oct 3/23: 0.29- Save Image module added, saves images and JSON to separate folder if requested
|
||||||
|
Sep 28/23: 0.28 - Unreleased - Added Variable types to X
|
||||||
|
Sep 28/23: 0.27 - Unreleased - Corrected scoring nodes to actually add the value of the score into the image metadata .... still goobered!
|
||||||
|
Sep 24/23: 0.26 - Unreleased - starting to correct scoring to get to image metadata
|
||||||
|
Sep 24/23: 0.25 - Added various X to String Nodes
|
||||||
Sep 24/23: 0.24 - Added In Image Reward scoring model with a single node to load model and output standard deviation and scoring via number or string nodes
|
Sep 24/23: 0.24 - Added In Image Reward scoring model with a single node to load model and output standard deviation and scoring via number or string nodes
|
||||||
Sep 24/23: 0.23 - Rework Aesthetic Score model and integrate it into single node to display score, added a requirements file
|
Sep 24/23: 0.23 - Rework Aesthetic Score model and integrate it into single node to display score, added a requirements file
|
||||||
Sep 23/23: 0.22 - Unreleased, convert ImageReward output to base ten score
|
Sep 23/23: 0.22 - Unreleased, convert ImageReward output to base ten score
|
||||||
|
|||||||
718
endless_nodes.py
718
endless_nodes.py
@@ -1,30 +1,40 @@
|
|||||||
"""
|
"""
|
||||||
@author: BiffMunky
|
@author: BiffMunky
|
||||||
@title: 🌌 An Endless Sea of Stars Nodes 🌌
|
@title: 🌌 An Endless Sea of Stars Node 🌌
|
||||||
@nickname: 🌌 Endless Nodes 🌌
|
@nickname: 🌌 Endless Nodes 🌌
|
||||||
@description: A small set of nodes I created for various numerical and text inputs. Features switches for text and numbers, parameter collection nodes, and two aesthetic scoring modwls.
|
@description: A small set of nodes I created for various numerical and text inputs. Features switches for text and numbers, parameter collection nodes, and two aesthetic scoring models.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Version 0.24 - Imagr Rearwd nodeaddeded
|
#0.29 - Save Image module added, saves images and JSON to separate folder if requested
|
||||||
#0.23 - Aesthetic Scorer addeded
|
#0.28 - Unreleased - Added Variable types to X
|
||||||
#0.22 Unreleased - intro'd asestheic score
|
#0.27 - Unreleased - Corrected scoring nodes to actually add the value of the score into the image metadata .... still goobered!
|
||||||
|
#0.26 - Unreleased - starting to correct scoring to get to image metadata
|
||||||
|
#0.25 - Added various X to String Nodes
|
||||||
|
#0.24 - Image reward node added
|
||||||
|
#0.23 - Aesthetic Scorer added
|
||||||
|
#0.22 Unreleased - intro'd aestheticscore
|
||||||
#0.21 unreleased -- trying for display nodes
|
#0.21 unreleased -- trying for display nodes
|
||||||
#0.20 sorted categories of nodes
|
#0.20 sorted categories of nodes
|
||||||
|
|
||||||
#--------------------------------------
|
#----------------------------------------------
|
||||||
# Endless Sea of Stars Custom Node Collection
|
# Endless Sea of Stars Custom Node Collection
|
||||||
#https://github.com/tusharbhutt/Endless-Nodes
|
#https://github.com/tusharbhutt/Endless-Nodes
|
||||||
|
#----------------------------------------------
|
||||||
#
|
#
|
||||||
#
|
#______________________________________________________________________________________________________________________________________________________________
|
||||||
|
# IMPORT MODULES BLOCK #
|
||||||
|
|
||||||
#import torch
|
|
||||||
|
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
from PIL.PngImagePlugin import PngInfo
|
from PIL.PngImagePlugin import PngInfo
|
||||||
|
from colorama import init, Fore, Back, Style
|
||||||
from os.path import join
|
from os.path import join
|
||||||
from warnings import filterwarnings
|
from warnings import filterwarnings
|
||||||
|
import ImageReward as RM
|
||||||
import clip
|
import clip
|
||||||
|
import colorama
|
||||||
import datetime
|
import datetime
|
||||||
|
import folder_paths as endless_paths
|
||||||
import io
|
import io
|
||||||
import json
|
import json
|
||||||
import math
|
import math
|
||||||
@@ -32,24 +42,30 @@ import numpy as np
|
|||||||
import os
|
import os
|
||||||
import pytorch_lightning as pl
|
import pytorch_lightning as pl
|
||||||
import re
|
import re
|
||||||
import sys
|
import socket
|
||||||
import statistics
|
import statistics
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
import torch
|
import torch
|
||||||
import torch.nn as nn
|
import torch.nn as nn
|
||||||
import ImageReward as RM
|
|
||||||
|
|
||||||
|
|
||||||
sys.path.insert(0, os.path.join(os.path.dirname(os.path.realpath(__file__)), "comfy"))
|
sys.path.insert(0, os.path.join(os.path.dirname(os.path.realpath(__file__)), "comfy"))
|
||||||
|
|
||||||
import comfy.sd
|
import comfy.sd
|
||||||
import comfy.utils
|
import comfy.utils
|
||||||
|
#import folder_paths
|
||||||
import folder_paths
|
|
||||||
import typing as tg
|
import typing as tg
|
||||||
|
|
||||||
#--------------------------------------
|
|
||||||
#Six Text Input Node for selection
|
|
||||||
|
|
||||||
|
# Initialize colorama for colored text
|
||||||
|
colorama.init(autoreset=True)
|
||||||
|
|
||||||
|
#______________________________________________________________________________________________________________________________________________________________
|
||||||
|
# "SWITCHES" BLOCK #
|
||||||
|
|
||||||
|
#----------------------------------------------
|
||||||
|
# Six Text Input Node for selection
|
||||||
|
|
||||||
class EndlessNode_SixTextInputSwitch:
|
class EndlessNode_SixTextInputSwitch:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
@@ -93,7 +109,8 @@ class EndlessNode_SixTextInputSwitch:
|
|||||||
else:
|
else:
|
||||||
return (text6,)
|
return (text6,)
|
||||||
|
|
||||||
#Eight Text Input Node for selection (needed more slots, what can I say)
|
#----------------------------------------------
|
||||||
|
# Eight Text Input Node for selection (needed more slots, what can I say)
|
||||||
|
|
||||||
|
|
||||||
class EndlessNode_EightTextInputSwitch:
|
class EndlessNode_EightTextInputSwitch:
|
||||||
@@ -144,8 +161,8 @@ class EndlessNode_EightTextInputSwitch:
|
|||||||
else:
|
else:
|
||||||
return (text8,)
|
return (text8,)
|
||||||
|
|
||||||
#--------------------------------------
|
#----------------------------------------------
|
||||||
##Six Integer Input and Output via connectors
|
# Six Integer Input and Output via connectors
|
||||||
|
|
||||||
|
|
||||||
class EndlessNode_SixIntIOSwitch:
|
class EndlessNode_SixIntIOSwitch:
|
||||||
@@ -176,20 +193,20 @@ class EndlessNode_SixIntIOSwitch:
|
|||||||
def six_intIO_switch(self, Input, INT1=0, INT2=0, INT3=0, INT4=0, INT5=0, INT6=0):
|
def six_intIO_switch(self, Input, INT1=0, INT2=0, INT3=0, INT4=0, INT5=0, INT6=0):
|
||||||
|
|
||||||
if Input == 1:
|
if Input == 1:
|
||||||
return (INT1, )
|
return (INT1,)
|
||||||
elif Input == 2:
|
elif Input == 2:
|
||||||
return (INT2, )
|
return (INT2,)
|
||||||
elif Input == 3:
|
elif Input == 3:
|
||||||
return (INT3, )
|
return (INT3,)
|
||||||
elif Input == 4:
|
elif Input == 4:
|
||||||
return (INT4, )
|
return (INT4,)
|
||||||
elif Input == 5:
|
elif Input == 5:
|
||||||
return (INT5, )
|
return (INT5,)
|
||||||
else:
|
else:
|
||||||
return (INT6, )
|
return (INT6,)
|
||||||
|
|
||||||
#--------------------------------------
|
#----------------------------------------------
|
||||||
##Six Integer Input and Output by Widget
|
# Six Integer Input and Output by Widget
|
||||||
|
|
||||||
class EndlessNode_SixIntIOWidget:
|
class EndlessNode_SixIntIOWidget:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
@@ -219,7 +236,12 @@ class EndlessNode_SixIntIOWidget:
|
|||||||
def six_int_widget(self,int1,int2,int3,int4,int5,int6):
|
def six_int_widget(self,int1,int2,int3,int4,int5,int6):
|
||||||
return(int1,int2,int3,int4,int5,int6)
|
return(int1,int2,int3,int4,int5,int6)
|
||||||
|
|
||||||
#Text Encode Combo Box with prompt
|
|
||||||
|
#______________________________________________________________________________________________________________________________________________________________
|
||||||
|
# PARAMETERS BLOCK #
|
||||||
|
|
||||||
|
#----------------------------------------------
|
||||||
|
# Text Encode Combo Box with prompt
|
||||||
|
|
||||||
class EndlessNode_XLParameterizerPrompt:
|
class EndlessNode_XLParameterizerPrompt:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
@@ -255,7 +277,8 @@ class EndlessNode_XLParameterizerPrompt:
|
|||||||
def ParameterizerPrompt(self,base_width,base_height,base_crop_w,base_crop_h,base_target_w,base_target_h,refiner_width,refiner_height,refiner_ascore,endlessG,endlessL):
|
def ParameterizerPrompt(self,base_width,base_height,base_crop_w,base_crop_h,base_target_w,base_target_h,refiner_width,refiner_height,refiner_ascore,endlessG,endlessL):
|
||||||
return(base_width,base_height,base_crop_w,base_crop_h,base_target_w,base_target_h,refiner_width,refiner_height,refiner_ascore,endlessG,endlessL)
|
return(base_width,base_height,base_crop_w,base_crop_h,base_target_w,base_target_h,refiner_width,refiner_height,refiner_ascore,endlessG,endlessL)
|
||||||
|
|
||||||
# CLIP tect encodee box without prompt
|
#----------------------------------------------
|
||||||
|
# CLIP text encode box without prompt
|
||||||
|
|
||||||
class EndlessNode_XLParameterizer:
|
class EndlessNode_XLParameterizer:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
@@ -286,8 +309,8 @@ class EndlessNode_XLParameterizer:
|
|||||||
def Parameterizer(self,base_width,base_height,base_crop_w,base_crop_h,base_target_w,base_target_h,refiner_width,refiner_height,refiner_ascore):
|
def Parameterizer(self,base_width,base_height,base_crop_w,base_crop_h,base_target_w,base_target_h,refiner_width,refiner_height,refiner_ascore):
|
||||||
return(base_width,base_height,base_crop_w,base_crop_h,base_target_w,base_target_h,refiner_width,refiner_height,refiner_ascore)
|
return(base_width,base_height,base_crop_w,base_crop_h,base_target_w,base_target_h,refiner_width,refiner_height,refiner_ascore)
|
||||||
|
|
||||||
|
#----------------------------------------------
|
||||||
#Text Encode Combo Box with prompt
|
# Text Encode Combo Box with prompt
|
||||||
|
|
||||||
class EndlessNode_ComboXLParameterizerPrompt:
|
class EndlessNode_ComboXLParameterizerPrompt:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
@@ -326,7 +349,8 @@ class EndlessNode_ComboXLParameterizerPrompt:
|
|||||||
def ComboParameterizerPrompt(self,base_width,base_height,base_crop_w,base_crop_h,base_target_w,base_target_h,refiner_width,refiner_height,refiner_pascore,refiner_nascore,PendlessG,PendlessL,NendlessG,NendlessL):
|
def ComboParameterizerPrompt(self,base_width,base_height,base_crop_w,base_crop_h,base_target_w,base_target_h,refiner_width,refiner_height,refiner_pascore,refiner_nascore,PendlessG,PendlessL,NendlessG,NendlessL):
|
||||||
return(base_width,base_height,base_crop_w,base_crop_h,base_target_w,base_target_h,refiner_width,refiner_height,refiner_pascore,refiner_nascore,PendlessG,PendlessL,NendlessG,NendlessL)
|
return(base_width,base_height,base_crop_w,base_crop_h,base_target_w,base_target_h,refiner_width,refiner_height,refiner_pascore,refiner_nascore,PendlessG,PendlessL,NendlessG,NendlessL)
|
||||||
|
|
||||||
# CLIP text encode box without prompt, COMBO that allows one box for both pos/neg parameters to be fed to CLIP text, with separate POS/NEG Aestheticscore
|
#----------------------------------------------
|
||||||
|
# CLIP text encode box without prompt, COMBO that allows one box for both pos/neg parameters to be fed to CLIP text, with separate POS/NEG Aesthetic score
|
||||||
|
|
||||||
class EndlessNode_ComboXLParameterizer:
|
class EndlessNode_ComboXLParameterizer:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
@@ -358,9 +382,11 @@ class EndlessNode_ComboXLParameterizer:
|
|||||||
def ComboParameterizer(self,base_width,base_height,base_crop_w,base_crop_h,base_target_w,base_target_h,refiner_width,refiner_height,refiner_pascore, refiner_nascore):
|
def ComboParameterizer(self,base_width,base_height,base_crop_w,base_crop_h,base_target_w,base_target_h,refiner_width,refiner_height,refiner_pascore, refiner_nascore):
|
||||||
return(base_width,base_height,base_crop_w,base_crop_h,base_target_w,base_target_h,refiner_width,refiner_height,refiner_pascore, refiner_nascore)
|
return(base_width,base_height,base_crop_w,base_crop_h,base_target_w,base_target_h,refiner_width,refiner_height,refiner_pascore, refiner_nascore)
|
||||||
|
|
||||||
|
#______________________________________________________________________________________________________________________________________________________________
|
||||||
|
# IMAGE SCORING BLOCK #
|
||||||
|
|
||||||
#--------------------------------------
|
#----------------------------------------------
|
||||||
## Aesthetic Scoring Type One
|
# Aesthetic Scoring Node
|
||||||
|
|
||||||
folder_paths.folder_names_and_paths["aesthetic"] = ([os.path.join(folder_paths.models_dir,"aesthetic")], folder_paths.supported_pt_extensions)
|
folder_paths.folder_names_and_paths["aesthetic"] = ([os.path.join(folder_paths.models_dir,"aesthetic")], folder_paths.supported_pt_extensions)
|
||||||
|
|
||||||
@@ -422,7 +448,7 @@ class EndlessNode_Scoring:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RETURN_TYPES = ("NUM",)
|
RETURN_TYPES = ("NUMBER","IMAGE")
|
||||||
FUNCTION = "calc_score"
|
FUNCTION = "calc_score"
|
||||||
CATEGORY = "Endless 🌌/Scoring"
|
CATEGORY = "Endless 🌌/Scoring"
|
||||||
|
|
||||||
@@ -442,13 +468,59 @@ class EndlessNode_Scoring:
|
|||||||
image2 = preprocess(pil_image).unsqueeze(0).to(device)
|
image2 = preprocess(pil_image).unsqueeze(0).to(device)
|
||||||
with torch.no_grad():
|
with torch.no_grad():
|
||||||
image_features = model2.encode_image(image2)
|
image_features = model2.encode_image(image2)
|
||||||
im_emb_arr = normalized(image_features.cpu().detach().numpy() )
|
im_emb_arr = normalized(image_features.cpu().detach().numpy())
|
||||||
prediction = model(torch.from_numpy(im_emb_arr).to(device).type(torch.cuda.FloatTensor))
|
prediction = model(torch.from_numpy(im_emb_arr).to(device).type(torch.cuda.FloatTensor))
|
||||||
final_prediction = round(float(prediction[0]), 2)
|
final_prediction = round(float(prediction[0]), 2)
|
||||||
del model
|
del model
|
||||||
return (final_prediction,)
|
return (final_prediction,)
|
||||||
|
|
||||||
|
# #---------------------------------------------- NOT WORKING, NEED TO LOOK AT IT
|
||||||
|
# # Aesthetic Scoring Node with Scoring passed to image
|
||||||
|
|
||||||
|
# class EndlessNode_ScoringAutoScore:
|
||||||
|
# def __init__(self):
|
||||||
|
# pass
|
||||||
|
|
||||||
|
# @classmethod
|
||||||
|
# def INPUT_TYPES(cls):
|
||||||
|
# return {
|
||||||
|
# "required": {
|
||||||
|
# "model_name": (folder_paths.get_filename_list("aesthetic"), {"multiline": False, "default": "chadscorer.pth"}),
|
||||||
|
# "image": ("IMAGE",),
|
||||||
|
# }
|
||||||
|
# }
|
||||||
|
|
||||||
|
# RETURN_TYPES = ("NUMBER","IMAGE")
|
||||||
|
# FUNCTION = "calc_score"
|
||||||
|
# OUTPUT_NODE = True
|
||||||
|
# CATEGORY = "Endless 🌌/Scoring"
|
||||||
|
|
||||||
|
# def calc_score(self, model_name, image):
|
||||||
|
# m_path = folder_paths.folder_names_and_paths["aesthetic"][0]
|
||||||
|
# m_path2 = os.path.join(m_path[0], model_name)
|
||||||
|
# model = MLP(768) # CLIP embedding dim is 768 for CLIP ViT L 14
|
||||||
|
# s = torch.load(m_path2)
|
||||||
|
# model.load_state_dict(s)
|
||||||
|
# model.to("cuda")
|
||||||
|
# model.eval()
|
||||||
|
# device = "cuda"
|
||||||
|
# model2, preprocess = clip.load("ViT-L/14", device=device) # RN50x64
|
||||||
|
# tensor_image = image[0]
|
||||||
|
# img = (tensor_image * 255).to(torch.uint8).numpy()
|
||||||
|
# pil_image = Image.fromarray(img, mode='RGB')
|
||||||
|
# image2 = preprocess(pil_image).unsqueeze(0).to(device)
|
||||||
|
# with torch.no_grad():
|
||||||
|
# image_features = model2.encode_image(image2)
|
||||||
|
# im_emb_arr = normalized(image_features.cpu().detach().numpy())
|
||||||
|
# prediction = model(torch.from_numpy(im_emb_arr).to(device).type(torch.cuda.FloatTensor))
|
||||||
|
# final_prediction = round(float(prediction[0]), 2)
|
||||||
|
# del model
|
||||||
|
# # Metadata part
|
||||||
|
# extra_pnginfo = {"SCORE": str(final_prediction)}
|
||||||
|
# return (final_prediction, image)
|
||||||
|
|
||||||
|
#----------------------------------------------
|
||||||
|
# Image Reward Scoring
|
||||||
|
|
||||||
class EndlessNode_ImageReward:
|
class EndlessNode_ImageReward:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
@@ -461,13 +533,11 @@ class EndlessNode_ImageReward:
|
|||||||
"model": ("STRING", {"multiline": False, "default": "ImageReward-v1.0"}),
|
"model": ("STRING", {"multiline": False, "default": "ImageReward-v1.0"}),
|
||||||
"prompt": ("STRING", {"multiline": True, "forceInput": True}),
|
"prompt": ("STRING", {"multiline": True, "forceInput": True}),
|
||||||
"images": ("IMAGE",),
|
"images": ("IMAGE",),
|
||||||
# "rounded": ("BOOL", {"default": False}) # Add a boolean input
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
RETURN_TYPES = ("FLOAT", "STRING", "FLOAT", "STRING")
|
RETURN_TYPES = ("FLOAT", "STRING", "FLOAT", "STRING")
|
||||||
RETURN_NAMES = ("SCORE_FLOAT", "SCORE_STRING", "VALUE_FLOAT", "VALUE_STRING")
|
RETURN_NAMES = ("SCORE_FLOAT", "SCORE_STRING", "VALUE_FLOAT", "VALUE_STRING")
|
||||||
OUTPUT_NODE = False
|
|
||||||
|
|
||||||
CATEGORY = "Endless 🌌/Scoring"
|
CATEGORY = "Endless 🌌/Scoring"
|
||||||
|
|
||||||
@@ -484,120 +554,510 @@ class EndlessNode_ImageReward:
|
|||||||
img = Image.fromarray(np.clip(i, 0, 255).astype(np.uint8))
|
img = Image.fromarray(np.clip(i, 0, 255).astype(np.uint8))
|
||||||
score += self.model.score(prompt, [img])
|
score += self.model.score(prompt, [img])
|
||||||
score /= len(images)
|
score /= len(images)
|
||||||
|
|
||||||
# if rounded:
|
|
||||||
# # Round the score to two decimal places
|
|
||||||
# score = round(score, 2)
|
|
||||||
|
|
||||||
# assume std dev follows normal distribution curve
|
# assume std dev follows normal distribution curve
|
||||||
valuescale = 0.5 * (1 + math.erf(score / math.sqrt(2))) * 10 # *10 to get a value between -10
|
valuescale = 0.5 * (1 + math.erf(score / math.sqrt(2))) * 10 # *10 to get a value between -10
|
||||||
return (score, str(score), valuescale, str(valuescale))
|
return (score, str(score), valuescale, str(valuescale))
|
||||||
|
|
||||||
|
|
||||||
# ##test of image saver ##
|
# #---------------------------------------------- NOT WORKING, NEED TO LOOK AT
|
||||||
|
# # Image Reward Scoring with score passed to image
|
||||||
|
|
||||||
|
# class EndlessNode_ImageRewardAutoScore:
|
||||||
# class EndlessNode_ImageSaver:
|
|
||||||
# def __init__(self):
|
# def __init__(self):
|
||||||
# self.output_dir = folder_paths.get_output_directory()
|
# self.model = None
|
||||||
# self.type = "output"
|
|
||||||
|
|
||||||
# @classmethod
|
# @classmethod
|
||||||
# def INPUT_TYPES(cls):
|
# def INPUT_TYPES(cls):
|
||||||
# return {
|
# return {
|
||||||
# "required": {
|
# "required": {
|
||||||
|
# "model": ("STRING", {"multiline": False, "default": "ImageReward-v1.0"}),
|
||||||
|
# "prompt": ("STRING", {"multiline": True, "forceInput": True}),
|
||||||
# "images": ("IMAGE",),
|
# "images": ("IMAGE",),
|
||||||
# "filename_prefix": ("STRING", {"default": "ComfyUI"}),
|
|
||||||
# "subfolder": ("STRING", {"default": None}), # Add subfolder input
|
|
||||||
# },
|
|
||||||
# "hidden": {
|
|
||||||
# "prompt": "PROMPT", "extra_pnginfo": "EXTRA_PNGINFO"
|
|
||||||
# },
|
# },
|
||||||
# }
|
# }
|
||||||
|
|
||||||
# RETURN_TYPES = ()
|
# RETURN_TYPES = ("FLOAT", "STRING", "FLOAT", "STRING", "IMAGE")
|
||||||
# FUNCTION = "save_images"
|
# RETURN_NAMES = ("SCORE_FLOAT", "SCORE_STRING", "VALUE_FLOAT", "VALUE_STRING", "TO_IMAGE")
|
||||||
|
|
||||||
# OUTPUT_NODE = True
|
# OUTPUT_NODE = True
|
||||||
|
|
||||||
# CATEGORY = "Endless 🌌/IO"
|
# CATEGORY = "Endless 🌌/Scoring"
|
||||||
|
|
||||||
# def save_images(self, images, filename_prefix="ComfyUI", prompt=None, extra_pnginfo=None, subfolder=None):
|
# FUNCTION = "score_meta"
|
||||||
|
|
||||||
# # Replace illegal characters in the filename prefix with dashes
|
# def score_meta(self, model, prompt, images):
|
||||||
# filename_prefix = re.sub(r'[<>:"\/\\|?*]', '-', filename_prefix)
|
# if self.model is None:
|
||||||
|
# self.model = RM.load(model)
|
||||||
|
|
||||||
# # Get the current date in Y-m-d format
|
# # Scoring part
|
||||||
# today = datetime.datetime.now().strftime("%Y-%m-%d")
|
# score = 0.0
|
||||||
|
|
||||||
# # If a custom subfolder is provided, use it; otherwise, use the date
|
|
||||||
# if subfolder is not None:
|
|
||||||
# full_output_folder = os.path.join(self.output_dir, subfolder)
|
|
||||||
# else:
|
|
||||||
# full_output_folder = os.path.join(self.output_dir, today)
|
|
||||||
|
|
||||||
# # Create the subfolder if it doesn't exist
|
|
||||||
# os.makedirs(full_output_folder, exist_ok=True)
|
|
||||||
|
|
||||||
# counter = self.get_next_number(full_output_folder)
|
|
||||||
|
|
||||||
# results = list()
|
|
||||||
# for image in images:
|
# for image in images:
|
||||||
# i = 255. * image.cpu().numpy()
|
# i = 255.0 * image.cpu().numpy()
|
||||||
# img = Image.fromarray(np.clip(i, 0, 255).astype(np.uint8))
|
# img = Image.fromarray(np.clip(i, 0, 255).astype(np.uint8))
|
||||||
|
# score += self.model.score(prompt, [img])
|
||||||
|
# score /= len(images)
|
||||||
|
# valuescale = 0.5 * (1 + math.erf(score / math.sqrt(2))) * 10
|
||||||
|
|
||||||
# metadata = PngInfo()
|
# # Metadata part
|
||||||
# if prompt is not None:
|
# extra_pnginfo = {"SCORE": str(score)}
|
||||||
# metadata.add_text("prompt", json.dumps(prompt))
|
|
||||||
# if extra_pnginfo is not None:
|
|
||||||
# for x in extra_pnginfo:
|
|
||||||
# metadata.add_text(x, json.dumps(extra_pnginfo[x]))
|
|
||||||
|
|
||||||
# file = f"{counter:05}-c-{filename_prefix}.png"
|
# # Returning both the score and the modified image
|
||||||
# img.save(os.path.join(full_output_folder, file), pnginfo=metadata, compress_level=4)
|
# return (score, str(score), valuescale, str(valuescale), images)
|
||||||
# results.append({
|
|
||||||
# "filename": file,
|
|
||||||
# "subfolder": full_output_folder,
|
|
||||||
# "type": self.type
|
|
||||||
# })
|
|
||||||
|
|
||||||
# # Check if a user-specified folder for TEXT files is provided
|
# ______________________________________________________________________________________________________________________________________________________________
|
||||||
# if subfolder is not None:
|
# IMAGE SAVERS BLOCK #
|
||||||
# # Create the full path for the TEXT file using the same name as the PNG
|
|
||||||
# text_file = os.path.join(subfolder, f"{counter:05}-c-{filename_prefix}.txt")
|
|
||||||
# else:
|
|
||||||
# # Use the same folder as the image if no custom subfolder is provided
|
|
||||||
# text_file = os.path.join(full_output_folder, f"{counter:05}-c-{filename_prefix}.txt")
|
|
||||||
|
|
||||||
# # Save some example text content to the TEXT file (you can modify this)
|
# ----------------------------------------------
|
||||||
# with open(text_file, 'w') as text:
|
# Saver type one: saves IMAGE and JSON files, can specify separate folders for each, or one, or none, and use Python timestamps
|
||||||
# text.write("This is an example text file.")
|
|
||||||
|
|
||||||
# counter += 1
|
|
||||||
|
|
||||||
# return {"ui": {"images": results}}
|
|
||||||
|
|
||||||
# def get_next_number(self, directory):
|
|
||||||
# files = os.listdir(directory)
|
|
||||||
# highest_number = 0
|
|
||||||
# for file in files:
|
|
||||||
# parts = file.split('-')
|
|
||||||
# try:
|
|
||||||
# num = int(parts[0])
|
|
||||||
# if num > highest_number:
|
|
||||||
# highest_number = num
|
|
||||||
# except ValueError:
|
|
||||||
# # If it's not a number, skip this file
|
|
||||||
# continue
|
|
||||||
|
|
||||||
# # Return the next number
|
|
||||||
# return highest_number + 1
|
|
||||||
|
|
||||||
|
|
||||||
#--------------------------------------
|
class EndlessNode_ImageSaver:
|
||||||
# CREDITS
|
def __init__(self):
|
||||||
|
self.output_dir = endless_paths.get_output_directory()
|
||||||
|
self.type = "output"
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def INPUT_TYPES(cls):
|
||||||
|
return {
|
||||||
|
"required": {
|
||||||
|
"images": ("IMAGE",),
|
||||||
|
"filename_prefix": ("STRING", {"default": "ComfyUI"}),
|
||||||
|
"delimiter": ("STRING", {"default": "_"}),
|
||||||
|
"filename_number_padding": ("INT", {"default": 4, "min": 1, "max": 9, "step": 1}),
|
||||||
|
"filename_number_start": (["false", "true"],),
|
||||||
|
"img_folder": ("STRING", {"default": None}),
|
||||||
|
"json_folder": ("STRING", {"default": None}),
|
||||||
|
},
|
||||||
|
"hidden": {
|
||||||
|
"prompt": "PROMPT", "extra_pnginfo": "EXTRA_PNGINFO"
|
||||||
|
},
|
||||||
|
}
|
||||||
|
RETURN_TYPES = ()
|
||||||
|
FUNCTION = "save_images"
|
||||||
|
OUTPUT_NODE = True
|
||||||
|
CATEGORY = "Endless 🌌/IO"
|
||||||
|
|
||||||
|
def save_images(self, images, filename_prefix="ComfyUI", delimiter="_",
|
||||||
|
filename_number_padding=4, filename_number_start='false',
|
||||||
|
img_folder=None, json_folder=None, prompt=None, extra_pnginfo=None):
|
||||||
|
|
||||||
|
# Replace illegal characters in the filename prefix with dashes
|
||||||
|
filename_prefix = re.sub(r'[<>:"\/\\|?*]', '-', filename_prefix)
|
||||||
|
|
||||||
|
# Set IMG Extension
|
||||||
|
img_extension = '.png'
|
||||||
|
|
||||||
|
counter = 1
|
||||||
|
|
||||||
|
results = list()
|
||||||
|
|
||||||
|
for image in images:
|
||||||
|
i = 255. * image.cpu().numpy()
|
||||||
|
img = Image.fromarray(np.clip(i, 0, 255).astype(np.uint8))
|
||||||
|
|
||||||
|
metadata = PngInfo()
|
||||||
|
if prompt is not None:
|
||||||
|
metadata.add_text("prompt", json.dumps(prompt))
|
||||||
|
if extra_pnginfo is not None:
|
||||||
|
for x in extra_pnginfo:
|
||||||
|
metadata.add_text(x, json.dumps(extra_pnginfo[x]))
|
||||||
|
|
||||||
|
img_file, json_file = self.generate_filenames(filename_prefix, delimiter, counter,filename_number_padding, filename_number_start,img_extension, img_folder, json_folder)
|
||||||
|
|
||||||
|
try:
|
||||||
|
if img_extension == '.png':
|
||||||
|
img.save(img_file, pnginfo=metadata, compress_level=4)
|
||||||
|
elif img_extension == '.jpeg':
|
||||||
|
img.save(img_file, quality=100, optimize=True)
|
||||||
|
|
||||||
|
with open(json_file, 'w', encoding='utf-8', newline='\n') as f:
|
||||||
|
if prompt is not None:
|
||||||
|
f.write(json.dumps(prompt, indent=4))
|
||||||
|
|
||||||
|
print(Fore.GREEN + f"+ File(s) saved to: {img_file}")
|
||||||
|
|
||||||
|
results.append({
|
||||||
|
"image_filename": os.path.basename(img_file),
|
||||||
|
"image_path": img_file,
|
||||||
|
"json_filename": os.path.basename(json_file),
|
||||||
|
"text_path": json_file,
|
||||||
|
"type": self.type
|
||||||
|
})
|
||||||
|
|
||||||
|
except OSError as e:
|
||||||
|
print(Fore.RED + " + Unable to save file: ", end='')
|
||||||
|
print({img_file})
|
||||||
|
print(e)
|
||||||
|
except Exception as e:
|
||||||
|
print(Fore.RED + " + Unable to save file due to the following error: ", end='')
|
||||||
|
print(e)
|
||||||
|
|
||||||
|
counter += 1
|
||||||
|
|
||||||
|
return {"ui": {"results": results}}
|
||||||
|
|
||||||
|
def generate_filenames(self, filename_prefix, delimiter, counter, filename_number_padding, filename_number_start, img_extension, img_folder, json_folder):
|
||||||
|
if filename_number_start == 'true':
|
||||||
|
img_file = f"{filename_prefix}{delimiter}{counter:0{filename_number_padding}}{img_extension}"
|
||||||
|
json_file = f"{filename_prefix}{delimiter}{counter:0{filename_number_padding}}.json"
|
||||||
|
else:
|
||||||
|
img_file = f"{filename_prefix}{delimiter}{counter:0{filename_number_padding}}{img_extension}"
|
||||||
|
json_file = f"{filename_prefix}{delimiter}{counter:0{filename_number_padding}}.json"
|
||||||
|
|
||||||
|
# Construct full paths for image and text files based on folders provided
|
||||||
|
|
||||||
|
if img_folder:
|
||||||
|
img_folder = self.replace_date_time_placeholders(img_folder)
|
||||||
|
os.makedirs(img_folder, exist_ok=True) # Create the image folder if it doesn't exist
|
||||||
|
img_file = os.path.join(img_folder, img_file)
|
||||||
|
else:
|
||||||
|
img_file = os.path.join(self.output_dir, img_file)
|
||||||
|
|
||||||
|
if json_folder:
|
||||||
|
json_folder = self.replace_date_time_placeholders(json_folder)
|
||||||
|
os.makedirs(json_folder, exist_ok=True) # Create the image folder if it doesn't exist
|
||||||
|
json_file = os.path.join(json_folder, json_file)
|
||||||
|
else:
|
||||||
|
json_file = os.path.join(os.path.dirname(img_file), json_file)
|
||||||
|
|
||||||
|
# Apply placeholders for date and time in filenames and folder
|
||||||
|
img_file = self.replace_date_time_placeholders(img_file)
|
||||||
|
json_file = self.replace_date_time_placeholders(json_file)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Check if files with the same name exist, increment counter if necessary
|
||||||
|
while os.path.exists(img_file) or os.path.exists(json_file):
|
||||||
|
counter += 1
|
||||||
|
if filename_number_start == 'true':
|
||||||
|
img_file = f"{filename_prefix}{delimiter}{counter:0{filename_number_padding}}{img_extension}"
|
||||||
|
json_file = f"{filename_prefix}{delimiter}{counter:0{filename_number_padding}}.json"
|
||||||
|
else:
|
||||||
|
img_file = f"{filename_prefix}{delimiter}{counter:0{filename_number_padding}}{img_extension}"
|
||||||
|
json_file = f"{filename_prefix}{delimiter}{counter:0{filename_number_padding}}.json"
|
||||||
|
|
||||||
|
# Construct full paths for image and text files based on folders provided
|
||||||
|
|
||||||
|
if img_folder:
|
||||||
|
img_folder = self.replace_date_time_placeholders(img_folder)
|
||||||
|
os.makedirs(img_folder, exist_ok=True) # Create the image folder if it doesn't exist
|
||||||
|
img_file = os.path.join(img_folder, img_file)
|
||||||
|
else:
|
||||||
|
img_file = os.path.join(self.output_dir, img_file)
|
||||||
|
|
||||||
|
if json_folder:
|
||||||
|
json_folder = self.replace_date_time_placeholders(json_folder)
|
||||||
|
os.makedirs(json_folder, exist_ok=True) # Create the image folder if it doesn't exist
|
||||||
|
json_file = os.path.join(json_folder, json_file)
|
||||||
|
else:
|
||||||
|
json_file = os.path.join(os.path.dirname(img_file), json_file)
|
||||||
|
|
||||||
|
# Apply placeholders for date and time in filenames and folder
|
||||||
|
img_file = self.replace_date_time_placeholders(img_file)
|
||||||
|
json_file = self.replace_date_time_placeholders(json_file)
|
||||||
|
|
||||||
|
return img_file, json_file
|
||||||
|
|
||||||
|
def replace_date_time_placeholders(self, filename):
|
||||||
|
# Replace date and time placeholders with actual date and time strings
|
||||||
|
now = datetime.datetime.now()
|
||||||
|
placeholders = {
|
||||||
|
'%Y': now.strftime('%Y'), # Year with century as a decimal number
|
||||||
|
'%y': now.strftime('%y'), # Year without century as a zero-padded decimal number
|
||||||
|
'%m': now.strftime('%m'), # Month as a zero-padded decimal number
|
||||||
|
'%d': now.strftime('%d'), # Day of the month as a zero-padded decimal number
|
||||||
|
'%H': now.strftime('%H'), # Hour (24-hour clock) as a zero-padded decimal number
|
||||||
|
'%M': now.strftime('%M'), # Minute as a zero-padded decimal number
|
||||||
|
'%S': now.strftime('%S'), # Second as a zero-padded decimal number
|
||||||
|
}
|
||||||
|
|
||||||
|
for placeholder, replacement in placeholders.items():
|
||||||
|
filename = filename.replace(placeholder, replacement)
|
||||||
|
|
||||||
|
return filename
|
||||||
|
# ______________________________________________________________________________________________________________________________________________________________
|
||||||
|
# CONVERTER NODES BLOCK #
|
||||||
|
|
||||||
|
# ----------------------------------------------
|
||||||
|
# Float value to Integer
|
||||||
|
|
||||||
|
class EndlessNode_FloattoInt:
|
||||||
|
CATEGORY = "Endless 🌌/Converters"
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def INPUT_TYPES(cls):
|
||||||
|
return {
|
||||||
|
"required": {"FloatValue": ("FLOAT", {"default": 0.0},)}
|
||||||
|
}
|
||||||
|
|
||||||
|
RETURN_TYPES = ("INT",)
|
||||||
|
FUNCTION = "inputfloat"
|
||||||
|
|
||||||
|
def inputfloat(self, FloatValue):
|
||||||
|
return int(FloatValue,)
|
||||||
|
|
||||||
|
|
||||||
|
# ----------------------------------------------
|
||||||
|
# Float value to Number, passes minimum one decimal
|
||||||
|
# There is no real "Number" function in Python, this is here so that nodes that need a NUMBER can take the FLOAT value
|
||||||
|
|
||||||
|
class EndlessNode_FloattoNum:
|
||||||
|
CATEGORY = "Endless 🌌/Converters"
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def INPUT_TYPES(cls):
|
||||||
|
return {
|
||||||
|
"required": {"FloatValue": ("FLOAT", {"default": 0.0,}),}
|
||||||
|
}
|
||||||
|
|
||||||
|
RETURN_TYPES = ("NUMBER",)
|
||||||
|
FUNCTION = "inputfloat"
|
||||||
|
|
||||||
|
def inputfloat(self, FloatValue):
|
||||||
|
return float(FloatValue,)
|
||||||
|
|
||||||
|
|
||||||
|
# ----------------------------------------------
|
||||||
|
# Float value to String, passes one to eight decimals
|
||||||
|
|
||||||
|
class EndlessNode_FloattoString:
|
||||||
|
CATEGORY = "Endless 🌌/Converters"
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def INPUT_TYPES(cls):
|
||||||
|
return {
|
||||||
|
"required": {"FloatValue": ("FLOAT", {"default": 0.0,},)}
|
||||||
|
}
|
||||||
|
|
||||||
|
RETURN_TYPES = ("STRING",)
|
||||||
|
FUNCTION = "inputfloat"
|
||||||
|
|
||||||
|
def inputfloat(self, FloatValue):
|
||||||
|
if isinstance(FloatValue, float):
|
||||||
|
formatted_value = f'{FloatValue:.1f}' if FloatValue.is_integer() else f'{FloatValue:.8f}'
|
||||||
|
return str((formatted_value),)
|
||||||
|
elif isinstance(FloatValue, int):
|
||||||
|
#Convert integer to float and then format
|
||||||
|
formatted_value = f'{float(FloatValue):.1f}'
|
||||||
|
return str((formatted_value),)
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
#Try to convert to float, and then format
|
||||||
|
float_value = float(FloatValue)
|
||||||
|
formatted_value = f'{float_value:.1f}' if float_value.is_integer() else f'{float_value:.8f}'
|
||||||
|
return str((formatted_value),)
|
||||||
|
except ValueError:
|
||||||
|
return ("Not a valid float",)
|
||||||
|
|
||||||
|
|
||||||
|
# # ---------------------------------------------- NEED TO FIX
|
||||||
|
# # Float value to X
|
||||||
|
|
||||||
|
# class EndlessNode_FloattoX:
|
||||||
|
# CATEGORY = "Endless 🌌/Converters"
|
||||||
|
|
||||||
|
# def __init__(self):
|
||||||
|
# pass
|
||||||
|
|
||||||
|
# @classmethod
|
||||||
|
# def INPUT_TYPES(cls):
|
||||||
|
# return {
|
||||||
|
# "required": {
|
||||||
|
# "FloatValue": ("FLOAT", {"default": 0, "min": -8675309362436420, "max": 8675309362436420}),
|
||||||
|
# },
|
||||||
|
# }
|
||||||
|
|
||||||
|
# RETURN_TYPES = ("INT", "NUMBER", "STR")
|
||||||
|
# FUNCTION = "return_constant_number"
|
||||||
|
|
||||||
|
# def return_constant_number(self, FloatValue):
|
||||||
|
|
||||||
|
# # Return number
|
||||||
|
# return (int(FloatValue), (FloatValue), str(FloatValue))
|
||||||
|
|
||||||
|
|
||||||
|
# ----------------------------------------------
|
||||||
|
# Integer to Float
|
||||||
|
|
||||||
|
class EndlessNode_InttoFloat:
|
||||||
|
CATEGORY = "Endless 🌌/Converters"
|
||||||
|
def __init__(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def INPUT_TYPES(cls):
|
||||||
|
return {
|
||||||
|
"required": {"IntegerValue": ("INT",),}
|
||||||
|
}
|
||||||
|
|
||||||
|
RETURN_TYPES = ("FLOAT",)
|
||||||
|
FUNCTION = "inputint"
|
||||||
|
|
||||||
|
def inputint(self, IntegerValue):
|
||||||
|
return int((IntegerValue),)
|
||||||
|
|
||||||
|
|
||||||
|
# ----------------------------------------------
|
||||||
|
# Integer to Number
|
||||||
|
|
||||||
|
class EndlessNode_InttoNum:
|
||||||
|
CATEGORY = "Endless 🌌/Converters"
|
||||||
|
def __init__(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def INPUT_TYPES(cls):
|
||||||
|
return {
|
||||||
|
"required": {"IntegerValue": ("INT",),}
|
||||||
|
}
|
||||||
|
|
||||||
|
RETURN_TYPES = ("NUMBER",)
|
||||||
|
FUNCTION = "inputint"
|
||||||
|
|
||||||
|
def inputint(self, IntegerValue):
|
||||||
|
return int((IntegerValue),)
|
||||||
|
|
||||||
|
|
||||||
|
# ----------------------------------------------
|
||||||
|
# Integer to String
|
||||||
|
|
||||||
|
class EndlessNode_InttoString:
|
||||||
|
CATEGORY = "Endless 🌌/Converters"
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def INPUT_TYPES(cls):
|
||||||
|
return {
|
||||||
|
"required": {"IntegerValue": ("INT",{"default": 0,},)}
|
||||||
|
}
|
||||||
|
RETURN_TYPES = ("STRING",)
|
||||||
|
FUNCTION = "inputint"
|
||||||
|
|
||||||
|
def inputint(self, IntegerValue):
|
||||||
|
return str((IntegerValue),)
|
||||||
|
|
||||||
|
# # ---------------------------------------------- NOT ORKING, NEED TO FIX
|
||||||
|
# # Integer value to X
|
||||||
|
|
||||||
|
# class EndlessNode_InttoX:
|
||||||
|
# CATEGORY = "Endless 🌌/Converters"
|
||||||
|
|
||||||
|
# def __init__(self):
|
||||||
|
# pass
|
||||||
|
|
||||||
|
# @classmethod
|
||||||
|
# def INPUT_TYPES(cls):
|
||||||
|
# return {
|
||||||
|
# "required": {
|
||||||
|
# "number": ("INT", {"default": 0, "min": -8675309, "max": 8675309}),
|
||||||
|
# },
|
||||||
|
# }
|
||||||
|
|
||||||
|
# RETURN_TYPES = ("FLOAT", "NUMBER", "STR")
|
||||||
|
# FUNCTION = "return_constant_number"
|
||||||
|
|
||||||
|
# def return_constant_number(self, number):
|
||||||
|
|
||||||
|
# # Return number
|
||||||
|
# return (float(number), float(number), str(number))
|
||||||
|
|
||||||
|
|
||||||
|
# ----------------------------------------------
|
||||||
|
# Number to Float
|
||||||
|
|
||||||
|
class EndlessNode_NumtoFloat:
|
||||||
|
CATEGORY = "Endless 🌌/Converters"
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def INPUT_TYPES(cls):
|
||||||
|
return {
|
||||||
|
"required": {"NumberValue": ("NUMBER",),}
|
||||||
|
}
|
||||||
|
|
||||||
|
RETURN_TYPES = ("FLOAT",)
|
||||||
|
FUNCTION = "inputnum"
|
||||||
|
|
||||||
|
def inputnum(self, NumberValue):
|
||||||
|
return float((NumberValue),)
|
||||||
|
|
||||||
|
|
||||||
|
# ----------------------------------------------
|
||||||
|
# Number to Integer
|
||||||
|
|
||||||
|
class EndlessNode_NumtoInt:
|
||||||
|
CATEGORY = "Endless 🌌/Converters"
|
||||||
|
def __init__(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def INPUT_TYPES(cls):
|
||||||
|
return {
|
||||||
|
"required": {"NumberValue": ("NUMBER",),}
|
||||||
|
}
|
||||||
|
RETURN_TYPES = ("INT",)
|
||||||
|
FUNCTION = "inputnum"
|
||||||
|
|
||||||
|
def inputnum(self, NumberValue):
|
||||||
|
return int((NumberValue),)
|
||||||
|
|
||||||
|
# ----------------------------------------------
|
||||||
|
# Number value to String
|
||||||
|
|
||||||
|
class EndlessNode_NumtoString:
|
||||||
|
def __init__(self):
|
||||||
|
pass
|
||||||
|
CATEGORY = "Endless 🌌/Converters"
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def INPUT_TYPES(cls):
|
||||||
|
return {
|
||||||
|
"required": {"NumberValue": ("NUMBER",),}
|
||||||
|
}
|
||||||
|
RETURN_TYPES = ("STRING",)
|
||||||
|
FUNCTION = "inputnum"
|
||||||
|
|
||||||
|
def inputnum(self, NumberValue):
|
||||||
|
return str((NumberValue),)
|
||||||
|
|
||||||
|
# NEED TO FIX STILL
|
||||||
|
# class EndlessNode_NumtoX:
|
||||||
|
# CATEGORY = "Endless 🌌/Converters"
|
||||||
|
|
||||||
|
# def __init__(self):
|
||||||
|
# pass
|
||||||
|
|
||||||
|
# @classmethod
|
||||||
|
# def INPUT_TYPES(cls):
|
||||||
|
# return {
|
||||||
|
# "required": {
|
||||||
|
# "number": ("FLOAT", {"default": 0, "min": -8675309362436420, "max": 8675309362436420}),
|
||||||
|
# },
|
||||||
|
# }
|
||||||
|
|
||||||
|
# RETURN_TYPES = ("FLOAT", "INT", "STR")
|
||||||
|
# FUNCTION = "return_constant_number"
|
||||||
|
|
||||||
|
# def return_constant_number(self, number):
|
||||||
|
|
||||||
|
# # Return number
|
||||||
|
# return (float(number), int(number), str(number))
|
||||||
|
|
||||||
|
|
||||||
|
#______________________________________________________________________________________________________________________________________________________________
|
||||||
|
# CREDITS #
|
||||||
|
|
||||||
#
|
#
|
||||||
# Comfyroll Custom Nodes for the overall node code layout, coding snippets, and inspiration for the text input and number switches
|
# Comfyroll Custom Nodes for the initial node code layout, coding snippets, and inspiration for the text input and number switches
|
||||||
#
|
#
|
||||||
# https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNode
|
# https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNode
|
||||||
#
|
#
|
||||||
@@ -608,14 +1068,28 @@ class EndlessNode_ImageReward:
|
|||||||
#
|
#
|
||||||
# https://github.com/comfyanonymous/ComfyUI
|
# https://github.com/comfyanonymous/ComfyUI
|
||||||
#
|
#
|
||||||
# ComfyUI-Strimmlarns-Aesthetic-Score for the original coding for Aesthetic Scoring Type One
|
# ComfyUI-Strimmlarns-Aesthetic-Score for the original coding for Aesthetic Scoring
|
||||||
#
|
#
|
||||||
# https://github.com/strimmlarn/ComfyUI-Strimmlarns-Aesthetic-Score
|
# https://github.com/strimmlarn/ComfyUI-Strimmlarns-Aesthetic-Score
|
||||||
#
|
#
|
||||||
# The scorer uses the MLP class code from Christoph Schuhmann
|
# The scorer uses the MLP class code from Christoph Schuhmann
|
||||||
#
|
#
|
||||||
#https://github.com/christophschuhmann/improved-aesthetic-predictor
|
#https://github.com/christophschuhmann/improved-aesthetic-predictor
|
||||||
#[Zane A's ComfyUI-ImageReward](https://github.com/ZaneA/ComfyUI-ImageReward) for the original coding for the Umagr Reward nodee
|
#[Zane A's ComfyUI-ImageReward](https://github.com/ZaneA/ComfyUI-ImageReward) for the original coding for the Image Reward node
|
||||||
#
|
#
|
||||||
#Zane's node in turn uses [ImageReward](https://github.com/THUDM/ImageReward)
|
#Zane's node in turn uses [ImageReward](https://github.com/THUDM/ImageReward)
|
||||||
|
#
|
||||||
|
#
|
||||||
|
#Mikey nodes to grab code snippet to pass scoring metadata to image
|
||||||
|
#
|
||||||
|
#https://github.com/bash-j/mikey_nodes
|
||||||
|
|
||||||
|
# Took some base code from the WAS save image node to repurpose it
|
||||||
|
#
|
||||||
|
#https://github.com/WASasquatch/was-node-suite-comfyui
|
||||||
#--------------------------------------
|
#--------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
######################################################################################## CELLAR DWELLERS
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
BIN
img/converters.png
Normal file
BIN
img/converters.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 20 KiB |
Reference in New Issue
Block a user