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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

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

2 B3 }( o$ d6 i由于相似图片搜索的php实现的 API 不怎么符合我的用途,所以我重新定义 API 的架构,改写成比较简单的函数方式,虽然还是用对象的方式包装。
/ F4 W% r0 O& {6 [
  1. <?php    ; d- @( K8 o8 N9 e. Z, o
  2. /**   ) {$ D6 n0 \7 r8 @/ t7 c9 u
  3. * 图片相似度比较   
    , a4 \9 W9 W( R- U1 w
  4. *   2 V! ]2 A4 b; b# ]' D
  5. * @version     $Id: ImageHash.php 4429 2012-04-17 13:20:31Z jax [        DISCUZ_CODE_1        ]nbsp;  ! A, S: Z0 g/ ^6 N2 P
  6. * @author      jax.hu   
    , y' `# x5 D& ~: G; g: w' D1 H
  7. *   
    3 M1 n. A5 [& [! ], a2 D4 G
  8. * <code>   
    % q9 Z5 h! }2 y- G! x9 D. H
  9. *  //Sample_1   5 G4 Z# X" S9 D- l% Q' n
  10. *  $aHash = ImageHash::hashImageFile('wsz.11.jpg');   8 }( m/ }' `3 N+ g+ N
  11. *  $bHash = ImageHash::hashImageFile('wsz.12.jpg');   
    . r$ B3 q. L- k6 y  x( a* G
  12. *  var_dump(ImageHash::isHashSimilar($aHash, $bHash));   
    2 x$ O( L) t; V5 M6 L5 ?  u
  13. *   6 `2 C. q% E+ k2 h- T# B9 B! h1 d
  14. *  //Sample_2   4 h7 G2 Z5 y/ D  v
  15. *  var_dump(ImageHash::isImageFileSimilar('wsz.11.jpg', 'wsz.12.jpg'));   $ ~  M1 M; c/ q* c* K1 a1 J  q4 @, J1 G' v/ n
  16. * </code>   
    % B; x/ P, R% Y- u8 [( B4 E# E' d0 X
  17. */   
    1 r. s7 N# Q0 l! [9 n
  18.     ( v* M- \4 k* P  B
  19. class ImageHash {   
    ) V5 C+ ?6 E. ^2 {9 q# E3 c
  20.     ( N* |8 _0 U+ l& f
  21.    /**取样倍率 1~10   " k7 K# X& m0 B9 g
  22.     * @access public   / i7 @' w2 n; N& ^6 |4 e: ^& R
  23.     * @staticvar int   $ r! Q6 J) H+ r4 s) r
  24.     * */    ! e% p( \- V% ]/ I6 [1 V
  25.    public static $rate = 2;    ; P( R. O/ l9 D( o
  26.    
    0 h+ a3 q) Q" _' G" A
  27.    /**相似度允许值 0~64   
    ) d4 _( c8 q- ?4 g2 m
  28.     * @access public   
    1 K- z4 `5 M; t8 S
  29.     * @staticvar int   
    " f1 S% a" Z7 o; k1 [
  30.     * */   
    * }. G# d/ I) [2 N! w
  31.    public static $similarity = 80;   
    " F; [  H) Y9 u
  32.    
    , _7 u: `% U5 S( z! w
  33.    /**图片类型对应的开启函数   
    8 ^! N0 l, q; F
  34.     * @access private   
    0 I6 e3 G: l/ q2 S  _* _. _
  35.     * @staticvar string   % @; y. x0 C! E" ~9 e9 i
  36.     * */   
    5 y: H5 n2 w3 B* v( o2 \& _
  37.    private static $_createFunc = array(   
    & V2 }' V$ v- H) q, b) Q
  38.        IMAGETYPE_GIF   =>'imageCreateFromGIF',    5 @( O* R, Z+ {% k
  39.        IMAGETYPE_JPEG  =>'imageCreateFromJPEG',    * D2 m3 E  _6 H2 @! P2 z! r
  40.        IMAGETYPE_PNG   =>'imageCreateFromPNG',    ; O- Z( C( d" X/ ~* a8 _
  41.        IMAGETYPE_BMP   =>'imageCreateFromBMP',   
    % Y0 }! V  u- H$ ]
  42.        IMAGETYPE_WBMP  =>'imageCreateFromWBMP',   
    / l+ q3 r# Y5 Z9 u
  43.        IMAGETYPE_XBM   =>'imageCreateFromXBM',   
    0 ^* w$ S! n/ o4 X( O! F$ L
  44.    );    $ J* l9 b" n' ~2 l
  45.     & y" _( Y, b$ D7 v; a+ o
  46.       {4 r" [/ D0 P- C
  47.    /**从文件建立图片   * r7 N+ _7 h2 q( d; R
  48.     * @param string $filePath 文件地址路径   5 `! D/ J. i+ N- y9 b& ^
  49.     * @return resource 当成功开启图片则传递图片 resource ID,失败则是 false   7 R7 U* Q' N% n& I
  50.     * */   
    - ~7 M  {: _9 z& p& J/ S$ M
  51.    public static function createImage($filePath){    $ N% @  g1 G( w9 T9 O
  52.        if(!file_exists($filePath)){ return false; }    4 m  [& z: J+ {8 q3 v
  53.     & D5 v) B* D7 g3 r2 Y) ]( R
  54.        /*判断文件类型是否可以开启*/   
      E1 P" k! j6 D5 H
  55.        $type = exif_imagetype($filePath);   
    6 |* Z! L* V$ f, U+ h+ m
  56.        if(!array_key_exists($type,self::$_createFunc)){ return false; }    2 Z; L4 n9 V, @4 E- ^4 N
  57.    
    & |: E' O6 h, @3 Y
  58.        $func = self::$_createFunc[$type];    9 V5 H/ b0 I0 v1 \$ B4 v
  59.        if(!function_exists($func)){ return false; }   
    ( W3 I7 \. P$ b1 b
  60.     1 {/ w3 ~# y+ B7 V
  61.        return $func($filePath);    * T0 |& W+ F: l% s
  62.    }    . S: b  n2 |- c: M  b+ v1 L
  63.     # a5 v% v) T1 k9 c, i* R1 E- u
  64.     0 e, M' w9 n8 e: h4 s
  65.    /**hash 图片   4 O) R' O3 D, a1 ?# N3 s
  66.     * @param resource $src 图片 resource ID   1 l* s+ @1 L% g: K: r) b/ v. L
  67.     * @return string 图片 hash 值,失败则是 false   
    4 f6 Q3 z1 O. t; b. n& c8 B
  68.     * */    9 D- G4 C- K- _  ~) S. O3 K5 k5 A
  69.    public static function hashImage($src){   
    , _. W( Z  ^: E4 Q) }8 [+ m
  70.        if(!$src){ return false; }    ' ?8 I% l- ?2 `% z$ [  Y
  71.     * C9 B0 s4 H$ ]7 D" B. U
  72.        /*缩小图片尺寸*/   
    , v9 u8 w/ W4 c( M
  73.        $delta = 8 * self::$rate;    # u- }2 p: V) Q$ U' w, [0 r
  74.        $img = imageCreateTrueColor($delta,$delta);   
    ) O. Z7 h+ f0 [; _/ f
  75.        imageCopyResized($img,$src, 0,0,0,0, $delta,$delta,imagesX($src),imagesY($src));   
    # m- H$ r; r, d* e1 @
  76.    
    * M% _' L- V" n
  77.        /*计算图片灰阶值*/    2 F- |# {1 g; [7 _
  78.        $grayArray = array();    2 L& h; \. L6 }" _" ?; i% j
  79.        for ($y=0; $y<$delta; $y++){   
    : l! Q/ D& `5 E  N3 ]. A9 `
  80.            for ($x=0; $x<$delta; $x++){    - B6 R+ O3 s7 I0 Y7 N" K7 ?
  81.                $rgb = imagecolorat($img,$x,$y);    - o) t- Z. x9 Y
  82.                $col = imagecolorsforindex($img, $rgb);    9 B  |3 `5 V8 h& m1 n
  83.                $gray = intval(($col['red']+$col['green']+$col['blue'])/3)& 0xFF;   
    - |" s5 V' V  \4 x
  84.     ' A" E4 [0 x+ Y
  85.                $grayArray[] = $gray;   
    2 k  z( e! \+ j2 T! I% }8 [
  86.            }   
    , c$ e1 y& z- Z. p4 g+ W$ D
  87.        }   
      I6 b6 `* d2 S3 C6 i2 _
  88.        imagedestroy($img);   
    * n& o7 F& V, s2 n9 h, @
  89.    
    $ n9 u: u1 U! n; [. @) W+ |5 y
  90.        /*计算所有像素的灰阶平均值*/   
    - O3 B2 w( j4 E. f; c* Q6 K. U! ], K
  91.        $average = array_sum($grayArray)/count($grayArray);    2 I% _0 F+ x( s; @, r
  92.    
    # Z2 [& P7 g" Y0 K" F0 ]) Y
  93.        /*计算 hash 值*/   
    * h, p6 B5 r1 h
  94.        $hashStr = '';   
    / k! @( h. K, Y  X; h
  95.        foreach ($grayArray as $gray){   
    2 c4 j; s/ Z- ^& c) X
  96.            $hashStr .= ($gray>=$average) ? '1' : '0';   
    $ ?- U. {5 z' X3 q7 P, \
  97.        }   
    ' m/ D& G( R& Y9 n1 \# K6 p
  98.     + H1 L/ s4 e& L; N, s9 P# C
  99.        return $hashStr;    ) j/ }) E. e+ j9 w; T
  100.    }    - h# a4 i0 B7 m2 w6 I1 F
  101.    
    " [- o$ ~3 {+ ^' i
  102.     ) P4 S: {9 R0 m: k* q, U
  103.    /**hash 图片文件   
    ' _: G. C# o) P6 E% K( [) {8 r
  104.     * @param string $filePath 文件地址路径   
    0 Y* o! M3 _" l) M& E: K
  105.     * @return string 图片 hash 值,失败则是 false   ; S; z4 i  `# C) l4 q) e; l, q
  106.     * */    # X. P7 O! S* n/ U' e9 K; u
  107.    public static function hashImageFile($filePath){   
    ' ?+ f  t( t3 k7 F( B2 i0 o# k
  108.        $src = self::createImage($filePath);   
    % ^# F$ r# Y8 i
  109.        $hashStr = self::hashImage($src);   
    & T- R* X$ z" F0 f" l
  110.        imagedestroy($src);    1 i, {0 c+ t: ]+ r8 b4 \6 C- g5 V
  111.     6 \' t* t: S6 F! O- z* i' c, X
  112.        return $hashStr;    7 q8 n3 W" M" C  i0 D2 }8 a- H: \
  113.    }    3 Z( O# ]3 J- @+ V
  114.    
    # p: h6 ^1 ?0 [
  115.       {, k, _# I7 Y
  116.    /**比较两个 hash 值,是不是相似   ; A, G/ t& t# b+ F3 L  O
  117.     * @param string $aHash A图片的 hash 值   
    5 k( Z% {, e: z% u
  118.     * @param string $bHash B图片的 hash 值   1 a8 z3 _; j4 K2 w1 h3 Z3 A9 ~
  119.     * @return bool 当图片相似则传递 true,否则是 false   . X- t& A; K. a' d+ J
  120.     * */    4 }9 ], R/ Q) W+ w  t9 @4 Y# i# |1 F
  121.    public static function isHashSimilar($aHash, $bHash){    + k% |. M8 n" `+ |* z0 }# ?; _9 M( U
  122.        $aL = strlen($aHash); $bL = strlen($bHash);    9 V/ \6 l: r) a8 b4 p* |, `2 m! H
  123.        if ($aL !== $bL){ return false; }    7 @3 R- J$ ^$ o3 R3 U
  124.     " i; J! W6 D4 X$ \
  125.        /*计算容许落差的数量*/    3 J9 m! [7 U" i" Y
  126.        $allowGap = $aL*(100-self::$similarity)/100;   
    9 W5 f- ]0 O+ S/ N) p2 P4 S+ y
  127.       n9 ]2 k$ u  ~  h! I# s  t; O
  128.        /*计算两个 hash 值的汉明距离*/    ! t, ]1 K5 @! f6 @* x
  129.        $distance = 0;   
    7 l, e2 ?. R3 f5 ~. v8 A3 Y6 V
  130.        for($i=0; $i<$aL; $i++){    " E& L0 e% T9 l9 a. K) T6 `9 e
  131.            if ($aHash{$i} !== $bHash{$i}){ $distance++; }   
    & h* {' n6 W7 ^4 A3 C5 m
  132.        }   
    & I6 N: B4 ^- O
  133.    
    8 ]2 G# `* V- j6 y3 z; \1 S
  134.        return ($distance<=$allowGap) ? true : false;    4 t) y$ n# Y+ G
  135.    }   
    % Z# Z: e2 [& G5 X* ^' ^' u# ~
  136.     $ S8 j2 S) Z% P! r$ l
  137.    
    # g) l; S+ M& _9 E
  138.    /**比较两个图片文件,是不是相似   ; b& z! M# o2 |& c3 M7 s
  139.     * @param string $aHash A图片的路径   1 a+ \& r3 W1 Y5 a& t
  140.     * @param string $bHash B图片的路径   ) c  Q+ K' q) b9 ^' ]  g  r/ M
  141.     * @return bool 当图片相似则传递 true,否则是 false   
    / U# [( o! [5 t6 P" Z
  142.     * */   
    0 Q4 T( d" }* N
  143.    public static function isImageFileSimilar($aPath, $bPath){   
    2 K7 P$ _! G" E7 h) T7 z* w
  144.        $aHash = ImageHash::hashImageFile($aPath);    & V8 y) x  m9 f  t  ~) R
  145.        $bHash = ImageHash::hashImageFile($bPath);   
    ) u5 n) P: ^/ p6 z6 d2 l+ w
  146.        return ImageHash::isHashSimilar($aHash, $bHash);   
    - L9 i1 o( ^: [4 b1 E
  147.    }   
    8 }2 H+ V; d2 C5 T
  148.    
    : n# }5 c" `$ X0 V
  149. }3 m: n- d2 x5 `- H* z7 T9 k$ b
复制代码
& O& i' I- W2 G3 }
& Q5 n1 Z2 x! I0 D/ ?) F
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2024-5-19 22:06 , Processed in 0.113397 second(s), 19 queries .

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