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 相关文章推荐
实用函数2
Nov 08 PHP
php 智能404跳转代码,适合换域名没改变目录的网站
Jun 04 PHP
php cookies中删除的一般赋值方法
May 07 PHP
PHP面向对象法则
Feb 23 PHP
phpmyadmin配置文件现在需要绝密的短密码(blowfish_secret)的2种解决方法
May 07 PHP
php微信浏览器分享设置以及回调详解
Aug 01 PHP
PHP中仿制 ecshop验证码实例
Jan 06 PHP
PHP 中常量的知识整理
Apr 14 PHP
ThinkPHP框架实现数据增删改
May 07 PHP
Yii2框架数据验证操作实例详解
May 02 PHP
Yii2框架视图(View)操作及Layout的使用方法分析
May 27 PHP
PHP PDO和消息队列的个人理解与应用实例分析
Nov 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
星际中一些鲜为人知的详细资料
2020/03/04 星际争霸
动画 《Pokemon Sword·Shield》系列WEB动画《薄明之翼》第2话声优阵容公开!
2020/03/06 日漫
ThinkPHP php 框架学习笔记
2009/10/30 PHP
Linux中为php配置伪静态
2014/12/17 PHP
Yii2处理密码加密及验证的方法
2019/05/12 PHP
js跨浏览器实现将字符串转化为xml对象的方法
2013/09/25 Javascript
jQuery简单自定义图片轮播插件及用法示例
2016/11/21 Javascript
解决layui前端框架 form表单,table表等内置控件不显示的问题
2018/08/19 Javascript
javascript设计模式 ? 解释器模式原理与用法实例分析
2020/04/17 Javascript
[01:04:22]2018DOTA2亚洲邀请赛 3.31 小组赛 B组 IG vs EG
2018/04/01 DOTA
python实现类似ftp传输文件的网络程序示例
2014/04/08 Python
用Python实现服务器中只重载被修改的进程的方法
2015/04/30 Python
python异常和文件处理机制详解
2016/07/19 Python
django中的HTML控件及参数传递方法
2018/03/20 Python
用Python实现数据的透视表的方法
2018/11/16 Python
在PyCharm中实现添加快捷模块
2020/02/12 Python
django实现模型字段动态choice的操作
2020/04/01 Python
pandas中的ExcelWriter和ExcelFile的实现方法
2020/04/24 Python
Python分析最近大火的网剧《隐秘的角落》
2020/07/02 Python
Booking.com德国:预订最好的酒店和住宿
2020/02/16 全球购物
在线实验室测试:HealthLabs.com
2020/05/03 全球购物
PHP如何与mysql建立链接
2013/05/05 面试题
热能动力工程毕业生自荐信
2013/11/07 职场文书
中秋节礼品促销方案
2014/02/02 职场文书
贺卡寄语大全
2014/04/11 职场文书
《大作家的小老师》教学反思
2014/04/16 职场文书
文明生主要事迹
2014/05/25 职场文书
安全环保标语
2014/06/09 职场文书
2014年国庆节演讲稿精选范文1500字
2014/09/25 职场文书
2015年后备干部工作总结
2015/05/15 职场文书
党支部鉴定意见
2015/06/02 职场文书
CSS中em的正确打开方式详解
2021/04/08 HTML / CSS
python基于turtle绘制几何图形
2021/06/15 Python
Python中Selenium对Cookie的操作方法
2021/07/09 Python
CKAD认证中部署k8s并配置Calico插件
2022/03/31 Servers
Java实现贪吃蛇游戏的示例代码
2022/09/23 Java/Android