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的MySQL连接类
Jun 07 PHP
PHP文件锁定写入实例解析
Jul 14 PHP
php文件上传你必须知道的几点
Oct 20 PHP
php实现倒计时效果
Dec 19 PHP
Linux系统中设置多版本PHP共存配合Nginx服务器使用
Dec 21 PHP
详解WordPress中简码格式标签编写的基本方法
Dec 22 PHP
php实现计算百度地图坐标之间距离的方法
May 05 PHP
PHP微信开发之根据用户回复关键词\位置返回附近信息
Jun 24 PHP
PHP运行模式汇总
Nov 06 PHP
关于ThinkPhp 框架表单验证及ajax验证问题
Jul 19 PHP
微信支付之JSAPI公众号支付详解
May 15 PHP
Laravel框架查询构造器 CURD操作示例
Sep 04 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内置过滤器FILTER使用实例
2014/06/25 PHP
解决yii2左侧菜单子级无法高亮问题的方法
2016/05/08 PHP
jquery json 实例代码
2010/12/02 Javascript
javascript实现在某个元素上阻止鼠标右键事件的方法和实例
2014/08/12 Javascript
AngularJS中$interval的用法详解
2016/02/02 Javascript
Angularjs---项目搭建图文教程
2016/07/08 Javascript
vue.js简单配置axios的方法详解
2017/12/13 Javascript
webpack4+Vue搭建自己的Vue-cli项目过程分享
2018/08/29 Javascript
Vue在页面数据渲染完成之后的调用方法
2018/09/11 Javascript
微信小程序授权登录及解密unionId出错的方法
2018/09/26 Javascript
jQuery移动端跑马灯抽奖特效升级版(抽奖概率固定)实现方法
2019/01/18 jQuery
实用的Vue开发技巧
2019/05/30 Javascript
swiper4实现移动端导航切换
2020/10/16 Javascript
微信小程序wx.navigateTo方法里的events参数使用详情及场景
2020/01/07 Javascript
[02:41]DOTA2英雄基础教程 谜团
2013/12/10 DOTA
零基础写python爬虫之抓取百度贴吧并存储到本地txt文件改进版
2014/11/06 Python
Numpy数组转置的两种实现方法
2018/04/17 Python
详解python如何在django中为用户模型添加自定义权限
2018/10/15 Python
对Python random模块打乱数组顺序的实例讲解
2018/11/08 Python
python实现n个数中选出m个数的方法
2018/11/13 Python
对Pycharm创建py文件时自定义头部模板的方法详解
2019/02/12 Python
Django打印出在数据库中执行的语句问题
2019/07/25 Python
python——全排列数的生成方式
2020/02/26 Python
深入了解Python enumerate和zip
2020/07/16 Python
python des,aes,rsa加解密的实现
2021/01/16 Python
详解如何用canvas画一个微笑的表情
2019/03/14 HTML / CSS
意大利简约的休闲品牌:Aspesi
2018/02/08 全球购物
理工大学毕业生自荐信范文
2014/02/22 职场文书
小学生秋游活动方案
2014/02/23 职场文书
服务质量承诺书
2014/03/27 职场文书
梅花魂教学反思
2014/04/25 职场文书
改进作风怎么办发言材料
2014/08/17 职场文书
社会实践活动总结格式
2015/05/11 职场文书
教师信息技术学习心得体会
2016/01/21 职场文书
Redis读写分离搭建的完整步骤
2021/09/14 Redis
Win11筛选键导致键盘失灵怎么解决? Win11关闭筛选键的技巧
2022/04/08 数码科技