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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

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

8 D! g) ^7 i; ]9 d  j! P6 c由于相似图片搜索的php实现的 API 不怎么符合我的用途,所以我重新定义 API 的架构,改写成比较简单的函数方式,虽然还是用对象的方式包装。
6 h5 @) n' |; P8 m! a  P
  1. <?php   
    8 i, x3 ]9 h8 J" E0 d
  2. /**   
    4 @  Y& F5 G6 C3 b& V9 h9 \0 z9 C# @
  3. * 图片相似度比较   " U9 h. Z8 E$ [( G% N9 k& `7 ^' ~
  4. *   
    ( L4 P8 U8 M- U7 N% k! k8 p9 ^2 Q
  5. * @version     $Id: ImageHash.php 4429 2012-04-17 13:20:31Z jax [        DISCUZ_CODE_1        ]nbsp;  
    # h  @$ O6 F) J' f' M1 x
  6. * @author      jax.hu   
    & ~9 m$ o# ^  E6 X! t; V$ t5 ~; {
  7. *   
    " V( o) N- _, k; |  _! C
  8. * <code>   . t0 d! g4 g( R; ?% C7 ^% W
  9. *  //Sample_1   
    # T1 \' `, D+ B3 n
  10. *  $aHash = ImageHash::hashImageFile('wsz.11.jpg');   
    0 e' {3 E7 ~0 ]9 f
  11. *  $bHash = ImageHash::hashImageFile('wsz.12.jpg');   - n( f3 j+ V3 k) r
  12. *  var_dump(ImageHash::isHashSimilar($aHash, $bHash));   
    % }0 A: W4 u3 R7 y
  13. *   7 P8 U/ m6 h( I: P) V' k. D" Q
  14. *  //Sample_2   ! E' u  q3 B( o6 \- r
  15. *  var_dump(ImageHash::isImageFileSimilar('wsz.11.jpg', 'wsz.12.jpg'));   
    $ B- B. {+ j  Q( O* z+ \
  16. * </code>   8 B- u" ]& H  j
  17. */   
    6 N( M8 R( _; R1 B% b- V( ]
  18.     , L( A) m/ H. y8 e* t: W
  19. class ImageHash {   
    8 e, \  S3 D. T- ]- l" N1 [
  20.    
    . X$ U8 \& f9 S( j; @1 J
  21.    /**取样倍率 1~10   
    - \7 r2 v7 n, C: a: v" d# j8 w8 M* o
  22.     * @access public   
    ' I% O- S4 _' f' Z3 R4 A; b: b5 W* U
  23.     * @staticvar int   3 S$ h- m! j: i# D
  24.     * */    ! J( y2 x- S" O. C) ^9 O2 c
  25.    public static $rate = 2;    . M( T0 x0 q. Z
  26.    
    6 t9 G( A: n7 H* h4 J- A
  27.    /**相似度允许值 0~64   
    & W1 J2 ]" c" _7 w8 |3 d' P
  28.     * @access public   
    # m$ H7 {6 e6 [$ w+ G; v) V# h1 I
  29.     * @staticvar int   
    : _, @, Y, J, W3 B& n# M
  30.     * */   
    7 N! c' w: Q( D, l! K& K4 Z7 o
  31.    public static $similarity = 80;   
    ; v4 ]6 g8 J; s9 S- A
  32.    
    * l( d( Y8 b8 q, ?! Q7 ?) w
  33.    /**图片类型对应的开启函数   
    2 M" p% _6 `5 _. _
  34.     * @access private   
    % i! ~9 ?( M. d6 h. ^
  35.     * @staticvar string   
    9 `3 o/ w1 S/ u$ y) S( x) P
  36.     * */   
    2 V& r- R4 l0 p% X. D
  37.    private static $_createFunc = array(    " W* I( D" f& A, o$ M4 H2 w" w
  38.        IMAGETYPE_GIF   =>'imageCreateFromGIF',   
    0 L3 m2 z% |2 F( w9 k
  39.        IMAGETYPE_JPEG  =>'imageCreateFromJPEG',   
    3 b* w! I0 I4 I/ h* U
  40.        IMAGETYPE_PNG   =>'imageCreateFromPNG',   
    ( F0 ^, B1 u7 ?; L( g
  41.        IMAGETYPE_BMP   =>'imageCreateFromBMP',    + X/ t; J+ ^% h: N
  42.        IMAGETYPE_WBMP  =>'imageCreateFromWBMP',   
    7 T5 P- x7 r. o& W+ w$ P# g4 y
  43.        IMAGETYPE_XBM   =>'imageCreateFromXBM',   
    ( k/ i! S1 U* [+ I- G* y/ r+ R
  44.    );    . _. m+ |# B+ S
  45.       y) k/ z$ O% [
  46.     0 Q& w! y: S- t. r8 x
  47.    /**从文件建立图片   
    3 F3 J) I. L0 W( `; r" z
  48.     * @param string $filePath 文件地址路径   
    - `9 g4 O5 }0 {, h! q
  49.     * @return resource 当成功开启图片则传递图片 resource ID,失败则是 false   " g+ k& g/ r: S  h" T; ?
  50.     * */    / [: v9 Q& e; a0 f# B: X
  51.    public static function createImage($filePath){    % N* g7 ?5 Y3 N" z. _! o3 ]
  52.        if(!file_exists($filePath)){ return false; }   
    5 ~9 n2 S* Q9 z: P  n7 L
  53.    
    , m- a' y& S7 D: j# j  p6 V
  54.        /*判断文件类型是否可以开启*/   
    4 ?' Q: P; Y( A9 f
  55.        $type = exif_imagetype($filePath);    3 L2 ?( X+ n6 A$ p/ \1 e) T- ~( y# X
  56.        if(!array_key_exists($type,self::$_createFunc)){ return false; }   
    2 S, _0 M" U3 A  t3 X3 Q' P
  57.    
    0 p: E2 i1 h- v/ L
  58.        $func = self::$_createFunc[$type];   
    5 ~  H1 a( u1 T& ]8 }( T  R
  59.        if(!function_exists($func)){ return false; }    # @7 P1 y9 F# M# [
  60.     7 M+ ~1 h; {& g+ ~0 ^8 a. r9 R
  61.        return $func($filePath);   
      ~* n" |" m5 [" t2 G$ A0 t3 `
  62.    }   
    8 T( f# w& e' {1 m7 @
  63.    
      p8 t& _3 T8 I. C0 \3 v
  64.     8 i5 L9 f- y# z/ w
  65.    /**hash 图片   6 j& X: h! o, h+ i
  66.     * @param resource $src 图片 resource ID   
    0 _  ~7 z& R- z# ]+ n
  67.     * @return string 图片 hash 值,失败则是 false   
    - \  N, ^% d. O7 {) _0 z8 N7 K/ f
  68.     * */   
    9 Q3 S# B; E6 j+ P( X1 o
  69.    public static function hashImage($src){   
    / L( I3 s) T* d9 j. M0 S
  70.        if(!$src){ return false; }   
    ; S7 [3 \0 ?  }. j3 x5 G% X9 E
  71.     + A( k& x1 r  k" ^
  72.        /*缩小图片尺寸*/   
    1 e! R5 n! j- s) O/ v
  73.        $delta = 8 * self::$rate;    4 g& i' M- `, h
  74.        $img = imageCreateTrueColor($delta,$delta);    7 B8 h) l  K( q2 D7 J: I$ X
  75.        imageCopyResized($img,$src, 0,0,0,0, $delta,$delta,imagesX($src),imagesY($src));   
    1 e* W0 m4 l: ~' w, j6 C; [' q+ Q
  76.     # A; t1 D9 B5 \! Z
  77.        /*计算图片灰阶值*/   
    * \1 C/ z9 A( Q1 Z6 }
  78.        $grayArray = array();    + u0 {: B1 |3 Y" [7 `/ D1 H: Z  E
  79.        for ($y=0; $y<$delta; $y++){   
    2 U5 R3 ^' A4 u0 t- G
  80.            for ($x=0; $x<$delta; $x++){    ( [1 U6 B( D' y9 t: y% A
  81.                $rgb = imagecolorat($img,$x,$y);   
    7 N+ B* E3 T6 B* u& X
  82.                $col = imagecolorsforindex($img, $rgb);   
    6 @3 n2 J; b9 r& E4 C
  83.                $gray = intval(($col['red']+$col['green']+$col['blue'])/3)& 0xFF;      ~& ]; D: \" f6 E0 z
  84.     , k4 t, a' z7 b" }- @% o% F# `; L
  85.                $grayArray[] = $gray;   
    : B( _$ R- `; }7 |, Y; j% S
  86.            }   
    / z* p% M+ ^. u, F# u5 L$ {* Z
  87.        }   
    ( K8 L9 @8 I. B1 s; l1 M
  88.        imagedestroy($img);   
    ) b0 h! _$ o6 t+ B8 d1 p8 O
  89.    
    : V( i, [3 p* ^2 u2 _) H& H" K
  90.        /*计算所有像素的灰阶平均值*/    - w# H- A& _% Z
  91.        $average = array_sum($grayArray)/count($grayArray);    & n* D6 C7 [: ^
  92.    
    # V3 ^8 [0 Z& Y3 l
  93.        /*计算 hash 值*/    ) ]7 ^2 M# F: ]8 ^
  94.        $hashStr = '';    ; |, d2 |% X- D4 q
  95.        foreach ($grayArray as $gray){   
    0 W$ y1 ~9 r7 D
  96.            $hashStr .= ($gray>=$average) ? '1' : '0';    * ^! S7 P; @. J, X: w  T
  97.        }   
    * l( O5 p% n5 R0 u* O! e
  98.    
    ) b6 s. t1 p. b5 M+ N
  99.        return $hashStr;   
    - q5 T% M; M. X* c, [# V
  100.    }    # h7 L) I5 u6 [+ ^; f/ ~
  101.     + L- ~7 F9 U$ B& ]3 `" E
  102.    
    8 r- v9 Z) {0 a
  103.    /**hash 图片文件   9 G2 d+ p6 f7 \% h' A" d
  104.     * @param string $filePath 文件地址路径   
    : e  [3 X2 V. V
  105.     * @return string 图片 hash 值,失败则是 false   
    6 j8 {5 O$ m$ y/ ~  l( f- O! w
  106.     * */    # a1 y. q8 s$ P/ F0 P# [# C4 _
  107.    public static function hashImageFile($filePath){   
    8 i' j$ ]7 L& R* ~6 a( R
  108.        $src = self::createImage($filePath);    0 ]* M  f0 V0 _( ]  D
  109.        $hashStr = self::hashImage($src);    6 E" b( d9 b  }% ?  P5 |# F; \& w
  110.        imagedestroy($src);   
    1 j  r4 C/ y$ }  t5 C' J
  111.    
    * v* R9 K* d5 X1 a: B7 b
  112.        return $hashStr;   
    7 ?& \9 {$ l/ R0 O' k: |! j
  113.    }   
    % d8 y$ Q& h' q/ p' H  o
  114.    
    # ~+ E8 j8 ?0 ?# d% w
  115.     . K( t# K8 i3 P7 I6 ]. g
  116.    /**比较两个 hash 值,是不是相似   6 J7 [0 S& \; z8 L5 a# L
  117.     * @param string $aHash A图片的 hash 值   
    , i2 |) c" R7 i& V
  118.     * @param string $bHash B图片的 hash 值   
    , v2 i9 J) \/ I, N4 h0 k
  119.     * @return bool 当图片相似则传递 true,否则是 false   ) p1 P6 M+ Z, J' _3 d1 v
  120.     * */   
    4 h6 T# A* Y0 R9 \) {
  121.    public static function isHashSimilar($aHash, $bHash){   
    / P3 [( [  X- M1 w& ^8 E. E
  122.        $aL = strlen($aHash); $bL = strlen($bHash);    1 C1 Y" M* J. ~( i
  123.        if ($aL !== $bL){ return false; }    . `! d) O8 W* s
  124.     2 f7 b. S4 k+ P* m7 q/ W2 }; `
  125.        /*计算容许落差的数量*/   
    8 F6 ^5 j) ^3 x  P  B% N) d  y0 i
  126.        $allowGap = $aL*(100-self::$similarity)/100;   
    7 `/ i# H. ~1 }0 J) u7 b# v
  127.     2 ~. s/ [8 [0 R6 K
  128.        /*计算两个 hash 值的汉明距离*/   
    + ]  j3 b3 H& y$ X
  129.        $distance = 0;    7 ?& u& @) {% w( Z
  130.        for($i=0; $i<$aL; $i++){   
      }/ R& B$ m7 y4 c  w  J" X
  131.            if ($aHash{$i} !== $bHash{$i}){ $distance++; }    : @0 n. C3 g$ g3 W, s3 `
  132.        }    3 ?8 H: X6 q$ l9 X0 M7 f7 U
  133.     1 y, Z8 D# ^+ X
  134.        return ($distance<=$allowGap) ? true : false;   
    0 }- s& s, A' M& m
  135.    }   
    " Q( A! O3 q: R# P) C4 i. N* ]
  136.     1 V4 t& c& I3 v: l: w
  137.       _' Y8 n2 l3 w
  138.    /**比较两个图片文件,是不是相似   
    3 R) P3 }6 r% Y: A
  139.     * @param string $aHash A图片的路径   
    8 F; T: t1 ]8 H
  140.     * @param string $bHash B图片的路径   
    # o2 h4 b) G) d! f' V
  141.     * @return bool 当图片相似则传递 true,否则是 false   
    5 G+ N" k* `. ^1 i
  142.     * */    4 F3 P% q# E+ a' g
  143.    public static function isImageFileSimilar($aPath, $bPath){    2 j3 B# m) G& i0 A6 Z
  144.        $aHash = ImageHash::hashImageFile($aPath);    9 Z9 l+ N* K9 T; }* |
  145.        $bHash = ImageHash::hashImageFile($bPath);    ; s% }$ q' d$ j
  146.        return ImageHash::isHashSimilar($aHash, $bHash);    - G9 P, G: L& A8 ]
  147.    }    . |# c; k( T) u& r
  148.     " W7 Z! z# f- D4 D
  149. }3 T, }2 m: T* h& Q5 S+ @
复制代码

/ _( N4 C) `6 Z: n4 N1 F1 y/ Q& ~- }8 q: m* W+ q7 {$ o# ~
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2024-12-22 21:39 , Processed in 0.141864 second(s), 21 queries .

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