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 图像函数大举例(非原创)
Jun 20 PHP
php和js如何通过json互相传递数据相关问题探讨
Feb 26 PHP
PHP系统命令函数使用分析
Jul 05 PHP
php求两个目录的相对路径示例(php获取相对路径)
Mar 27 PHP
PHP检测字符串是否为UTF8编码的常用方法
Nov 21 PHP
10款PHP开源商城系统汇总介绍
Jul 23 PHP
WordPress中获取指定分类及其子分类下的文章数目
Dec 31 PHP
ThinkPHP的常用配置选项汇总
Mar 24 PHP
PHP实现文件上传下载实例
Oct 18 PHP
CI框架中类的自动加载问题分析
Nov 21 PHP
Laravel框架实现简单的学生信息管理平台案例
May 07 PHP
PHPStorm2020.1永久激活及下载更新至2020(推荐)
Sep 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
smarty+adodb+部分自定义类的php开发模式
2006/12/31 PHP
php截取utf-8中文字符串乱码的解决方法
2010/03/29 PHP
PHP命名空间用法实例分析
2019/09/04 PHP
jQuery JSON的解析方式分享
2011/04/05 Javascript
JS 模态对话框和非模态对话框操作技巧汇总
2013/04/15 Javascript
jquery如何实现在加载完iframe的内容后再进行操作
2013/09/10 Javascript
鼠标左键单击冲突的问题解决方法(防止冒泡)
2014/05/14 Javascript
JavaScript实现找出字符串中第一个不重复的字符
2014/09/03 Javascript
JS实现动态给图片添加边框的方法
2015/04/01 Javascript
JavaScript将字符串转换为整数的方法
2015/04/14 Javascript
jQuery Ajax使用实例
2015/04/16 Javascript
AngularJS的内置过滤器详解
2015/05/14 Javascript
JavaScript DOM 学习总结(五)
2015/11/24 Javascript
Bootstrap table的使用方法
2016/11/02 Javascript
浅谈angularjs依赖服务注入写法的注意点
2017/04/24 Javascript
JavaScript实现滑动导航栏效果
2017/08/30 Javascript
关于jquery中attr()和prop()方法的区别
2018/05/28 jQuery
vuedraggable+element ui实现页面控件拖拽排序效果
2020/07/29 Javascript
使用Vue实现调用接口加载页面初始数据
2019/10/28 Javascript
[50:05]VGJ.S vs OG 2018国际邀请赛淘汰赛BO3 第二场 8.22
2018/08/23 DOTA
Python中实现远程调用(RPC、RMI)简单例子
2014/04/28 Python
python控制台英汉汉英电子词典
2020/04/23 Python
Python数据分析之获取双色球历史信息的方法示例
2018/02/03 Python
纯python实现机器学习之kNN算法示例
2018/03/01 Python
python 处理数字,把大于上限的数字置零实现方法
2019/01/28 Python
使用Python和Prometheus跟踪天气的使用方法
2019/05/06 Python
将python包发布到PyPI和制作whl文件方式
2019/12/25 Python
python让函数不返回结果的方法
2020/06/22 Python
Burt’s Bees英国官网:世界领先的天然个人护理品牌
2020/08/17 全球购物
自我鉴定书范文
2013/10/02 职场文书
聘用意向书范本
2014/04/01 职场文书
齐云山导游词
2015/02/06 职场文书
超市采购员岗位职责
2015/04/07 职场文书
社区节水倡议书
2015/04/29 职场文书
趣味运动会广播稿
2015/08/19 职场文书
Windows Server 2012配置DNS服务器的方法
2022/04/29 Servers