Skip to content

Instantly share code, notes, and snippets.

@rmzaki
Last active July 12, 2018 08:27
Show Gist options
  • Save rmzaki/dd7af37f8a472d7b709d9f5c7751c5a8 to your computer and use it in GitHub Desktop.
Save rmzaki/dd7af37f8a472d7b709d9f5c7751c5a8 to your computer and use it in GitHub Desktop.
類似画像 jpg,png,gif対応
http://yuzurus.hatenablog.jp/entry/search-image
http://www.kochi-tech.ac.jp/library/ron/2012/2012info/1130340.pdf
http://aidiary.hatenablog.com/entry/20091003/1254574041
<?php
// 画像ディレクトリパス
$dir = './images';
// baseになる画像(画像URLでも可)
$base_image_path = './images/sample.jpeg';
// 比較する画像パスの配列
$image_paths = glob($dir . '/{*.jpeg,*.jpg,*.png,*.gif}', GLOB_BRACE);
// base画像のヒストグラム
$base_his = makeHistogram($base_image_path);
// 比較画像のヒストグラム
$image_his = [];
foreach ($image_paths as $id => $path) {
$image_his[$id] = makeHistogram($path);
}
// 比較
$result = [];
foreach ($image_his as $id => $his) {
for ($i = 0; $i < 64; $i++) {
$result[$id] += min($base_his[$i], $his[$i]);
}
}
print_r($result);
/**
* ヒストグラムのビンを計算
* @param $rgb
* @return int
*/
function rgb2no($colors)
{
// gifがビットシフトで対応できないのでimagecolorsforindexでrgbを渡す
// $r = ($rgb >> 16) & 0xFF;
// $g = ($rgb >> 8) & 0xFF;
// $b = $rgb & 0xFF;
$r = $colors['red'];
$g = $colors['green'];
$b = $colors['blue'];
$rn = floor($r / 64);
$gn = floor($g / 64);
$bn = floor($b / 64);
return 16 * $rn + 4 * $gn + $bn;
}
/**
* 画像からカラーヒストグラムを作成(csv形式)
* @param $path 画像保存先
* @param bool $cache
* @return array
*/
function makeHistogram($path, $cache = true)
{
/*
量が多い場合は毎度ファイルを作るわけにいかないので、結果をjson_encodeしてDBに保存
*/
$csvfile = preg_replace('/\.(jpg|jpeg)$/', '-his.csv', $path);
if ($cache) {
if (file_exists($csvfile)) {
$s = file_get_contents($csvfile);
return explode(',', $s);
}
}
if (strpos($path, '.png') !== false) {
$im = imagecreatefrompng($path);
} elseif (strpos($path, '.gif') !== false) {
$im = imagecreatefromgif($path);
} else {
$im = imagecreatefromjpeg($path);
}
$sx = imagesx($im);
$sy = imagesy($im);
// ピクセルを数える
$his = array_fill(0, 64, 0);
for ($y = 0; $y < $sy; $y++) {
for ($x = 0; $x < $sx; $x++) {
$rgb = imagecolorat($im, $x, $y);
$colors = imagecolorsforindex($im, $rgb);
$no = rgb2no($colors);
$his[$no]++;
}
}
// 8bitに正規化
$pixels = $sx * $sy;
for ($i = 0; $i < 64; $i++) {
$his[$i] = floor(256 * $his[$i] / $pixels);
}
file_put_contents($csvfile, implode(',', $his));
imagecolorsforindex($im);
return $his;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment