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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2018-7-7 23:06:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
摘要: 本文讲的是分享一个PHP简易的图片相似度比较类, 由于相似图片搜索的php实现的 API 不怎么符合我的用途,所以我重新定义 API 的架构,改写成比较简单的函数方式,虽然还是用对象的方式包装。  代码如下 复制代码 <?php    /**   * 图
) D, m* u' {8 C7 o5 Q: a" \0 P( z5 H% i8 x: J
, f7 Q+ e5 E1 f; Q2 @
由于相似图片搜索的php实现的 API 不怎么符合我的用途,所以我重新定义 API 的架构,改写成比较简单的函数方式,虽然还是用对象的方式包装。

/ u" t8 x$ X% J* ~9 w
  1. <?php    6 ^9 b, w8 l4 X2 ^( g) L) V& b" C
  2. /**   
    % z9 E4 O) \0 b( u
  3. * 图片相似度比较   $ L% o, T+ ~6 X% z. M1 m
  4. *   / P1 _  ^8 {9 g5 j( P& ?  s
  5. * @version     $Id: ImageHash.php 4429 2012-04-17 13:20:31Z jax [        DISCUZ_CODE_1        ]nbsp;  
    ( X1 u2 F6 \1 k5 P; F% [  t* {
  6. * @author      jax.hu   + N+ M& Z  i+ @3 u* S3 J) g& ^
  7. *   
    ) Y7 p! c* f1 \- k
  8. * <code>   
    ) n  p3 ]! W( ^9 o% ^
  9. *  //Sample_1   0 }& E1 b8 Y" p1 _- \  b
  10. *  $aHash = ImageHash::hashImageFile('wsz.11.jpg');   
    & C0 y5 B! H" W* \+ D' d
  11. *  $bHash = ImageHash::hashImageFile('wsz.12.jpg');   ; `5 }/ B1 @7 l
  12. *  var_dump(ImageHash::isHashSimilar($aHash, $bHash));   7 f4 U% x0 I8 V" ^7 c0 k% w) i
  13. *   
    , F. ]- P* _3 z+ h4 o' x
  14. *  //Sample_2   
      t4 v# l2 \1 ?  e+ s2 O* w
  15. *  var_dump(ImageHash::isImageFileSimilar('wsz.11.jpg', 'wsz.12.jpg'));   - o* S: D6 K5 L
  16. * </code>   
    0 o+ n3 j$ r8 {5 \
  17. */   
    - M  ]: {1 q( s" ~
  18.    
    % B& B) Y; [/ y' z8 G
  19. class ImageHash {    / i5 v! W3 ~1 R5 K! ?- ?9 ~- o
  20.    
    3 S* ?$ W0 p/ K+ ~5 m6 z4 \4 W/ @
  21.    /**取样倍率 1~10   % b. V# y8 l8 @
  22.     * @access public   : ~2 B& b; \8 ]: q6 w! Q+ Y6 i
  23.     * @staticvar int   
    6 K* h, O/ R# c$ m2 o/ @
  24.     * */   
    % a/ B" A: r+ ?' A, K# J7 M0 d
  25.    public static $rate = 2;    . I$ ]- t1 ]" `* h0 P! K
  26.     . ]6 m3 Q+ ^9 e) t! X' ]
  27.    /**相似度允许值 0~64   % D* j/ G/ v, c  N" z( M" @
  28.     * @access public   # V1 @! b" j& N6 R: w
  29.     * @staticvar int   
    5 o/ k. @9 z# U
  30.     * */    # R0 O$ l4 a% @& l* A) D0 L
  31.    public static $similarity = 80;   
    3 B; H9 C/ {8 |9 w
  32.    
    " N0 G1 t0 n, n" S2 P. f# q) c
  33.    /**图片类型对应的开启函数   0 y8 t; M, U$ P: |( Q3 q4 M
  34.     * @access private   
    * r  I( D5 e- A/ q( {
  35.     * @staticvar string   
    - a: z) W$ y9 g" h# _/ ~
  36.     * */   
    2 G) F& j: S/ e( q; Q6 k
  37.    private static $_createFunc = array(    ; Z' a. G4 D) `$ `5 m5 a4 _% w+ {
  38.        IMAGETYPE_GIF   =>'imageCreateFromGIF',   
    : M3 I" e& I# b% V
  39.        IMAGETYPE_JPEG  =>'imageCreateFromJPEG',    ) ^% S. [6 R+ {8 g
  40.        IMAGETYPE_PNG   =>'imageCreateFromPNG',    1 E- J- b* w: C. u. l
  41.        IMAGETYPE_BMP   =>'imageCreateFromBMP',   
    . \, ^7 k' o7 A0 P. ^5 z
  42.        IMAGETYPE_WBMP  =>'imageCreateFromWBMP',   
    + U& g! @/ q. u! z0 L8 X: }
  43.        IMAGETYPE_XBM   =>'imageCreateFromXBM',    3 ~% w/ F6 i4 l5 i! E3 }
  44.    );   
    6 i) @6 E+ F( K, s& m  e1 t
  45.     8 H+ H* v6 `( X* ^+ r
  46.     / a. g+ d1 N6 y: f; \7 p& m" M2 z
  47.    /**从文件建立图片   
    7 @2 b( q6 H9 g) `, ^2 {5 B
  48.     * @param string $filePath 文件地址路径   
    " _, L  b, |& e; A3 a8 U& O
  49.     * @return resource 当成功开启图片则传递图片 resource ID,失败则是 false     ^3 v! Q  m, d( Q
  50.     * */   
    ( J5 I, R/ c1 f- Z3 K' e
  51.    public static function createImage($filePath){    * U* F- \& s' R
  52.        if(!file_exists($filePath)){ return false; }   
    * \* s, h& ~. z" t2 T# l
  53.     9 p* W1 z1 U" c" K% k  l
  54.        /*判断文件类型是否可以开启*/    * C5 r7 o+ }+ t! N
  55.        $type = exif_imagetype($filePath);   
    3 b7 ], z7 k& E9 L. L5 ^: \
  56.        if(!array_key_exists($type,self::$_createFunc)){ return false; }   
      T, N7 b  O( P* F
  57.    
    - I& B; H  p9 Q) g
  58.        $func = self::$_createFunc[$type];    9 Z5 j$ c4 B: X9 O' I+ L
  59.        if(!function_exists($func)){ return false; }    0 x0 B  \; G' w0 w  a
  60.    
    ! h9 O8 v) `8 p8 U7 a& Y; X/ v3 |1 n
  61.        return $func($filePath);   
      e% K3 [$ f7 x" T" e% v1 z( x# z
  62.    }    ( R2 m  L8 G) }# G
  63.    
    8 z0 p2 g  ]4 W. C4 \6 B
  64.     " S% [4 v2 @% @; i) ?9 f) F4 M
  65.    /**hash 图片   3 e% ~! P8 ^  w- b
  66.     * @param resource $src 图片 resource ID   0 ^1 G% W% J0 Y8 C, t$ f& p
  67.     * @return string 图片 hash 值,失败则是 false   
    ' \/ z! R! Q, b; `# ^
  68.     * */   
    8 T1 e: N7 b2 o; \/ |/ ~
  69.    public static function hashImage($src){   
    ) W2 I% y# R  a0 p" B4 o5 b
  70.        if(!$src){ return false; }    + }* z( P) m' l  g: x
  71.     " _$ _' H( g& X, O7 n" H3 ^
  72.        /*缩小图片尺寸*/    # t$ F8 Q! P' U
  73.        $delta = 8 * self::$rate;   
    : D2 r, ]4 z" W1 Z+ w
  74.        $img = imageCreateTrueColor($delta,$delta);      Y' o3 \: \7 F' F6 {" }6 a3 [
  75.        imageCopyResized($img,$src, 0,0,0,0, $delta,$delta,imagesX($src),imagesY($src));   
    * R2 z/ ]4 @- l+ \) N. v- g( b
  76.     * o8 r7 i$ e3 E0 T( s- w
  77.        /*计算图片灰阶值*/    ! p9 h) v3 @. w# r( ~% s
  78.        $grayArray = array();   
    2 u& U' X4 z  o* z. }/ _9 l5 U
  79.        for ($y=0; $y<$delta; $y++){   
    5 V7 J2 Q- [$ F% C2 q3 P" w; d
  80.            for ($x=0; $x<$delta; $x++){   
    4 [+ i; n, G: R+ n7 }
  81.                $rgb = imagecolorat($img,$x,$y);    ' q& ]  I; v1 N* D
  82.                $col = imagecolorsforindex($img, $rgb);   
    ( X2 S7 T4 r+ ^+ J3 H5 ^
  83.                $gray = intval(($col['red']+$col['green']+$col['blue'])/3)& 0xFF;   
    ! v  g8 F2 e4 [; t, R
  84.    
    # q: x) j- z: G0 O
  85.                $grayArray[] = $gray;    9 m: r* w! t( f; h  B5 T
  86.            }    8 j4 v8 |, h6 I+ @& ?, [! \& `& k
  87.        }   
    2 e! H  h5 k1 s- t
  88.        imagedestroy($img);    # [. D5 t9 h, U/ w. m  c: M
  89.    
    $ z" P1 u* F! h- |
  90.        /*计算所有像素的灰阶平均值*/    " B* n6 K/ w( ?' X* C
  91.        $average = array_sum($grayArray)/count($grayArray);   
    6 D5 m1 m' ]6 d  R' W2 [
  92.    
    . U2 D4 F3 ~+ E
  93.        /*计算 hash 值*/   
    ( t8 k* f, M4 Z4 f! J7 l
  94.        $hashStr = '';    . M3 K; S; w7 I" i! T' c! x
  95.        foreach ($grayArray as $gray){      L5 d4 b0 Q* {5 A$ ?5 |! M' w
  96.            $hashStr .= ($gray>=$average) ? '1' : '0';    : {8 G# \; m# F" ?& Y  k( v
  97.        }   
    , G4 W9 y4 l' U; ]* O! M" C4 G
  98.     # \0 K" f% U% Y1 L& S
  99.        return $hashStr;    7 [& o, E2 h3 V$ \+ O! j0 A
  100.    }      k0 h6 ~& F  O6 A
  101.    
    8 |$ \  t  W: N: ^: @+ Z/ n
  102.     2 V8 h# z1 Q& m4 n/ B1 V4 V. ^8 c
  103.    /**hash 图片文件   % Q7 Y6 f+ |+ _. t
  104.     * @param string $filePath 文件地址路径   + S3 ]& M, p* n
  105.     * @return string 图片 hash 值,失败则是 false   
    ! o1 K, I& j) I
  106.     * */    0 t! F7 w9 h. t
  107.    public static function hashImageFile($filePath){    ( b# }" E. j# s- T' t* Y9 B7 ]4 F
  108.        $src = self::createImage($filePath);    - a+ s3 a' ~) N4 e/ S' g
  109.        $hashStr = self::hashImage($src);   
    5 Z8 U, b  e" K9 V. g
  110.        imagedestroy($src);   
    4 t/ o. ^9 N/ c+ B$ j' M
  111.    
    , ~+ Y% g/ j& J1 w: G' X5 G; n
  112.        return $hashStr;    & N% g& _( z2 P0 G0 o
  113.    }   
    6 V2 c+ v" T9 [) E" }- Q5 L
  114.     ' f% b2 z# g% Q, c
  115.    
    ) T5 d4 L+ b8 o' Z
  116.    /**比较两个 hash 值,是不是相似   9 a) A. c* N$ l5 c- f" g
  117.     * @param string $aHash A图片的 hash 值   
    . y- U. }, X1 Y6 w" L
  118.     * @param string $bHash B图片的 hash 值   
    , x% J# Y3 b! D8 e. f( \% P- S0 R
  119.     * @return bool 当图片相似则传递 true,否则是 false   . N7 j1 u& o, p9 f1 l9 K+ c
  120.     * */   
    7 o! E# f+ P5 B, l
  121.    public static function isHashSimilar($aHash, $bHash){   
    # r8 w: a3 ?6 M, G4 R9 e
  122.        $aL = strlen($aHash); $bL = strlen($bHash);   
    ) D; ~" J. M% ^
  123.        if ($aL !== $bL){ return false; }   
    % M7 ]& c' O8 ~5 |) Q
  124.     1 c# L4 Q. }* q( a% N
  125.        /*计算容许落差的数量*/    1 V$ s7 _9 Q" D: i0 k/ ?
  126.        $allowGap = $aL*(100-self::$similarity)/100;   
    . a' g2 e1 G# M) O  f, Z
  127.    
    3 R$ ^2 l4 S) l& i/ D
  128.        /*计算两个 hash 值的汉明距离*/   
    - `1 j% A: v% ^0 B! d8 n# K+ v
  129.        $distance = 0;   
    8 N1 U( A' c1 X" ]5 J, @7 r
  130.        for($i=0; $i<$aL; $i++){    , W! c9 W, T. h( Q, ]4 q9 j! {
  131.            if ($aHash{$i} !== $bHash{$i}){ $distance++; }    3 m8 Y7 K$ J' l( J; u# N
  132.        }    4 i1 ]+ u# ?1 n6 c  ]: }
  133.     + ]/ e/ r' r$ S5 b* z! s" E
  134.        return ($distance<=$allowGap) ? true : false;    8 s$ h4 g- U; ]
  135.    }   
    . g. S" Z" W* G# q
  136.     2 t6 G* `: T7 k: J. l+ p
  137.    
    4 W6 w+ Y2 A! B7 @5 o
  138.    /**比较两个图片文件,是不是相似   
    ) g* Y/ W0 |% r0 ~
  139.     * @param string $aHash A图片的路径   : ^9 M0 Y  J3 L0 G% \
  140.     * @param string $bHash B图片的路径   8 s0 z  A$ W5 a1 V
  141.     * @return bool 当图片相似则传递 true,否则是 false   
    : B7 B- h, m# r9 f8 t
  142.     * */    7 j- u7 Z4 w) @4 d. z5 O( q: D
  143.    public static function isImageFileSimilar($aPath, $bPath){   
    8 |! U# ?. E' S6 L% Z9 D
  144.        $aHash = ImageHash::hashImageFile($aPath);    . }$ E/ Z( @; e2 P- T' J0 ?' E
  145.        $bHash = ImageHash::hashImageFile($bPath);      q6 p3 m- B: ~
  146.        return ImageHash::isHashSimilar($aHash, $bHash);   
    # G  Z& B5 Y4 P4 ^+ {! s
  147.    }   
    " L8 P/ x; ^% f( w7 g9 a
  148.    
    : a. l3 l$ _0 Y2 R: Y' U+ R
  149. }
      j! @; Q" E" j
复制代码
: l* r4 Y* y0 \& S  I# I+ g3 ^: Z( I
$ Q/ _1 Y, h8 p/ Q5 u1 C- w& k6 ?
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2024-9-17 03:33 , Processed in 0.112792 second(s), 19 queries .

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