initial checkin
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
import os
|
||||
import folder_paths
|
||||
import json
|
||||
import torch
|
||||
from PIL import Image
|
||||
import numpy as np
|
||||
import json
|
||||
|
||||
from nodes import SaveImage
|
||||
|
||||
|
||||
class KY_SaveImageToPath(SaveImage):
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {"required":
|
||||
{"IMG": ("IMAGE",),
|
||||
"path": ("STRING", {"default": "ComfyUI.png"})},
|
||||
"hidden":
|
||||
{"prompt": "PROMPT", "extra_pnginfo": "EXTRA_PNGINFO"}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("IMAGE",)
|
||||
FUNCTION = "save_image_to_path"
|
||||
OUTPUT_NODE = True
|
||||
CATEGORY = "KY Nodes/Image"
|
||||
|
||||
def save_image_to_path(self, IMG, path="ComfyUI.png", prompt=None, extra_pnginfo=None):
|
||||
#results = self.save_images(images, filename_prefix, prompt, extra_pnginfo)
|
||||
saved_paths = []
|
||||
#folder_structure = []
|
||||
#folder_structure = json.loads(folder_structure)
|
||||
base_directory = path
|
||||
full_file_path = path
|
||||
images = IMG
|
||||
|
||||
# Ensure base directory exists
|
||||
#os.makedirs(base_directory, exist_ok=True)
|
||||
|
||||
for i, image in enumerate(images):
|
||||
# Convert the image tensor to a PIL Image
|
||||
img = Image.fromarray((image.cpu().numpy() * 255).astype(np.uint8))
|
||||
|
||||
# Create the full folder path based on the folder structure
|
||||
#full_folder_path = self.create_folder_path(base_directory, [])
|
||||
#os.makedirs(full_folder_path, exist_ok=True)
|
||||
|
||||
# Create the file name and ensure it doesn't overwrite existing files
|
||||
#index = 0 + i
|
||||
#while True:
|
||||
#full_file_name = file_name_template.format(index=index)
|
||||
# full_file_path = path #os.path.join(full_folder_path, full_file_name)
|
||||
# if not os.path.exists(full_file_path):
|
||||
# break
|
||||
# index += 1
|
||||
|
||||
# Save the image
|
||||
img.save(full_file_path)
|
||||
|
||||
# Save metadata if provided
|
||||
#if metadata:
|
||||
# metadata_file_name = f"{os.path.splitext(full_file_name)[0]}_metadata.txt"
|
||||
# metadata_file_path = os.path.join(full_folder_path, metadata_file_name)
|
||||
# with open(metadata_file_path, 'w') as f:
|
||||
# f.write(metadata)
|
||||
|
||||
saved_paths.append(path)
|
||||
break
|
||||
#return (", ".join(saved_paths),)
|
||||
#results = (", ".join(saved_paths))
|
||||
return {
|
||||
"ui": {
|
||||
#"images": results['ui']['IMG']
|
||||
"images": path
|
||||
},
|
||||
"result": (IMG,)
|
||||
}
|
||||
def create_folder_path(self, base_directory, folder_structure):
|
||||
path = base_directory
|
||||
for folder in folder_structure:
|
||||
path = os.path.join(path, folder['name'])
|
||||
for child in folder['children']:
|
||||
path = self.create_folder_path(path, [child])
|
||||
return path
|
||||
|
||||
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
from .advanced_lying_sigma_sampler import AdvancedLyingSigmaSamplerNode
|
||||
from .KY_SaveImageToPath import KY_SaveImageToPath
|
||||
|
||||
# 将节点映射到NODE_CLASS_MAPPINGS和NODE_DISPLAY_NAME_MAPPINGS
|
||||
NODE_CLASS_MAPPINGS = {
|
||||
"AdvancedLyingSigmaSampler": AdvancedLyingSigmaSamplerNode,
|
||||
"KY_SaveImageToPath": KY_SaveImageToPath
|
||||
}
|
||||
|
||||
NODE_DISPLAY_NAME_MAPPINGS = {
|
||||
"AdvancedLyingSigmaSampler": "Advanced Lying Sigma Sampler",
|
||||
"KY_SaveImageToPath": "Save Image To target Path"
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
# Based on the concept from https://github.com/muerrilla/sd-webui-detail-daemon
|
||||
# Original code courtesy from https://github.com/blepping/
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
import inspect
|
||||
|
||||
from comfy.samplers import KSAMPLER
|
||||
import numpy as np
|
||||
|
||||
if TYPE_CHECKING:
|
||||
import torch
|
||||
|
||||
def advanced_lying_sigma_sampler(
|
||||
model: object,
|
||||
x: torch.Tensor,
|
||||
sigmas: torch.Tensor,
|
||||
*,
|
||||
sampler: object,
|
||||
dishonesty_factor: float,
|
||||
start_percent: float,
|
||||
end_percent: float,
|
||||
smooth_factor: float = 0.5,
|
||||
**kwargs: dict,
|
||||
) -> torch.Tensor:
|
||||
start_sigma = round(model.inner_model.inner_model.model_sampling.percent_to_sigma(start_percent), 4)
|
||||
end_sigma = round(model.inner_model.inner_model.model_sampling.percent_to_sigma(end_percent), 4)
|
||||
|
||||
def model_wrapper(x: torch.Tensor, sigma: torch.Tensor, **extra_args: dict):
|
||||
sigma_float = float(sigma.max().detach().cpu())
|
||||
if end_sigma <= sigma_float <= start_sigma:
|
||||
adjustment = dishonesty_factor * (0.5 * (1 - np.cos(smooth_factor * np.pi)))
|
||||
sigma = sigma * (1.0 + adjustment)
|
||||
return model(x, sigma, **extra_args)
|
||||
|
||||
for k in (
|
||||
"inner_model",
|
||||
"sigmas",
|
||||
):
|
||||
if hasattr(model, k):
|
||||
setattr(model_wrapper, k, getattr(model, k))
|
||||
|
||||
# Check if denoise_mask is supported by the sampler function
|
||||
if 'denoise_mask' in inspect.signature(sampler.sampler_function).parameters:
|
||||
return sampler.sampler_function(
|
||||
model_wrapper,
|
||||
x,
|
||||
sigmas,
|
||||
denoise_mask=kwargs.get('denoise_mask'),
|
||||
**kwargs,
|
||||
**sampler.extra_options,
|
||||
)
|
||||
else:
|
||||
return sampler.sampler_function(
|
||||
model_wrapper,
|
||||
x,
|
||||
sigmas,
|
||||
**kwargs,
|
||||
**sampler.extra_options,
|
||||
)
|
||||
|
||||
class AdvancedLyingSigmaSamplerNode:
|
||||
DESCRIPTION = "高级sigma控制器,使用前最好关闭float rounding并重启comfui,以达到最佳控制效果|For advanced sigma controllers, it is best to turn off float rounding and restart comfui before use for optimal control."
|
||||
CATEGORY = "KY Nodes/advanced_samplers"
|
||||
RETURN_TYPES = ("SAMPLER",)
|
||||
FUNCTION = "initialize"
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> dict:
|
||||
return {
|
||||
"required": {
|
||||
"sampler": ("SAMPLER",),
|
||||
"dishonesty_factor": (
|
||||
"FLOAT",
|
||||
{
|
||||
"default": -0.1,
|
||||
"min": -1.0,
|
||||
"max": 1.0,
|
||||
"step": 0.001,
|
||||
"tooltip": "默认值-0.1,一般来说这是一个较大值|Default value -0.1, which is generally a larger value."
|
||||
}
|
||||
),
|
||||
"start_percent": (
|
||||
"FLOAT",
|
||||
{
|
||||
"default": 0.1,
|
||||
"min": 0.0,
|
||||
"max": 1.0,
|
||||
"step": 0.01,
|
||||
"tooltip": "bilibili@深深蓝hana."
|
||||
}
|
||||
),
|
||||
"end_percent": (
|
||||
"FLOAT",
|
||||
{
|
||||
"default": 0.9,
|
||||
"min": 0.0,
|
||||
"max": 1.0,
|
||||
"step": 0.01,
|
||||
"tooltip": "bilibili@深深蓝hana."
|
||||
}
|
||||
),
|
||||
"smooth_factor": (
|
||||
"FLOAT",
|
||||
{
|
||||
"default": 0.5,
|
||||
"min": 0.0,
|
||||
"max": 1.0,
|
||||
"step": 0.01,
|
||||
"tooltip": "bilibili@深深蓝hana."
|
||||
}
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def initialize(
|
||||
cls,
|
||||
sampler: object,
|
||||
dishonesty_factor: float,
|
||||
start_percent: float,
|
||||
end_percent: float,
|
||||
smooth_factor: float,
|
||||
) -> tuple:
|
||||
return (
|
||||
KSAMPLER(
|
||||
advanced_lying_sigma_sampler,
|
||||
extra_options={
|
||||
"sampler": sampler,
|
||||
"dishonesty_factor": dishonesty_factor,
|
||||
"start_percent": start_percent,
|
||||
"end_percent": end_percent,
|
||||
"smooth_factor": smooth_factor,
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
NODE_CLASS_MAPPINGS = {
|
||||
"AdvancedLyingSigmaSampler": AdvancedLyingSigmaSamplerNode,
|
||||
}
|
||||
NODE_DISPLAY_NAME_MAPPINGS = {
|
||||
"AdvancedLyingSigmaSampler": "Advanced Lying Sigma Sampler"
|
||||
}
|
||||
Reference in New Issue
Block a user