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 相关文章推荐
优化NFR之一 --MSSQL Hello Buffer Overflow
Oct 09 PHP
配置Apache2.2+PHP5+CakePHP1.2+MySQL5运行环境
Apr 25 PHP
php 大数据量及海量数据处理算法总结
May 07 PHP
php var_export与var_dump 输出的不同
Aug 09 PHP
PHP CURL获取cookies模拟登录的方法
Nov 04 PHP
PHP输出当前进程所有变量/常量/模块/函数/类的示例
Nov 07 PHP
Laravel 5框架学习之路由、控制器和视图简介
Apr 07 PHP
PHP5.2下preg_replace函数的问题
May 08 PHP
PHP微信公众号自动发送红包API
Jun 01 PHP
layui框架实现文件上传及TP3.2.3(thinkPHP)对上传文件进行后台处理操作示例
May 12 PHP
PHP使用 Imagick 扩展实现图片合成,圆角处理功能示例
Sep 09 PHP
PHP Swoole异步Redis客户端实现方法示例
Oct 24 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支持页面回退的两种方法
2008/01/10 PHP
php获取apk包信息的方法
2014/08/15 PHP
php中socket通信机制实例详解
2015/01/03 PHP
jQuery 第二课 操作包装集元素代码
2010/03/14 Javascript
网页广告中JS代码的信息监听示例
2014/04/02 Javascript
不用一句js代码初始化组件
2016/01/27 Javascript
对jquery的ajax进行二次封装以及ajax缓存代理组件:AjaxCache详解
2016/04/11 Javascript
js中判断变量类型函数typeof的用法总结
2016/08/09 Javascript
微信小程序 数据访问实例详解
2016/10/08 Javascript
AngularJS 文件上传控件 ng-file-upload详解
2017/01/13 Javascript
基于vue.js实现侧边菜单栏
2017/03/20 Javascript
javascript中的面向对象
2017/03/30 Javascript
Vue学习之路之登录注册实例代码
2017/07/06 Javascript
bootstrap-table实现服务器分页的示例 (spring 后台)
2017/09/01 Javascript
form表单数据封装成json格式并提交给服务器的实现方法
2017/12/14 Javascript
vue获取当前点击的元素并传值的实例
2018/03/09 Javascript
vuex 的简单使用
2018/03/22 Javascript
详解webpack 入门与解析
2018/04/09 Javascript
实例介绍JavaScript中多种组合继承
2019/01/20 Javascript
微信小程序 swiper 组件遇到的问题及解决方法
2019/05/26 Javascript
关于微信小程序map组件z-index的层级问题分析
2019/07/09 Javascript
NodeJS和浏览器中this关键字的不同之处
2021/03/03 NodeJs
python 调用HBase的简单实例
2016/12/18 Python
Python实现好友全头像的拼接实例(推荐)
2017/06/24 Python
Python图像处理之识别图像中的文字(实例讲解)
2018/05/10 Python
浅谈Python2、Python3相对路径、绝对路径导入方法
2018/06/22 Python
Python操作rabbitMQ的示例代码
2019/03/19 Python
使用python实现男神女神颜值打分系统(推荐)
2019/10/31 Python
python+selenium定时爬取丁香园的新型冠状病毒数据并制作出类似的地图(部署到云服务器)
2020/02/09 Python
python中文分词库jieba使用方法详解
2020/02/11 Python
matplotlib设置颜色、标记、线条,让你的图像更加丰富(推荐)
2020/09/25 Python
selenium设置浏览器为headless无头模式(Chrome和Firefox)
2021/01/08 Python
The Beach People美国:澳洲海滨奢华品牌
2018/07/05 全球购物
大学生物业管理求职信
2013/10/24 职场文书
个人收入证明范本
2014/01/12 职场文书
竞选学生会演讲稿
2014/04/25 职场文书