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 相关文章推荐
WHOIS类的修改版
Oct 09 PHP
一个PHP的String类代码
Apr 20 PHP
小文件php+SQLite存储方案
Sep 04 PHP
PHP的SQL注入过程分析
Jan 06 PHP
探讨GDFONTPATH能否被winxp下的php支持
Jun 21 PHP
php把数据表导出为Excel表的最简单、最快的方法(不用插件)
May 10 PHP
Symfony2学习笔记之控制器用法详解
Mar 17 PHP
PHP微信开发之查询微信精选文章
Jun 23 PHP
PHP 极验验证码实例讲解
Sep 29 PHP
PHP观察者模式原理与简单实现方法示例
Aug 25 PHP
php实现构建排除当前元素的乘积数组方法
Oct 06 PHP
Docker 安装 PHP并与Nginx的部署实例讲解
Feb 27 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程序的国际化实现方法(利用gettext)
2011/08/14 PHP
将酷狗krc歌词解析并转换为lrc歌词php源码
2014/06/20 PHP
php猜单词游戏
2015/09/29 PHP
thinkphp中的url跳转用法分析
2016/07/12 PHP
js操作ajax返回的json的注意问题!
2010/02/23 Javascript
jquery组件使用中遇到的问题整理及解决
2014/02/21 Javascript
跟我学Node.js(四)---Node.js的模块载入方式与机制
2014/06/04 Javascript
[将免费进行到底]在Amazon的一年免费服务器上安装Node.JS, NPM和OurJS博客
2014/08/18 Javascript
使用jquery组件qrcode生成二维码及应用指南
2015/02/22 Javascript
jQuery简单实现验证邮箱格式
2015/07/15 Javascript
JavaScript中的Repaint和Reflow用法详解
2015/07/27 Javascript
基于jQuery实现响应式圆形图片轮播特效
2015/11/25 Javascript
谈一谈jQuery核心架构设计
2016/03/28 Javascript
javascript实现消灭星星小游戏简单版
2016/11/15 Javascript
javaScript中的空值和假值
2017/12/18 Javascript
vue中的数据绑定原理的实现
2018/07/02 Javascript
解决前后端分离 vue+springboot 跨域 session+cookie失效问题
2019/05/13 Javascript
浅谈Vue.js之初始化el以及数据的绑定说明
2019/11/14 Javascript
Vue axios与Go Frame后端框架的Options请求跨域问题详解
2020/03/03 Javascript
Python天气预报采集器实现代码(网页爬虫)
2012/10/07 Python
Python FTP操作类代码分享
2014/05/13 Python
Python的Flask框架中配置多个子域名的方法讲解
2016/06/07 Python
Python3的urllib.parse常用函数小结(urlencode,quote,quote_plus,unquote,unquote_plus等)
2016/09/18 Python
Python爬取当当、京东、亚马逊图书信息代码实例
2017/12/09 Python
Python3.5 处理文本txt,删除不需要的行方法
2018/12/10 Python
python使用sklearn实现决策树的方法示例
2019/09/12 Python
html5 利用重力感应实现摇一摇换颜色可用来做抽奖等等
2014/05/07 HTML / CSS
Koral官方网站:女性时尚运动服
2019/04/10 全球购物
全球速卖通俄罗斯站:AliExpress俄罗斯
2019/06/17 全球购物
什么是URL
2015/12/13 面试题
护士毕业自我鉴定
2014/02/07 职场文书
教师个人自我剖析材料
2014/09/29 职场文书
员工拾金不昧表扬稿
2015/05/05 职场文书
2015年大学生暑期实习报告
2015/07/13 职场文书
《秋天的怀念》教学反思
2016/02/17 职场文书
建房合同协议书
2016/03/21 职场文书