First commit
This commit is contained in:
+156
@@ -0,0 +1,156 @@
|
||||
from typing import List, Union
|
||||
import numpy as np
|
||||
from comfy_api.latest import io
|
||||
from PIL import Image
|
||||
import torch
|
||||
from diffusers import DiffusionPipeline
|
||||
# import os
|
||||
|
||||
model_downloaded = False
|
||||
|
||||
class MiniT2ISampler(io.ComfyNode):
|
||||
"""
|
||||
An example node
|
||||
|
||||
Class methods
|
||||
-------------
|
||||
define_schema (io.Schema):
|
||||
Tell the main program the metadata, input, output parameters of nodes.
|
||||
fingerprint_inputs:
|
||||
optional method to control when the node is re executed.
|
||||
check_lazy_status:
|
||||
optional method to control list of input names that need to be evaluated.
|
||||
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def define_schema(cls) -> io.Schema:
|
||||
"""
|
||||
Return a schema which contains all information about the node.
|
||||
Some types: "Model", "Vae", "Clip", "Conditioning", "Latent", "Image", "Int", "String", "Float", "Combo".
|
||||
For outputs the "io.Model.Output" should be used, for inputs the "io.Model.Input" can be used.
|
||||
The type can be a "Combo" - this will be a list for selection.
|
||||
"""
|
||||
return io.Schema(
|
||||
node_id="MiniT2I",
|
||||
display_name="MiniT2I Sampler",
|
||||
category="MiniT2I",
|
||||
inputs=[
|
||||
io.String.Input("prompt", multiline=True, lazy=True),
|
||||
io.Int.Input(
|
||||
"steps",
|
||||
default=10,
|
||||
min=0,
|
||||
max=4096,
|
||||
step=1, # Slider's step
|
||||
display_mode=io.NumberDisplay.number, # Cosmetic only: display as "number" or "slider"
|
||||
lazy=True, # Will only be evaluated if check_lazy_status requires it
|
||||
),
|
||||
io.Float.Input(
|
||||
"guidance",
|
||||
default=2.5,
|
||||
min=0.0,
|
||||
max=100.0,
|
||||
step=0.1,
|
||||
round=0.001, #The value representing the precision to round to, will be set to the step value by default. Can be set to False to disable rounding.
|
||||
display_mode=io.NumberDisplay.number,
|
||||
lazy=True,
|
||||
),
|
||||
io.Combo.Input("model_type", options=["b16","l16"]),
|
||||
io.Int.Input(
|
||||
"seed",
|
||||
default=1,
|
||||
step=1,
|
||||
lazy=True, # Will only be evaluated if check_lazy_status requires it
|
||||
),
|
||||
],
|
||||
outputs=[
|
||||
io.Image.Output(),
|
||||
],
|
||||
)
|
||||
|
||||
# @classmethod
|
||||
# def check_lazy_status(cls, image, string_field, int_field, float_field, print_to_screen):
|
||||
# """
|
||||
# Return a list of input names that need to be evaluated.
|
||||
#
|
||||
# This function will be called if there are any lazy inputs which have not yet been
|
||||
# evaluated. As long as you return at least one field which has not yet been evaluated
|
||||
# (and more exist), this function will be called again once the value of the requested
|
||||
# field is available.
|
||||
#
|
||||
# Any evaluated inputs will be passed as arguments to this function. Any unevaluated
|
||||
# inputs will have the value None.
|
||||
# """
|
||||
# if print_to_screen == "enable":
|
||||
# return ["int_field", "float_field", "string_field"]
|
||||
# else:
|
||||
# return []
|
||||
|
||||
|
||||
@classmethod
|
||||
def pil2tensor(cls, image: Union[Image.Image, List[Image.Image]]) -> torch.Tensor:
|
||||
"""
|
||||
Convert PIL image(s) to tensor, matching ComfyUI's implementation.
|
||||
|
||||
Args:
|
||||
image: Single PIL Image or list of PIL Images
|
||||
|
||||
Returns:
|
||||
torch.Tensor: Image tensor with values normalized to [0, 1]
|
||||
"""
|
||||
if isinstance(image, list):
|
||||
if len(image) == 0:
|
||||
return torch.empty(0)
|
||||
return torch.cat([cls.pil2tensor(img) for img in image], dim=0)
|
||||
|
||||
# Convert PIL image to RGB if needed
|
||||
if image.mode == 'RGBA':
|
||||
image = image.convert('RGB')
|
||||
elif image.mode != 'RGB':
|
||||
image = image.convert('RGB')
|
||||
|
||||
# Convert to numpy array and normalize to [0, 1]
|
||||
img_array = np.array(image).astype(np.float32) / 255.0
|
||||
|
||||
# Return tensor with shape [1, H, W, 3]
|
||||
return torch.from_numpy(img_array)[None,]
|
||||
|
||||
@classmethod
|
||||
def execute(cls, prompt, steps, guidance, model_type, seed) -> io.NodeOutput:
|
||||
global model_downloaded
|
||||
torch.manual_seed(seed)
|
||||
|
||||
HUB_MODEL_ID = "MiniT2I/MiniT2I"
|
||||
pipe = DiffusionPipeline.from_pretrained(
|
||||
HUB_MODEL_ID,
|
||||
custom_pipeline=HUB_MODEL_ID,
|
||||
local_files_only=model_downloaded,
|
||||
trust_remote_code=True,
|
||||
)
|
||||
if pipe:
|
||||
model_downloaded = True
|
||||
|
||||
output = pipe(
|
||||
prompt,
|
||||
model_type=model_type,
|
||||
guidance_scale=guidance,
|
||||
num_inference_steps=steps,
|
||||
torch_dtype=torch.bfloat16,
|
||||
)
|
||||
|
||||
return io.NodeOutput(cls.pil2tensor(output.images))
|
||||
# return io.NodeOutput(image)
|
||||
|
||||
"""
|
||||
The node will always be re executed if any of the inputs change but
|
||||
this method can be used to force the node to execute again even when the inputs don't change.
|
||||
You can make this node return a number or a string. This value will be compared to the one returned the last time the node was
|
||||
executed, if it is different the node will be executed again.
|
||||
This method is used in the core repo for the LoadImage node where they return the image hash as a string, if the image hash
|
||||
changes between executions the LoadImage node is executed again.
|
||||
"""
|
||||
#@classmethod
|
||||
#def fingerprint_inputs(s, image, string_field, int_field, float_field, print_to_screen):
|
||||
# return ""
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
|
||||
Sampler for MiniT2I
|
||||
https://huggingface.co/MiniT2I/MiniT2I
|
||||
|
||||
Workflows are in the templates section.
|
||||
|
||||
|
||||
|
||||
Just a quickie. Bit slow cause the model is not cached in memory.
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
from typing_extensions import override
|
||||
from comfy_api.latest import ComfyExtension, io
|
||||
from .MiniT2I import MiniT2ISampler
|
||||
|
||||
|
||||
class MiniT2IExtension(ComfyExtension):
|
||||
@override
|
||||
async def get_node_list(self) -> list[type[io.ComfyNode]]:
|
||||
return [
|
||||
MiniT2ISampler,
|
||||
]
|
||||
|
||||
|
||||
async def comfy_entrypoint() -> MiniT2IExtension: # ComfyUI calls this to load your extension and its nodes.
|
||||
return MiniT2IExtension()
|
||||
|
||||
@@ -0,0 +1,185 @@
|
||||
{
|
||||
"id": "e572e121-bf51-413f-bba1-ca525f710414",
|
||||
"revision": 0,
|
||||
"last_node_id": 4,
|
||||
"last_link_id": 2,
|
||||
"nodes": [
|
||||
{
|
||||
"id": 1,
|
||||
"type": "PreviewImage",
|
||||
"pos": [
|
||||
1397.0351491908762,
|
||||
-950.3260055448459
|
||||
],
|
||||
"size": [
|
||||
140,
|
||||
246
|
||||
],
|
||||
"flags": {},
|
||||
"order": 2,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "images",
|
||||
"type": "IMAGE",
|
||||
"link": 1
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "images",
|
||||
"type": "IMAGE",
|
||||
"links": null
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"cnr_id": "comfy-core",
|
||||
"ver": "0.26.0",
|
||||
"Node name for S&R": "PreviewImage"
|
||||
},
|
||||
"widgets_values": []
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"type": "PreviewImage",
|
||||
"pos": [
|
||||
1416.1947412443299,
|
||||
-549.015734080902
|
||||
],
|
||||
"size": [
|
||||
140,
|
||||
246
|
||||
],
|
||||
"flags": {},
|
||||
"order": 3,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "images",
|
||||
"type": "IMAGE",
|
||||
"link": 2
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "images",
|
||||
"type": "IMAGE",
|
||||
"links": null
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"cnr_id": "comfy-core",
|
||||
"ver": "0.26.0",
|
||||
"Node name for S&R": "PreviewImage"
|
||||
},
|
||||
"widgets_values": []
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"type": "MiniT2I",
|
||||
"pos": [
|
||||
850.8583116297305,
|
||||
-918.896001453913
|
||||
],
|
||||
"size": [
|
||||
400,
|
||||
208
|
||||
],
|
||||
"flags": {},
|
||||
"order": 0,
|
||||
"mode": 0,
|
||||
"inputs": [],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "IMAGE",
|
||||
"type": "IMAGE",
|
||||
"links": [
|
||||
1
|
||||
]
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "MiniT2I"
|
||||
},
|
||||
"widgets_values": [
|
||||
"Purple monkey dishwasher",
|
||||
100,
|
||||
2.5,
|
||||
"b16",
|
||||
1,
|
||||
"increment"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"type": "MiniT2I",
|
||||
"pos": [
|
||||
820.5800443091753,
|
||||
-530.5854576396309
|
||||
],
|
||||
"size": [
|
||||
400,
|
||||
208
|
||||
],
|
||||
"flags": {},
|
||||
"order": 1,
|
||||
"mode": 0,
|
||||
"inputs": [],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "IMAGE",
|
||||
"type": "IMAGE",
|
||||
"links": [
|
||||
2
|
||||
]
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "MiniT2I"
|
||||
},
|
||||
"widgets_values": [
|
||||
"Purple monkey dishwasher",
|
||||
100,
|
||||
6,
|
||||
"l16",
|
||||
1,
|
||||
"increment"
|
||||
]
|
||||
}
|
||||
],
|
||||
"links": [
|
||||
[
|
||||
1,
|
||||
2,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
"IMAGE"
|
||||
],
|
||||
[
|
||||
2,
|
||||
3,
|
||||
0,
|
||||
4,
|
||||
0,
|
||||
"IMAGE"
|
||||
]
|
||||
],
|
||||
"groups": [],
|
||||
"config": {},
|
||||
"extra": {
|
||||
"ds": {
|
||||
"scale": 1.588548164722016,
|
||||
"offset": [
|
||||
-504.72890778875325,
|
||||
878.5672286853679
|
||||
]
|
||||
},
|
||||
"frontendVersion": "1.45.19",
|
||||
"VHS_latentpreview": false,
|
||||
"VHS_latentpreviewrate": 0,
|
||||
"VHS_MetadataImage": true,
|
||||
"VHS_KeepIntermediate": true
|
||||
},
|
||||
"version": 0.4
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
[project]
|
||||
name = "MiniT2I-ComfyUI"
|
||||
version = "1.0.0"
|
||||
description = "MiniT2i for ComfyUI"
|
||||
license = { file = "LICENSE" }
|
||||
dependencies = [
|
||||
]
|
||||
classifiers = [
|
||||
"Operating System :: OS Independent" # Works on all operating systems
|
||||
]
|
||||
dynamic = ["dependencies"]
|
||||
|
||||
[project.urls]
|
||||
Repository = "https://github.com/niknah/MiniT2I-ComfyUI"
|
||||
Documentation = "https://huggingface.co/MiniT2I/MiniT2I"
|
||||
"Bug Tracker" = "https://github.com/niknah/MiniT2I-ComfyUI/issues"
|
||||
|
||||
[tool.comfy]
|
||||
PublisherId = "niknah"
|
||||
DisplayName = "MiniT2I"
|
||||
Reference in New Issue
Block a user