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中的时间显示
Jan 18 PHP
基于php-fpm 参数的深入理解
Jun 03 PHP
php多个字符串替换成同一个的解决方法
Jun 18 PHP
浅析PHP页面局部刷新功能的实现小结
Jun 21 PHP
php5.3 不支持 session_register() 此函数已启用的解决方法
Nov 12 PHP
php多功能图片处理类分享(php图片缩放类)
Mar 14 PHP
通过curl模拟post和get方式提交的表单类
Apr 23 PHP
php获取客户端电脑屏幕参数的方法
Jan 09 PHP
php实现window平台的checkdnsrr函数
May 27 PHP
php语言的7种基本的排序方法
Dec 28 PHP
php常用数组array函数实例总结【赋值,拆分,合并,计算,添加,删除,查询,判断,排序】
Dec 07 PHP
php实现的XML操作(读取)封装类完整实例
Feb 23 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的ASP防火墙
2006/10/09 PHP
php eval函数用法 PHP中eval()函数小技巧
2012/10/31 PHP
php实现将任意进制数转换成10进制的方法
2015/04/17 PHP
php命名空间设计思想、用法与缺点分析
2019/07/17 PHP
Yii2 queue的队列使用详解
2019/07/19 PHP
sina的lightbox效果。
2007/01/09 Javascript
Discuz! 6.1_jQuery兼容问题
2008/09/23 Javascript
页面版文本框智能提示JS代码
2009/11/20 Javascript
De facto standard 世界上不可思议的事实标准
2010/08/29 Javascript
jquery 面包屑导航 具体实现
2013/06/05 Javascript
js读取cookie方法总结
2014/10/31 Javascript
javascript中函数作为参数调用的方法
2015/02/09 Javascript
javascript实现获取浏览器版本、浏览器类型
2015/12/02 Javascript
jquery捕捉回车键及获取checkbox值与异步请求的方法
2015/12/24 Javascript
深入浅析JSON.parse()、JSON.stringify()和eval()的作用详解
2016/04/03 Javascript
Bootstrap编写导航栏和登陆框
2016/05/30 Javascript
浅谈JS函数定义方式的区别
2016/10/30 Javascript
详解Angular CLI + Electron 开发环境搭建
2017/07/20 Javascript
JS 中LocalStorage和SessionStorage的使用
2017/08/17 Javascript
nodejs用gulp管理前端文件方法
2018/06/24 NodeJs
小程序开发踩坑:页面窗口定位(相对于浏览器定位)(推荐)
2019/04/25 Javascript
基于javascript实现贪吃蛇小游戏
2019/11/25 Javascript
JS实现简易计算器
2020/02/14 Javascript
vue单文件组件无法获取$refs的问题
2020/06/24 Javascript
Vue 实现对quill-editor组件中的工具栏添加title
2020/08/03 Javascript
[48:30]LGD vs infamous Supermajor小组赛D组 BO3 第一场 6.3
2018/06/04 DOTA
python实现简单的购物程序代码实例
2020/03/03 Python
python实现文法左递归的消除方法
2020/05/22 Python
美国办公用品购物网站:Quill.com
2016/09/01 全球购物
写好自荐信的几个要点
2013/12/26 职场文书
个人担保书范文
2014/05/20 职场文书
2014年绿化工作总结
2014/12/09 职场文书
搞笑结婚保证书
2015/05/08 职场文书
驳回起诉裁定书
2015/05/19 职场文书
党支部考察意见范文
2015/06/02 职场文书
oracle连接ODBC sqlserver数据源的详细步骤
2021/07/25 Oracle