初回コミット

This commit is contained in:
e
2024-10-03 14:34:58 +09:00
committed by GitHub
parent c5e4a91008
commit 2398891a6e
4 changed files with 246 additions and 0 deletions
+53
View File
@@ -0,0 +1,53 @@
# ComfyUI-Load-DirectoryFiles
## 概要
[ComfyUI](https://github.com/comfyanonymous/ComfyUI)のCustomNode
指定したディレクトリにあるプロンプト(txt)と画像(png)を読み込みます。
indexを指定することで、指定したファイルを出力します。
これは、計画した画像生成をすることを想定して作りました。
プロンプトと画像を合わせて参照することで、プロンプトだけでは描きにくい問題を緩和します。
例えば、ControlNetやi2iを使用することでプロンプトを補うことができるため、試行回数を減らすことに繋がります。
## ファイル形式について
以下のように、同じ番号で名前を付けたテキストと画像の組み合わせを1つのフォルダに格納します。なお、ネガティブプロンプトも対応させたので、名前に"_n"を付けています
```
# プロンプト
001.txt
002.txt
003.txt
# 画像
001.png
002.png
003.png
# ネガティブプロンプト
001_n.txt
002_n.txt
003_n.txt
```
## 前提
- ComfyUIのインストールを完了していること
## 導入
```
git clone educator-art/ComfyUI-Load-DirectoryFiles ./custom_node
```
## 応用
ComfyUIの[basic_api_example.py](https://github.com/comfyanonymous/ComfyUI/blob/master/script_examples/basic_api_example.py)を参考にしてComfyUIのAPIを活用したプログラムを作成し、指定した枚数の画像生成を自動化しました。 これにより、当初の目的を実現できました。
※ 応用は拡張機能の範囲外となりますので、詳しい方法は割愛します。
## ライセンス
- GPL-3.0 License
+10
View File
@@ -0,0 +1,10 @@
from .nodes.nodes import *
from .nodes.nodes_advanced import *
NODE_CLASS_MAPPINGS = {
"Load Images and Prompts from Directory": LoadImageAndPromptsFromDirectory,
"Load Images and Prompts from Directory(Advanced)": LoadImageAndPromptsFromDirectory_Advanced,
}
print("Load Class: LoadImageAndPromptsFromDirectory")
print("Load Class: LoadImageAndPromptsFromDirectory_Advanced")
+84
View File
@@ -0,0 +1,84 @@
import numpy as np
import torch
from PIL import Image
import os
import glob
class LoadImageAndPromptsFromDirectory:
def __init__(self):
self.max_len = 0
self.text_files_path = []
self.text_negative_files_path = []
self.image_files_path = []
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"dir": (
"STRING",
{"multiline": False, "default": "Please input Directory Path"},
),
"files_index": (
"INT",
{"default": 0, "min": 0, "max": 4096},
),
}
}
RETURN_TYPES = ("STRING", "STRING", "IMAGE")
FUNCTION = "load_data"
OUTPUT_NODE = True
CATEGORY = "Load Images and Prompts from Directory"
def check_directory(self, dir):
if not os.path.isdir(dir):
raise ValueError(f"指定されたディレクトリが存在しません: {dir}")
image_files = sorted(glob.glob(os.path.join(dir, "*.png")))
text_files = sorted(glob.glob(os.path.join(dir, "*.txt")))
text_files = [f for f in text_files if not f.endswith('_n.txt')]
text_files_negative=sorted(glob.glob(os.path.join(dir, "*_n.txt")))
if image_files == 0 or text_files == 0:
raise RuntimeError("テキストファイルか画像ファイルが存在しません。")
if len(image_files) != len(text_files):
raise ValueError("テキストファイルと画像ファイルの数が一致しません。")
self.text_files_path = text_files
self.text_negative_files_path=text_files_negative
self.image_files_path = image_files
self.max_len = len(image_files)
def pil_to_tensor(self, image: Image.Image) -> torch.Tensor:
return torch.from_numpy(np.array(image).astype(np.float32) / 255.0).unsqueeze(0)
def load_data(self, dir, files_index):
if self.max_len == 0:
self.check_directory(dir)
text_name = os.path.splitext(
os.path.basename(self.text_files_path[files_index])
)[0]
image_name = os.path.splitext(
os.path.basename(self.image_files_path[files_index])
)[0]
if text_name != image_name:
raise ValueError("プロンプトと画像のファイル名が一致しません。")
with open(self.text_files_path[files_index], "r", encoding="utf-8") as file:
prompt_string = file.read()
with open(self.text_negative_files_path[files_index], "r", encoding="utf-8") as file:
prompt_negative_string = file.read()
image = Image.open(self.image_files_path[files_index]).convert("RGB")
image_tensor = self.pil_to_tensor(image)
return (prompt_string, prompt_negative_string, image_tensor)
+99
View File
@@ -0,0 +1,99 @@
"""
2024.10.02 Created
Automatic1111 WebUIのBreak文、ComfyUIへPromptをSplitして出力する対応
"""
import numpy as np
import torch
from PIL import Image
import os
import glob
class LoadImageAndPromptsFromDirectory_Advanced:
def __init__(self):
self.max_len = 0
self.text_files_path = []
self.text_negative_files_path = []
self.image_files_path = []
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"dir": (
"STRING",
{"multiline": False, "default": "Please input Directory Path"},
),
"files_index": (
"INT",
{"default": 0, "min": 0, "max": 4096},
),
}
}
# Automatic 1111 Web UIのPromptのBreak文に対応(Break文:5件対応なので最大、6件のプロンプト文)
RETURN_TYPES = ("STRING", "STRING", "STRING", "STRING", "STRING", "STRING", "STRING", "IMAGE")
RETURN_NAMES = ("1st prompt", "2nd prompt", "3rd prompt","4th prompt","5th prompt" , "6th prompt", "negative prompt", "image")
FUNCTION = "load_data"
OUTPUT_NODE = True
CATEGORY = "Load Images and Prompts from Directory"
def check_directory(self, dir):
if not os.path.isdir(dir):
raise ValueError(f"指定されたディレクトリが存在しません: {dir}")
image_files = sorted(glob.glob(os.path.join(dir, "*.png")))
text_files = sorted(glob.glob(os.path.join(dir, "*.txt")))
text_files = [f for f in text_files if not f.endswith('_n.txt')]
text_files_negative=sorted(glob.glob(os.path.join(dir, "*_n.txt")))
if image_files == 0 or text_files == 0:
raise RuntimeError("テキストファイルか画像ファイルが存在しません。")
if len(image_files) != len(text_files):
raise ValueError("テキストファイルと画像ファイルの数が一致しません。")
self.text_files_path = text_files
self.text_negative_files_path=text_files_negative
self.image_files_path = image_files
self.max_len = len(image_files)
def pil_to_tensor(self, image: Image.Image) -> torch.Tensor:
return torch.from_numpy(np.array(image).astype(np.float32) / 255.0).unsqueeze(0)
def load_data(self, dir, files_index):
if self.max_len == 0:
self.check_directory(dir)
text_name = os.path.splitext(
os.path.basename(self.text_files_path[files_index])
)[0]
image_name = os.path.splitext(
os.path.basename(self.image_files_path[files_index])
)[0]
if text_name != image_name:
raise ValueError("プロンプトと画像のファイル名が一致しません。")
with open(self.text_files_path[files_index], "r", encoding="utf-8") as file:
prompt_string = file.read()
# 追記
prompt_split_string = ["", "", "", "", "", ""]
prompt_string = prompt_string.replace("\n", "").strip()
segments = [segment for segment in prompt_string.split("BREAK,")]
for i in range(min(len(segments), len(prompt_split_string))):
prompt_split_string[i] = segments[i]
with open(self.text_negative_files_path[files_index], "r", encoding="utf-8") as file:
prompt_negative_string = file.read()
image = Image.open(self.image_files_path[files_index]).convert("RGB")
image_tensor = self.pil_to_tensor(image)
# 修正
return (prompt_split_string[0],prompt_split_string[1],prompt_split_string[2],prompt_split_string[3],prompt_split_string[4],prompt_split_string[5], prompt_negative_string, image_tensor)