您尚未登录,请登录后浏览更多内容! 登录 | 立即注册

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 14660|回复: 0
打印 上一主题 下一主题

[php学习资料] 分享一个PHP简易的图片相似度比较类

[复制链接]
跳转到指定楼层
楼主
发表于 2018-7-7 23:06:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
摘要: 本文讲的是分享一个PHP简易的图片相似度比较类, 由于相似图片搜索的php实现的 API 不怎么符合我的用途,所以我重新定义 API 的架构,改写成比较简单的函数方式,虽然还是用对象的方式包装。  代码如下 复制代码 <?php    /**   * 图
" j  h) t0 i, m: C
+ m" s8 J" @7 P) q

0 Q% k* r; B# K由于相似图片搜索的php实现的 API 不怎么符合我的用途,所以我重新定义 API 的架构,改写成比较简单的函数方式,虽然还是用对象的方式包装。

4 d1 X( _" m6 E
  1. <?php    0 J& \! |" Z, M/ Q& E2 g
  2. /**   ) n) K( s, s& R; e4 `  d
  3. * 图片相似度比较   
    % h5 d( U: j6 W3 O
  4. *   ' i6 {& L6 `3 ~
  5. * @version     $Id: ImageHash.php 4429 2012-04-17 13:20:31Z jax [        DISCUZ_CODE_1        ]nbsp;  . E$ d5 I$ f: k/ I0 o$ ~
  6. * @author      jax.hu   
    4 @' v9 Z  P  l- j  ?/ r
  7. *   
      h3 m) ~2 f" m/ G* w
  8. * <code>   1 k& j" b5 n" n! m$ t
  9. *  //Sample_1   
    4 {& z9 @' M! m7 B
  10. *  $aHash = ImageHash::hashImageFile('wsz.11.jpg');   
    , e* {) G8 O% j0 Z( C
  11. *  $bHash = ImageHash::hashImageFile('wsz.12.jpg');   ' |. S3 y1 q$ k
  12. *  var_dump(ImageHash::isHashSimilar($aHash, $bHash));   
    * H( n, A2 a& {
  13. *   
    " t; V( i$ T  m, `: t( d# L
  14. *  //Sample_2   
    9 Y' O' x5 T4 w: g( g
  15. *  var_dump(ImageHash::isImageFileSimilar('wsz.11.jpg', 'wsz.12.jpg'));   ' F3 {" w" h3 y* ?
  16. * </code>   1 R1 t1 Q, F) z* b* B# x
  17. */    2 I% I0 J$ K5 g% ~$ P
  18.     0 t3 o/ |4 `, h) @
  19. class ImageHash {    1 G. Y# v1 o6 R8 j1 W5 k) k* k
  20.     : N1 b. {9 @; S/ V3 B$ F* X
  21.    /**取样倍率 1~10   
    % y0 |* U/ j2 J. p, C) g
  22.     * @access public   
    - K- H2 I* u; K: _' W5 W
  23.     * @staticvar int   ; }7 `" A  d/ f9 s4 h
  24.     * */   
    4 P. w5 L! g! j0 {% g
  25.    public static $rate = 2;   
    8 n5 f4 m, f0 R( R0 J( a/ m
  26.    
    3 P! z% N6 ^) `% S
  27.    /**相似度允许值 0~64   
    $ T8 ]$ K- I/ r7 d
  28.     * @access public   0 K2 W0 k2 ~( e; |1 s9 M
  29.     * @staticvar int   
    & f0 d# c: g! M3 o9 W5 z0 `$ o" q
  30.     * */   
    ) z- }8 D" s* L  Y; k% B
  31.    public static $similarity = 80;    ' n2 N( Z4 N" X
  32.     / u  N- w# C0 B6 p* ^: Z1 W7 k
  33.    /**图片类型对应的开启函数   2 v8 U$ D$ _& e/ Y, Q9 K
  34.     * @access private   
    & y) q) J$ C) S+ _
  35.     * @staticvar string   * [; `6 X9 W& q4 c# z7 X
  36.     * */   
    % W' x; v0 L2 Y1 t# n1 Q" s
  37.    private static $_createFunc = array(    8 \0 @' a5 J0 c; i+ i* R1 h  v
  38.        IMAGETYPE_GIF   =>'imageCreateFromGIF',    9 g  n0 f9 o! G! S' h& _& d+ Q# C
  39.        IMAGETYPE_JPEG  =>'imageCreateFromJPEG',    " C* P; P& c& |' G
  40.        IMAGETYPE_PNG   =>'imageCreateFromPNG',    ) g) g( f4 W* I
  41.        IMAGETYPE_BMP   =>'imageCreateFromBMP',    5 a7 b9 ]* a# D
  42.        IMAGETYPE_WBMP  =>'imageCreateFromWBMP',   
    1 Q7 A2 v; T5 z4 k( S2 w/ T
  43.        IMAGETYPE_XBM   =>'imageCreateFromXBM',   
    1 Q, U2 V. o5 o) X
  44.    );    ; R6 S$ Y. }& |" ]
  45.    
    ! C* y5 [+ e' H% y) p9 l2 E
  46.     * T1 b+ ~7 J- Q9 ?2 @
  47.    /**从文件建立图片   
    & b; U: I# i6 N  K/ d
  48.     * @param string $filePath 文件地址路径   + v% C$ p3 i) P: @! x
  49.     * @return resource 当成功开启图片则传递图片 resource ID,失败则是 false   
    9 h% _, V) [. {
  50.     * */   
    7 \4 P) H' I% ]" I" D1 R
  51.    public static function createImage($filePath){   
    7 ?$ x4 I$ @. O! r
  52.        if(!file_exists($filePath)){ return false; }    4 L6 z' X# e# w9 p! H7 d$ `' s4 J
  53.     : H; t9 Q/ v% ?! ?
  54.        /*判断文件类型是否可以开启*/   
    , t/ M" S- [5 L
  55.        $type = exif_imagetype($filePath);   
    & b; D4 C# [( }2 R1 ^. V! W
  56.        if(!array_key_exists($type,self::$_createFunc)){ return false; }   
    ' V8 o  O9 d$ R2 q1 A
  57.     & J* x6 N& i" {  }" v9 n/ x, q
  58.        $func = self::$_createFunc[$type];   
    9 m0 O! @. k! k: {
  59.        if(!function_exists($func)){ return false; }   
    & `8 t3 n/ C. J; v7 L1 z* l
  60.     ; j+ O" C- |7 B& @' e! F; y$ D& J
  61.        return $func($filePath);    - O  j" s- X; i0 t
  62.    }   
    1 u3 Y4 z% Y$ E5 S( A( v3 N; h
  63.    
    * V( j7 u5 U$ `, A; g
  64.    
    * q5 M! Z$ y" b3 S0 a
  65.    /**hash 图片   % \. v$ t9 D% W  D' d4 u8 F% \9 F
  66.     * @param resource $src 图片 resource ID   ) }; d7 m' x. o: k
  67.     * @return string 图片 hash 值,失败则是 false   
    ) C* p, Q" J2 E; t& s3 C
  68.     * */   
    ( }9 ^3 O4 g& u2 v0 \; k' f
  69.    public static function hashImage($src){    2 ^1 o* m# w7 P0 A2 [6 q
  70.        if(!$src){ return false; }   
    & z! [, A6 _1 [7 h* h, f: E
  71.    
    ' i. @) z9 G2 ^: L9 a3 L3 c, T
  72.        /*缩小图片尺寸*/   
    7 u9 [- A; c, L- {6 X+ ^
  73.        $delta = 8 * self::$rate;   
    ) y) W% G$ v* P* z! w
  74.        $img = imageCreateTrueColor($delta,$delta);    2 e& m4 o  ?0 v& ~& U! q( @! X
  75.        imageCopyResized($img,$src, 0,0,0,0, $delta,$delta,imagesX($src),imagesY($src));   
    + x5 |4 u/ a7 G. n" n1 L
  76.     6 X0 M0 F' O+ B
  77.        /*计算图片灰阶值*/   
    5 K8 G9 x- t; n# l1 N; ?& s  x
  78.        $grayArray = array();    ) {7 I$ Z9 H' k+ r" L+ N
  79.        for ($y=0; $y<$delta; $y++){   
    # O1 a2 u/ R: g$ h
  80.            for ($x=0; $x<$delta; $x++){      G. J- G3 h5 N  V% s
  81.                $rgb = imagecolorat($img,$x,$y);   
    $ I0 w4 p, h3 s
  82.                $col = imagecolorsforindex($img, $rgb);    , s: i% i4 o/ ^3 E1 H) i
  83.                $gray = intval(($col['red']+$col['green']+$col['blue'])/3)& 0xFF;    & B% y- V8 X* j3 W3 C! ]/ A% T+ K+ j
  84.     ! Y2 W7 J* k  a$ z. C4 A- |
  85.                $grayArray[] = $gray;    " C3 a$ \7 R1 v& G2 W9 i
  86.            }   
    . y! {* C( d. B+ }
  87.        }   
    0 t) \) U% L8 ], P. |+ g6 `  @1 r
  88.        imagedestroy($img);   
    4 s0 A( |+ X& m% {6 ^
  89.    
    , L! l; ~7 B2 `& h! G$ J/ [  Q
  90.        /*计算所有像素的灰阶平均值*/   
    . f) R0 p) m; |3 I0 T: x- E
  91.        $average = array_sum($grayArray)/count($grayArray);   
    . x# a/ w/ ~, ^% {+ p9 l% m0 g3 i- {- z
  92.     1 H; X2 I7 `9 L# R! t! t7 j
  93.        /*计算 hash 值*/    8 G1 N! T7 [+ }
  94.        $hashStr = '';    : u: B. z& G. L1 I
  95.        foreach ($grayArray as $gray){    ( m2 ^! }  y6 Z" [; E
  96.            $hashStr .= ($gray>=$average) ? '1' : '0';   
    - |# ~! J' G! n1 c) y0 {8 W+ H$ G! K
  97.        }   
    ' T, O) e  d  ~( ?; p
  98.    
    / q1 _1 j' O% t7 I
  99.        return $hashStr;    * |8 O& Z! I) K2 o$ ?
  100.    }   
    & c0 _. ]3 n  B# P* j' @
  101.       o% V! P) e2 @' s! W% C; ~
  102.     + F  t: _( r/ ?5 _
  103.    /**hash 图片文件   # |* y9 }3 m4 j+ o1 N0 ?0 {0 a9 J
  104.     * @param string $filePath 文件地址路径   
    # G# W* @0 y. x0 |1 k: \$ s/ k9 c
  105.     * @return string 图片 hash 值,失败则是 false   
    # I6 j8 W( F5 P! a1 n# P4 x
  106.     * */   
    0 }" g" v* Z1 `  R* [# f& W- M
  107.    public static function hashImageFile($filePath){    / n3 p& Y9 z5 y% [1 X
  108.        $src = self::createImage($filePath);    ! c1 ]1 o! \. {
  109.        $hashStr = self::hashImage($src);   
    1 ^% z$ R5 w7 B! U0 v" Q1 q0 V
  110.        imagedestroy($src);    ' Z! G. G: H7 h* w0 h
  111.    
    2 a  U2 Z' z9 v' S
  112.        return $hashStr;    # R4 z. D2 _3 U( x& D* \" F" G  A
  113.    }    6 \! K  L& j6 E
  114.     ) r9 Z) d0 u- v/ h- H* Z0 Y$ Q. G
  115.    
    ' Q3 o# _" s% u3 p, b$ I* S
  116.    /**比较两个 hash 值,是不是相似   
    % N" W# K, Y9 i1 u" S( J
  117.     * @param string $aHash A图片的 hash 值   
    7 z, y2 b+ @) _6 I- p# U
  118.     * @param string $bHash B图片的 hash 值   
    ; O  S' w( D7 a; G3 n
  119.     * @return bool 当图片相似则传递 true,否则是 false   , X9 ?5 _  ]% M! U- S+ @8 s- r
  120.     * */      r) ^  \$ n* p: m9 J$ [5 f* S
  121.    public static function isHashSimilar($aHash, $bHash){    $ {, V& D% I' L9 W, j
  122.        $aL = strlen($aHash); $bL = strlen($bHash);   
      i5 I2 X4 K/ }0 `' @7 a7 ]/ |! R
  123.        if ($aL !== $bL){ return false; }    6 ]  v1 E- \3 z
  124.    
    5 W: w0 y' }8 E1 v/ `
  125.        /*计算容许落差的数量*/   
    & b) H* ~9 A6 f
  126.        $allowGap = $aL*(100-self::$similarity)/100;   
    % `+ T7 \1 ]' Q/ R
  127.    
    ) I% t; Z" U& Y+ N: [6 t
  128.        /*计算两个 hash 值的汉明距离*/    9 i7 I8 C2 Q0 k4 Q9 q6 }' v6 ^
  129.        $distance = 0;    ' {1 r4 C+ Q; c; |- T
  130.        for($i=0; $i<$aL; $i++){    9 g$ b3 k! l/ I
  131.            if ($aHash{$i} !== $bHash{$i}){ $distance++; }   
    : b$ _1 s- L7 y8 e
  132.        }   
    # S, w2 A% A. H9 u% m  ]2 v" c8 ]8 H  C6 o
  133.     ( }4 \  L& r7 G% ^& k+ v2 i
  134.        return ($distance<=$allowGap) ? true : false;    - e1 ~6 X+ L. A: @) \4 J/ ^
  135.    }   
    7 l6 \: B) r  v
  136.    
    * k: j' @+ w0 n: l# l# G# u
  137.    
    3 K5 F2 l7 \% v7 Y5 d1 X4 r
  138.    /**比较两个图片文件,是不是相似   $ S; `- @) B( v& h5 [6 Z- F! {
  139.     * @param string $aHash A图片的路径   8 W% m7 D$ Q. w$ F2 l5 L
  140.     * @param string $bHash B图片的路径   
    / P. w' ]% R0 O: H% v  x- g% K; _
  141.     * @return bool 当图片相似则传递 true,否则是 false   
    + K) c6 A( U- o) h
  142.     * */   
    ( t0 {4 u8 @) ]7 L
  143.    public static function isImageFileSimilar($aPath, $bPath){    8 g& p1 A3 @) m" |% b/ }
  144.        $aHash = ImageHash::hashImageFile($aPath);    # A3 V4 h8 I# Z9 F0 O$ P
  145.        $bHash = ImageHash::hashImageFile($bPath);   
    ) t7 L/ g$ U6 \( S' x* G- d
  146.        return ImageHash::isHashSimilar($aHash, $bHash);    - p% l* E7 Q5 ]5 t: J8 U
  147.    }    ; M* F6 d  g& V+ O
  148.    
    7 j  e. Q' A: L9 ^
  149. }4 @9 U, |* s! P! H" t* D2 l; y
复制代码
% p* H; C6 x: \: F/ H: c! e
. `, N" q+ ]% t) |
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-6-20 02:59 , Processed in 0.055862 second(s), 20 queries .

Copyright © 2001-2026 Powered by cncml! X3.2. Theme By cncml!