compare-screenshots について
過去のベースラインを正解と決めつけず、スクリーンショットを承認済みのデザインと比較するビジュアルレビュー用スキルです。画像指標と局所確認を組み合わせ、目標が曖昧な場合はユーザーに判断を求めます。
主な機能
- 01明確な視覚比較の目標設定
- 02スクリーンショット条件の比較可能性確認
- 03画像とエッジの比較生成
- 04境界と局所的な差異の確認
- 05判定ではなく診断としての指標利用
活用シーン
- 01承認済みデザインに対する UI 変更の確認
- 02視覚効果の切れや重なりの検出
- 03参照画像なしでのスクリーンショット評価
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ dzhng/ skills --skill compare-screenshotsインストール後、Claude Code で/compare-screenshotsを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/reference-landmarks.mdsubagent-visual-review.mdscripts/visual-parity-diff.eval.mjsvisual-parity-diff.mjstest/visual-parity-diff.test.mjstest/fixtures/target-without-helper-packages/README.mdvendor/pixelmatch/index.jsLICENSEpackage.jsonvendor/pngjs/lib/bitmapper.jsbitpacker.jschunkstream.jsconstants.jscrc.jsfilter-pack.jsfilter-parse-async.jsfilter-parse-sync.jsfilter-parse.jsformat-normaliser.jsinterlace.jspacker-async.jspacker-sync.jspacker.jspaeth-predictor.jsparser-async.jsparser-sync.jsparser.jspng-sync.jspng.jssync-inflate.js詳細
スクリーンショットを比較する
画像を意図した結果と照らし合わせて評価します。ユーザーが承認したデザインが目標です。過去のベースラインは以前の試行にすぎず、誤っている場合があります。指標は差異を見つけるためのものであり、正しさを判断するものではありません。探索から実装までの一連の流れについては、design-with-images を参照してください。
ワークフロー
- 目標を定めます。 ユーザーが承認したリファレンスや明示されたデザイン要件がある場合は、それに従い、独自の好みに置き換えないでください。そうでない場合は、視覚的な要件、実物として描かれているもの、そしてその見た目を担う分野の専門知識から目標を導きます。具体的な文を1〜2文で書き留めます(「低い位置から差す太陽が東に長い影を落とす。木々が樹冠を満たし、このズーム倍率でもラベルが読める」など)。
- 正解が明確でない場合(妥当な解釈が複数ある、好みや製品の意図に関わる判断が必要、あるいは担当者しか決められないトレードオフがある場合)は、作業を止めてユーザーに確認してください。比較を提示します。尋ねるのを避けてベースラインを黙って既定値にしないでください。そうすると、ベースラインが誤っていた点までそのまま取り込まれてしまいます。
- 比較可能な状態であることを確認します。 見えている違いがキャプチャのアーティファクトではなく、実際の差であることを確かめます。同じビューポート、DPR、ルート/ページ、固定した時刻/ティック、カメラの意図、UI の状態、データ、必要に応じてフォント/アセットを使用します。条件が揃わない場合は、キャプチャ設定を修正するか、不一致の影響がないクロップ/特徴だけを比較します。
- 承認されたデザインを測定します。 リファレンスとの一致を確認する場合は、コードを変更したり候補を受け入れたりする前に、Reference Landmarks を読み、記入を完了します。そのうえで、確認したい内容に応じた成果物を生成します。並べた画像、主要特徴のクロップ/拡大、グレースケール、グレースケールの絶対差分ヒートマップ、pixelmatch の差分、画像ごとの Sobel/エッジマップ、エッジ差分ヒートマップ、JSON メトリクスなどです。
- 全体を判断する前に境界を確認します。 変更した視覚効果ごとに、ネイティブスケールと揃えた詳細クロップで全方向を確認します。効果のフェード全体と周辺の余白を含めます。コンポーネントの枠で終わるクロップでは、はみ出しが隠れてしまいます。上/右/下/左の広がりを個別に確認し、推測した CSS の境界ではなく、見えているテキスト、罫線、シルエットを基準にします。効果が通過する前景の特徴(線、アイコン、テキスト、隣接パネル)をすべて確認します。明るさ、色、鮮明さ、連続性が目標に一致している必要があります。読みやすい線でも、不適切に暗くなっていることがあります。各確認について、リファレンスでの観察 → 候補での観察 → 合格/修正/不確実という形で、使用したクロップとともに記録します。局所的な距離やコントラストの判断にはランドマーク表を使います。全体フレームの平均値では局所的な欠陥を判断できません。
- 目標に照らして差異を一つずつ判断します。 2枚の画像が異なる箇所ごとに、実際に何が起きているのかを平易な言葉で示します(コンテンツの欠落、カメラの誤り、階層の不備、コントラスト不足、奥行きの誤り、テキストの重なり、レイアウトのずれ、端の切れ、予期しないぼけ、スタイルの不一致など)。そして、どちらが正解に近いかを判断します。候補、ベースライン、両方とも誤り、あるいは本当に甲乙つけがたい、のいずれもあり得ます。
- 意見が分かれる判断や重要度の高い判断には、中立的な第三者の意見を求めます。
references/subagent-visual-review.mdに従い、2枚の画像のみを中立的なラベルで提示して、新たなサブエージェントに確認してもらいます。 - 不一致を承認済みの目標に合わせて解消します。 選択したデザインを実装する際は、間隔、形状、柔らかさ、タイポグラフィ、階層に関する重要な差異を記録します。差異が解消されるか、ユーザーが目標を変更するまで修正、再キャプチャ、再確認を繰り返します。コードが単純になるという理由で、差異を黙って許容しないでください。
- 最終判断を一つ示して結論づけます。 候補のほうが誤りが少ない(受け入れ、ベースラインが存在する場合は改めて承認する)、ベースラインのほうが誤りが少ない(却下)、両方とも誤り(追加の修正が必要。残っている問題を説明する)、または不明確(ユーザーに確認する)のいずれかです。すべての境界/重なりの確認に合格するか、ユーザーが明示的に承認した逸脱がある場合に限り、受け入れます。不確実な場合に必要なのは、合格ではなく、より詳しい証拠です。全体的な類似度や肯定的な第三者意見で、局所的な欠陥を相殺することはできません。スコアが低いという理由だけで受け入れたり、高いという理由だけで却下したりしないでください。数値を動かすために、コンテンツを隠す、詳細をぼかす、差異をクロップして除外する、キャプチャの忠実性を損なうといったことは決してしないでください。
有用な指標
質問に答えられる指標を選びます。全体的な視覚比較では、次の指標を報告します。
mae:グレースケールの平均絶対差。0~255で、値が小さいほど近いことを示します。rmse:グレースケールの二乗平均平方根誤差。値が小さいほど近いことを示します。diffRatio16、diffRatio32、diffRatio64:各グレースケール差分しきい値を超えるピクセルの割合です。pixelmatchRatio:グレースケール画像に対する pixelmatch の不一致率です。edgeEnergyCurrentとedgeEnergyCandidate:Sobel エッジ強度の平均値です。edgeEnergyRatio:候補画像と現行画像の比率です。1を大きく下回る場合は、通常、形状、オブジェクト、ラベル、地形の欠落を示します。1を大きく上回る場合は、通常、細部にノイズが多いか、不正確であることを示します。edgeDiffRatio32:Sobel エッジに有意な差があるピクセルの割合です。avgLuminanceCurrent、avgLuminanceCandidate、avgLuminanceDelta:平均輝度とその差です。より広範な距離スコアが改善していても、レンダリングが目に見えて暗すぎる、または明るすぎる場合に使用します。- シーンに関連するコンテンツの代替指標:黒色/空白の割合、地形らしい部分の割合、水らしい部分の割合、チームカラーの割合、ラベル/テキストマスクの割合。
UI/ドキュメント/レイアウトのレビューでは、全体的なピクセル距離よりも適切な場合、切り抜き範囲、テキスト/前景マスクの占有率、コントラストの確認、エッジのクリッピング、要素の位置、変更前後の寸法も使用します。
単一画像の指標
上記の指標はいずれも、ある画像を別の画像と比較するものです。そのため、比較対象がない場合に「このキャプチャには価値があるか」という問いには答えられません。また、2枚の画像のスコアは対称なので、距離が非常に大きくても、どちらが空のフレームなのかは分かりません。単一の PNG から粗いグリッドで算出する、いくつかの絶対値を確認してください。
colorEntropyBitsが約3.0未満、またはdominantColorShareが約0.6を超える場合:1色がフレームの大半を占めています。シーンがまばら、照明が当たっていない、または被写体が一度も描画されていない可能性があります。edgeDensityが約0.04未満の場合:ほとんど形状がありません。空の構図、プリミティブが主体のシーン、または切り抜き範囲の外に被写体がある可能性があります。luminanceContrastが約60未満の場合:霧、暗さ、かすみなどにより、フレーム全体の明暗が1つの帯に圧縮されています。- 本来不透明であるはずのキャプチャで
transparentShareが0を超える場合:キャプチャ自体に問題があります。透明ピクセルには残された RGB 値がそのまま保持されるため、合成されるまでは、見えないフレームでも豊かな色合いに見えることがあります。シーン指標では測定前に合成し、見えない部分の割合を名前付きで示すため、推測する必要はありません。上記の2画像間の指標は保存された RGB 値をそのまま読み取るため、透明度についてはこのフィールドで判断できます。
これらは「疑い」を示すしきい値であり、合否判定の基準ではありません。意図的にシンプルなデザイン、夜のシーン、空の状態を示す画面、ホワイトボードでは、いずれも正常にしきい値に該当します。確認すべき箇所を見つけるために使い、フレームで実際に何が起きているかを説明してください。数値を上げるためにキャプチャを調整してはいけません。それは差分を切り抜いて消すのと同じ失敗です。
距離スコア
固定ペアに対して単一の数値が役立つ場合、このデフォルトの式は構造的な変更に適しています。
distance = 0.35 * diffRatio32 + 0.25 * pixelmatchRatio + 0.25 * edgeDiffRatio32 + 0.15 * min(1, abs(log2(edgeEnergyRatio)))
この値が表すのはもう一方の画像との距離だけです。ベースラインが間違っている可能性があるため、距離が0でも成功とは限らず、距離が大きくても失敗とは限りません。シーンがより豊かになった、モデルがより鮮明になった、ラベルが目立つようになった、実際の奥行きが加わった、照明が改善されたといった場合には、距離が大きくなることは正当です。このスコアを使って画像がどこで変化したかを見つけ、どちらが正しいかはステップ5で判断します。このフィールド名には、何を測定するかが分かる名前(「パリティ」ではなく「距離」)を付け、判定結果だと誤解されないようにしてください。
フレーム全体のスコアを報告し、UI がショットの大部分を占める場合は、ラベル付きのワールド部分の切り抜きスコアも報告します。ワールド部分の切り抜きスコアでレンダラーの変化箇所を特定し、UI/カメラの問題が分かるようにフレーム全体のスコアも残してください。
スコアの扱い
- 各反復で、同じペアの前回の距離と今回の距離を示し、変化が目標に近づいているのか、遠ざかっているのか、診断上のノイズなのかを述べます。
- コンテンツの欠落バグには、エッジ指標を優先します。平坦な俯瞰マップではグレースケール差分が一見中程度に見えても、エッジの強度を見れば、木、道路、街並み、軍隊のシルエットが欠落していることが分かる場合があります。
- UIが安定していて、それが大部分を占める一方、ワールドのレンダリングが問題となっている場合は、UIを切り分けます。ラベルを付けたフルフレームのスコアも残します。
- カメラが正しくない場合、ピクセルスコアは診断にのみ使用します。まずカメラの意図を修正し、その後でレンダリングを評価します。
ツール
比較スクリプトは、実行時にスクリーンショット比較が本当に必要な場合を除き、製品コードではなく、スキル内または一時的なワークスペースに置きます。
scripts/visual-parity-diff.mjsは、再利用可能なローカルヘルパーです。PNGとピクセル差分の実行環境はスキルに同梱されているため、対象リポジトリにpngjsやpixelmatchは必要ありません。REFERENCE_DIR=<png-folder>、CANDIDATE_DIR=<png-folder>、必要に応じてOUT_DIR=<artifact-folder>を指定して実行します。REPORT_ORDER=a,b,cで順序を固定できます。CROPS_JSON=<file>でラベル付きの切り抜きを追加できます(画像IDをキーとし、各切り抜きはピクセル単位、または{ "unit": "ratio" }による正規化境界で指定します)。ペアレポートには、それぞれの側のsceneMetricsブロックが含まれます。- 対応する画像がないフォルダーに同じヘルパーを適用するには、
REFERENCE_DIRを省略します。単一画像に関する上記の数値を記載したscene-metrics.jsonが出力され、差分アーティファクトは生成されません。単独のスクリーンショットや、誰かが確認する前のキャプチャ一式に使用したり、大きな距離のどちら側が空なのかを特定したりできます。 scripts/visual-parity-diff.eval.mjsは、このヘルパー自体の評価用スクリプトです。正解が構成上あらかじめ分かっているフィクスチャ(空、透明、プリミティブ主体、作り込み済み、退化)を生成し、分類、不変性、CLIの仕様を検証します。スクリプトを変更した後は、同じREPO_ROOTを指定して実行します。フィクスチャではなくコードに問題があると確認するまでは、しきい値を緩めて失敗したチェックを通さないでください。- ほかのタスクでは、用途ごとのスクリプトをアプリケーションに追加するのではなく、同じアーティファクト一式を応用します。必要なペアがカバーされていなければ、ヘルパーを拡張します。
参考資料
references/subagent-visual-review.md:履歴によるバイアスが懸念される場合に、独立した判断を得るための中立的なサブエージェント向けプロンプト/設定です。