Skip to content

BondAI-Japan/ui-visual-diff

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ui-visual-diff

AI 生成 UI 画像 (banner / GPT-Image / 概念図) と実装した HTML/React コンポーネントの screenshot を比較するための CLI ツール。LLM judge への evidence として使う。

何ができるか

6 つのアルゴリズムで 2 枚の UI 画像を比較し、それぞれ「何が違うか」を異なる角度から可視化します。

ツール 何を見る 出力 使いどころ
pixel-diff RGB ピクセル絶対差 赤ハイライト diff PNG + ratio HTML→HTML regression。AI 画像比較ではほぼ常に大差で参考程度
ssim 局所構造類似度 (Canny 前処理 + SSIM) ヒートマップ PNG + global SSIM 色味やテクスチャを無視して構造だけ比較
canny エッジ抽出 + IoU 個別エッジ PNG + 赤青 overlay PNG + IoU 数値 「輪郭の重なり具合」で骨格一致度を見る
clip CLIP embedding コサイン類似度 スカラー値 (0〜1) 「同じ意図のデザインか」のグローバル一致
grid 8×8 グリッド SSIM グリッドオーバーレイ PNG + per-cell JSON 「どのマスがズレてるか」位置情報付き
region-mapping diff cluster + DOM bbox の overlap クラスタ rect + 対応 data-visual-id + computed style LLM judge / repair agent への決定打

compare サブコマンドで 6 ツールを順次実行して outputs/report.md に全結果を集約します。

region-mapping (DOM 結合)

HTML の主要要素に data-visual-id="..." を付け、capture サブコマンドが screenshot と同時に 全 [data-visual-id] の bbox + computed styleinputs/dom-bboxes.json に dump。region-mapping ツールは以下を実行:

  1. AI 画像 vs HTML render の per-pixel diff intensity (Gaussian blur で隣接 pixel をマージ)
  2. 閾値 + morphological close → connected components で diff cluster の矩形 を抽出
  3. 各クラスタを全 DOM bbox と overlap (IoU + coverage) → coverage_cluster × specificity^0.4 で ranking
  4. 出力: outputs/region-mapping.png (赤=cluster, 緑=最マッチ DOM, 青=他 DOM, 緑線=対応) + outputs/region-mapping.json (各クラスタの top-3 matches w/ computed style)

これにより LLM judge / repair agent は 「diff cluster #3 → [data-visual-id='metric-visitors']、現状 font-size: 22px のような具体修正指示を生成できます。React でも JSX に data-visual-id を付ければ同じ仕組みで動きます。

セットアップ (uvx 経由)

uv / uvx をインストール済みであれば追加セットアップは不要です。

Playwright の Chromium は system-wide cache (macOS: ~/Library/Caches/ms-playwright、Linux: ~/.cache/ms-playwright) に入るため、1 マシンに 1 回だけ ダウンロードすれば venv が違っても共有されます:

# 初回のみ: chromium DL (system cache)
uvx --from /Users/masao/project/ui-visual-diff playwright install chromium

# 以降は普通に呼ぶだけ
uvx --from /Users/masao/project/ui-visual-diff ui-visual-diff capture ...

(任意) editable install で開発する場合:

cd /Users/masao/project/ui-visual-diff
uv venv
source .venv/bin/activate
uv pip install -e .
# chromium がまだなら同じく 1 回だけ:
playwright install chromium

使い方

バージョン確認

uvx --from /Users/masao/project/ui-visual-diff ui-visual-diff --version

HTML を screenshot + DOM bbox dump

uvx --from /Users/masao/project/ui-visual-diff ui-visual-diff capture \
    examples/target.html \
    --out-png inputs/html-render.png \
    --out-bboxes inputs/dom-bboxes.json \
    --viewport 1672x941

全ツール一括実行

uvx --from /Users/masao/project/ui-visual-diff ui-visual-diff compare \
    inputs/ai-image.png inputs/html-render.png \
    --bboxes inputs/dom-bboxes.json \
    --out outputs
open outputs/report.md

skill / CI から呼ぶときは --json を付けると stdout に整形済み JSON dict (results + errors サマリ) を吐きます。進捗ログは stderr に回るので stdout 側はそのまま jq 等でパース可能。--strict を付けると 1 つでも失敗したときに exit 1。

ui-visual-diff compare ai.png html.png --bboxes bb.json --out /tmp/run --json
# stdout: { "ai_image": "/abs/...", "results": {...}, "errors": {...} }

エラー時のスタックトレースを見たいときは -v (or --verbose) を付けるか UVD_DEBUG=1 を立ててください。デフォルトでは error: <type>: <message> の 1 行のみ stderr に出ます。

個別ツール実行

uvx --from /Users/masao/project/ui-visual-diff ui-visual-diff tool clip \
    inputs/ai-image.png inputs/html-render.png --out outputs

uvx --from /Users/masao/project/ui-visual-diff ui-visual-diff tool ssim \
    inputs/ai-image.png inputs/html-render.png --out outputs

uvx --from /Users/masao/project/ui-visual-diff ui-visual-diff tool grid \
    inputs/ai-image.png inputs/html-render.png --out outputs

uvx --from /Users/masao/project/ui-visual-diff ui-visual-diff tool region-mapping \
    inputs/ai-image.png inputs/html-render.png \
    --bboxes inputs/dom-bboxes.json --out outputs

ツール名: pixel-diff / ssim / canny / clip / grid / region-mapping

並列実行時の注意

このパッケージのデフォルト出力パス (outputs/inputs/html-render.pnginputs/dom-bboxes.json) は cwd 相対 です。複数の caller (Claude Code skill の fork、CI ジョブ、並列ループ等) が同じ cwd を共有すると、PNG / JSON が互いに上書きされて結果が壊れます。

並列で呼ぶ caller は必ず明示的な --out (および capture--out-png / --out-bboxes) を渡してください。 各 fork ごとに固有のディレクトリ (例: /tmp/ui-diff-<run-id>/) を渡すのが安全です。compare の exit code は 0 = 全成功、2 = 一部成功、1 = 全失敗 で返るので、skill 側はこれを見て継続判断できます (--strict 指定時はどれか 1 つでも失敗したら 1)。

アルゴリズム解説

1. ピクセル差分

各 pixel の RGB 絶対差が閾値超なら赤くマーク。1px ズレで全境界が真っ赤になるので AI 画像比較では参考程度。HTML→HTML regression test ではデファクト。

2. SSIM (Structural Similarity Index)

11×11 などの小窓を画像上でスライドさせ、各窓で「平均輝度・分散・共分散」を比較。色そのものではなく 明るさ分布のパターン を見るので人間の目に近い。本ツールでは前処理に Canny を入れて 構造のズレだけ 拾う。

3. Canny エッジ抽出

明るさが急変する線 (= 輪郭) だけ抽出した白黒線画。テクスチャやグラデを捨てて骨格だけ残すため SSIM や IoU の前処理として有用。

4. CLIP 埋め込みコサイン類似度

学習済みマルチモーダルモデルに画像を食わせて 512 次元のベクトルを取る。意味的特徴 で比較するので「同じデザイン意図か」のグローバル一致度になる。位置情報は失う。絶対値はノイジーなので「iteration 前 vs 後」の 相対指標 として使うのが堅い。

5. グリッド分割 SSIM ヒートマップ

画像を 8×8 マスに分割して各マスで SSIM。「右上のマスだけスコアが低い」のような 位置付きの差分 が出るので LLM judge が "ヘッダー右側がズレ" と語りやすくなる。

6. Region mapping

上記 (1) と同じ diff intensity を Gaussian blur → 閾値 → connected components で「ズレている矩形クラスタ」を取り出し、data-visual-id 付き DOM bbox との overlap で「どの React/HTML 要素が原因か」を ranking。LLM judge への evidence を最も具体的に出せる。

LLM judge との組み合わせ

[AI 画像] ─┐
           ├─→ ① CLIP 類似度        → グローバル一致度 (1 数値)
[HTML SS] ─┤
           ├─→ ② Canny → SSIM       → 構造のみのヒートマップ
           │
           ├─→ ⑤ 8×8 グリッド SSIM   → 位置付き差分
           │
           └─→ ⑥ region-mapping     → DOM 要素レベルの修正指示
                ↓
        ①②⑤⑥ + 元 2 画像 → LLM judge → "ヘッダー右ロゴ位置がズレ" 等

絶対閾値での合否判定ではなく、iteration ごとの相対改善 を測る指標として使う運用を推奨。

Claude Code Skill 統合

このCLIは masao-origin/.claude/skills/run-ui-visual-iter/ から呼ばれる前提で設計されています。skill ペアは:

skill 役割
run-ui-visual-iter orchestrator (context: fork)。Phase 1-4 で CLI を順次呼び、評価器 → generator → 再評価のループを回す
assign-ui-visual-evaluator internal evaluator (ref なし、metrics + 画像 vision で 5 観点採点)。eval-schema.json (kind: metric) 並置

5 採点軸:

  • clip_cosine (CLIP コサイン類似度) — 意味的類似 25%
  • grid_ssim_mean (8×8 SSIM 平均) — 構造類似 20%
  • region_match_specificity (cluster の leaf 一致率) — 修正可能性 15%
  • text_fidelity (LLM vision) — テキスト一致 20%
  • layout_fidelity (LLM vision) — レイアウト一致 20%

Skill 経由起動例:

Skill({skill: "run-ui-visual-iter", args: "<ai_image> <html_target> --max 5 --threshold-clip 0.93"})

skill は CLI を uvx --from /Users/masao/project/ui-visual-diff 経由で叩くので、本パッケージのインストール手順を踏むだけで利用可能。

ディレクトリ構成

ui-visual-diff/
├── pyproject.toml
├── README.md
├── ui_visual_diff/
│   ├── __init__.py
│   ├── __main__.py           # python -m ui_visual_diff entry
│   ├── _common.py
│   ├── defaults.py           # CLI default paths shared by main()s and cli.py
│   ├── pixel_diff.py
│   ├── ssim_heatmap.py
│   ├── canny_edges.py
│   ├── clip_similarity.py
│   ├── grid_heatmap.py
│   ├── region_mapping.py
│   ├── run_all.py
│   ├── capture.py            # Playwright screenshot + bbox dump
│   └── cli.py                # argparse subcommand entry
├── examples/
│   └── target.html           # data-visual-id 付き HTML サンプル
├── inputs/                   # 実行時生成 (gitignored)
└── outputs/                  # 実行時生成 (gitignored)

About

Compare AI-generated UI images against HTML/React renders. CLI used by masao-origin run-ui-visual-iter skill.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages