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 相关文章推荐
用session做客户验证时的注意事项
Oct 09 PHP
WINDOWS下php5.2.4+mysql6.0+apache2.2.4+ZendOptimizer-3.3.0配置
Mar 28 PHP
php 购物车的例子
May 04 PHP
重新认识php array_merge函数
Aug 31 PHP
PHP查找数值数组中不重复最大和最小的10个数的方法
Apr 20 PHP
PHP可变函数学习小结
Nov 29 PHP
PHP图像裁剪缩略裁切类源码及使用方法
Jan 07 PHP
php自动提交表单的方法(基于fsockopen与curl)
May 09 PHP
php array_udiff_assoc 计算两个数组的差集实例
Nov 12 PHP
PHP获取IP地址所在地信息的实例(使用纯真IP数据库qqwry.dat)
Nov 15 PHP
基于php实现的验证码小程序
Dec 13 PHP
PHP实现的用户注册表单验证功能简单示例
Feb 25 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 不错的学习资料
2009/02/06 PHP
通过JavaScript或PHP检测Android设备的代码
2011/03/09 PHP
PHP类继承 extends使用介绍
2014/01/14 PHP
PHP网页游戏学习之Xnova(ogame)源码解读(十)
2014/06/24 PHP
PHP的Yii框架中过滤器相关的使用总结
2016/03/29 PHP
PHP简单验证码功能机制实例详解
2019/03/27 PHP
javascript 学习笔记(onchange等)
2010/11/14 Javascript
js遍历td tr等html元素
2012/12/13 Javascript
jQuery contains过滤器实现精确匹配使用方法
2013/04/12 Javascript
JS中数组Array的用法示例介绍
2014/02/20 Javascript
jQuery验证插件validation使用指南
2015/04/21 Javascript
JS实现随机乱撞彩色圆球特效的方法
2015/05/05 Javascript
JS图片放大效果简单实现代码
2016/09/08 Javascript
JS实现的缓冲运动效果示例
2018/04/30 Javascript
vue.js父子组件通信动态绑定的实例
2018/09/28 Javascript
vue获取验证码倒计时组件
2019/08/26 Javascript
详解element-ui级联菜单(城市三级联动菜单)和回显问题
2019/10/02 Javascript
Python contextlib模块使用示例
2015/02/18 Python
python通过pil将图片转换成黑白效果的方法
2015/03/16 Python
Python socket网络编程TCP/IP服务器与客户端通信
2017/01/05 Python
Python3.X 线程中信号量的使用方法示例
2017/07/24 Python
利用aardio给python编写图形界面
2017/08/21 Python
Python基于whois模块简单识别网站域名及所有者的方法
2018/04/23 Python
Python:合并两个numpy矩阵的实现
2019/12/02 Python
TensorFlow2.1.0最新版本安装详细教程
2020/04/08 Python
Python Excel vlookup函数实现过程解析
2020/06/22 Python
python 图像增强算法实现详解
2021/01/24 Python
HTML5给汉字加拼音收起展开组件的实现代码
2020/04/08 HTML / CSS
十佳美德少年事迹材料
2014/02/05 职场文书
《将心比心》教学反思
2014/04/08 职场文书
学生会个人总结范文
2015/02/15 职场文书
计划生育工作总结2015
2015/04/03 职场文书
大学团日活动总结书
2015/05/11 职场文书
公务员处分决定书
2015/06/25 职场文书
采购员工作总结范文
2015/08/12 职场文书
Python max函数中key的用法及原理解析
2021/06/26 Python