PHP实现的简易版图片相似度比较


Posted in PHP onJanuary 07, 2015

由于相似图片搜索的php实现的 API 不怎么符合我的用途,所以我重新定义 API 的架构,改写成比较简单的函数方式,虽然还是用对象的方式包装。

<?php    

/**   

* 图片相似度比较   

*   

* @version     $Id: ImageHash.php 4429 2012-04-17 13:20:31Z jax $   

* @author      jax.hu   

*   

* <code>   

*  //Sample_1   

*  $aHash = ImageHash::hashImageFile('wsz.11.jpg');   

*  $bHash = ImageHash::hashImageFile('wsz.12.jpg');   

*  var_dump(ImageHash::isHashSimilar($aHash, $bHash));   

*   

*  //Sample_2   

*  var_dump(ImageHash::isImageFileSimilar('wsz.11.jpg', 'wsz.12.jpg'));   

* </code>   

*/    

    

class ImageHash {    

    

   /**取样倍率 1~10   

    * @access public   

    * @staticvar int   

    * */    

   public static $rate = 2;    

    

   /**相似度允许值 0~64   

    * @access public   

    * @staticvar int   

    * */    

   public static $similarity = 80;    

    

   /**图片类型对应的开启函数   

    * @access private   

    * @staticvar string   

    * */    

   private static $_createFunc = array(    

       IMAGETYPE_GIF   =>'imageCreateFromGIF',    

       IMAGETYPE_JPEG  =>'imageCreateFromJPEG',    

       IMAGETYPE_PNG   =>'imageCreateFromPNG',    

       IMAGETYPE_BMP   =>'imageCreateFromBMP',    

       IMAGETYPE_WBMP  =>'imageCreateFromWBMP',    

       IMAGETYPE_XBM   =>'imageCreateFromXBM',    

   );    

    

    

   /**从文件建立图片   

    * @param string $filePath 文件地址路径   

    * @return resource 当成功开启图片则传递图片 resource ID,失败则是 false   

    * */    

   public static function createImage($filePath){    

       if(!file_exists($filePath)){ return false; }    

    

       /*判断文件类型是否可以开启*/    

       $type = exif_imagetype($filePath);    

       if(!array_key_exists($type,self::$_createFunc)){ return false; }    

    

       $func = self::$_createFunc[$type];    

       if(!function_exists($func)){ return false; }    

    

       return $func($filePath);    

   }    

    

    

   /**hash 图片   

    * @param resource $src 图片 resource ID   

    * @return string 图片 hash 值,失败则是 false   

    * */    

   public static function hashImage($src){    

       if(!$src){ return false; }    

    

       /*缩小图片尺寸*/    

       $delta = 8 * self::$rate;    

       $img = imageCreateTrueColor($delta,$delta);    

       imageCopyResized($img,$src, 0,0,0,0, $delta,$delta,imagesX($src),imagesY($src));    

    

       /*计算图片灰阶值*/    

       $grayArray = array();    

       for ($y=0; $y<$delta; $y++){    

           for ($x=0; $x<$delta; $x++){    

               $rgb = imagecolorat($img,$x,$y);    

               $col = imagecolorsforindex($img, $rgb);    

               $gray = intval(($col['red']+$col['green']+$col['blue'])/3)& 0xFF;    

    

               $grayArray[] = $gray;    

           }    

       }    

       imagedestroy($img);    

    

       /*计算所有像素的灰阶平均值*/    

       $average = array_sum($grayArray)/count($grayArray);    

    

       /*计算 hash 值*/    

       $hashStr = '';    

       foreach ($grayArray as $gray){    

           $hashStr .= ($gray>=$average) ? '1' : '0';    

       }    

    

       return $hashStr;    

   }    

    

    

   /**hash 图片文件   

    * @param string $filePath 文件地址路径   

    * @return string 图片 hash 值,失败则是 false   

    * */    

   public static function hashImageFile($filePath){    

       $src = self::createImage($filePath);    

       $hashStr = self::hashImage($src);    

       imagedestroy($src);    

    

       return $hashStr;    

   }    

    

    

   /**比较两个 hash 值,是不是相似   

    * @param string $aHash A图片的 hash 值   

    * @param string $bHash B图片的 hash 值   

    * @return bool 当图片相似则传递 true,否则是 false   

    * */    

   public static function isHashSimilar($aHash, $bHash){    

       $aL = strlen($aHash); $bL = strlen($bHash);    

       if ($aL !== $bL){ return false; }    

    

       /*计算容许落差的数量*/    

       $allowGap = $aL*(100-self::$similarity)/100;    

    

       /*计算两个 hash 值的汉明距离*/    

       $distance = 0;    

       for($i=0; $i<$aL; $i++){    

           if ($aHash{$i} !== $bHash{$i}){ $distance++; }    

       }    

    

       return ($distance<=$allowGap) ? true : false;    

   }    

    

    

   /**比较两个图片文件,是不是相似   

    * @param string $aHash A图片的路径   

    * @param string $bHash B图片的路径   

    * @return bool 当图片相似则传递 true,否则是 false   

    * */    

   public static function isImageFileSimilar($aPath, $bPath){    

       $aHash = ImageHash::hashImageFile($aPath);    

       $bHash = ImageHash::hashImageFile($bPath);    

       return ImageHash::isHashSimilar($aHash, $bHash);    

   }    

    

} 
PHP 相关文章推荐
用PHP和ACCESS写聊天室(十)
Oct 09 PHP
PHP 网络开发详解之远程文件包含漏洞
Apr 25 PHP
关于ob_get_contents(),ob_end_clean(),ob_start(),的具体用法详解
Jun 24 PHP
ThinkPHP模板自定义标签使用方法
Jun 26 PHP
PHP 5.3新增魔术方法__invoke概述
Jul 23 PHP
Symfony2实现从数据库获取数据的方法小结
Mar 18 PHP
mac os快速切换多个PHP版本的方法
Mar 07 PHP
laravel 配置路由 api和web定义的路由的区别详解
Sep 03 PHP
PHP实现通过二维数组键值获取一维键名操作示例
Oct 11 PHP
laravel 获取某个查询的查询SQL语句方法
Oct 12 PHP
PHP底层运行机制与工作原理详解
Jul 31 PHP
laravel入门知识点整理
Sep 15 PHP
PHP中使用SimpleXML检查XML文件结构实例
Jan 07 #PHP
php中$_POST与php://input的区别实例分析
Jan 07 #PHP
php静态文件返回304技巧分享
Jan 06 #PHP
php判断当前用户已在别处登录的方法
Jan 06 #PHP
php实现utf-8转unicode函数分享
Jan 06 #PHP
windows中为php安装mongodb与memcache
Jan 06 #PHP
phpQuery让php处理html代码像jQuery一样方便
Jan 06 #PHP
You might like
php基于openssl的rsa加密解密示例
2016/07/11 PHP
php获取文件名称和扩展名的方法
2017/02/07 PHP
php str_getcsv把字符串解析为数组的实现方法
2017/04/05 PHP
微信第三方登录(原生)demo【必看篇】
2017/05/26 PHP
php简单构造json多维数组的方法示例
2017/06/08 PHP
php实现的顺序线性表示例
2019/05/04 PHP
RR vs IO BO3 第一场2.13
2021/03/10 DOTA
JavaScript-世界上误解最深的语言分析
2007/08/12 Javascript
一步一步制作jquery插件Tabs实现过程
2010/07/06 Javascript
IE与FireFox中的childNodes区别
2011/10/20 Javascript
JS cookie中文乱码解决方法
2014/01/28 Javascript
jQuery实现隔行背景色变色
2014/11/24 Javascript
node.js中的fs.writeFile方法使用说明
2014/12/14 Javascript
js实现三张图(文)片一起切换的banner焦点图
2015/08/25 Javascript
JS基于Mootools实现的个性菜单效果代码
2015/10/21 Javascript
深入理解JavaScript单体内置对象
2016/06/06 Javascript
JavaScript实现二分查找实例代码
2017/02/22 Javascript
微信小程序开发之map地图实现教程
2017/06/08 Javascript
JS实现图片转换成base64的各种应用场景实例分析
2018/06/22 Javascript
[09:33]2015国际邀请赛第四日TOP10
2015/08/08 DOTA
Python中使用Inotify监控文件实例
2015/02/14 Python
python实现神经网络感知器算法
2017/12/20 Python
Django框架视图函数设计示例
2019/07/29 Python
在python中使用nohup命令说明
2020/04/16 Python
Python中操作各种多媒体,视频、音频到图片的代码详解
2020/06/04 Python
python dict如何定义
2020/09/02 Python
Python数据库封装实现代码示例解析
2020/09/05 Python
使用Python爬取Json数据的示例代码
2020/12/07 Python
Matlab使用Plot函数实现数据动态显示方法总结
2021/02/25 Python
国际知名设计师时装商店:Coggles
2016/09/05 全球购物
雷曼兄弟的五金店:Lehman’s Hardware Store
2019/04/10 全球购物
租房协议书样本
2014/08/20 职场文书
优秀党员学习焦裕禄精神思想汇报范文
2014/09/10 职场文书
面试自我评价范文
2014/09/17 职场文书
2014年污水处理厂工作总结
2014/12/19 职场文书
碧霞祠导游词
2015/02/09 职场文书