Skip to content

Commit

Permalink
fork: custom nodes for doodle project
Browse files Browse the repository at this point in the history
  • Loading branch information
devniel committed Jul 10, 2024
1 parent 2bef134 commit d5e3016
Show file tree
Hide file tree
Showing 19 changed files with 364 additions and 2 deletions.
5 changes: 3 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ __pycache__/
!/input/example.png
/models/
/temp/
/custom_nodes/
#/custom_nodes/
!custom_nodes/example_node.py.example
extra_model_paths.yaml
/.vs
Expand All @@ -15,4 +15,5 @@ venv/
!/web/extensions/logging.js.example
!/web/extensions/core/
/tests-ui/data/object_info.json
/user/
/user/
*.log
2 changes: 2 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
{
}
1 change: 1 addition & 0 deletions custom_nodes/ComfyScript
Submodule ComfyScript added at c55575
1 change: 1 addition & 0 deletions custom_nodes/ComfyUI-BRIA_AI-RMBG
Submodule ComfyUI-BRIA_AI-RMBG added at 827fcd
1 change: 1 addition & 0 deletions custom_nodes/ComfyUI-Custom-Scripts
Submodule ComfyUI-Custom-Scripts added at 3f2c02
1 change: 1 addition & 0 deletions custom_nodes/ComfyUI-Manager
Submodule ComfyUI-Manager added at 3d447e
1 change: 1 addition & 0 deletions custom_nodes/ComfyUI_LayerStyle
Submodule ComfyUI_LayerStyle added at 4808f0
1 change: 1 addition & 0 deletions custom_nodes/Comfy_Felsirnodes
Submodule Comfy_Felsirnodes added at 447140
1 change: 1 addition & 0 deletions custom_nodes/comfy_mtb
Submodule comfy_mtb added at f9d2eb
1 change: 1 addition & 0 deletions custom_nodes/comfyui-ollama
Submodule comfyui-ollama added at 769eb5
125 changes: 125 additions & 0 deletions custom_nodes/doodle-tiles-node/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
from PIL import Image, ImageOps, ImageFilter
import numpy as np
import random
from skimage.restoration import denoise_nl_means, estimate_sigma
from skimage import img_as_float, img_as_ubyte
import torch

# Tensor to PIL
def tensor2pil(image):
return Image.fromarray(np.clip(255. * image.cpu().numpy().squeeze(), 0, 255).astype(np.uint8))

# PIL to Tensor
def pil2tensor(image):
return torch.from_numpy(np.array(image).astype(np.float32) / 255.0).unsqueeze(0)

class DoodleTilesGenerator:
"""
A node for creating a mosaic image with solid color background and black & white tiles merged such that
white areas become transparent and black areas retain color.
This node applies a denoising filter to enhance tile quality and resizes tiles for a unique artistic effect.
"""

@classmethod
def INPUT_TYPES(cls):
"""
Define input types for ComfyUI node.
"""
return {
"required": {
"images": ("IMAGE",),
"tile_width": ("INT", {
"default": 128,
"min": 1,
"max": 1024,
"step": 1,
}),
"tile_height": ("INT", {
"default": 128,
"min": 1,
"max": 1024,
"step": 1,
}),
"bg_width": ("INT", {
"default": 1024,
"min": 100,
"max": 5000,
"step": 1,
}),
"bg_height": ("INT", {
"default": 1024,
"min": 100,
"max": 5000,
"step": 1,
}),
"bg_color": ("STRING", {
"default": "(254, 80, 0)",
"multiline": False,
}),
"stroke_color": ("STRING", {
"default": "(171, 54, 0)",
"multiline": False,
})
},
}

RETURN_TYPES = ("IMAGE",)
RETURN_NAMES = ("images",)
FUNCTION = "create_mosaic"
CATEGORY = "image"

def create_mosaic(self, images, tile_width, tile_height, bg_width, bg_height, bg_color, stroke_color):
# Process the background color string input
bg_color = eval(bg_color)

# Process the stroke color string input
stroke_color = eval(stroke_color)

# Create a solid color background image
background = Image.new('RGBA', (bg_width, bg_height), color=bg_color)

# Load tiles and prepare masks
tiles = []
for image in images:
original_tile = tensor2pil(image).convert('L')
resized_tile = original_tile.resize((int(tile_width * 0.8), int(tile_height * 0.8)), Image.LANCZOS)
mask = resized_tile.point(lambda p: p <= 128 and 255)
tile_image = ImageOps.colorize(resized_tile, stroke_color, stroke_color)

np_image = np.array(tile_image)
float_image = img_as_float(np_image)
sigma_est = np.mean(estimate_sigma(float_image, channel_axis=-1))
denoised_image = denoise_nl_means(float_image, h=2.0 * sigma_est, fast_mode=True,
patch_size=7, patch_distance=11, channel_axis=-1)
denoised_tile = Image.fromarray(img_as_ubyte(denoised_image))
denoised_tile = denoised_tile.filter(ImageFilter.EDGE_ENHANCE_MORE)

centered_tile = Image.new('RGBA', (tile_width, tile_height), bg_color+(0,))
centered_mask = Image.new('L', (tile_width, tile_height), 0)
top_left_corner = ((tile_width - denoised_tile.width) // 2, (tile_height - denoised_tile.height) // 2)
centered_tile.paste(denoised_tile, top_left_corner)
centered_mask.paste(mask, top_left_corner)

tiles.append((centered_tile, centered_mask))

random.shuffle(tiles)

# Place tiles on the background using masks
num_tiles_x = int(np.ceil(bg_width / tile_width))
num_tiles_y = int(np.ceil(bg_height / tile_height))

for y in range(num_tiles_y):
for x in range(num_tiles_x):
tile, mask = tiles[(x + y * num_tiles_x) % len(tiles)]
background.paste(tile, (x * tile_width, y * tile_height), mask)

# Convert the final PIL image to a format that ComfyUI can handle as an output
output_image = pil2tensor(background)
return (output_image,)

# A dictionary that contains all nodes you want to export with their names
# NOTE: names should be globally unique
NODE_CLASS_MAPPINGS = {
"Doodle Tiles Generator": DoodleTilesGenerator
}
3 changes: 3 additions & 0 deletions custom_nodes/doodle-tiles-node/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
numpy==1.26.4
Pillow==10.3.0
scikit-image==0.22.0
1 change: 1 addition & 0 deletions custom_nodes/rembg-comfyui-node
Submodule rembg-comfyui-node added at fac7df
1 change: 1 addition & 0 deletions custom_nodes/rgthree-comfy
Submodule rgthree-comfy added at 017a15
1 change: 1 addition & 0 deletions custom_nodes/was-node-suite-comfyui
Submodule was-node-suite-comfyui added at 6c3fed
1 change: 1 addition & 0 deletions execution.py
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,7 @@ def validate_inputs(prompt, item, validated):
"input_name": x
}
}

errors.append(error)
continue

Expand Down
Empty file.
216 changes: 216 additions & 0 deletions requirements.conda.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
# This file may be used to create an environment using:
# $ conda create --name <env> --file <this file>
# platform: linux-64
_libgcc_mutex=0.1=main
_openmp_mutex=5.1=1_gnu
absl-py=2.1.0=pypi_0
accelerate=0.29.3=pypi_0
addict=2.4.0=pypi_0
aiohttp=3.9.4=pypi_0
aiosignal=1.3.1=pypi_0
annotated-types=0.6.0=pypi_0
antlr4-python3-runtime=4.9.3=pypi_0
anyio=4.3.0=pypi_0
asttokens=2.4.1=pypi_0
async-timeout=4.0.3=pypi_0
attrs=23.2.0=pypi_0
ca-certificates=2024.3.11=h06a4308_0
cachetools=5.3.3=pypi_0
certifi=2024.2.2=pypi_0
cffi=1.16.0=pypi_0
charset-normalizer=3.3.2=pypi_0
click=8.1.7=pypi_0
cmake=3.29.2=pypi_0
coloredlogs=15.0.1=pypi_0
colour-science=0.4.4=pypi_0
comfy-script=0.4.6=pypi_0
comfyui-ib-customnodes=0.2.2=pypi_0
comfyui-tooling-nodes=0.1.0=pypi_0
comm=0.2.2=pypi_0
contourpy=1.2.1=pypi_0
cstr=0.1.0=pypi_0
cycler=0.12.1=pypi_0
datasets=2.19.0=pypi_0
decorator=5.1.1=pypi_0
diffusers=0.27.2=pypi_0
dill=0.3.8=pypi_0
einops=0.7.0=pypi_0
exceptiongroup=1.2.1=pypi_0
executing=2.0.1=pypi_0
fairscale=0.4.13=pypi_0
fastapi=0.110.2=pypi_0
ffmpy=0.3.0=pypi_0
filelock=3.13.4=pypi_0
flatbuffers=24.3.25=pypi_0
fonttools=4.51.0=pypi_0
frozenlist=1.4.1=pypi_0
fsspec=2024.3.1=pypi_0
gitdb=4.0.11=pypi_0
gitpython=3.1.43=pypi_0
google-ai-generativelanguage=0.6.2=pypi_0
google-api-core=2.18.0=pypi_0
google-api-python-client=2.126.0=pypi_0
google-auth=2.29.0=pypi_0
google-auth-httplib2=0.2.0=pypi_0
google-generativeai=0.5.2=pypi_0
googleapis-common-protos=1.63.0=pypi_0
grpcio=1.62.2=pypi_0
grpcio-status=1.48.2=pypi_0
h11=0.14.0=pypi_0
httpcore=1.0.5=pypi_0
httplib2=0.22.0=pypi_0
httpx=0.27.0=pypi_0
huggingface-hub=0.22.2=pypi_0
humanfriendly=10.0=pypi_0
idna=3.7=pypi_0
image-reward=1.5=pypi_0
imageio=2.34.0=pypi_0
imageio-ffmpeg=0.4.9=pypi_0
img2texture=1.0.6=pypi_0
importlib-metadata=7.1.0=pypi_0
importlib-resources=6.4.0=pypi_0
ipython=8.18.1=pypi_0
ipywidgets=8.1.2=pypi_0
jax=0.4.26=pypi_0
jaxlib=0.4.26=pypi_0
jedi=0.19.1=pypi_0
jinja2=3.1.3=pypi_0
joblib=1.4.0=pypi_0
jsonschema=4.21.1=pypi_0
jsonschema-specifications=2023.12.1=pypi_0
jupyterlab-widgets=3.0.10=pypi_0
kiwisolver=1.4.5=pypi_0
kornia=0.7.2=pypi_0
kornia-rs=0.1.3=pypi_0
lazy-loader=0.4=pypi_0
ld_impl_linux-64=2.38=h1181459_1
libffi=3.4.4=h6a678d5_0
libgcc-ng=11.2.0=h1234567_1
libgomp=11.2.0=h1234567_1
libstdcxx-ng=11.2.0=h1234567_1
llvmlite=0.42.0=pypi_0
loguru=0.7.2=pypi_0
markdown-it-py=3.0.0=pypi_0
markupsafe=2.1.5=pypi_0
matplotlib=3.8.4=pypi_0
matplotlib-inline=0.1.7=pypi_0
mdurl=0.1.2=pypi_0
mediapipe=0.10.11=pypi_0
ml-dtypes=0.4.0=pypi_0
mpmath=1.3.0=pypi_0
multidict=6.0.5=pypi_0
multiprocess=0.70.16=pypi_0
ncurses=6.4=h6a678d5_0
nest-asyncio=1.6.0=pypi_0
networkx=3.2.1=pypi_0
numba=0.59.1=pypi_0
numpy=1.26.4=pypi_0
nvidia-cublas-cu12=12.1.3.1=pypi_0
nvidia-cuda-cupti-cu12=12.1.105=pypi_0
nvidia-cuda-nvrtc-cu12=12.1.105=pypi_0
nvidia-cuda-runtime-cu12=12.1.105=pypi_0
nvidia-cudnn-cu12=8.9.2.26=pypi_0
nvidia-cufft-cu12=11.0.2.54=pypi_0
nvidia-curand-cu12=10.3.2.106=pypi_0
nvidia-cusolver-cu12=11.4.5.107=pypi_0
nvidia-cusparse-cu12=12.1.0.106=pypi_0
nvidia-nccl-cu12=2.19.3=pypi_0
nvidia-nvjitlink-cu12=12.4.127=pypi_0
nvidia-nvtx-cu12=12.1.105=pypi_0
ollama=0.1.9=pypi_0
omegaconf=2.3.0=pypi_0
onnxruntime=1.17.1=pypi_0
onnxruntime-gpu=1.17.1=pypi_0
opencv-contrib-python=4.9.0.80=pypi_0
opencv-python-headless=4.7.0.72=pypi_0
openssl=3.0.13=h7f8727e_0
opt-einsum=3.3.0=pypi_0
packaging=24.0=pypi_0
pandas=2.2.2=pypi_0
parso=0.8.4=pypi_0
pexpect=4.9.0=pypi_0
pilgram=1.2.1=pypi_0
pillow=10.3.0=pypi_0
pip=23.3.1=py39h06a4308_0
platformdirs=4.2.0=pypi_0
pooch=1.8.1=pypi_0
prompt-toolkit=3.0.43=pypi_0
proto-plus=1.23.0=pypi_0
protobuf=3.20.3=pypi_0
psutil=5.9.8=pypi_0
ptyprocess=0.7.0=pypi_0
pure-eval=0.2.2=pypi_0
pyarrow=15.0.2=pypi_0
pyarrow-hotfix=0.6=pypi_0
pyasn1=0.6.0=pypi_0
pyasn1-modules=0.4.0=pypi_0
pycparser=2.22=pypi_0
pydantic=2.7.0=pypi_0
pydantic-core=2.18.1=pypi_0
pygments=2.17.2=pypi_0
pymatting=1.1.12=pypi_0
pyparsing=3.1.2=pypi_0
pypng=0.20220715.0=pypi_0
python=3.9.19=h955ad1f_0
python-dateutil=2.9.0.post0=pypi_0
pytz=2024.1=pypi_0
pywavelets=1.6.0=pypi_0
pyyaml=6.0.1=pypi_0
qrcode=7.4.2=pypi_0
readline=8.2=h5eee18b_0
referencing=0.34.0=pypi_0
regex=2023.12.25=pypi_0
rembg=2.0.56=pypi_0
requests=2.31.0=pypi_0
requirements-parser=0.9.0=pypi_0
rich=13.7.1=pypi_0
rich-argparse=1.4.0=pypi_0
rpds-py=0.18.0=pypi_0
rsa=4.9=pypi_0
safetensors=0.4.2=pypi_0
scikit-image=0.22.0=pypi_0
scikit-learn=1.4.2=pypi_0
scipy=1.13.0=pypi_0
segment-anything=1.0=pypi_0
setuptools=68.2.2=py39h06a4308_0
shellingham=1.5.4=pypi_0
six=1.16.0=pypi_0
smmap=5.0.1=pypi_0
sniffio=1.3.1=pypi_0
sounddevice=0.4.6=pypi_0
sqlite=3.41.2=h5eee18b_0
stack-data=0.6.3=pypi_0
starlette=0.37.2=pypi_0
sympy=1.12=pypi_0
threadpoolctl=3.4.0=pypi_0
tifffile=2024.2.12=pypi_0
timm=0.6.13=pypi_0
tk=8.6.12=h1ccaba5_0
tokenizers=0.19.1=pypi_0
tomli=2.0.1=pypi_0
torch=2.2.2=pypi_0
torchsde=0.2.6=pypi_0
torchvision=0.17.2=pypi_0
tqdm=4.66.2=pypi_0
traitlets=5.14.3=pypi_0
trampoline=0.1.2=pypi_0
transformers=4.40.0=pypi_0
triton=2.2.0=pypi_0
typer=0.12.3=pypi_0
typer-config=1.4.0=pypi_0
types-setuptools=69.5.0.20240423=pypi_0
typing-extensions=4.11.0=pypi_0
tzdata=2024.1=pypi_0
uritemplate=4.1.1=pypi_0
urllib3=2.2.1=pypi_0
wcwidth=0.2.13=pypi_0
wget=3.2=pypi_0
wheel=0.41.2=py39h06a4308_0
widgetsnbextension=4.0.10=pypi_0
wrapt=1.16.0=pypi_0
xxhash=3.4.1=pypi_0
xz=5.4.6=h5eee18b_0
yapf=0.40.2=pypi_0
yarl=1.9.4=pypi_0
zipp=3.18.1=pypi_0
zlib=1.2.13=h5eee18b_0
Loading

0 comments on commit d5e3016

Please sign in to comment.