AI総合研究所

SHARE

X(twiiter)にポストFacebookに投稿はてなブックマークに登録URLをコピー

ComfyUIとは?導入方法や使い方、拡張機能について解説!

この記事のポイント

  • ComfyUIは、ノードベースの直感的なインターフェースでAI画像生成を効率化できるオープンソースツール
  • ノードベースのインターフェースで、画像生成プロセスを視覚的に構築・管理可能
  • Stable Diffusion、VAE、LoRAなど、多様なモデルを柔軟に組み合わせて高品質な画像を生成
  • txt2img、img2imgなど、様々な画像生成手法に対応し、豊富なカスタムノードで機能拡張が可能
  • ComfyUI Managerを使用することで、必要な拡張機能を簡単にインストール・管理可能

監修者プロフィール

坂本 将磨

Microsoft AIパートナー、LinkX Japan代表。東京工業大学大学院で技術経営修士取得、研究領域:自然言語処理、金融工学。NHK放送技術研究所でAI、ブロックチェーン研究に従事。学会発表、国際ジャーナル投稿、経営情報学会全国研究発表大会にて優秀賞受賞。シンガポールでのIT、Web3事業の創業と経営を経て、LinkX Japan株式会社を創業。

クリエイティブな画像生成の需要が高まる中、より使いやすく柔軟なAIツールが求められています。
そんな中で注目を集めているのが、ノードベースの直感的なインターフェースを特徴とする「ComfyUI」です。

しかし、その豊富な機能や設定方法について、どこから始めればよいか迷われている方も多いのではないでしょうか。

本記事では、ComfyUIの基本概念から実践的な使い方まで、詳しく解説します。インストール手順や基本的な画像生成の方法はもちろん、モデルやVAEの効果的な活用法、カスタムノードによる機能拡張まで、具体的な例を交えて紹介します。

特に、2024年10月にリリースされた最新バージョン「ComfyUI V1」の新機能や、テキストから画像生成(txt2img)、画像から画像生成(img2img)といった実践的な活用シーンについても詳しく説明していきます。

AI画像生成ツールの導入を検討されている方々に、本記事がComfyUIを理解し効果的に活用するための手引きとなれば幸いです。

ComfyUIとは

ComfyUI(コンフィユーアイ)は、AIを活用した画像生成に特化したユーザーインターフェイスで、特に「Stable Diffusion」などの生成モデルを簡単に操作できるよう設計されています。
このツールは、直感的なインターフェイスを提供し、技術的なバックグラウンドがなくても、誰でも手軽に高品質な画像を生成することが可能です。

ComfyUIの魅力は、その使いやすさと、ユーザーが必要とする調整や指示を自然言語で簡単に行える点にあります。これにより、AI画像生成のプロセスがより身近で効果的なものとなっています。
ComfyUIロゴ

ComfyUI V1のリリースについて

2024年10月21日に、ComfyUIを開発、メンテナンスしているComfy Orgより、最新アップデートとしてComfyUI V1のリリースがアナウンスされました。

ComfyUI V1になることで、主に以下のようなアップデートが行われます。

新しいユーザーインターフェース

UIが一新され、より使いやすくなりました。

ComfyUIV1のUI
ComfyUI V1のUI

新しいUIには、以下のような特徴があります。

機能 説明
トップメニューバー 多くの操作をメニューバーに統合、カスタムメニュー追加が容易
モデルやログへの簡単アクセス トレイアイコン右クリックで迅速にアクセス
モデルライブラリ モデルのブラウズとドラッグ&ドロップが可能
ワークフローブラウザ ワークフローの保存・管理が簡単に
自動モデルダウンロード 不足しているモデルの自動ダウンロード機能

完全にパッケージ化されたデスクトップバージョン

ComfyUIのデスクトップバージョンがリリースされます。このデスクトップバージョンには、以下のような特徴があります。

機能 説明
コード署名とセキュリティ ComfyUIはセキュリティ警告なしで起動し、コード署名済み
クロスプラットフォーム Windows、macOS、Linux対応
自動更新 常に最新バージョンに自動更新
軽量パッケージ 200MBの小サイズ
推奨Python環境同梱 簡単インストール
ComfyUIマネージャー搭載 最新ノードを簡単インストール
タブ機能 複数ワークフロー管理
カスタムキーバインド 自由に設定可能
リソース自動インポート 既存データを自動インポート
統合ログビューア デバッグ用ログ表示



このデスクトップバージョンは、クローズドベータとして既にリリースされています。今後は、オープンベータ版をリリースし、その際にソースコードもオープンソース化する予定だそうです。

以上が、ComfyUI V1の主な新機能と改善点です。このリリースにより、ユーザー体験が大幅に向上し、技術的な知識がない方でも簡単に利用できるようになりました。
公式のアナウンスに関してはこちらをご覧下さい。

画像生成研修


ComfyUIの主要機能

ComfyUIの画面ComfyUIの画面

ノードベースのワークフロー

ComfyUIは、ノードベースのインターフェイスを採用しており、ユーザーは視覚的にワークフローを構築することができます。こ
れにより、複雑な画像生成プロセスをシンプルに理解し、操作することが可能です。

カスタマイズ可能なフィルターとエフェクト

色調整やエフェクト、フィルターの適用など、多彩なオプションが用意されており、ユーザーは自分のニーズに合わせて画像を微調整できます。

多言語対応の指示入力

自然言語での指示入力をサポートしており、日本語や英語など、ユーザーが慣れ親しんだ言語でAIに指示を与えることができます。

高度な設定オプション

上級者向けに、より細かいパラメータ設定や、複数のモデルを組み合わせた生成プロセスのカスタマイズも可能です。
これにより、ユーザーはより専門的な結果を得ることができます。

リアルタイムプレビュー

操作内容をリアルタイムでプレビューできるため、生成結果を確認しながら効率的に作業を進めることができます。


ComfyUIの導入方法

今回は、Azureの仮想マシン(Linux)上でComfyUIをインストールする手順をご紹介します。

ComfyUIのリポジトリをクローン

まずは、ComfyUIのリポジトリをクローンしていきます。仮想マシンのターミナルを開き、以下のコマンドを実行して下さい。

git clone https://github.com/comfyanonymous/ComfyUI.git

クローンのコマンド入力
クローンのコマンド入力

すると、以下のようにリポジトリがインストールされます。

ComfyUIリポジトリのインストール完了ComfyUIリポジトリのインストール完了画面

以下のコマンドで、ComfyUIのディレクトリに移動しておきます。

cd ComfyUI

ComfyUIディレクトリへの移動ComfyUIディレクトリへの移動


仮想環境の立ち上げ

仮想環境を使用することで、ComfyUI専用の環境を作成し、他のPythonプロジェクトとの依存関係の競合を防ぐことができます。また、問題が発生した場合も環境を簡単にリセットできます。

ComfyUIを動作させるツールをPythonの仮想環境内にインストールし、それを用いてComfyUIを起動させます。


まずは、以下のコマンドを用いて、「comfy」という名前のComfyUI用の仮想環境を作成します。

python -m venv comfy

仮想環境の作成画面仮想環境の作成画面

次に以下を実行し、今作成した仮想環境をアクティベートして下さい。

source ./comfy/bin/activate

仮想環境のアクティベート仮想環境のアクティベート


ツールのインストール

仮想環境内でTorchをインストールします。以下を実行して下さい。

pip install torch torchvision torchaudio --extra-index-url https://download.pytorch.org/whl/cu121


ツールインストールコマンドの入力ツールインストールコマンドの入力

以下のようにインストールが進んで行きます。

ツールインストール中の画面ツールインストール中の画面

最終的に下記のような表示されたら、インストールは完了です。

ツールインストール完了画面ツールインストール完了画面

次に、必要な依存関係をインストールします。
下記のコマンドを実行して下さい。

pip install -r requirements.txt

依存関係インストールのコマンド入力依存関係インストールのコマンド入力

以下のような表示が出てきたら、依存関係のインストールが完了です。

依存関係インストールの完了画面依存関係インストールの完了画面


起動方法の選択

今回は、仮想マシンでComfyUIを起動します。

仮想マシンの性質上、ComfyUIにアクセスする方法は以下の2種類に分けられます。


選択した方の項目をご覧下さい。

ComfyUIを公開して様々なデバイスからアクセスする

ComfyUIを公開できるように、設定項目を編集します。
まずは、ComfyUIのディレクトリにいる事を確認し、以下の項目を実行して下さい。

rm main.py

mainファイルの削除mainファイルの削除

これによって、main.pyという名前のファイルが削除されます。

次に、以下のコマンドを実行し、同じ「main.py」という名前のファイルを作成・編集します。

nano main.py

編集画面起動のコマンド入力編集画面起動のコマンド入力

コマンドを実行すると、以下のように編集画面が立ち上がります。

編集画面の起動編集画面の起動

そこに、以下のコードを貼り付けて下さい。

なお、もともと用意されていた「main.py」ファイルのコードを、ComfyUIを公開するように修正したものとなります。


import comfy.options
comfy.options.enable_args_parsing()

import os
import importlib.util
import folder_paths
import time
from comfy.cli_args import args
from app.logger import setup_logger


setup_logger(verbose=args.verbose)


def execute_prestartup_script():
    def execute_script(script_path):
        module_name = os.path.splitext(script_path)[0]
        try:
            spec = importlib.util.spec_from_file_location(module_name, script_path)
            module = importlib.util.module_from_spec(spec)
            spec.loader.exec_module(module)
            return True
        except Exception as e:
            print(f"Failed to execute startup-script: {script_path} / {e}")
        return False

    if args.disable_all_custom_nodes:
        return

    node_paths = folder_paths.get_folder_paths("custom_nodes")
    for custom_node_path in node_paths:
        possible_modules = os.listdir(custom_node_path)
        node_prestartup_times = []

        for possible_module in possible_modules:
            module_path = os.path.join(custom_node_path, possible_module)
            if os.path.isfile(module_path) or module_path.endswith(".disabled") or module_path == "__pycache__":
                continue

            script_path = os.path.join(module_path, "prestartup_script.py")
            if os.path.exists(script_path):
                time_before = time.perf_counter()
                success = execute_script(script_path)
                node_prestartup_times.append((time.perf_counter() - time_before, module_path, success))
    if len(node_prestartup_times) > 0:
        print("\nPrestartup times for custom nodes:")
        for n in sorted(node_prestartup_times):
            if n[2]:
                import_message = ""
            else:
                import_message = " (PRESTARTUP FAILED)"
            print("{:6.1f} seconds{}:".format(n[0], import_message), n[1])
        print()

execute_prestartup_script()


# Main code
import asyncio
import itertools
import shutil
import threading
import gc

import logging

if os.name == "nt":
    logging.getLogger("xformers").addFilter(lambda record: 'A matching Triton is not available' not in record.getMessage())

if __name__ == "__main__":
    if args.cuda_device is not None:
        os.environ['CUDA_VISIBLE_DEVICES'] = str(args.cuda_device)
        logging.info("Set cuda device to: {}".format(args.cuda_device))

    if args.deterministic:
        if 'CUBLAS_WORKSPACE_CONFIG' not in os.environ:
            os.environ['CUBLAS_WORKSPACE_CONFIG'] = ":4096:8"

    import cuda_malloc

if args.windows_standalone_build:
    try:
        import fix_torch
    except:
        pass

import comfy.utils
import yaml

import execution
import server
from server import BinaryEventTypes
import nodes
import comfy.model_management

def cuda_malloc_warning():
    device = comfy.model_management.get_torch_device()
    device_name = comfy.model_management.get_torch_device_name(device)
    cuda_malloc_warning = False
    if "cudaMallocAsync" in device_name:
        for b in cuda_malloc.blacklist:
            if b in device_name:
                cuda_malloc_warning = True
        if cuda_malloc_warning:
            logging.warning("\nWARNING: this card most likely does not support cuda-malloc, if you get \"CUDA error\" please run ComfyUI with: --disable-cuda-malloc\n")

def prompt_worker(q, server):
    e = execution.PromptExecutor(server, lru_size=args.cache_lru)
    last_gc_collect = 0
    need_gc = False
    gc_collect_interval = 10.0

    while True:
        timeout = 1000.0
        if need_gc:
            timeout = max(gc_collect_interval - (current_time - last_gc_collect), 0.0)

        queue_item = q.get(timeout=timeout)
        if queue_item is not None:
            item, item_id = queue_item
            execution_start_time = time.perf_counter()
            prompt_id = item[1]
            server.last_prompt_id = prompt_id

            e.execute(item[2], prompt_id, item[3], item[4])
            need_gc = True
            q.task_done(item_id,
                        e.history_result,
                        status=execution.PromptQueue.ExecutionStatus(
                            status_str='success' if e.success else 'error',
                            completed=e.success,
                            messages=e.status_messages))
            if server.client_id is not None:
                server.send_sync("executing", { "node": None, "prompt_id": prompt_id }, server.client_id)

            current_time = time.perf_counter()
            execution_time = current_time - execution_start_time
            logging.info("Prompt executed in {:.2f} seconds".format(execution_time))

        flags = q.get_flags()
        free_memory = flags.get("free_memory", False)

        if flags.get("unload_models", free_memory):
            comfy.model_management.unload_all_models()
            need_gc = True
            last_gc_collect = 0

        if free_memory:
            e.reset()
            need_gc = True
            last_gc_collect = 0

        if need_gc:
            current_time = time.perf_counter()
            if (current_time - last_gc_collect) > gc_collect_interval:
                comfy.model_management.cleanup_models()
                gc.collect()
                comfy.model_management.soft_empty_cache()
                last_gc_collect = current_time
                need_gc = False

async def run(server, address='', port=8188, verbose=True, call_on_start=None):
    await asyncio.gather(server.start(address, port, verbose, call_on_start), server.publish_loop())


def hijack_progress(server):
    def hook(value, total, preview_image):
        comfy.model_management.throw_exception_if_processing_interrupted()
        progress = {"value": value, "max": total, "prompt_id": server.last_prompt_id, "node": server.last_node_id}

        server.send_sync("progress", progress, server.client_id)
        if preview_image is not None:
            server.send_sync(BinaryEventTypes.UNENCODED_PREVIEW_IMAGE, preview_image, server.client_id)
    comfy.utils.set_progress_bar_global_hook(hook)


def cleanup_temp():
    temp_dir = folder_paths.get_temp_directory()
    if os.path.exists(temp_dir):
        shutil.rmtree(temp_dir, ignore_errors=True)


def load_extra_path_config(yaml_path):
    with open(yaml_path, 'r') as stream:
        config = yaml.safe_load(stream)
    for c in config:
        conf = config[c]
        if conf is None:
            continue
        base_path = None
        if "base_path" in conf:
            base_path = conf.pop("base_path")
        for x in conf:
            for y in conf[x].split("\n"):
                if len(y) == 0:
                    continue
                full_path = y
                if base_path is not None:
                    full_path = os.path.join(base_path, full_path)
                logging.info("Adding extra search path {} {}".format(x, full_path))
                folder_paths.add_model_folder_path(x, full_path)


if __name__ == "__main__":
    if args.temp_directory:
        temp_dir = os.path.join(os.path.abspath(args.temp_directory), "temp")
        logging.info(f"Setting temp directory to: {temp_dir}")
        folder_paths.set_temp_directory(temp_dir)
    cleanup_temp()

    if args.windows_standalone_build:
        try:
            import new_updater
            new_updater.update_windows_updater()
        except:
            pass

    loop = asyncio.new_event_loop()
    asyncio.set_event_loop(loop)
    server = server.PromptServer(loop)
    q = execution.PromptQueue(server)

    extra_model_paths_config_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), "extra_model_paths.yaml")
    if os.path.isfile(extra_model_paths_config_path):
        load_extra_path_config(extra_model_paths_config_path)

    if args.extra_model_paths_config:
        for config_path in itertools.chain(*args.extra_model_paths_config):
            load_extra_path_config(config_path)

    nodes.init_extra_nodes(init_custom_nodes=not args.disable_all_custom_nodes)

    cuda_malloc_warning()

    server.add_routes()
    hijack_progress(server)

    threading.Thread(target=prompt_worker, daemon=True, args=(q, server,)).start()

    if args.output_directory:
        output_dir = os.path.abspath(args.output_directory)
        logging.info(f"Setting output directory to: {output_dir}")
        folder_paths.set_output_directory(output_dir)

    #These are the default folders that checkpoints, clip and vae models will be saved to when using CheckpointSave, etc.. nodes
    folder_paths.add_model_folder_path("checkpoints", os.path.join(folder_paths.get_output_directory(), "checkpoints"))
    folder_paths.add_model_folder_path("clip", os.path.join(folder_paths.get_output_directory(), "clip"))
    folder_paths.add_model_folder_path("vae", os.path.join(folder_paths.get_output_directory(), "vae"))
    folder_paths.add_model_folder_path("diffusion_models", os.path.join(folder_paths.get_output_directory(), "diffusion_models"))

    if args.input_directory:
        input_dir = os.path.abspath(args.input_directory)
        logging.info(f"Setting input directory to: {input_dir}")
        folder_paths.set_input_directory(input_dir)

    if args.quick_test_for_ci:
        exit(0)

    call_on_start = None
    if args.auto_launch:
        def startup_server(scheme, address, port):
            import webbrowser
            if os.name == 'nt' and address == '0.0.0.0':
                address = '127.0.0.1'
            webbrowser.open(f"{scheme}://{address}:{port}")
        call_on_start = startup_server

    # ここで listen アドレスを 0.0.0.0 に設定
    args.listen = '0.0.0.0'

    try:
        loop.run_until_complete(server.setup())
        loop.run_until_complete(run(server, address=args.listen, port=args.port, verbose=not args.dont_print_server, call_on_start=call_on_start))
    except KeyboardInterrupt:
        logging.info("\nStopped server")

    cleanup_temp()


コードの貼り付け完了コードの貼り付け完了

コードを貼り付ける事が出来たら、「Ctrl + O」>「Enter」>「Ctrl + X」でエディタを抜けます。

これで、ComfyUIを公開して様々なデバイスからアクセスする準備が出来ました。ComfyUIの起動へと移動して下さい。

VMのバーチャルデスクトップで起動

何もせず、次のComfyUIの起動に進んで大丈夫です。


ComfyUIの起動

それでは、ComfyUIを起動してみましょう。以下のコマンドを実行して下さい。

python main.py

ComfyUIの起動コマンドの入力ComfyUIの起動コマンドの入力

以下のように出力されます、一番下に表示されている赤枠で囲んだURLを控えて下さい。

ComfyUIの起動完了ComfyUIの起動完了

VMのバーチャルデスクトップで起動する方は、バーチャルデスクトップ上で、控えたURLにアクセスすることで、ComfyUIを開くことが出来ます。

ComfyUIを公開して様々なデバイスからアクセスする方は、控えたURLが「http://〇:△」のような形になっていると思います。〇部分を仮想マシンのパブリックIPアドレスに変更し、それを検索バーに入力することで、ComfyUIへとアクセスすることが出来ます。

「http:// {パブリックIPアドレス}:△」

URLにアクセスしてみると、以下のようにCompyUIの起動が確認出来ました。

CompyUIの起動完了CompyUIの起動完了

ComfyUIでは上記のように、画像生成のプロセスをノードベースで直感的に組み立てることが出来ます。


ComfyUIの使い方

それでは、ComfyUIの実際の使い方についてご紹介します。

用語解説

まずは具体的な使い方の前に、ComfyUIの核となるノードワークフローの2つの用語について解説します。

ノード

ノードは、画像生成プロセスの各ステップを実行する基本単位です。
各ノードは、特定のタスク(例:テキストのエンコード、画像の生成、画像のデコードなど)を担当し、それぞれが独立して機能します。

ワークフロー

ワークフローは、複数のノードをつなぎ合わせて、画像生成の一連のプロセスを構成するものです。
ワークフローを作成することで、ノード同士のデータフローを視覚的に定義し、複雑な画像生成プロセスを管理できます。

つまり、下記の画像において、いくつもあるグレーの四角形の部品のようなものをノードと呼び、それらが繋がりあっている全体をワークフローと呼びます。

用語解説用語解説


モデルのダウンロード

実際に画像を生成するには、モデルやVAEを用意する必要があります。
そのため、一旦ComfyUI上ではなく、仮想マシンのターミナル上で作業します。

モデル等の用意には主に以下の2種類の方法があります。

  • ComfyUI上に直接ダウンロードする方法
  • 既にあるStable diffusion webuiのモデルと共有する方法です。

ComfyUI上に直接ダウンロードする方法

CompyUIのディレクトリの中には、以下のように「models」というフォルダがあります。

CompyUIのディレクトリの中身CompyUIのディレクトリの中身

そして、「models」の中には、以下のように様々なフォルダが用意されています。

modelsの中身modelsの中身

モデル等の用意をするには、これらの中の該当フォルダに保存して下さい。

例えば、モデルをダウンロードするなら「checkpoints」に、VAEをダウンロードするなら「vae」に保存するという具合です。

Stable Fiffusion WebUIのモデルと共有する方法

ComfyUI専用でモデル等をダウンロードしていると、ストレージを圧迫してしまいます。
そこで、既にStable diffusion webuiを使用しており、そこにモデル等が保存されている場合、ComfyUIにもそのモデルを共有する事が出来ます。

まずは、forgeのパスを取得します。以下のコマンドを順に実行して下さい。

cd ~/stable-diffusion-webui-forge
pwd

すると、下記のようにforgeのパスを取得出来ました。

forgeのパス取得forgeのパス取得

次は、順に以下のコマンドを実行して下さい。

cd ~/ComfyUI
nano extra_model_paths.yaml.example

編集画面起動のコマンド入力編集画面起動のコマンド入力

すると、編集画面が起動します。

パス編集画面の起動パス編集画面の起動

赤枠で囲んだ部分を削除し、先ほど取得したforgeのパスを取得します。

パスの編集内容パスの編集内容

以下のように貼り付けることが出来ました。

forgeのパス貼り付け完了forgeのパス貼り付け完了

「Ctrl + O」>「Enter」>「Ctrl + X」でエディタを抜けます。

次に、以下のコマンドを実行し、ファイル名を変更します。

mv extra_model_paths.yaml.example extra_model_paths.yaml

ファイルの名称変更ファイルの名称変更

これで、モデルを共有して使用することが出来るようになりました。


基本操作

画面の移動

ダブルクリックしてスクロール

右クリック > 「Add Node」 > 追加したいノードの選択
右クリックによるノードの追加右クリックによるノードの追加

  • ダブルクリックの場合
    ダブルクリック > 検索バーに名前を入力 > 表示された中から追加したいノードを見つけてクリック
    ダブルクリックによるノードの追加ダブルクリックによるノードの追加

ノードの接続

接続元のポートをドラッグし、接続先のポートにドロップ

ドラッグ中ドラッグ中
ドラッグして

ドロップ後ドロップ後
ドロップする

ノードの削除

ノードを選択し、「Delete」または「Backspace」

ノードの削除1ノードの削除1

ノードを選択すると、白い枠線が出る。
この状態で、「Delete」または「Backspace」をすると、以下のように削除できる

ノードの削除2ノードの削除2

作成したワークフローの保存

右バーの「Save」をクリック > 任意の名前を入力 > 「OK」をクリック

まずは、右バーにある「Save」をクリックします。
SaveのクリックSaveのクリック

以下のような表示が出てくるので、お好きな名前を入力し、その後「OK」をクリックします。
名前の入力名前の入力

なお、ご自身のローカルPCにjsonファイルが保存されます。

ダウンロードしたワークフローの利用方法

右バーの「Load」をクリック > 使用するワークフローを選択 > 「開く」をクリック

右バーの「Load」をクリックします。

LoadのクリックLoadのクリック

ローカルPC内のファイル一覧が表示されるので、使用したいワークフローを選択して下さい。なおここで選択するファイルの形式は、jsonファイル以外にも、pngファイルで動作することが確認出来ました。
使用するワークフローの選択使用するワークフローの選択

ワークフローを選択したら、右下の「開く」をクリックします。
使用するワークフローの起動使用するワークフローの起動


ComfyUIの各機能の使い方

ノードを組み合わせてワークフローを構築していくという流れになります。ワークフローを構築することで、自由に画像生成の処理を行うことが出来ます。

例えば、入力を画像にしたり、はじめに画像が生成された後に解像度を上げたり、ノイズの除去をすることで、さらに良い出力を狙うといった事が出来るようになります。

ここで、ワークフローはネット上で公開されているものがあり、基本的にはそれらをダウンロードして利用する事が多いです。

テキストから画像生成(txt2img)

まずは最も基本的な、テキストから画像を生成(txt2imgという)する事を試してみましょう。

ComfyUIの初期起動時には、txt2imgのワークフローの大枠が用意されているので、これを活用していきます。

まずは、「Load Checkpoint」でモデルを選択します。

モデルの選択モデルの選択

次に、プロンプトを入力します。「CLIP Text Encode(Prompt)」に入力していく事になります。

なお、下記のようにノードに注目すると、上が「positive」、下が「negative」に接続されている事が分かります。
従って、上にはプロンプトを、下にはネガティブプロンプトを入力します。

プロンプトの入力プロンプトの入力

最後に、右バーの「Queue Prompt」をクリックすることで画像を生成することが出来ます。
画像生成の実行画像生成の実行

すると以下のように、生成された画像が表示されました。
生成された画像1生成された画像1

なお生成された画像は、「ComfyUI」ディレクトリの中の「output」フォルダの中に保存されていきます。

ComfyUIで生成した画像の保存場所ComfyUIで生成した画像の保存場所


VAEの追加

次は、任意のVAEを追加してみましょう。なお、先程のモデルも変えています。

まずは、「Load VAE」のノードを追加します。

VAEノードの追加VAEノードの追加

次に、「Load VAE」と「VAE Decode」を接続します。この際、「Load Checkpoint」との接続は自動で解除されます。

VAEノードの接続VAEノードの接続

「Load VAE」で任意のVAEを選択し、画像を生成してみましょう。

VAE導入後に生成された画像1VAE導入後に生成された画像1

解説したワークフローでしっかり画像を生成することが出来ました。


プロンプトに活用するモデルの変更

ここで、プロンプトとネガティブプロンプトに使用するモデルを異なるものにしてみます。

先ほどVAEを追加したワークフローの中で、ネガティブプロンプトに使用するモデルを以下のように変更しました。

プロンプトに活用するモデルの変更プロンプトに活用するモデルの変更

以下が、生成された画像です。

プロンプトに活用するモデルを変更して生成された画像プロンプトに活用するモデルを変更して生成された画像


画像から画像生成(img2img)

それでは、既存の画像に対して何らかの変換を施し、新しい画像を生成する事を試してみましょう。
ワークフローは、こちらからダウンロードしたものを使用します。

サイトにアクセスすると、以下のような画面が表示されます。

サイトにアクセスワークフローの参照先

下部にある画像を右クリックし、任意の名前を付けて保存します。

img2img画像の保存img2img画像の保存

ComfyUI内の「Load」にて、先ほど保存したファイルを選択します。

img2imgの選択img2imgの選択

以下のように、img2imgのワークフローが読み込まれました。

img2imgワークフローの起動img2imgワークフローの起動

「開く」をクリックしても、反映されない場合は、何回か繰り返したり、ComfyUIに入り直してLoadし直すことで上手く行く場合があります。

img2imgを使用する際は、下記のように「choose file to upload」をクリックし、入力したい画像を選択します。

入力画像のアップロード入力画像のアップロード

以下のような画像を設定してみました。

入力画像のアップロード完了入力画像のアップロード完了

モデルを選択し、以下のプロンプトを入力しました。金髪を青髪にするのが狙いです。

1girl, blue hair


以下が、生成された画像です。

img2img生成画像img2img生成画像

以下が元画像です。

img2img元画像img2img元画像

適当にパラメータを設定したので、完全に髪色だけ変更できた訳ではありませんが、なかなか良い出力だと思います。


各種ノードの解説

デフォルトのワークフローデフォルトのワークフロー

簡単に、デフォルトのワークフローにあるノードを解説して行きたいと思います。各ノードが参照しているフォルダは、モデル等のダウンロードセクションにて設定したパスを参照しています。

Load Checkpoint

LoadCheckpointLoad Checkpoint

「Load Checkpoint」では、チェックポイントを選択します。つまり、使用するAIモデルを指定します。

CLIP Text Encode

CLIPTextEncodeCLIP Text Encode

「CLIP Text Encode」では、プロンプトを入力します。ノ
ードの接続先を確認してみると、上がpositive、下がnegativeへと接続されています。

これは、上のノードがポジティブプロンプト、下のノードがネガティブプロンプトであることを表しています。

Empty Latent Image

EmptyLatentImageEmpty Latent Image

「Empty Latent Image」では、生成される画像のサイズと、バッチ処理の数を決める事が出来ます。バッチ処理の数を大きくすることで、効率的に処理を行うことが出来ます。

KSamplerKSampler

KSampler

KSamplerでは、画像生成プロセスで使用されるサンプリングアルゴリズムを選択し、パラメータを決定します。また、ここで生成される画像は、潜在空間の画像であり、人間の目で直接見ることができる形ではありません。

VAE Decode

VAEDecodeVAE Decode

「VAE Decode」では、潜在空間の画像をピクセル空間の画像、つまり私たちが視覚的に認識できる画像に変換しています。

SaveImageSave Image

Save Image

「Save Image」では、画像をフォルダに保存します。

実用上は、カスタムノードといって、ComfyUIのワークフローに新たな機能や処理を追加するための拡張モジュールを使用する事が多いです。
これにより、標準ノードでは実現できない独自の処理や特定のニーズに対応することが可能になります。


拡張機能

カスタムノードを管理するのに便利な「ComfyUI Manager」のインストール方法を解説します。
以下のコマンドを実行して下さい。

cd ~/ComfyUI/custom_nodes
git clone https://github.com/ltdrdata/ComfyUI-Manager.git

ComfyUIManagerのインストール中

これでインストールが完了です。ComfyUIを開くと、以下のように「Manager」と「Share」のタブが追加されていることが確認できます。

ComfyUIManagerインストール後の画面

これを使用することで、カスタムノードを簡単に管理することが出来ます。

「Maneger」をクリックしてみると、以下のような表示が出てきます。

ComfyUIManagerの表示ComfyUIManagerの表示

例えば、ネットから持って来た何かしらのワークフローを使用しようとした時に、そのワークフローがカスタムノードを使用していた場合、その時点でのあなたのComfyUIは持ってきたワークフローを使用することが出来ません。

そんな時は、以下の「Install Missing Custom Nodes」を使用することで、数クリックで足りないカスタムノードをインストールすることが出来ます。

InstallMissingCustomNodesInstall Missing Custom Nodes


2回目以降の起動方法

2回目以降は、以下を実行する事で、ComfyUIを起動出来ます。

source ./comfy/bin/activate
cd ~/ComfyUI
python main.py

ComfyUIの商用利用について

ComfyUI自体はオープンソースであり、商用利用も可能です。

しかし、ComfyUIを使って画像を生成し、それを商用利用する場合、いくつかの注意点があります。

1.使用するモデルのライセンス

ComfyUIはStable Diffusionなどの画像生成モデルを利用しますが、モデルごとにライセンスが異なります。商用利用可能なモデルとそうでないモデルがあるので、使用するモデルのライセンスをよく確認する必要があります。

例えば、Stable Diffusion 1.5はCreativeML Open RAIL-Mライセンスで、商用利用が可能です。しかし、Stable Diffusion 2.1はCreativeML Open RAIL++-Mライセンスで、商用利用が制限されています。

2.生成画像の著作権

生成された画像の著作権は、一般的にその画像を生成した人に帰属するとされています。しかし、著作権に関する法律や解釈は国や地域によって異なる場合があり、まだ明確に定まっていない部分もあります。
そのため、生成画像を商用利用する場合は、法的なリスクを理解しておく必要があります。

3. 倫理的な問題*

生成AI技術は急速に発展しており、倫理的な問題も議論されています。例えば、他人の著作物を無断で学習データとして使用することや、差別的な画像を生成することなどが問題視されています。
ComfyUIを商用利用する場合は、これらの倫理的な問題にも配慮する必要があります。

より詳しく知りたい場合は、以下の情報を参考にしてください。

ComfyUIを商用利用する場合は、上記の点に注意し、責任を持って使用してください。

AI駆動開発


まとめ

本記事では、ノードベースのAI画像生成インターフェース「ComfyUI」について、基本的な概念から実践的な使い方まで解説しました。特に2024年10月にリリースされたComfyUI V1は、デスクトップアプリケーション化やUI改善により、より直感的な操作性を実現しています。

インストール手順から始まり、テキストから画像生成(txt2img)や画像から画像生成(img2img)といった基本機能、さらにはStable DiffusionモデルやVAEの効果的な活用方法まで、具体例を交えて紹介しました。また、ComfyUI Managerを使用した拡張機能の管理方法についても説明し、より高度な画像生成を可能にする方法を示しました。

ComfyUIの特徴である視覚的なワークフロー構築により、複雑な画像生成プロセスも直感的に理解・管理できます。カスタムノードによる機能拡張や、充実したモデル管理機能を活用することで、よりクリエイティブな画像生成が可能となります。AIを活用した画像生成に興味がある方々にとって、ComfyUIは強力なツールとなるでしょう。

AI活用のノウハウ集「AI総合研究所」サービスご紹介資料

「AI総合研究所 サービス紹介資料」は、AI導入のノウハウがないというお客様にも使いやすい最先端のAI導入ノウハウを知れる資料です。

資料ダウンロード
監修者

坂本 将磨

Microsoft AIパートナー、LinkX Japan代表。東京工業大学大学院で技術経営修士取得、研究領域:自然言語処理、金融工学。NHK放送技術研究所でAI、ブロックチェーン研究に従事。学会発表、国際ジャーナル投稿、経営情報学会全国研究発表大会にて優秀賞受賞。シンガポールでのIT、Web3事業の創業と経営を経て、LinkX Japan株式会社を創業。

関連記事

AI導入の最初の窓口。

お悩み・課題に合わせて活用方法をご案内いたします。
お気軽にお問合せください。

AI総合研究所 Bottom banner

ご相談
お問い合わせは
こちら!