導入
Webアプリケーションにおいて、「ユーザーがアップロードした画像と似た画像を検索する」機能は、重複排除やレコメンデーションエンジンにおいて非常に強力なツールとなります。外部APIや機械学習ライブラリを使わず、PHPの標準的な画像処理ライブラリであるGDを使用して、軽量かつシンプルに類似画像を判定する方法を解説します。この手法は、画像の「色味」を数値化して比較することで、視覚的な類似性を算出します。
基礎知識
画像を検索するために重要なのは、画像をそのまま比較するのではなく、特徴を「データ」として抽出することです。
今回の手法では、画像全体のピクセルを平均化して「4×4の小さな画像(サムネイル)」に変換します。これにより、高解像度の画像も16個のピクセル情報へと圧縮されます。
ここでポイントとなるのが「Lab色空間」です。通常のRGB(光の三原色)はコンピュータが扱いやすい形式ですが、人間の目に見える色味の近さを計算するには不向きです。Lab色空間は、輝度(L)と色相(a, b)を分離した形式であり、これを用いることで、人間が感じる「色の近さ」を数学的な距離として算出できるようになります。
実装/解決策
実装のステップは以下の通りです。
1. 画像を読み込み、4×4ピクセルに縮小する。
2. 各ピクセルのRGB値を取得し、それをLab色空間の座標に変換する。
3. 比較対象となる画像との間で、各ピクセルごとのLab座標の距離(ユークリッド距離)を算出する。
4. 合計距離が小さいものほど「似ている」と判断し、昇順でソートする。
サンプルプログラム
以下のコードは、指定ディレクトリ内の画像を読み込み、基準画像との類似度を計算してソートする実用的なスニペットです。
$value){
// Lab座標の距離を積算
$distance += lab_distance($value, $lab[$key]);
}
$diff[basename($file)] = $distance;
}
// 距離が小さい順(似ている順)にソート
asort($diff);
foreach($diff as $filename => $score) {
echo “ファイル名: {$filename} (スコア: {$score})
“;
}
/
- 画像読み込みとGDリソースの生成
/
function load_image($filepath){
$info = getimagesize($filepath);
switch ($info[‘mime’]) {
case ‘image/jpeg’: return imagecreatefromjpeg($filepath);
case ‘image/png’: return imagecreatefrompng($filepath);
case ‘image/gif’: return imagecreatefromgif($filepath);
default: return null;
}
}
/
- 画像を4×4に縮小してLab値の配列を返す
/
function image_lab($image){
$thumb = imagecreatetruecolor(4, 4);
imagecopyresampled($thumb, $image, 0, 0, 0, 0, 4, 4, imagesx($image), imagesy($image));
$lab = [];
for($x=0; $x<4; $x++){
for($y=0; $y<4; $y++){
$rgb = imagecolorsforindex($thumb, imagecolorat($thumb, $x, $y));
$lab[] = rgb2lab([$rgb['red'], $rgb['green'], $rgb['blue']]);
}
}
return $lab;
}
// ※注: rgb2lab, xyz2lab, lab_distance 関数は参考元コードのロジックをそのまま利用してください。
?>
応用・注意点
1. 計算負荷の管理: 比較する画像の枚数が多い場合、毎回全画像を計算するのは非効率です。事前にDBに各画像のLab値(16ピクセル分)を保存しておき、検索時にはDB上の値と比較するように設計しましょう。
2. 精度の向上: 4×4の解像度では大まかな色味しか判別できません。より詳細な比較が必要な場合は8×8などに上げることが可能ですが、計算時間は指数関数的に増えるため注意が必要です。
3. 限界の理解: この手法は「色味の類似」を判定するものです。構図や対象物の形まで含めた類似検索を行う場合は、PHash(Perceptual Hash)などのアルゴリズムを併用することをお勧めします。