Imghash:相似图片搜索的php实现
作者:admin 日期:2012-05-19
图片相似搜索的简单原理
根据文章里的描述,其实原理比较简单,大致有如下几个步骤:
1、缩小尺寸。将图片缩小到8×8的尺寸,总共64个像素。这一步的作用是去除图片的细节,只保留结构、明暗等基本信息,摒弃不同尺寸、比例带来的图片差异。
2、简化色彩。将缩小后的图片,转为64级灰度。也就是说,所有像素点总共只有64种颜色。
3、计算平均值。计算所有64个像素的灰度平均值。
4、比较像素的灰度。将每个像素的灰度,与平均值进行比较。大于或等于平均值,记为1;小于平均值,记为0。
5、计算哈希值。将上一步的比较结果,组合在一起,就构成了一个64位的整数,这就是这张图片的指纹。组合的次序并不重要,只要保证所有图片都采用同样次序就行了。得到指纹以后,就可以对比不同的图片,看看64位中有多少位是不一样的。
这种算法的优点是简单快速,不受图片大小缩放的影响,缺点是图片的内容不能变更。实际应用中,往往采用更强大的pHash算法和SIFT算法,它们能够识别图片的变形。只要变形程度不超过25%,它们就能匹配原图。
图片相似搜索的PHP实现
- /**
- *
- * 相似图片搜索hash的php实现
- * @author welefen
- *
- */
- class Imghash{
- private static $_instance = null;
- public $rate = 2;
- public static function getInstance(){
- if (self::$_instance === null){
- self::$_instance = new self();
- }
- return self::$_instance;
- }
- public function run($file){
- if (!function_exists('imagecreatetruecolor')){
- throw new Exception('must load gd lib', 1);
- }
- $isString = false;
- if (is_string($file)){
- $file = array($file);
- $isString = true;
- }
- $result = array();
- foreach ($file as $f){
- $result[] = $this->hash($f);
- }
- return $isString ? $result[0] : $result;
- }
- public function checkIsSimilarImg($imgHash, $otherImgHash){
- if (file_exists($imgHash) && file_exists($otherImgHash)){
- $imgHash = $this->run($imgHash);
- $otherImgHash = $this->run($otherImgHash);
- }
- if (strlen($imgHash) !== strlen($otherImgHash)) return false;
- $count = 0;
- $len = strlen($imgHash);
- for($i=0;$i<$len;$i++){
- if ($imgHash{$i} !== $otherImgHash{$i}){
- $count++;
- }
- }
- return $count <= (5 * $rate * $rate) ? true : false;
- }
- public function hash($file){
- if (!file_exists($file)){
- return false;
- }
- $height = 8 * $this->rate;
- $width = 8 * $this->rate;
- $img = imagecreatetruecolor($width, $height);
- list($w, $h) = getimagesize($file);
- $source = $this->createImg($file);
- imagecopyresampled($img, $source, 0, 0, 0, 0, $width, $height, $w, $h);
- $value = $this->getHashValue($img);
- imagedestroy($img);
- return $value;
- }
- public function getHashValue($img){
- $width = imagesx($img);
- $height = imagesy($img);
- $total = 0;
- $array = array();
- for ($y=0;$y<$height;$y++){
- for ($x=0;$x<$width;$x++){
- $gray = ( imagecolorat($img, $x, $y) >> 8 ) & 0xFF;
- if (!is_array($array[$y])){
- $array[$y] = array();
- }
- $array[$y][$x] = $gray;
- $total += $gray;
- }
- }
- $average = intval($total / (64 * $this->rate * $this->rate));
- $result = '';
- for ($y=0;$y<$height;$y++){
- for ($x=0;$x<$width;$x++){
- if ($array[$y][$x] >= $average){
- $result .= '1';
- }else{
- $result .= '0';
- }
- }
- }
- return $result;
- }
- public function createImg($file){
- $ext = $this->getFileExt($file);
- if ($ext === 'jpeg') $ext = 'jpg';
- $img = null;
- switch ($ext){
- case 'png' : $img = imagecreatefrompng($file);break;
- case 'jpg' : $img = imagecreatefromjpeg($file);break;
- case 'gif' : $img = imagecreatefromgif($file);
- }
- return $img;
- }
- public function getFileExt($file){
- $infos = explode('.', $file);
- $ext = strtolower($infos[count($infos) - 1]);
- return $ext;
- }
- }
调用方式如下:
- require_once "Imghash.class.php";
- $instance = ImgHash::getInstance();
- $result = $instance->checkIsSimilarImg('chenyin/IMG_3214.png', 'chenyin/IMG_3212.JPG');
如果$result值为true, 则表明2个图片相似,否则不相似。
其他
在实际的相似图片搜索中,算图片的指纹并不是难点,难点而是在怎么从海量的图片指纹里找出与之相似的指纹。
原文链接:http://www.welefen.com/similar-image-search-in-php.html
下一篇: VB实现Asp中的server.urlencode功能
文章来自: 本站原创
引用通告: 查看所有引用 | 我要引用此文章
Tags: php
相关日志:
广告位