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 最大运行时间 max_execution_time修改方法
Mar 08 PHP
php实现监听事件
Nov 06 PHP
PHP中使用glob函数实现一句话删除某个目录下的所有文件
Jul 22 PHP
ThinkPHP中自定义目录结构的设置方法
Aug 15 PHP
PHP Session机制简介及用法
Aug 19 PHP
ThinkPHP 表单自动验证运用示例
Oct 13 PHP
Smarty模板简单配置与使用方法示例
May 23 PHP
PHP微信支付开发实例
Jun 22 PHP
Yii2表单事件之Ajax提交实现方法
May 04 PHP
PHP面向对象程序设计之构造方法和析构方法详解
Jun 13 PHP
thinkphp框架表单数组实现图片批量上传功能示例
Apr 04 PHP
PHP tp5中使用原生sql查询代码实例
Oct 28 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
Zerg剧情介绍
2020/03/14 星际争霸
php采集时被封ip的解决方法
2010/08/29 PHP
PHP小教程之实现双向链表
2014/06/12 PHP
PHP设计模式(六)桥连模式Bridge实例详解【结构型】
2020/05/02 PHP
jQuery 遍历json数组的实现代码
2020/09/22 Javascript
得到form下的所有的input的js代码
2013/11/07 Javascript
js实现编辑div节点名称的方法
2014/12/17 Javascript
从零学习node.js之模块规范(一)
2017/02/21 Javascript
利用JS做网页特效_大图轮播(实例讲解)
2017/08/09 Javascript
node.js+captchapng+jsonwebtoken实现登录验证示例
2017/08/17 Javascript
XMLHttpRequest对象_Ajax异步请求重点(推荐)
2017/09/28 Javascript
vue项目中导入swiper插件的方法
2018/01/30 Javascript
JS中的算法与数据结构之链表(Linked-list)实例详解
2019/08/20 Javascript
使用Vue-cli 中为单独页面设置背景图片铺满全屏
2020/07/17 Javascript
解决VUE项目localhost端口服务器拒绝连接,只能用127.0.0.1的问题
2020/08/14 Javascript
[01:04:20]完美世界DOTA2联赛PWL S2 LBZS vs Forest 第一场 11.29
2020/12/02 DOTA
使用python删除nginx缓存文件示例(python文件操作)
2014/03/26 Python
Python的randrange()方法使用教程
2015/05/15 Python
python机器学习之神经网络(二)
2017/12/20 Python
好的Python培训机构应该具备哪些条件
2018/05/23 Python
对pandas中Series的map函数详解
2018/07/25 Python
Python网络爬虫之爬取微博热搜
2019/04/18 Python
Python 用matplotlib画以时间日期为x轴的图像
2019/08/06 Python
利用python Selenium实现自动登陆京东签到领金币功能
2019/10/31 Python
通过python-pptx模块操作ppt文件的方法
2020/12/26 Python
德国玩具商店:Planet Happy DE
2021/01/16 全球购物
对象的序列化(serialization)类是面向流的,应如何将对象写入到随机存取文件中
2015/06/22 面试题
外企办公室竞聘演讲稿
2013/12/29 职场文书
白酒营销策划方案
2014/08/17 职场文书
开展批评与自我批评发言材料
2014/10/17 职场文书
2014年学校党建工作总结
2014/11/11 职场文书
2015年护士医德医风自我评价
2015/03/03 职场文书
2015年社会治安综合治理工作总结
2015/04/10 职场文书
Python快速实现一键抠图功能的全过程
2021/06/29 Python
最新最全的手机号验证正则表达式
2022/02/24 Javascript
zabbix配置nginx监控的实现
2022/05/25 Servers