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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2018-7-7 23:06:35 | 只看该作者 回帖奖励 |正序浏览 |阅读模式
摘要: 本文讲的是分享一个PHP简易的图片相似度比较类, 由于相似图片搜索的php实现的 API 不怎么符合我的用途,所以我重新定义 API 的架构,改写成比较简单的函数方式,虽然还是用对象的方式包装。  代码如下 复制代码 <?php    /**   * 图
' R, L" ]4 v7 k. c+ N9 ?; K3 }: n1 S; y- h2 b

/ S  n6 {+ i* K; J  A由于相似图片搜索的php实现的 API 不怎么符合我的用途,所以我重新定义 API 的架构,改写成比较简单的函数方式,虽然还是用对象的方式包装。
0 a# j7 B" b4 E
  1. <?php    # e: g  N5 ?, ^* F6 @
  2. /**   
    * Q" k" Z2 R7 [: Z1 v
  3. * 图片相似度比较   ' A# r$ D5 n% u, S# P
  4. *   
    % a9 {: |) d6 J8 a0 E- m% Y1 Q3 h
  5. * @version     $Id: ImageHash.php 4429 2012-04-17 13:20:31Z jax [        DISCUZ_CODE_1        ]nbsp;  
    2 Y- j% q/ K% Q  L7 O; z
  6. * @author      jax.hu   
    & {2 F' x8 c4 `2 X5 Y' p( V% ~
  7. *   
    0 d7 D# i$ U% X  n2 S# u; L
  8. * <code>   3 D0 u5 ?* F2 x9 i) J3 S
  9. *  //Sample_1   9 y" ?2 w. {# }% ^
  10. *  $aHash = ImageHash::hashImageFile('wsz.11.jpg');   
    ( m+ m" ?) d  u+ `' T8 J
  11. *  $bHash = ImageHash::hashImageFile('wsz.12.jpg');   
    6 {8 }- Z; M1 U/ P
  12. *  var_dump(ImageHash::isHashSimilar($aHash, $bHash));   & o7 f4 s& ]% t8 Y1 K& P$ d( y
  13. *   ) }) E% i0 h4 ]2 Y
  14. *  //Sample_2   
    ) T* m. w9 v9 ]  c5 T0 J
  15. *  var_dump(ImageHash::isImageFileSimilar('wsz.11.jpg', 'wsz.12.jpg'));   
    7 G/ i+ }: Q. Q5 E) `& S
  16. * </code>   9 Y' I+ U9 F4 k) k9 u# s0 [. r: m" @
  17. */    7 p$ [7 l3 n- f
  18.    
    3 I! Q' [6 u  J6 O; h! H& G1 ?8 N
  19. class ImageHash {   
    2 J* Z- _0 @- T
  20.    
    ' L9 y( E" {1 j4 u; w
  21.    /**取样倍率 1~10   # ^3 v$ }5 \% T. }8 i' Y% E; H. K! G( z
  22.     * @access public   
    : k2 o5 H0 v: p7 K
  23.     * @staticvar int   
    # i, w  a9 i4 ~7 T. A: W) \
  24.     * */    ' k2 ~8 [* w2 R( W. A
  25.    public static $rate = 2;    ) e. p) c3 Q1 j2 h9 G6 [
  26.     6 n8 G4 v/ V8 x. }, h1 v
  27.    /**相似度允许值 0~64   
    4 J4 z! C4 I. c! s( C: J9 j
  28.     * @access public   ; G, W% \/ H7 C! [4 l, D+ f
  29.     * @staticvar int   ( M* _$ u+ \* H: A; p( a
  30.     * */   
    1 J" s! c% b  W9 o0 n0 f
  31.    public static $similarity = 80;    , w1 @0 r& R7 q: [2 D
  32.    
    6 O1 }# f2 R2 `" N" W; s! e
  33.    /**图片类型对应的开启函数   $ ~: L4 G  Q$ O9 t, s+ Y5 J
  34.     * @access private     s/ y# O: H2 r) `5 \: H# c1 f5 S
  35.     * @staticvar string   
    % ^% j4 A6 D# h# H
  36.     * */   
    ; v/ G* L0 I2 c2 L2 g
  37.    private static $_createFunc = array(   
    % o2 j$ N4 k& \
  38.        IMAGETYPE_GIF   =>'imageCreateFromGIF',    8 A. _- h$ ~  U. \& e/ E0 h
  39.        IMAGETYPE_JPEG  =>'imageCreateFromJPEG',      ^, t$ \, `- H* s0 f5 m. B
  40.        IMAGETYPE_PNG   =>'imageCreateFromPNG',    1 V' S8 w" ]1 y% W
  41.        IMAGETYPE_BMP   =>'imageCreateFromBMP',   
    1 ^4 ~- m( p$ \, i5 g2 v
  42.        IMAGETYPE_WBMP  =>'imageCreateFromWBMP',   
    9 P8 B# Q: P. }! N5 q
  43.        IMAGETYPE_XBM   =>'imageCreateFromXBM',    2 M8 ~0 l# |2 I% j9 Y0 B
  44.    );   
    & f" y. n( V- B1 O7 R* C
  45.    
    # @9 i! _6 p) ~% ]9 F5 u
  46.     1 o$ I0 l4 i+ [4 ]' i
  47.    /**从文件建立图片   
    / g' T+ Z, h' k+ I" Q/ f8 j
  48.     * @param string $filePath 文件地址路径   
    4 j$ @4 c7 Z& Z; R
  49.     * @return resource 当成功开启图片则传递图片 resource ID,失败则是 false   8 |% _* n" H: Z! P" O0 c
  50.     * */    5 a$ X* z1 d; i* l- `$ {% j* E
  51.    public static function createImage($filePath){   
    2 x1 l" d' m( Q4 O) v
  52.        if(!file_exists($filePath)){ return false; }    : B, m/ h# Q! H- C. U; I5 P
  53.    
      W& a0 t% V. d. ^
  54.        /*判断文件类型是否可以开启*/    7 Y1 k! e3 g8 U' W$ y$ `
  55.        $type = exif_imagetype($filePath);   
    + E! g# K1 {) z$ X  W: _- [+ z
  56.        if(!array_key_exists($type,self::$_createFunc)){ return false; }    % b2 ~  o6 ~5 {% w
  57.    
    ) A: G; G  P' A" [. [( C5 |
  58.        $func = self::$_createFunc[$type];    ) I2 K" m: O: y( i6 `' g, U
  59.        if(!function_exists($func)){ return false; }    ( f! {9 n3 U$ C/ w8 ~6 ~
  60.    
    5 J( I  O/ x1 \* o: h2 ?
  61.        return $func($filePath);   
    1 t/ j: r: I% D) M6 ^
  62.    }    / V! f- c; U) N1 \! R
  63.     1 K0 p+ z1 X$ N8 E" z
  64.    
    $ u0 a+ i3 \9 T- _/ ~
  65.    /**hash 图片   
    ) N' @( t, m1 O% N" E' r. C6 v. f
  66.     * @param resource $src 图片 resource ID   % h; a. ^. V( T& p& ]& Y
  67.     * @return string 图片 hash 值,失败则是 false   7 C; w4 t$ U: i8 x
  68.     * */      G( a0 d$ \7 s- ?. Y1 x2 W* `. ~  g0 i
  69.    public static function hashImage($src){    & ]7 D$ Q. d6 W4 W
  70.        if(!$src){ return false; }    4 y9 }" P# O8 u: A$ _+ a
  71.    
    . o* r7 R0 Z. @$ w! x1 J( l, }
  72.        /*缩小图片尺寸*/    6 v: A2 u$ r3 _8 R2 k2 t- m: j
  73.        $delta = 8 * self::$rate;    6 X8 i; [) J- v
  74.        $img = imageCreateTrueColor($delta,$delta);   
    2 s! }) O- f) a3 R
  75.        imageCopyResized($img,$src, 0,0,0,0, $delta,$delta,imagesX($src),imagesY($src));   
    , B1 h  E6 d' F9 Y
  76.     1 h3 m; U% e4 u. G  x+ p
  77.        /*计算图片灰阶值*/   
    . h4 J- K: }: n/ B/ U9 [/ F) w
  78.        $grayArray = array();    3 q4 n1 N2 J: X
  79.        for ($y=0; $y<$delta; $y++){   
    6 N9 M# g9 u+ b4 V1 |) O+ ?5 X! i
  80.            for ($x=0; $x<$delta; $x++){   
    ' ]/ t* r, G  }1 u' Z$ U
  81.                $rgb = imagecolorat($img,$x,$y);    . p3 ^4 P% Q3 K2 `! g  `7 [
  82.                $col = imagecolorsforindex($img, $rgb);   
    0 r3 w4 b% B$ j8 Z# a; Y
  83.                $gray = intval(($col['red']+$col['green']+$col['blue'])/3)& 0xFF;   
    ! ]4 ~' Z" U, O9 \; d
  84.    
    ! `, }: l; a) D3 \# _
  85.                $grayArray[] = $gray;   
    - z4 D( v. l0 v7 ~8 |
  86.            }    - p/ k; b5 l7 I' G" E, d
  87.        }   
    : s6 K# a$ k- N: p% M% p# H
  88.        imagedestroy($img);    + x& ]" V* Y) |( L& h. ~$ T
  89.    
    + a- \3 M: x" w1 H4 n: b
  90.        /*计算所有像素的灰阶平均值*/   
    4 O8 Y5 t* d$ n  v# ]9 _% I
  91.        $average = array_sum($grayArray)/count($grayArray);    8 o" H5 z, w, X- B3 Z
  92.    
    * O$ X, B) s) \2 s3 T$ M
  93.        /*计算 hash 值*/    3 [& H; n% e# O) Q+ e- P6 N
  94.        $hashStr = '';   
      w6 P' L% U! m! d6 p$ K
  95.        foreach ($grayArray as $gray){   
    " Z' a9 ]" i2 z, \
  96.            $hashStr .= ($gray>=$average) ? '1' : '0';   
    ( Y! t) c8 K; g; M' Y6 l
  97.        }   
    + {/ N- f" z2 d- |& ]/ `
  98.     7 X& T0 Z  b( q: a2 C& [; B! J# \/ \2 g& c
  99.        return $hashStr;    6 @% k% x; s7 m( l
  100.    }    . O2 i1 I1 _, M; V# z4 T9 C
  101.     " E$ R% o9 [) a$ R1 Y9 K$ \
  102.    
    % \4 G8 u; h$ G# \$ ]+ r
  103.    /**hash 图片文件   
    * H% N6 u) A& W$ O: a% F  {
  104.     * @param string $filePath 文件地址路径   ) r8 F9 G+ ~. h. x& j
  105.     * @return string 图片 hash 值,失败则是 false   9 N" w7 j7 i' v) @% S2 J* p9 a
  106.     * */    ) M! J; x, X; O+ j& w+ X8 \3 K
  107.    public static function hashImageFile($filePath){   
    8 g6 Y) X! v6 e/ U- D$ O' N
  108.        $src = self::createImage($filePath);   
    8 ^7 Y3 j% w7 r9 \6 h) _
  109.        $hashStr = self::hashImage($src);    " i8 A3 B8 u% ^
  110.        imagedestroy($src);   
    4 M- \# S8 j9 T( B2 G  |
  111.    
    * _, O  a8 B2 O: x
  112.        return $hashStr;    8 c: P  i" P( Q
  113.    }    4 Q+ u* x- J8 x' F
  114.    
    7 E/ H. r2 T5 C- S* X! Y% O
  115.    
    - j! y  ]' v5 k8 C: h
  116.    /**比较两个 hash 值,是不是相似   
    ! O3 C. C  S: B  j- K; A0 ^0 N
  117.     * @param string $aHash A图片的 hash 值   
    + Y2 j. H" H+ a+ \) K4 V
  118.     * @param string $bHash B图片的 hash 值   
    ( R9 [3 p" q6 |/ o& @: p8 U
  119.     * @return bool 当图片相似则传递 true,否则是 false   / r1 V9 {8 p" f+ ^% ]+ V
  120.     * */    % B- e; y( E7 E' |" N
  121.    public static function isHashSimilar($aHash, $bHash){    . H4 k- b1 w7 d) p8 E* I$ |2 ?2 p
  122.        $aL = strlen($aHash); $bL = strlen($bHash);    6 K3 ^, j& r3 p7 H  q
  123.        if ($aL !== $bL){ return false; }   
    1 g- R) G. N. ?7 J0 |
  124.       h: X8 n4 k9 ?
  125.        /*计算容许落差的数量*/    7 y! _, z$ D! e9 a# [, P( c/ L' Q. H
  126.        $allowGap = $aL*(100-self::$similarity)/100;    2 x# a* j/ m* M# [- o( B5 O- p
  127.     " u$ y1 P3 L% W1 C. d2 z
  128.        /*计算两个 hash 值的汉明距离*/    5 _. u3 X+ b. b' C2 G' ?
  129.        $distance = 0;    1 o6 b8 ?2 S. x5 F/ j
  130.        for($i=0; $i<$aL; $i++){      H- Q+ v+ U* Z
  131.            if ($aHash{$i} !== $bHash{$i}){ $distance++; }   
    . d  u; W( G1 C' F; ?( P
  132.        }    - S% w8 B  E5 B& b: Y% ?
  133.    
    9 I0 Z  G5 L0 T
  134.        return ($distance<=$allowGap) ? true : false;   
    / H( ^5 s$ p3 K: p( _$ O. }
  135.    }    % M0 y2 D! p1 ^# X4 |5 Y2 a
  136.    
    * F$ A+ H  p. i' L) z$ b
  137.     * j; s2 c5 ]( c. r0 q
  138.    /**比较两个图片文件,是不是相似   
    - K) a5 l* n5 z# Q
  139.     * @param string $aHash A图片的路径   
    9 J2 D. \; C, v0 B& c4 l; V
  140.     * @param string $bHash B图片的路径   & e- g& l( h* Q$ X. a9 z
  141.     * @return bool 当图片相似则传递 true,否则是 false   % M  Z6 w3 H1 m$ E
  142.     * */   
    & c* ?! ?6 ?: i1 u
  143.    public static function isImageFileSimilar($aPath, $bPath){      t- q6 C) w1 d- S
  144.        $aHash = ImageHash::hashImageFile($aPath);   
    ; N+ c" {3 ]* b. Z+ d
  145.        $bHash = ImageHash::hashImageFile($bPath);    ( H  l! ?5 W9 n! u) b
  146.        return ImageHash::isHashSimilar($aHash, $bHash);   
    + x: {  W/ N- i7 A
  147.    }    . k: i  z6 ~& }+ d" h+ m' C# Z
  148.    
      [( m& [* L6 \' Z% h7 ]! `# c
  149. }8 i7 s9 D# c6 |
复制代码

  |0 n+ l7 n% \/ a) z- G1 o7 r4 ]9 w. i9 e' s9 C, {( `# I
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-1-30 15:02 , Processed in 0.068112 second(s), 20 queries .

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