猫の手ツール

Color Analysis Engine

ピクセル量子化と色差判定による
代表色抽出の最適化手法

画像に含まれる何百万ものピクセルから、デザインに使える「代表色」をどう選ぶか。色の集計に外部ライブラリを使わず、ブラウザの計算リソースだけで完結させるための独自の「量子化ハック」と「サンプリング戦略」を解説します。

このツールの入力から出力まで

現行コードの確認日:

入力
写真を1枚選び、代表色を一覧として取り出します。
処理
長辺150px以下の解析画像から量子化した色を数え、白・黒・透明に近い画素と近すぎる候補を除きます。
出力
代表色を最大6色のHEX・RGB一覧として画面へ表示し、色カードからHEXをコピーできます。

まず確認する点:一覧は代表色で、写真内の任意の1点の色ではありません。小さな色領域は縮小で他の色と混ざり、6色未満になる場合もあります。

仕上がりの例

猫の写真から代表色を抽出した結果の表示例です。

元画像・抽出結果
左は茶トラの愛猫の写真。右は写真から抽出した6色のカラーパレットと色コード。

元画像・抽出結果

左は茶トラの愛猫の写真。右は写真から抽出した6色のカラーパレットと色コード。

掲載画像はサイトにある既存の公開作例です。保存済みの資料では運営者の愛猫の写真を使用しています。今回の確認日が、この作例を実行した日を表すわけではありません。

保存済み検証記録の条件を見る

資料の種類は「ツールのプレビュー・結果画面を保存した記録」です。公開作例と保存済み記録で素材や色などが異なる場合があるため、下の数値は保存済み検証記録の条件として読んでください。

記録の入力画像
800×1222px (JPEG)
記録の画面キャプチャ
536×301px (PNG)
保存済み記録の主な操作・出力条件
画面の項目記録の値現行コードの初期値・範囲
記録の代表色#E4CCB4 / #6C3C24 / #9C6C54 / #CCB484 / #240C0C / #9C540C—

資料ファイルの作成日は実行日として扱っていません。個別端末の処理速度や、ほかの写真に対する検出・加工の精度を測定した資料でもありません。

実装の確認箇所:src/pages/image/color-palette/index.astro。以下のコード抜粋と出力条件は、この本番実装に基づいて説明します。

仕組みを読み進めるときは、Canvas APIと画像処理(画像寸法、drawImage、画素と透明度の扱い)、メモリ管理と画像処理(画素バッファ、縮小と容量予算)が参考になります。

1. 24段階幅でまとめる色空間の量子化

デジタル画像の色数は膨大です。各ピクセルのRGB値をそのままカウントすると、微細なノイズ(微妙に違うだけの似た色)が分散してしまい、正確な「代表色」が求まりません。本ツールでは、RGB各チャンネルを一定のステップ(区切り)で切り捨てる「量子化」を行い、色をグループ化し、各区間の中央の値を代表値にします。

メリット: 計算負荷の重いメディアンカット法やk-means法などの本格的なクラスタリングを使わずとも、Mapオブジェクトへの1パスのスキャンだけで、視覚的に支配的なカラーグループを高速に特定できます。

量子化の区間幅は 24 です。元画像にあった色をそのまま返すのではなく、同じ区間の値を中央の色にまとめます。

function quantizedColor(r, g, b) {
  return [r, g, b].map(value => Math.floor(value / 24) * 24 + 12);
}

2. ユークリッド距離を用いた「色被り」の動的排除

出現頻度だけで上位の色を選ぶと、パレットが「ほぼ同じ青色ばかり」になってしまうことがよくあります。本ツールでは、候補色を選出する際に、既に選ばれた色との「色差(三次元空間上の直線距離)」を計算し、似すぎている色をスキップするフィルタリングを導入しています。

メリット: この「多様性確保」のロジックにより、頻度上位の近い色を減らします。ただし 6 色に満たない場合は近い色も追加するため、人物と背景などの意味を識別して選ぶわけではありません。

3. 解析する画素数を減らす「サンプリング・リサイズ」戦略

全画素を解析する方法では、解像度が大きいほどJavaScriptで数える画素も増えます。本ツールでは、色抽出専用の「解析用オフスクリーンCanvas」を作成し、画像を大幅に縮小してからスキャンしています。

メリット: 解析対象を長辺 150px、最大 22,500 画素に抑えます。処理時間は端末により異なります。縮小時にブラウザネイティブの補間(Smoothing)が働くため、近接する色が混ざることがあります。細い線や小さな色の領域は、縮小後の結果に十分反映されない場合があります。

出力の仕様と確認する点

最初に長辺 1500px 以下のプレビューを作り、色解析ではさらに長辺 150px 以下に縮小します。各チャンネルがすべて 245 超の白、すべて 15 未満の黒、アルファ 128 未満の画素は集計から除外します。

色を頻度順に並べ、RGB の距離が 45 未満の候補を一旦除外して最大 6 色を選びます。候補が少ない画像は 6 色未満、白や黒だけなら抽出失敗になる場合があります。

表示する HEX と RGB は量子化した色です。色カードから HEX をコピーできます。画像中の特定の点の色を知りたい場合は、パレットの代表色とスポイトの1画素値を区別してください。