Extensions/ComfyUI-QualityGate
ComfyUI Extension

ComfyUI-QualityGate

顔→人物生成でブレる頭サイズ比(頭幅/肩幅)と顔の一致を、参照に近い順へ自動ランキング。顔類似×頭サイズ比×鮮鋭度の合成スコアで選別し、合格分だけ納品するComfyUIカスタムノード。

By nobu1990·Created 2 months ago·Updated 2 months ago· 0
nobu1990/ComfyUI-QualityGate
Nodes
On cloudLocal install
Stars0
Updated2 months ago
Readme

ComfyUI-QualityGate

「顔写真 → 人物生成」で毎回ブレる頭サイズ比(頭幅/肩幅)と顔の一致を、参照(お手本)に近い順へ自動ランキングする ComfyUI カスタムノード。 バッチ生成した候補を受け取り、顔類似 × 頭サイズ比 × 鮮鋭度を合成スコア化 → 近い順に並べ替え → 合格分だけを納品する。

InstantID / PhotoMaker / IP-Adapter / PuLID などで人物を生成すると、顔は似ていても頭サイズ比が崩れたり、逆に比率は良いが顔が別人化したりする。従来は 数十枚生成して手作業で外れを捨てるのが標準手順。そこを定量化して自動化する。

既存の選別ノードとの違い: Aesthetic Score / PickScore / ImageReward などは「絵の綺麗さ」は測れるが、 頭サイズ比が参照と合っているか本人の顔を保っているか は測れない。本ノードは pose 幾何(耳/肩)と 顔埋め込み(ArcFace)で その2つを直接計測 し、綺麗さではなく「お手本への一致度」で選ぶ。


何を測って選んでいるか

how it works

参照(お手本)の頭サイズ比 R = 耳幅 / 肩幅 を基準に、バッチ各画像の R を計測してズレを採点する(上図の左が"比率"のお手本 = proportion_reference)。 上図の BEST(ΔR=0.001, score 0.94)と WORST(ΔR=0.029, score 0.51)のように、 node は比率差と顔類似を定量化して順位化する。R は頭幅/肩幅の比なので上半身クロップでも全身でも測れる(本デモは上半身)。「綺麗さ」ではなく「参照からの逸脱」を数値で選ぶのが核。

Before / After(実バッチ 40枚 → 上位8枚)

同一人物・別 seed で生成した40枚(背景もバラバラ)を CompositeRank(顔類似 × 頭サイズ比 × 鮮鋭度)で全採点し、参照に近い順へ並べた。背景の違いに釣られず、顔と比率で連続スコアの順位が付く。

| Before:生成そのまま(40枚・score降順) | After:上位8枚(自動選別・納品分) | |---|---| | before | after |

参照(左: face_reference / 右: proportion_reference)。顔のお手本と比率のお手本は別々に指定でき、別人でもよい:

reference

指標の設計 — 「美しさ」ではなく「計測」

頭サイズ比の"良し悪し=美"は定義不能な地雷なので主張しない。代わりに 参照画像からの逸脱を数値化して近い順に並べる。

計測指標(実データで検証・確定):

R = 耳〜耳の距離(頭幅) / 肩幅        ※微小クロップ K 回の平均 (TTA) で算出

| 設計判断 | 根拠(実測) | |---|---| | 頭幅に 耳〜耳 (Pose 7,8) を採用 | 髪が下に伸びても不変=髪型に頑健。髪で耳が隠れても Pose が位置推定し、可視/不可視で挙動が変わらない(分岐不要) | | 肩幅 (Pose 11,12) を基準 | body スケールに正規化=クロップ・距離に不変 | | TTA (K枚クロップ平均) で測定 | 単発はキーポイント揺れ std≈0.006 が信号 std≈0.012 の半分を占める(指標検証時の値)。K枚平均でノイズを 1/√K に低減し、S/N ≈ 70.01 の比率差を識別可能 に | | 採点は 指数減衰 exp(-|ΔR|/tol) | ハードクランプだと参照がバッチから離れた際に全画像0点で飽和し順位が付かない。指数減衰なら遠くても単調に下がり常に近い順へランキングできる |

旧案「髪込み頭面積 ÷ 胴体長²」は (1) 長い髪で過大 (2) 全身画像の小さい顔で顔検出が失敗、のため不採用。耳〜耳は顔検出もセグメントも顎ラインも要らず最も頑健。

精度・速度(実バッチ40枚での実測)

| 指標 | 値 | |---|---| | 頭サイズ比 R の計測分解能(TTA後 S/N) | ≈ 7(ΔR ≈ 0.01 を識別) | | 実バッチ40枚の R ばらつき | 0.389–0.426(std 0.0073) =目視困難な微差を定量ランク | | 顔類似スコアのばらつき | 0.52–0.95 =同一人物でも角度/崩れで分離 | | 1枚あたり処理時間 | ≈ 0.5 s(pose + ArcFace + 鮮鋭度、pose は CPU 実行) | | 選別 | 40枚を全採点 → 上位 k 枚を自動抽出(目視選別を置換)。決定的=同入力で順位再現 |

採点は多軸合成。合成スコアの内訳(同バッチの最上位/最下位):

| | identity(顔類似) | proportion(頭サイズ比) | sharpness(鮮鋭度) | 合成 | |---|---|---|---|---| | 1位 (best) | 0.93 | 0.93 | 1.00 | 0.94 | | 40位 (worst) | 0.64 | 0.24 | 0.81 | 0.51 |

最下位は3軸すべてが低い(顔がやや外れ・頭サイズ比が離れ・わずかにボケ)。最上位は全軸が高く、複数の妥協点を1つの合成スコアで解いているのが分かる。


ノード

すべて QualityGate カテゴリに登録される。

★ Composite Rank — 顔類似 × 頭サイズ比 × 鮮鋭度で総合ランキング(本パックの主力)

参照顔とお手本の頭サイズ比に総合で近い順へバッチを並べ替える。顔類似と比率はしばしば相反する(顔を寄せると頭サイズ比が崩れる)ため、重み付き合成で最適な妥協点を選ぶ。

| 入力 | 内容 | |---|---| | face_reference | 保持したい本人の顔(正解の頭) | | proportion_reference | 目標の頭サイズ比のお手本(正解の比率) | | images | 並べ替え対象バッチ | | w_identity / w_proportion / w_sharpness | 各軸の重み(0で無効化) | | tolerance | 頭サイズ比採点の e-folding スケール(小さいほど近さに敏感, 既定 0.02) |

出力: ranked_images(近い順)/ best_image(1位)/ report(軸ごとの内訳スコア)

★ Composite Rank Folder — 大量候補向け・メモリ非依存

上と同じ採点式で、フォルダを1枚ずつストリーミング採点する。画像を全部メモリに載せず [読込→採点→破棄] するので、候補が何百枚でも RAM は top_k 枚ぶんしか使わない。二段構成の第2段(後述)。

folder は ComfyUI の output/ 配下サブフォルダをドロップダウンで選択。出力: top_images / best_image / report

Proportion Match Rank — 頭サイズ比だけで並べ替え

顔参照が不要なケース向けの軽量版。reference(お手本1枚)+ images → 頭サイズ比が近い順。出力: ranked_images / best_image / target_ratio / report

このほか、参照不要の汎用QAノード(顔の有無・ボケ検出)も同梱しているが、本パックの主眼は上記3ノードによる「参照一致ランキング」。


二段構成(VRAM対策)

候補を多く出すと、サンプラーが全 latent を一括処理して VRAM OOM になる。そこで生成と選別を分離する:

  1. Stage 1(生成専用): RepeatLatentBatch を小さく保ち、SaveToFolder で候補をフォルダへ書き出す。Queue を複数回まわすと候補が積み上がる。
  2. Stage 2(選別): CompositeRankFolder が同じフォルダを1枚ずつ採点し、上位だけ納品。

サンプルは example_workflows/qwen_FAST_generate_candidates.json(Stage 1)/ stage2_rank_folder.json(Stage 2)。


インストール

cd ComfyUI/custom_nodes
git clone https://github.com/nobu1990/ComfyUI-QualityGate
pip install -r ComfyUI-QualityGate/requirements.txt

| 機能 | 追加依存 | 無い場合の挙動 | |---|---|---| | 鮮鋭度・基本画像処理 | opencv-python, numpy | — | | 頭サイズ比(Proportion / Composite) | mediapipe(Pose) | 該当軸を skipped にしてカスケードを壊さない | | 顔類似(Composite の identity 軸) | insightface + onnxruntime(-gpu) + buffalo_l | w_identity を自動的に 0 扱い |

ComfyUI を再起動すると QualityGate カテゴリにノードが追加される。pose モデルは初回に models/ へ自動DLされる。

動作確認環境(Tested on)

以下で動作確認済み。これ以外でも動くが、特に identity 軸は insightface のバージョン差に注意(本実装は高レベル API を使わず ONNX を直接ロードして回避している)。

  • Windows 11 / Python 3.11
  • opencv-python 4.13 / numpy 2.4
  • mediapipe 0.10.35(pose、CPU 実行)
  • onnxruntime-gpu 1.26(ArcFace。CUDA / CPU どちらでも動作)
  • insightface 0.2.1

GPU は任意。 頭サイズ比の pose 計測は CPU、顔類似の ArcFace は CPU/GPU どちらでも動く(1枚あたり ≈ 0.5 s は CPU pose での実測)。

使い方

example_workflows/composite_rank_demo.json を ComfyUI にドラッグ&ドロップ。実運用では VAEDecode の IMAGE 出力を CompositeRankimages に繋ぎ、best_image(または ranked_images の上位)を SaveImage に送る。大量候補なら二段構成を使う。

開発 / テスト

ComfyUI や torch 無しで検出ロジックを検証できる(設計上、計測は純粋関数):

python tests/test_body_proportion.py   # 頭サイズ比の計測・採点
python tests/test_identity.py          # 顔類似スコア
python tests/test_cascade.py           # 汎用QAカスケード
python tests/test_nodes.py             # ノード配線の統合テスト

設計の考え方

計測 → スコア化 → 閾値で自動選別」という単純な骨格を、計測の中身を差し替えるだけで拡張できるようにしている。いまは頭サイズ比(pose 幾何)・顔類似(ArcFace)・鮮鋭度を測っているが、同じ枠組みに新しいチェック(例: プロンプト指示追従)を後から足せる。

ロードマップ:

  • [ ] 複数物体プロンプトの指示追従検証(VLM 分解照合 / VQAScore 系。既存ノードに未パッケージの空白)
  • [ ] リトライループのサンプルワークフロー

License

MIT