2つの画像がどの位違うのかを数値化するプログラムです。
ピクセル毎の色の違いを合計するだけの簡単な比較です。
教科書の初めに出てくるような一般的な手法で、SSD (sum of squared difference) という名前が付いています。
- 画像サイズがだいたい合ってないとダメ (縦、又は横が2倍違うとエラー)
- エラーがマズイ人はエラーの代わりに適切な値を返すように変更して下さい。
- 非対称な画像が回転してたり、部分的に一致してる場合とかは考慮していません。
- 最終結果はRGB色空間(0,0,0)-(255,255,255)の平均距離の2乗値です。
- 画像フォーマットは、少なくとも PNG, GIF, JPEG の3種類に対応してます。(後は GD ライブラリ次第)
- コードは見やすさ優先です。
- 速さを追求したい人は while($x) { $x-- ;... とか自分で変えて下さい。
10分で作った割に、意外と使えそうなのでコードを晒します。
<?php
/*
* dissimilarity measure
* sum of squared difference
* 2011/10/13- yoya@awm.jp
*/
function usage() {
echo "Usage: php bitmap_comp.php <file1> <file2>\n";
}
if (($argc != 3) || (! is_readable($argv[1])) || (! is_readable($argv[2]))) {
usage();
exit (1);
}
$data1 = file_get_contents($argv[1]);
$data2 = file_get_contents($argv[2]);
$im1 = imagecreatefromstring($data1);
$im2 = imagecreatefromstring($data2);
if ($im1 === false || $im2 === false) {
echo "Error: image1 or image2 has broken.";
exit (1);
}
$width1 = imagesx($im1); $height1 = imagesy($im1);
$width2 = imagesx($im2); $height2 = imagesy($im2);
$width_ratio = $width2 / $width1;
$height_ratio = $height2 / $height1;
if ($width_ratio < 0.5 || 2.0 < $width_ratio ||
$height_ratio < 0.5 || 2.0 < $height_ratio) {
echo "Error: image1(".$width1."x".$height1.") image2(".$width2."x".$height2.")\n";
exit (1);
}
$width = min($width1, $width2);
$height = min($height1, $height2);
$distance_square_sum = 0;
for ($y = 0 ; $y < $height ; $y++) {
for ($x = 0 ; $x < $width ; $x++) {
$i1 = imagecolorat($im1, $x, $y);
$i2 = imagecolorat($im2, $x, $y);
$rgb1 = imagecolorsforindex($im1, $i1);
$rgb2 = imagecolorsforindex($im2, $i2);
$red_diff = $rgb1['red'] - $rgb2['red'];
$green_diff = $rgb1['green'] - $rgb2['green'];
$blue_diff = $rgb1['blue'] - $rgb2['blue'];
$distance_square_sum += $red_diff*$red_diff + $green_diff*$green_diff + $blue_diff*$blue_diff;
}
}
echo $distance_square_sum / ($width * $height) . "\n";