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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2018-7-7 23:06:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
摘要: 本文讲的是分享一个PHP简易的图片相似度比较类, 由于相似图片搜索的php实现的 API 不怎么符合我的用途,所以我重新定义 API 的架构,改写成比较简单的函数方式,虽然还是用对象的方式包装。  代码如下 复制代码 <?php    /**   * 图  ^; O2 h+ K+ J2 L5 Q6 y% d6 n
" Z/ \, S8 @+ @8 H

5 a+ d, r4 r; d! I- ]由于相似图片搜索的php实现的 API 不怎么符合我的用途,所以我重新定义 API 的架构,改写成比较简单的函数方式,虽然还是用对象的方式包装。
7 }! D. H* q) ^: V, u
  1. <?php   
    1 L! B" W- n: G; i" p7 Y0 B# ^
  2. /**   8 x1 ?. L; t( ~( G1 S, P) M
  3. * 图片相似度比较   ; l6 s+ L* [, t; i+ K7 R' L* b
  4. *   
    , a+ ~% f/ y% y# \
  5. * @version     $Id: ImageHash.php 4429 2012-04-17 13:20:31Z jax [        DISCUZ_CODE_1        ]nbsp;  # |" q" s4 i% O( }& l9 G) b/ c1 \
  6. * @author      jax.hu   
    - X) `, A( u1 y, h3 z& h& b
  7. *   ( ~! L3 i' Q7 Q, R# p9 `6 G/ e
  8. * <code>   + v. F/ F2 t( u4 r
  9. *  //Sample_1   
    5 g5 K) R+ S1 v6 b: G5 X7 @3 `
  10. *  $aHash = ImageHash::hashImageFile('wsz.11.jpg');   
    ! J7 Z* Y; Q: [+ q* h0 r
  11. *  $bHash = ImageHash::hashImageFile('wsz.12.jpg');   
    ' |5 `& F) A7 y3 a) z  y; s$ W
  12. *  var_dump(ImageHash::isHashSimilar($aHash, $bHash));   
    % r2 R7 e- j  I2 Q4 O- a
  13. *   
    5 i) L" }& j  j9 ~; N9 M' {/ X
  14. *  //Sample_2   
    . N$ j+ n- O" a+ z& Q  W
  15. *  var_dump(ImageHash::isImageFileSimilar('wsz.11.jpg', 'wsz.12.jpg'));   
    & a, K" U0 b4 y( I2 y- [- e9 H7 T
  16. * </code>   
    * H3 B- {' u9 l3 E; y
  17. */    & U/ A" s% I# J8 c! g
  18.     4 o4 p/ l4 u, Q1 E6 i
  19. class ImageHash {    4 Y5 @- b2 C9 V9 b
  20.     6 G$ a  g. z0 W7 K
  21.    /**取样倍率 1~10   
    . C3 T- }7 Z8 ^2 C$ a' G
  22.     * @access public   
    " P6 T' I& X$ {4 r3 G# e9 y$ P: \
  23.     * @staticvar int   
    1 y: a) x* g, m! [  l
  24.     * */   
    0 ?- h$ @9 ?. l  T4 c$ s
  25.    public static $rate = 2;   
    , }# W' h" Q' I; f8 q
  26.     + h2 |0 _4 h% e+ L
  27.    /**相似度允许值 0~64   
    9 Q, C" Y9 t. g
  28.     * @access public   
    ( a: q+ @+ l1 t4 w7 n! v8 T
  29.     * @staticvar int   
    + b& J# o9 {" w  y. j8 J8 Z- x" z
  30.     * */   
    # v* R& N$ G7 ~
  31.    public static $similarity = 80;    9 `* b: Q& `; u/ Q/ C
  32.    
    3 t! z7 D! w9 ?* [6 g, u  E9 i
  33.    /**图片类型对应的开启函数   & L7 I% M+ e- B4 `  t% C: D
  34.     * @access private   
    0 x: c1 z5 {5 E3 ]
  35.     * @staticvar string   ! t/ @/ ~5 l, S7 s
  36.     * */   
    / U3 p* I- Q# }: B3 |6 i) D4 }
  37.    private static $_createFunc = array(   
    , ]1 {  \9 E" k: @( J9 o2 m5 }
  38.        IMAGETYPE_GIF   =>'imageCreateFromGIF',   
    * o# a9 G; b+ t5 }
  39.        IMAGETYPE_JPEG  =>'imageCreateFromJPEG',   
    5 @, ~, K4 a  L/ g
  40.        IMAGETYPE_PNG   =>'imageCreateFromPNG',    . X8 D- Y- V" W  R
  41.        IMAGETYPE_BMP   =>'imageCreateFromBMP',   
    # F1 W. t- D8 I0 m- F$ K
  42.        IMAGETYPE_WBMP  =>'imageCreateFromWBMP',   
    5 S- L! e: l& k0 D" Y
  43.        IMAGETYPE_XBM   =>'imageCreateFromXBM',    - H- l3 o- y( V& i
  44.    );   
    # h4 }% F) ^' Z7 C; F  n" P% p& f
  45.    
    3 A6 s  j7 @9 }1 G6 G
  46.     ) c" m  K$ s5 K1 Z
  47.    /**从文件建立图片   
    ( }; K! M3 D% X4 E5 [) M# W4 D9 B
  48.     * @param string $filePath 文件地址路径   
    6 h9 e0 p; ]6 b) j% P# W
  49.     * @return resource 当成功开启图片则传递图片 resource ID,失败则是 false   
    % j7 h$ u  L/ k+ t. E; A: c+ ]% I$ w
  50.     * */    3 W$ I, }2 z# N1 u; k
  51.    public static function createImage($filePath){    % a  ~3 _# j% P8 A7 j0 M
  52.        if(!file_exists($filePath)){ return false; }    6 G0 X/ R, ^0 ~/ e
  53.    
    & P5 @7 E! S& }8 J+ {( n( i
  54.        /*判断文件类型是否可以开启*/   
    9 O' Q/ E+ |4 i( j- d' A% d  B
  55.        $type = exif_imagetype($filePath);   
    6 \1 d! P6 I. U' D9 D
  56.        if(!array_key_exists($type,self::$_createFunc)){ return false; }   
    ( C; a- V2 ?' @! D; V' N" ?. q
  57.     2 h  V' Z0 B. x! T. a
  58.        $func = self::$_createFunc[$type];    / r0 ^& z$ r7 B. _
  59.        if(!function_exists($func)){ return false; }    7 J+ V/ g0 Z6 O0 r/ j
  60.    
    : t8 a0 |% @" c7 r8 W; }& ]
  61.        return $func($filePath);    ' j( m. b( p( [- U; c4 X
  62.    }   
    5 r* {/ R! N! v% f! P) ]! g2 M! S
  63.     % ]) M4 Z5 t# a( L
  64.    
    ' B, r0 [3 W$ O$ c
  65.    /**hash 图片   
    ; Q# s( a0 ]* K, i* A2 K" \
  66.     * @param resource $src 图片 resource ID   
    5 z) \6 r' Y$ [( ]5 l" g
  67.     * @return string 图片 hash 值,失败则是 false   
    * t+ K) Q2 t: H1 p! X& n5 d
  68.     * */   
    " p# _* A. V$ W, ^/ m
  69.    public static function hashImage($src){    7 Q4 [3 ?* M( u$ n5 p
  70.        if(!$src){ return false; }   
    * F/ G  `; @5 o4 L
  71.    
    - Q9 Y. Y9 ~; ?1 _9 k9 X8 B
  72.        /*缩小图片尺寸*/    % Y, W* O3 E% W, T
  73.        $delta = 8 * self::$rate;   
    * \, E2 I0 \( v( @
  74.        $img = imageCreateTrueColor($delta,$delta);   
    - N+ p7 ~3 P5 k  W
  75.        imageCopyResized($img,$src, 0,0,0,0, $delta,$delta,imagesX($src),imagesY($src));    + w" Y# ?7 U, H2 _) A+ G
  76.     & t; k8 S& u, O% [1 R
  77.        /*计算图片灰阶值*/   
    3 i; Q) [% b6 S6 C: g) ?
  78.        $grayArray = array();    7 r( c7 P* X; _! A! [3 X& T, t/ L  |
  79.        for ($y=0; $y<$delta; $y++){   
    $ t% H# s  Y$ Z4 H/ B( F
  80.            for ($x=0; $x<$delta; $x++){    2 ]. }3 S: s, w& o4 H8 `$ B
  81.                $rgb = imagecolorat($img,$x,$y);   
    ! }6 _1 j8 f+ q; g, P9 e/ K! \
  82.                $col = imagecolorsforindex($img, $rgb);    / y1 I! J; _& F; ~$ G
  83.                $gray = intval(($col['red']+$col['green']+$col['blue'])/3)& 0xFF;    # M0 G4 |' P6 U6 w6 a9 v2 |
  84.    
    0 [3 ?1 K. H9 B/ h* _
  85.                $grayArray[] = $gray;   
    : B8 R4 {9 }- ?& s; R" V9 L( |
  86.            }   
    " F2 L$ ~  N( H& {9 E# D
  87.        }   
    ) X% z9 D, O1 a! R; e' `% V
  88.        imagedestroy($img);    * w+ M6 e- G+ U7 y  S2 H
  89.    
    % W' v0 f. e7 l) }% e2 s
  90.        /*计算所有像素的灰阶平均值*/   
    7 y' J9 e* B: i
  91.        $average = array_sum($grayArray)/count($grayArray);   
    3 j! Z, _4 {6 g; S5 U' B
  92.    
    1 M) V4 p: k/ V7 J+ K+ U. V& n/ E3 g
  93.        /*计算 hash 值*/   
    5 s4 @# G- a" U
  94.        $hashStr = '';   
      n, ~5 b; a) Q! _# x( I
  95.        foreach ($grayArray as $gray){    . l2 ?3 v! G3 \! Z4 b4 }- ~2 g5 t
  96.            $hashStr .= ($gray>=$average) ? '1' : '0';    ! d2 D( i! x/ W6 f% }. z3 N) O
  97.        }      ]% T6 K1 u% P( Q# ~
  98.     5 y' v7 Y) X& u6 t+ J( p
  99.        return $hashStr;    ! B  B6 h, Z# z0 J. u5 _
  100.    }   
    & N& g8 r0 w' s6 l! z( s
  101.    
    6 b0 y( ?7 t7 u" ^- A7 ^6 c
  102.     + M+ k3 W: p6 y9 W1 `) W3 _# z
  103.    /**hash 图片文件   : i: T1 y- {* ?  z0 j
  104.     * @param string $filePath 文件地址路径   
    . E+ O0 z& I8 c$ H/ h+ x3 Y
  105.     * @return string 图片 hash 值,失败则是 false   
    # t8 L1 t0 d' w8 Y6 Z2 j
  106.     * */    & H1 I4 {3 e+ I+ F( d: P' @
  107.    public static function hashImageFile($filePath){      {6 `- ?$ f; w8 L5 z2 t/ o( Y" \
  108.        $src = self::createImage($filePath);   
    + l. z- H" a7 M* }4 d( X8 A& ?
  109.        $hashStr = self::hashImage($src);   
    3 b9 }8 U  S6 k* C& r
  110.        imagedestroy($src);   
    $ g2 P) l1 l8 F/ v0 A* e: l  r
  111.    
    ! X8 e* @, P3 k5 q; [1 S
  112.        return $hashStr;    ( w, C/ j' r+ R9 T- P
  113.    }    5 Z; P* c* m0 n" F. e& C
  114.     2 d8 S8 N7 i2 r' p5 g
  115.     ' |: M/ O! n3 o5 Q
  116.    /**比较两个 hash 值,是不是相似   
    ! F' }! P4 f' R5 I! q# F
  117.     * @param string $aHash A图片的 hash 值   , _: g! I7 o1 X- c* p
  118.     * @param string $bHash B图片的 hash 值   
    ! u/ y/ C9 ~- X4 |$ X' {: }' P
  119.     * @return bool 当图片相似则传递 true,否则是 false   
    . r7 p' H! c, b: T
  120.     * */   
    0 L% [8 q: H7 i) L3 `5 e- U* q
  121.    public static function isHashSimilar($aHash, $bHash){   
    & l9 Q' P& p2 X% S( F& u
  122.        $aL = strlen($aHash); $bL = strlen($bHash);    % V* d& u. x& y5 t/ \
  123.        if ($aL !== $bL){ return false; }    0 e5 Y, A# D, P( a, F( B4 }
  124.    
    , R! t4 H1 p  X3 V
  125.        /*计算容许落差的数量*/    5 _4 f: ~$ v2 u. V- j- y  i
  126.        $allowGap = $aL*(100-self::$similarity)/100;   
    1 E5 M' }" I" r' V. S& H0 R% @3 W; ]
  127.    
    & c  `( Z, j0 G
  128.        /*计算两个 hash 值的汉明距离*/   
    # E7 w) X0 {, E" k0 `7 g% w# }
  129.        $distance = 0;   
    , H4 I( Q. m! `( i
  130.        for($i=0; $i<$aL; $i++){   
    8 R2 i6 r# J+ O6 o! g% ]
  131.            if ($aHash{$i} !== $bHash{$i}){ $distance++; }    1 P6 j9 E7 K8 ]$ _5 f
  132.        }    2 |7 x4 [3 U+ E  ~0 g7 [
  133.    
    2 G! x7 m5 O' D" [/ [
  134.        return ($distance<=$allowGap) ? true : false;    / C9 x1 V% W1 K4 f' e& N3 i8 h
  135.    }    " z7 w+ c: _( p% i/ U" s2 `+ x
  136.    
    : Y2 Z* j& M6 R- B7 l
  137.    
    + Z3 w. T5 E$ m& R8 n( d% K
  138.    /**比较两个图片文件,是不是相似   
    $ A8 `. V4 d/ s+ H& ?. l% r3 H
  139.     * @param string $aHash A图片的路径   * B* R/ l4 v9 m- t- [1 W% ~6 z+ [
  140.     * @param string $bHash B图片的路径   5 e. v' e  c5 ?: G3 C
  141.     * @return bool 当图片相似则传递 true,否则是 false   6 s9 n3 E! Q9 w  K! f
  142.     * */    - k& L5 m  r" K+ ]% b* t
  143.    public static function isImageFileSimilar($aPath, $bPath){   
    - [' I% r1 Y* x) o/ h5 D5 S8 O
  144.        $aHash = ImageHash::hashImageFile($aPath);   
    0 p0 T- J1 Q* L! Y. U
  145.        $bHash = ImageHash::hashImageFile($bPath);   
    4 L/ P3 ]8 _# y. Q8 T& g
  146.        return ImageHash::isHashSimilar($aHash, $bHash);    * I: G( S- g7 S4 q6 h2 F' t. J
  147.    }   
    # Y' P; o0 X/ v% Z
  148.     7 q% T! W, w, _- B* A
  149. }  J! C$ f$ j; {- K% z( i0 ^" f
复制代码

4 n# V" k. w# F1 Z/ T/ j! v' k- X; w+ E) s7 Y- r
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2024-5-17 10:58 , Processed in 0.103860 second(s), 19 queries .

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