背景:简单识别图片相似度。使用PHP实现
在网上查了写资料,这里作为整理,比较高级的算法这里不讨论,这里仅仅说一下php容易实现的简单算法。算法的思路是对图片进行压缩处理,得到特征hash,然后对比hash进行监测相似度。
这类算法称为:感知哈希算法,包括aHash、pHash、dHash。顾名思义,感知哈希不是以严格的方式计算Hash值,而是以更加相对的方式计算哈希值,因为“相似”与否,就是一种相对的判定。
以下来自网络,没有实际测试:
- aHash:平均值哈希。速度比较快,但是常常不太精确。
- pHash:感知哈希。精确度比较高,但是速度方面较差一些。
- dHash:差异值哈希。Amazing!精确度较高,且速度也非常快。因此我就选择了dHash作为我图片判重的算法。
<?php
/**
* Created by: newsgao <ng@cnuw.net>
* Time: 2018/5/24 16:41
*/
$_start = microtime(true);
$hash_1 = dHash("./1.jpg");
$hash_2 = dHash("./2.jpg");
echo "汉明距离:" . getLeng($hash_1, $hash_2) . "\n";
$_end = microtime(true);
echo "耗时:" . round(($_end - $_start) * 1000, 4) . "ms ";
echo "内存:" . round(memory_get_usage() / 1024, 3) . "KB \n";
/**
* 根据图片路径获取图片指纹
* @param $src
* @return bool|string
*/
function dHash($src)
{
if (!file_exists($src)) {
return false;
}
$info = getimagesize($src);
if ($info === false) {
return false;
}
$w = 9; // 采样宽度
$h = 8; // 采样高度
$dst = imagecreatetruecolor($w, $h);
$img = imagecreatefromstring(file_get_contents($src));
// 缩放
$img && imagecopyresized($dst, $img, 0, 0, 0, 0, $w, $h, $info[0], $info[1]);
$hash = '';
for ($y = 0; $y < $h; $y++) {
$pix = getGray(imagecolorat($dst, 0, $y));
for ($x = 1; $x < $w; $x++) {
$_pix = getGray(imagecolorat($dst, $x, $y));
$_pix > $pix ? $hash .= '1' : $hash .= '0';
$pix = $_pix;
}
}
$hash = base_convert($hash, 2, 16);
//imagejpeg($dst,"$hash.jpg");
return $hash;
}
/**
* 获取像素点的灰度值
* @param $rgb
* @return int
*/
function getGray($rgb)
{
$r = ($rgb >> 16) & 0xFF;
$g = ($rgb >> 8) & 0xFF;
$b = $rgb & 0xFF;
return intval(($r + $g + $b) / 3) & 0xFF;
}
/**
* 获取汉明距离
* @param $dhash_1
* @param $dhash_2
*/
function getLeng($dhash_1, $dhash_2)
{
$tem = hex2bin($dhash_1) ^ hex2bin($dhash_2);
$tem = bin2hex($tem);
$tem = base_convert($tem, 16, 2);
return substr_count($tem, '1');
}