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 相关文章推荐
用Flash图形化数据(二)
Oct 09 PHP
动态新闻发布的实现及其技巧
Oct 09 PHP
PHP 图片文件上传实现代码
Dec 29 PHP
怎样给PHP源代码加密?PHP二进制加密与解密的解决办法
Apr 22 PHP
解析使用ThinkPHP应该掌握的调试手段
Jun 20 PHP
php selectradio和checkbox默认选择的实现方法详解
Jun 29 PHP
php中session使用示例
Mar 29 PHP
PHP的文件操作与算法实现的面试题示例
Aug 10 PHP
WordPress中重置文章循环的rewind_posts()函数讲解
Jan 11 PHP
PHP模板引擎Smarty内置变量调解器用法详解
Apr 11 PHP
php类的自动加载操作实例详解
Sep 28 PHP
PHP使用OB缓存实现静态化功能示例
Mar 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微框架Dispatch简介
2014/06/12 PHP
php目录遍历函数opendir用法实例
2014/11/20 PHP
详细解读PHP中接口的应用
2015/08/12 PHP
yii2 页面底部加载css和js的技巧
2016/04/21 PHP
基于PHP后台的Android新闻浏览客户端
2016/05/23 PHP
php is_writable判断文件是否可写实例代码
2016/10/13 PHP
Laravel 5.5官方推荐的Nginx配置学习教程
2017/10/06 PHP
PHP autoload使用方法及步骤详解
2020/09/05 PHP
jQuery实现选项卡切换效果简单演示
2015/12/09 Javascript
jQuery animate和CSS3相结合实现缓动追逐效果附源码下载
2016/04/18 Javascript
js获取对象、数组的实际长度,元素实际个数的实现代码
2016/06/08 Javascript
javascript中对象的定义、使用以及对象和原型链操作小结
2016/12/14 Javascript
简单实现vue验证码60秒倒计时功能
2017/10/11 Javascript
vue 纯js监听滚动条到底部的实例讲解
2018/09/03 Javascript
vue click.stop阻止点击事件继续传播的方法
2018/09/04 Javascript
JS实现提示效果弹出及延迟隐藏的功能
2019/08/26 Javascript
微信小程序图片自适应实现解析
2020/01/21 Javascript
javascript实现留言板功能
2020/02/08 Javascript
微信小程序学习总结(四)事件与冒泡实例分析
2020/06/04 Javascript
python实现获取序列中最小的几个元素
2014/09/25 Python
Python中使用装饰器时需要注意的一些问题
2015/05/11 Python
Python中列表list以及list与数组array的相互转换实现方法
2017/09/22 Python
mac安装scrapy并创建项目的实例讲解
2018/06/13 Python
python实现多线程端口扫描
2019/08/31 Python
利用python、tensorflow、opencv、pyqt5实现人脸实时签到系统
2019/09/25 Python
python add_argument()用法解析
2020/01/29 Python
解决pytorch-yolov3 train 报错的问题
2020/02/18 Python
Python基于requests库爬取网站信息
2020/03/02 Python
canvas实现烟花的示例代码
2020/01/16 HTML / CSS
一套VC试题
2015/01/23 面试题
中国入世承诺
2014/04/01 职场文书
家长寄语大全
2014/04/02 职场文书
旅游文化节策划方案
2014/06/06 职场文书
党支部组织生活会整改方案
2014/09/30 职场文书
商务宴请邀请函范文
2015/02/02 职场文书
党风廉政建设心得体会(2016最新版)
2016/01/22 职场文书