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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

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

! d7 z$ Q* u! ?  P由于相似图片搜索的php实现的 API 不怎么符合我的用途,所以我重新定义 API 的架构,改写成比较简单的函数方式,虽然还是用对象的方式包装。

3 w9 V7 T9 e+ M& u4 X6 d8 G9 W' K5 K
  1. <?php   
    , O& x: n5 |& x& F8 m
  2. /**   
    % \( T% l- \  C) q  j  S9 P
  3. * 图片相似度比较   
    ; z$ |1 _9 U8 Q% T& |8 G) K5 i
  4. *   
    * h. w' _0 a1 N
  5. * @version     $Id: ImageHash.php 4429 2012-04-17 13:20:31Z jax [        DISCUZ_CODE_1        ]nbsp;  
    : U4 b% _9 q" o; [6 V5 Y7 ~
  6. * @author      jax.hu   9 O( a+ }/ q  S
  7. *   
    / S$ F& N9 @5 U: {4 M
  8. * <code>   % Y9 _" m- L5 O0 u, }/ g" @
  9. *  //Sample_1   
    3 a  C! @' G" T8 v% ]' {8 X
  10. *  $aHash = ImageHash::hashImageFile('wsz.11.jpg');   
    / A3 k- I' E# n- m% s
  11. *  $bHash = ImageHash::hashImageFile('wsz.12.jpg');   
    $ G1 }* h9 s& V5 M+ l
  12. *  var_dump(ImageHash::isHashSimilar($aHash, $bHash));   , Y6 k$ \, f- l8 i( K+ l
  13. *   " W* D7 I/ c; I$ h
  14. *  //Sample_2   
    & v: w4 ]4 H8 m$ i! A, `8 l8 N% _
  15. *  var_dump(ImageHash::isImageFileSimilar('wsz.11.jpg', 'wsz.12.jpg'));   
    4 f! V9 R, |& r3 H4 i' N: C# U) j  @
  16. * </code>   
    ! E( X9 K  Z* W2 x
  17. */   
    6 f3 |# g) q3 r' a% r
  18.     * T( r4 Z+ C, e; T* I
  19. class ImageHash {   
    - k5 j5 ?9 L6 W+ j! j
  20.    
    0 h1 L7 Q( E' R% D
  21.    /**取样倍率 1~10   
    % J9 W  U( w& c
  22.     * @access public   8 G2 F" _) E, }7 Y6 ~
  23.     * @staticvar int   
    / D  ?3 E  U5 ^- U5 P* d$ Y
  24.     * */   
    0 i, f5 J# w; D. a$ W* Z0 d
  25.    public static $rate = 2;   
    ( d0 K$ L8 }% h; t7 H) R
  26.     . w$ P* i9 M/ F2 H8 k2 R8 y; ]
  27.    /**相似度允许值 0~64   
    5 l& u  n" h- J4 Y+ l1 Y7 H
  28.     * @access public   ( H: b; q' z0 q! [8 H
  29.     * @staticvar int   
    4 V, i, S9 g6 \0 _5 L  q! f4 a
  30.     * */   
    7 V3 h1 P; L6 T1 q) T; M3 \: [
  31.    public static $similarity = 80;    8 I1 g- g: t2 b; p0 p4 f( |* [
  32.    
    + Q5 w9 F7 R; l! t/ O# x+ R
  33.    /**图片类型对应的开启函数   
    4 y. B$ k# ~3 q) `  P2 ?  T
  34.     * @access private   
      J+ S- ]- U/ O& a% ]% S3 ~( b5 r
  35.     * @staticvar string   
    7 K( ?+ [- @5 a  n. `7 T) j2 g6 `
  36.     * */    8 e1 Q1 P9 i7 `5 Q
  37.    private static $_createFunc = array(    ; Y( M& O+ B) `: H0 `. b
  38.        IMAGETYPE_GIF   =>'imageCreateFromGIF',    ' e" K. p* w, l% U. v+ z
  39.        IMAGETYPE_JPEG  =>'imageCreateFromJPEG',      l3 U+ M9 u; A) a& C# x" ~: M
  40.        IMAGETYPE_PNG   =>'imageCreateFromPNG',   
    3 R. D( m+ s, q3 C+ V+ k% Q
  41.        IMAGETYPE_BMP   =>'imageCreateFromBMP',    % C/ Y3 Q+ ?, s. U( [# S2 G# E
  42.        IMAGETYPE_WBMP  =>'imageCreateFromWBMP',    2 n! [, G2 ?# N3 e# Y; l
  43.        IMAGETYPE_XBM   =>'imageCreateFromXBM',   
    ; t- [/ ^, N4 x8 N+ q8 v& n
  44.    );    5 n$ i- {6 l9 o% j0 y/ c7 x
  45.     * P- v2 n, e# [
  46.    
    + a( \" W/ u) a% V
  47.    /**从文件建立图片   
    2 K& I) H& I$ e9 J4 p  w
  48.     * @param string $filePath 文件地址路径   
    , Q9 G- z0 X& J6 O1 i
  49.     * @return resource 当成功开启图片则传递图片 resource ID,失败则是 false   
    , H2 k0 v) I. ~; f8 X3 Y+ G0 b" Y
  50.     * */   
    0 f# j! t+ g. @" O
  51.    public static function createImage($filePath){    8 E$ @: w, g8 h
  52.        if(!file_exists($filePath)){ return false; }   
    ; Y! Q& _1 t- F- {
  53.     9 t% Y: g+ Q$ [3 C* L' c
  54.        /*判断文件类型是否可以开启*/   
    . L5 N& R9 P; o$ x' M0 J% t
  55.        $type = exif_imagetype($filePath);   
    3 m$ E; i2 u% K1 w' b9 P
  56.        if(!array_key_exists($type,self::$_createFunc)){ return false; }    & r# J2 _6 ]: F) H2 h
  57.    
    * \# Q/ ^) V, L5 b4 Y* |
  58.        $func = self::$_createFunc[$type];    8 Q$ {. H, M0 I/ N8 K% c
  59.        if(!function_exists($func)){ return false; }    . S8 [, ^6 J( o1 v# n* \' B) w
  60.     # o# k* M+ d/ z$ |- v
  61.        return $func($filePath);    " z8 j  `" ]" f  S1 L( v$ x
  62.    }    + L: Q- |) d4 O1 y( E) U. V
  63.     : ]5 ?0 E& p+ Z0 ~/ L8 Z
  64.     5 a' h8 y1 D! s. R1 L' b  x4 @
  65.    /**hash 图片   . Y# d% ]" Y1 i3 ]0 O8 V- Y! c1 U- I
  66.     * @param resource $src 图片 resource ID   
    9 p$ @8 i, [# L3 t7 x) ?( {: W
  67.     * @return string 图片 hash 值,失败则是 false   0 E$ j1 o0 i' ~$ N$ {
  68.     * */    6 ], y! c, J0 B' E
  69.    public static function hashImage($src){    7 a6 w* x/ b& T% m0 c. e
  70.        if(!$src){ return false; }   
      N: v9 X9 n5 j! r# U! a# y1 F
  71.    
    # l0 D5 R3 d" m+ `: s
  72.        /*缩小图片尺寸*/   
    / B( q9 `$ J, }7 g. h
  73.        $delta = 8 * self::$rate;    " _9 s; s- u4 ^% s
  74.        $img = imageCreateTrueColor($delta,$delta);    ' o5 z2 f6 d. S& \" Q
  75.        imageCopyResized($img,$src, 0,0,0,0, $delta,$delta,imagesX($src),imagesY($src));   
    # g6 r! y' r' Z5 H
  76.    
    0 C9 I2 k+ ~0 h/ `; l. C
  77.        /*计算图片灰阶值*/   
    6 U5 D5 n1 i6 X$ @- o' S
  78.        $grayArray = array();    , P8 g9 E8 h. c/ E& L6 p
  79.        for ($y=0; $y<$delta; $y++){    ! v0 u4 P7 O* k: Y
  80.            for ($x=0; $x<$delta; $x++){   
    * v- C3 X% `. _- w
  81.                $rgb = imagecolorat($img,$x,$y);   
    . B+ U# d' ]2 e) z- d+ `# U7 d% S
  82.                $col = imagecolorsforindex($img, $rgb);   
    ) e) n6 K8 L8 x5 n' d* `
  83.                $gray = intval(($col['red']+$col['green']+$col['blue'])/3)& 0xFF;   
    ( Z5 s0 f' n1 S
  84.     0 U) d& p9 h& w6 g
  85.                $grayArray[] = $gray;   
    % N/ y5 b, s( {" V% C3 J3 m1 v
  86.            }    ; a4 j) z, @% |& Q! R  b
  87.        }    * }( z! k& N2 k) b* M
  88.        imagedestroy($img);   
    1 I* R* ~% u. k
  89.     5 ^  @1 U6 t  }: S0 Z. k6 H( \
  90.        /*计算所有像素的灰阶平均值*/   
    & C3 w5 c2 W1 k% v
  91.        $average = array_sum($grayArray)/count($grayArray);   
    ( |( I- x1 R) ]; N5 M
  92.     6 }. W2 k3 k9 a7 I( j! a. @
  93.        /*计算 hash 值*/    & q2 D* [8 M  X7 e8 g; T4 Z: D, @, M
  94.        $hashStr = '';   
    ! u0 U# o, y. k0 B( k
  95.        foreach ($grayArray as $gray){   
    8 c- M  ?! Y- m% F
  96.            $hashStr .= ($gray>=$average) ? '1' : '0';    5 p8 J$ ?5 e8 x, N4 |& P
  97.        }   
    7 p* ?4 l3 `3 b+ B6 v
  98.    
    ) Q' f5 J) S( V$ l7 R
  99.        return $hashStr;   
    / P; q* x/ w+ ^# y# N# V
  100.    }   
    % F$ a* U- x9 g2 f0 p! e. W0 R
  101.    
    - i0 r0 X2 l# |& z; b7 P: ~
  102.     & x0 {, x/ f! J6 r2 m
  103.    /**hash 图片文件   
    : Y' t3 D$ i, c0 c
  104.     * @param string $filePath 文件地址路径   ; T8 ?9 w8 e# ~0 S7 h3 o) {
  105.     * @return string 图片 hash 值,失败则是 false   * F6 {7 o$ _, L9 j' ~5 b
  106.     * */   
    * h0 y% k1 h6 P+ P' R: u/ r
  107.    public static function hashImageFile($filePath){   
    9 H* G( H! {; D
  108.        $src = self::createImage($filePath);   
    0 Q! m0 o0 k; P0 j) K* X8 P
  109.        $hashStr = self::hashImage($src);    / V/ R4 p0 T* E
  110.        imagedestroy($src);   
    * T0 d: o1 c+ \) A
  111.    
    9 b, j1 r+ T/ y" k# @4 O7 t
  112.        return $hashStr;   
    : n9 _8 A, V4 t6 ?
  113.    }   
    8 N  W3 i! y! r# F6 v# R2 w/ U
  114.    
    * v( G9 G$ R1 V1 }4 Z
  115.     " s2 h% T- h( Y0 c, c
  116.    /**比较两个 hash 值,是不是相似   ' h: |' Q2 H% R- T
  117.     * @param string $aHash A图片的 hash 值   # H: \5 a7 l- ]# x8 C( V
  118.     * @param string $bHash B图片的 hash 值   ( N7 K3 ]$ H6 ?; H1 W6 V: t
  119.     * @return bool 当图片相似则传递 true,否则是 false   
    6 S. l$ j+ d' E6 R" ?
  120.     * */   
    2 B! X+ T6 y: x1 s8 N; t
  121.    public static function isHashSimilar($aHash, $bHash){    0 V0 l3 V% e$ r+ \1 i
  122.        $aL = strlen($aHash); $bL = strlen($bHash);   
    ! C) N! X' Q2 L+ Z
  123.        if ($aL !== $bL){ return false; }    ( u+ m3 R2 |3 ~$ u5 J
  124.    
    / F0 E9 d. \6 o- a
  125.        /*计算容许落差的数量*/    ( a5 \6 A7 u/ U- g3 k: A
  126.        $allowGap = $aL*(100-self::$similarity)/100;   
    6 `- {1 U; V4 j9 M$ i% w
  127.     " ~, I. E5 S+ O) M+ c8 B
  128.        /*计算两个 hash 值的汉明距离*/   
    8 \) \+ A' t, d5 @- z0 [) q0 H6 c
  129.        $distance = 0;    " p9 q* M& H2 B" d
  130.        for($i=0; $i<$aL; $i++){    ) Y, _0 K4 s& N: g/ L& k
  131.            if ($aHash{$i} !== $bHash{$i}){ $distance++; }    - m( k' N& w' W# t) a
  132.        }    : ^) \% A( ]2 K  j
  133.    
    + m# \2 _9 B2 [& m0 ~& \
  134.        return ($distance<=$allowGap) ? true : false;   
    6 j$ @6 w: b! i1 D0 S
  135.    }      f% w! S! h- q- f0 B
  136.     & \5 d) [: w5 }) ^6 l* \+ b9 X
  137.    
      M1 I1 x$ L) F' D5 l, f
  138.    /**比较两个图片文件,是不是相似   6 `, [) V- g7 r: y) S3 H& g0 E$ p
  139.     * @param string $aHash A图片的路径   9 q/ R$ I! K+ T, [9 O! `
  140.     * @param string $bHash B图片的路径   
    . v( m) F0 u7 X* j5 h! N( U7 k3 x
  141.     * @return bool 当图片相似则传递 true,否则是 false   * C# d7 O; r7 P
  142.     * */    $ T% l  t, c0 e) n; n: z
  143.    public static function isImageFileSimilar($aPath, $bPath){    : q% x3 C( Z( G& n$ d. `, L
  144.        $aHash = ImageHash::hashImageFile($aPath);   
    & i2 o0 o! y' y6 \/ c: b) E
  145.        $bHash = ImageHash::hashImageFile($bPath);   
    * ?# M( ]0 x) X* M) U
  146.        return ImageHash::isHashSimilar($aHash, $bHash);    1 K- N+ V& D( Y
  147.    }   
    ( Y, r# ?9 x) [& o
  148.     + ]3 \( O# @. b8 F2 D
  149. }
    ; K6 B# c0 b7 D
复制代码
+ l6 d' g; K0 l4 ?" G
7 V8 s! s7 `. P& u4 I  A
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2024-12-22 20:36 , Processed in 0.168687 second(s), 20 queries .

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