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 ADODB使用方法集锦
Mar 25 PHP
保存到桌面、设为桌面且带图标的PHP代码
Nov 19 PHP
PHP提示Cannot modify header information - headers already sent by解决方法
Sep 22 PHP
浅谈PHP中output_buffering
Jul 13 PHP
thinkphp跨库操作的简单代码实例
Sep 22 PHP
遍历指定目录,并存储目录内所有文件属性信息的php代码
Oct 28 PHP
浅谈PHP发送HTTP请求的几种方式
Jul 25 PHP
thinkphp5修改view到根目录实例方法
Jul 02 PHP
php实现对文件压缩简单的方法
Sep 29 PHP
laravel 框架结合关联查询 when()用法分析
Nov 22 PHP
PHP pthreads v3使用中的一些坑和注意点分析
Feb 21 PHP
php中array_fill函数的实例用法
Mar 02 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
Apache设置虚拟WEB
2006/10/09 PHP
php实现的RSS生成类实例
2015/04/23 PHP
PHP中mysqli_get_server_version()的实例用法
2020/02/03 PHP
javascript 硬盘序列号+其它硬件信息
2008/12/23 Javascript
javascript之bind使用介绍
2011/10/09 Javascript
js限制文本框只能输入数字(正则表达式)
2012/07/15 Javascript
js使用eval解析json(js中使用json)
2014/01/17 Javascript
JavaScript获取XML数据附示例截图
2014/03/05 Javascript
小心!AngularJS结合RequireJS做文件合并压缩的那些坑
2016/01/09 Javascript
WebSocket+node.js创建即时通信的Web聊天服务器
2016/08/08 Javascript
AngularJS Toaster使用详解
2017/02/24 Javascript
微信小程序tabbar底部导航
2018/11/05 Javascript
vue+elementUI实现表格关键字筛选高亮
2020/10/26 Javascript
解决vue更新路由router-view复用组件内容不刷新的问题
2019/11/04 Javascript
Vue通过for循环随机生成不同的颜色或随机数的实例
2019/11/09 Javascript
vue实现五子棋游戏
2020/05/28 Javascript
[07:38]2014DOTA2国际邀请赛 Newbee顺利挺进胜者组赛后专访
2014/07/15 DOTA
python正则表达式修复网站文章字体不统一的解决方法
2013/02/21 Python
Python Web框架Flask中使用新浪SAE云存储实例
2015/02/08 Python
Python中使用MELIAE分析程序内存占用实例
2015/02/18 Python
几个提升Python运行效率的方法之间的对比
2015/04/03 Python
python3.6+opencv3.4实现鼠标交互查看图片像素
2018/02/26 Python
tensorflow实现简单的卷积网络
2018/05/24 Python
Python实现多进程的四种方式
2019/02/22 Python
Django框架序列化与反序列化操作详解
2019/11/01 Python
在OpenCV里使用Camshift算法的实现
2019/11/22 Python
pytorch自定义二值化网络层方式
2020/01/07 Python
Django操作session 的方法
2020/03/09 Python
selenium+超级鹰实现模拟登录12306
2021/01/24 Python
python实现按日期归档文件
2021/01/30 Python
大学生的网络创业计划书
2013/12/26 职场文书
《鹬蚌相争》教学反思
2014/04/22 职场文书
敬老院标语
2014/06/27 职场文书
物联网工程专业推荐信
2014/09/08 职场文书
基层工作经验证明样本
2014/11/16 职场文书
幼儿园小班班务总结
2015/08/03 职场文书