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 相关文章推荐
递归列出所有文件和目录
Oct 09 PHP
PHP+AJAX实现无刷新注册(带用户名实时检测)
Dec 02 PHP
PHP面向对象法则
Feb 23 PHP
PHP 透明水印生成代码
Aug 27 PHP
php正则表达式使用的详细介绍
Apr 27 PHP
qq登录,新浪微博登录接口申请过程中遇到的问题
Jul 22 PHP
PHP实现将textarea的值根据回车换行拆分至数组
Jun 10 PHP
yum命令安装php7和相关扩展
Jul 04 PHP
php获取服务器操作系统相关信息的方法
Oct 08 PHP
详解PHP数据压缩、加解密(pack, unpack)
Dec 17 PHP
PHPCMS手机站伪静态设置详细教程
Feb 06 PHP
php实现简单加入购物车功能
Mar 07 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模板中出现空行解决方法
2011/03/08 PHP
mysql 查询指定日期时间内sql语句实现原理与代码
2012/12/16 PHP
ThinkPHP应用模式扩展详解
2014/07/16 PHP
PHP调用C#开发的dll类库方法
2014/07/28 PHP
php批量删除操作代码分享
2017/02/26 PHP
ThinkPHP5 框架引入 Go AOP,PHP AOP编程项目详解
2020/05/12 PHP
表单提交验证类
2006/07/14 Javascript
用window.location.href实现刷新另个框架页面
2007/03/07 Javascript
关于setInterval、setTimeout在jQuery中的使用注意事项
2011/09/28 Javascript
js实现按Ctrl+Enter发送效果
2014/09/18 Javascript
JavaScript中扩展Array contains方法实例
2020/08/23 Javascript
在windows上用nodejs搭建静态文件服务器的简单方法
2016/08/11 NodeJs
JS获取鼠标位置距浏览器窗口距离的方法示例
2017/04/11 Javascript
微信小程序 刷新上拉下拉不会断详细介绍
2017/05/11 Javascript
gulp教程_从入门到项目中快速上手使用方法
2017/09/14 Javascript
js中获取URL参数的共用方法getRequest()方法实例详解
2018/10/24 Javascript
详解JavaScript中的Object.is()与&quot;===&quot;运算符总结
2020/06/17 Javascript
[52:02]完美世界DOTA2联赛PWL S2 FTD.C vs SZ 第一场 11.27
2020/11/30 DOTA
python打开url并按指定块读取网页内容的方法
2015/04/29 Python
Python SQL查询并生成json文件操作示例
2018/08/17 Python
python在html中插入简单的代码并加上时间戳的方法
2018/10/16 Python
python自定义线程池控制线程数量的示例
2019/02/22 Python
深入浅析Python 中的sklearn模型选择
2019/10/12 Python
Python之字典添加元素的几种方法
2020/09/30 Python
python subprocess pipe 实时输出日志的操作
2020/12/05 Python
Python Selenium XPath根据文本内容查找元素的方法
2020/12/07 Python
利用CSS3动画实现圆圈由小变大向外扩散的效果实例
2018/09/10 HTML / CSS
使用HTML5 Canvas绘制圆角矩形及相关的一些应用举例
2016/03/22 HTML / CSS
四年的个人工作自我评价
2013/12/10 职场文书
城建学院毕业生自荐信
2014/01/31 职场文书
硕士生工作推荐信
2014/03/07 职场文书
青年文明号创建承诺
2014/03/31 职场文书
教研活动总结
2014/04/28 职场文书
2014房屋登记授权委托书
2014/10/13 职场文书
北京英文导游词
2015/02/12 职场文书
2015年公司行政后勤工作总结
2015/05/20 职场文书