導入
Web開発において、ユーザーがアップロードした画像と既存の画像を比較し、似た色合いの画像を見つけ出したいというニーズは少なくありません。例えば、ECサイトでの商品レコメンドや、画像投稿サイトでの重複チェックなどが挙げられます。今回は、PHPの標準的な画像処理ライブラリ「GD」を用いて、画像の「平均色」を算出し、それをもとに類似画像を特定する手法を解説します。
基礎知識
画像の類似検索において最もシンプルなアプローチの一つが、画像全体の「平均RGB値」を算出することです。
RGB(Red, Green, Blue)は、光の三原色を数値化したもので、各0〜255の範囲で表現されます。画像全体の色情報を平均化することで、その画像が全体的に「赤っぽいのか」「青っぽいのか」という特徴量を数値化できます。GDライブラリのimagecopyresampledを使用すれば、画像を小さなサムネイルに縮小することで、計算コストを大幅に抑えつつ色分布を抽出することが可能です。
実装/解決策
画像比較のステップは以下の通りです。
1. 画像を読み込み、16×16ピクセル程度の極小サイズに縮小する。
2. 縮小した各ピクセルのRGB値を合計し、ピクセル数で割って平均値を算出する。
3. 比較対象となる全画像に対してこの処理を行い、基準画像との「色の距離」を算出する。
4. 距離が近い順にソートして結果を返す。
サンプルプログラム
/
function getAverageColor($filepath) {
$image = @imagecreatefromstring(file_get_contents($filepath));
if (!$image) return null;
$thumb = imagecreatetruecolor(16, 16);
// 計算速度向上のため、16×16に縮小して色を平均化
imagecopyresampled($thumb, $image, 0, 0, 0, 0, 16, 16, imagesx($image), imagesy($image));
$red = $green = $blue = 0;
for ($x = 0; $x < 16; $x++) {
for ($y = 0; $y < 16; $y++) {
$rgb = imagecolorat($thumb, $x, $y);
$red += ($rgb >> 16) & 0xFF;
$green += ($rgb >> 8) & 0xFF;
$blue += $rgb & 0xFF;
}
}
imagedestroy($image);
imagedestroy($thumb);
$pixelCount = 16 16;
return [
‘r’ => $red / $pixelCount,
‘g’ => $green / $pixelCount,
‘b’ => $blue / $pixelCount
];
}
/
- 二つのRGB値の距離(マンハッタン距離)を計算
/
function getColorDistance($c1, $c2) {
return abs($c1[‘r’] – $c2[‘r’]) + abs($c1[‘g’] – $c2[‘g’]) + abs($c1[‘b’] – $c2[‘b’]);
}
// 実行例
$baseColor = getAverageColor(‘target.jpg’);
$candidates = [‘img1.jpg’, ‘img2.jpg’, ‘img3.jpg’];
$results = [];
foreach ($candidates as $file) {
$color = getAverageColor($file);
if ($color) {
$results[$file] = getColorDistance($baseColor, $color);
}
}
// 距離が小さい順(似ている順)にソート
asort($results);
print_r($results);
?>
応用・注意点
この手法は実装が容易である一方、現場レベルではいくつかの限界があります。
1. 明暗の影響を受けやすい
RGB平均では、黒っぽい画像と鮮やかな画像が同じ色相であっても「距離」が遠くなります。より高度な検索が必要な場合は、RGBを「HSV(色相・彩度・明度)」や「Lab色空間」に変換して比較することをおすすめします。これにより、明暗を除外した「色味そのものの比較」が可能になります。
2. パフォーマンス
大量の画像をリアルタイムでスキャンする場合、毎回画像を開いて計算するのは非効率です。あらかじめアップロード時に平均色を計算し、DBのカラムに格納しておく(インデックスを貼る)運用が、実務上の定石です。