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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2018-7-7 23:06:35 | 只看该作者 回帖奖励 |正序浏览 |阅读模式
摘要: 本文讲的是分享一个PHP简易的图片相似度比较类, 由于相似图片搜索的php实现的 API 不怎么符合我的用途,所以我重新定义 API 的架构,改写成比较简单的函数方式,虽然还是用对象的方式包装。  代码如下 复制代码 <?php    /**   * 图, F% u) N4 P2 ^
, `1 y3 l% g* ^7 Y$ \

" `7 S! L" g' p5 Z由于相似图片搜索的php实现的 API 不怎么符合我的用途,所以我重新定义 API 的架构,改写成比较简单的函数方式,虽然还是用对象的方式包装。
' Q  u" j: _9 ^6 }
  1. <?php   
    8 h. a# \, V, W0 |# l* K/ m3 r
  2. /**   , o: l5 f( m8 m0 t3 g
  3. * 图片相似度比较   ' l& a/ J/ w' z/ @2 U2 w8 f
  4. *   0 I7 u2 C; j. W: _$ C# \" R$ [7 ]
  5. * @version     $Id: ImageHash.php 4429 2012-04-17 13:20:31Z jax [        DISCUZ_CODE_1        ]nbsp;  
    1 Z- ~: P9 ~* X  b% ?  d
  6. * @author      jax.hu   ) ~1 c( K* o' J/ ^/ W3 R; w& c: r
  7. *   
    7 g  L2 d% w6 n, {5 f9 O$ r
  8. * <code>   
    " z- [2 t+ n5 {. O
  9. *  //Sample_1   2 |! J. B$ \: a! e" [2 d
  10. *  $aHash = ImageHash::hashImageFile('wsz.11.jpg');   
    / {. e6 y5 H! A1 i1 A
  11. *  $bHash = ImageHash::hashImageFile('wsz.12.jpg');   
    6 M0 U3 l8 |6 F9 E3 j4 t1 m6 t! ]
  12. *  var_dump(ImageHash::isHashSimilar($aHash, $bHash));   3 W. K1 s$ L: P- _
  13. *   . M6 L( [+ V* J5 y/ G; P0 c
  14. *  //Sample_2   
    " a9 H5 ^) |  D  [0 f- ?! _/ O
  15. *  var_dump(ImageHash::isImageFileSimilar('wsz.11.jpg', 'wsz.12.jpg'));   
    - C) y. u# H1 Z4 ~% J- m2 k
  16. * </code>   
    7 g5 [! G4 u* o: ^% ~
  17. */    0 Z# H" C$ }, t0 d8 v0 B& e2 O
  18.     . O/ o1 h4 z7 N1 ^$ C  T
  19. class ImageHash {   
    * M& J( \, ]) |- B& H& m* g
  20.    
    7 b; M6 a$ K- y! x$ a
  21.    /**取样倍率 1~10   
    2 s$ K8 L- l% o4 Y+ r& ]# C7 ~8 ^+ [
  22.     * @access public   ! R  W) c5 o6 I
  23.     * @staticvar int   
    1 z$ q( \0 s' z& j- {, i
  24.     * */   
    / a' h" ?5 N2 K- `1 S
  25.    public static $rate = 2;    ' U: g7 Q+ o; y6 |" v$ I5 I8 ^
  26.     + v4 u6 _: H6 [( F
  27.    /**相似度允许值 0~64   4 k9 c" t) T* G4 a2 m
  28.     * @access public   
    " K  m5 z; l1 {$ G0 d8 o$ I" w9 @
  29.     * @staticvar int   
    + u% _+ h& g8 B' `6 {7 J8 o) R7 G
  30.     * */    0 C  u( o& Q! \1 n  `4 V+ `
  31.    public static $similarity = 80;    : N  B( M, W, E  B# L) A8 F. v
  32.     0 G9 L- P3 o" {# t4 Y: U- M
  33.    /**图片类型对应的开启函数   
    : x" I) D: c* L8 i+ m8 r# z
  34.     * @access private   " e+ d9 l9 l$ u
  35.     * @staticvar string   
    ) M! Y- C7 m( L3 h
  36.     * */   
    ! F+ h9 r) D& }1 X0 C
  37.    private static $_createFunc = array(   
    ( ^4 a9 o/ o4 O7 m
  38.        IMAGETYPE_GIF   =>'imageCreateFromGIF',   
    % c- x' D! W( R! @" N
  39.        IMAGETYPE_JPEG  =>'imageCreateFromJPEG',    # `% H1 h* Z, U1 n% [" M# I
  40.        IMAGETYPE_PNG   =>'imageCreateFromPNG',    8 J8 t0 u+ P3 R4 |  b
  41.        IMAGETYPE_BMP   =>'imageCreateFromBMP',   
    & z2 F; X. D  Y, Z8 f  a" e
  42.        IMAGETYPE_WBMP  =>'imageCreateFromWBMP',    5 O2 N! m; a, L5 @& f$ H" c
  43.        IMAGETYPE_XBM   =>'imageCreateFromXBM',    3 `5 r& l3 v! Y. ~/ _
  44.    );    : e: t9 e% a; k! G& L
  45.     $ I# Q# y/ p/ T  W5 G. w
  46.     ' ^4 X, X" C. q, L( }7 o- L
  47.    /**从文件建立图片   8 ?$ I6 J! O! d2 H
  48.     * @param string $filePath 文件地址路径   
    ( W6 y& {7 }6 j! U5 u, |
  49.     * @return resource 当成功开启图片则传递图片 resource ID,失败则是 false   5 d  W; I: m$ U- \
  50.     * */   
    . ~! P% m3 H3 b( d" t
  51.    public static function createImage($filePath){    8 ]1 x# @9 u+ y* I/ j9 P. z
  52.        if(!file_exists($filePath)){ return false; }   
    $ d; H/ S& N9 F2 t7 L, }
  53.    
    $ l+ N" Y- E4 c/ l' B2 G$ q
  54.        /*判断文件类型是否可以开启*/    . o( x/ Q$ `& V# f9 |' g# N
  55.        $type = exif_imagetype($filePath);    2 u, ]7 n, [2 s4 ~
  56.        if(!array_key_exists($type,self::$_createFunc)){ return false; }    $ k( k9 Q3 G; e: L
  57.     6 i" v( ]9 i. _* P5 Z
  58.        $func = self::$_createFunc[$type];   
    4 g  o% X% p; d9 n/ w
  59.        if(!function_exists($func)){ return false; }   
      |) z: D9 c" p3 f8 ?9 n1 \* |" }/ [
  60.    
    4 q7 p  X6 Z1 [" V
  61.        return $func($filePath);   
    9 T' y, `9 C# d1 L
  62.    }   
    + l6 _6 n4 h# u3 {2 {. F$ S, a1 K9 i
  63.    
    + `  c& A' B- S  x# ^- |
  64.    
    % K8 [7 ^: |: R. T5 c- l8 v: `( y5 V
  65.    /**hash 图片   " b2 g' ^: O, \3 n
  66.     * @param resource $src 图片 resource ID   6 }1 E# E3 D( i7 u! }/ D
  67.     * @return string 图片 hash 值,失败则是 false   
    & D8 M7 F  a; r4 C8 n
  68.     * */    ( E  N, `9 K8 m  j9 ?4 I) z
  69.    public static function hashImage($src){   
    5 @# t' e" n9 I
  70.        if(!$src){ return false; }   
    # D8 R* z! S; f/ t7 K
  71.    
    % j5 O# U  `3 k7 f) H
  72.        /*缩小图片尺寸*/   
    3 P4 }4 d+ t& A/ ^" l& Q: t
  73.        $delta = 8 * self::$rate;    3 q4 _& P. u$ O- y! h6 L
  74.        $img = imageCreateTrueColor($delta,$delta);   
    0 C: p. }: B$ d. N: d
  75.        imageCopyResized($img,$src, 0,0,0,0, $delta,$delta,imagesX($src),imagesY($src));   
    8 J% ^0 ?5 U% ]0 k
  76.     ' s& z7 `1 Q- A
  77.        /*计算图片灰阶值*/   
      C! o6 w! v0 ?3 S
  78.        $grayArray = array();    : Y) G4 |9 H. I( b# m
  79.        for ($y=0; $y<$delta; $y++){   
    . L9 N* [8 [$ B$ i, T: s! \0 {- ^
  80.            for ($x=0; $x<$delta; $x++){   
    % j4 w2 ~3 F" q. k, R# i
  81.                $rgb = imagecolorat($img,$x,$y);   
    % }7 j. F" Z6 ^7 V) W
  82.                $col = imagecolorsforindex($img, $rgb);   
    8 Z8 T3 m* Z" Z- g, g% Z
  83.                $gray = intval(($col['red']+$col['green']+$col['blue'])/3)& 0xFF;   
    # `2 D; \3 f+ L5 g
  84.    
    1 k( \: p2 O4 J3 U) L- F; z
  85.                $grayArray[] = $gray;   
    : K+ a) Q8 ]4 x' e! n& Y, E- U5 j
  86.            }   
    . H9 V$ l  t' m: @  q( [# Z/ \7 h
  87.        }   
    ' [4 F% C! R0 Z) M
  88.        imagedestroy($img);    . ^0 j+ `8 a, v4 Y
  89.    
    3 F& t7 d: J9 B8 b: t5 e* b
  90.        /*计算所有像素的灰阶平均值*/    : y4 g. }) q2 [( v" |3 G
  91.        $average = array_sum($grayArray)/count($grayArray);    , ?/ q  ?+ |6 J  k" ]
  92.    
    * x* r, M+ @# \) Q& |" ~. x
  93.        /*计算 hash 值*/   
    4 P' O, v: s, U. l% p, L! Z) Y
  94.        $hashStr = '';    & i4 p7 S+ a( v
  95.        foreach ($grayArray as $gray){   
    ( e/ U7 p, j2 G* t- J
  96.            $hashStr .= ($gray>=$average) ? '1' : '0';   
    ; ^- ]1 M0 E# [  t
  97.        }   
    ! V! P3 L  \6 P3 u  ~2 D6 x
  98.     + ~7 O3 ^, }( l# y1 q6 K! j9 M
  99.        return $hashStr;    ; u. L/ l* p/ }1 X/ u' K: W- i
  100.    }    ) C/ J" X( C2 L4 k5 z3 h6 s& p" [
  101.     0 s6 p4 Q" E$ e# m# D; |/ i8 q" u
  102.     ; q* `# B2 |1 h" m
  103.    /**hash 图片文件   2 M6 z1 |7 g% x+ Z; W) J
  104.     * @param string $filePath 文件地址路径   ; b7 T, H+ d* [8 Y6 t
  105.     * @return string 图片 hash 值,失败则是 false   
    1 }5 f4 y2 R* d
  106.     * */    4 k1 ?# u1 ^# h% f* K5 w$ Z& G0 ?
  107.    public static function hashImageFile($filePath){      l- [8 R8 I/ I- f: T* N8 y! T
  108.        $src = self::createImage($filePath);    % B' `- h: |( }. C  t
  109.        $hashStr = self::hashImage($src);   
    + k/ e: x+ k& Z
  110.        imagedestroy($src);    ' M7 v( m% r8 ]$ L4 r7 p9 [& S
  111.    
    # U, u" Z: m; v5 `2 Y
  112.        return $hashStr;    ( \0 }2 ~# ]8 P* C4 J! R% b
  113.    }   
    , ^9 S; _8 ^% f* T8 x
  114.    
    1 w, i$ I4 D" J4 M
  115.    
    + C! e8 \: K) S0 C( v
  116.    /**比较两个 hash 值,是不是相似   
    8 X! T8 n9 Q- Q' ^8 n7 T
  117.     * @param string $aHash A图片的 hash 值   
    + [5 \, Z- n+ g
  118.     * @param string $bHash B图片的 hash 值   
    1 y5 ^% |- Q. V) x( f
  119.     * @return bool 当图片相似则传递 true,否则是 false   4 R" @5 z6 B& w: t5 O
  120.     * */    ' H1 w% e1 b+ Q3 S: ~% o
  121.    public static function isHashSimilar($aHash, $bHash){   
    9 I% l, V. I% h6 l; z* d# `( P! @
  122.        $aL = strlen($aHash); $bL = strlen($bHash);    1 k7 d4 ~3 P, e0 i' i/ ~
  123.        if ($aL !== $bL){ return false; }   
    . A; \1 @, U! m# y  f- {4 y5 E( F
  124.     7 q: \) x2 Q7 e
  125.        /*计算容许落差的数量*/    8 e- X: S% L6 v; i' U
  126.        $allowGap = $aL*(100-self::$similarity)/100;    8 T6 T* |) C7 D* f# i1 w9 k
  127.    
    & [4 t+ p% }& r: ~2 ]- o
  128.        /*计算两个 hash 值的汉明距离*/   
    : _8 i1 E6 M% r: Y
  129.        $distance = 0;    2 [/ X- b  J/ B: ]
  130.        for($i=0; $i<$aL; $i++){   
    ( T6 v$ q* P6 ?4 X  b
  131.            if ($aHash{$i} !== $bHash{$i}){ $distance++; }   
    , _$ d- t: P0 N3 m
  132.        }    + k7 P" n% h; ]% t5 \  ?, F2 Q' ?
  133.    
    - ]. P  i3 v  d5 \( O; b
  134.        return ($distance<=$allowGap) ? true : false;   
    # {* P2 i" Q" }" x
  135.    }   
    ) J5 b. e$ N7 p0 ]" B4 K: T' ]! W' \
  136.    
    ) R0 i6 Y5 e/ z8 r
  137.    
    0 X) q3 J" K4 F0 Y1 O) |
  138.    /**比较两个图片文件,是不是相似   : Q7 z9 R5 M. W' F
  139.     * @param string $aHash A图片的路径   
    4 a6 B0 N0 ~* x) S2 w
  140.     * @param string $bHash B图片的路径   ( ~) v7 l0 a7 A' c& h" h: d6 h
  141.     * @return bool 当图片相似则传递 true,否则是 false   
      a$ r/ p. N' q  O
  142.     * */    5 B( \) d' D# @! [
  143.    public static function isImageFileSimilar($aPath, $bPath){    $ ~7 I7 [# p5 {" f  `
  144.        $aHash = ImageHash::hashImageFile($aPath);   
    ( h0 p3 v. A2 B# p. v
  145.        $bHash = ImageHash::hashImageFile($bPath);   
    ( R  F9 p0 f; A1 L; a
  146.        return ImageHash::isHashSimilar($aHash, $bHash);    . b+ C0 l) L/ U
  147.    }    2 w" l/ Z+ l; A, _! l
  148.    
    / W; R1 F- N: ~' p
  149. }
    - o' y" S: q. r7 M) h* y. r
复制代码
( k3 s6 h) J9 {  Y2 `$ \, U
! g& L8 u# Y# }3 |) a
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-5-2 16:51 , Processed in 0.055494 second(s), 20 queries .

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