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 学习资料零碎东西
Dec 04 PHP
第二章 PHP入门基础之php代码写法
Dec 30 PHP
php的memcache类分享(memcache队列)
Mar 26 PHP
PHP使用array_multisort对多个数组或多维数组进行排序
Dec 16 PHP
PHP 正则表达式小结
Feb 12 PHP
PHP实现支持SSL连接的SMTP邮件发送类
Mar 05 PHP
PHP环境搭建的详细步骤
Jun 30 PHP
PHP应用跨时区功能的实现方法
Mar 21 PHP
PHP使用Session实现上传进度功能详解
Aug 06 PHP
laravel框架添加数据,显示数据,返回成功值的方法
Oct 11 PHP
PHP7 其他语言层面的修改
Mar 09 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中对各种加密算法、Hash算法的速度测试对比代码
2014/07/08 PHP
thinkphp在模型中自动完成session赋值示例代码
2014/09/09 PHP
ajax调用返回php接口返回json数据的方法(必看篇)
2017/05/05 PHP
ThinkPHP整合datatables实现服务端分页的示例代码
2018/02/10 PHP
laravel实现按月或天或小时统计mysql数据的方法
2019/10/09 PHP
不用ajax实现点击文字即可编辑的方法
2007/12/16 Javascript
去掉gridPanel表头全选框的小例子
2013/07/18 Javascript
js 通过cookie实现刷新不变化树形菜单
2014/10/30 Javascript
JavaScript实现打开链接页面的方式汇总
2016/06/02 Javascript
深入理解JavaScript定时机制
2016/10/27 Javascript
JavaScript实现图片轮播组件代码示例
2016/11/22 Javascript
详解基于Bootstrap+angular的一个豆瓣电影app
2017/06/26 Javascript
vue.js项目打包上线的图文教程
2017/11/16 Javascript
深入浅析Vue全局组件与局部组件的区别
2018/06/15 Javascript
vue-cli初始化项目中使用less的方法
2018/08/09 Javascript
jquery操作checkbox的常用方法总结【附测试源码下载】
2019/06/10 jQuery
Vue组件通信中非父子组件传值知识点总结
2019/12/05 Javascript
微信小程序利用云函数获取手机号码
2019/12/17 Javascript
微信小程序实现拼图小游戏
2020/10/22 Javascript
vue-cli 3如何使用vue-bootstrap-datetimepicker日期插件
2021/02/20 Vue.js
[06:04]DOTA2国际邀请赛纪录片:Just For LGD
2013/08/11 DOTA
Python手机号码归属地查询代码
2016/05/04 Python
使用Python制作简单的小程序IP查看器功能
2019/04/16 Python
Django继承自带user表并重写的例子
2019/11/18 Python
完美解决python针对hdfs上传和下载的问题
2020/06/05 Python
Python爬取微信小程序Charles实现过程图解
2020/09/29 Python
网站美工岗位职责
2014/04/02 职场文书
《理想的风筝》教学反思
2014/04/11 职场文书
查摆问题自我剖析材料
2014/08/18 职场文书
群众路线教育实践活动自我剖析思想汇报
2014/10/04 职场文书
2014年学校法制宣传日活动总结
2014/11/01 职场文书
物流业务员岗位职责
2015/04/03 职场文书
公司捐书倡议书
2015/04/27 职场文书
导游词之太行山青龙峡
2020/01/14 职场文书
Python初识逻辑与if语句及用法大全
2021/08/07 Python
Python制作表白爱心合集
2022/01/22 Python