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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2018-7-7 23:06:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
摘要: 本文讲的是分享一个PHP简易的图片相似度比较类, 由于相似图片搜索的php实现的 API 不怎么符合我的用途,所以我重新定义 API 的架构,改写成比较简单的函数方式,虽然还是用对象的方式包装。  代码如下 复制代码 <?php    /**   * 图
  J- ?, p( G7 Z9 r4 f" I* j5 ?" @6 y- u. n" s' Q  t! j
+ a7 F9 ~4 A9 \4 p! O, \
由于相似图片搜索的php实现的 API 不怎么符合我的用途,所以我重新定义 API 的架构,改写成比较简单的函数方式,虽然还是用对象的方式包装。
: K( S3 c% u6 R1 J& O
  1. <?php    0 s9 b; w1 N- o! q  R% j2 n2 e
  2. /**   : V6 b: @' I6 [3 M, n
  3. * 图片相似度比较   6 \5 P  E4 Q3 j* d% c
  4. *   
    5 m7 P3 W6 `4 g8 J
  5. * @version     $Id: ImageHash.php 4429 2012-04-17 13:20:31Z jax [        DISCUZ_CODE_1        ]nbsp;  
    , T  n& @* Q9 R5 [+ ~( a
  6. * @author      jax.hu   
    , V0 t4 L6 b8 ]7 D5 K
  7. *   
    $ z& L  g' ~7 E; B
  8. * <code>   - P# S, e7 S' v
  9. *  //Sample_1   
    # r% r2 S2 n0 T$ d0 D8 d
  10. *  $aHash = ImageHash::hashImageFile('wsz.11.jpg');   
      e7 @0 l+ y: e+ @+ ]! A1 r
  11. *  $bHash = ImageHash::hashImageFile('wsz.12.jpg');   
    5 i$ S* Q% y5 y( S
  12. *  var_dump(ImageHash::isHashSimilar($aHash, $bHash));   8 D* h# K, A* E; C; F( E" \& ^; X, R
  13. *   ) C$ k8 {- z2 A! A, V6 h* d
  14. *  //Sample_2   
    + @; N; ^. l% l& ^  {4 o6 I
  15. *  var_dump(ImageHash::isImageFileSimilar('wsz.11.jpg', 'wsz.12.jpg'));   
    + n+ W7 E* O; ?8 u1 Q3 E7 I
  16. * </code>   
    ' ^( v) O" V, ]- o
  17. */    ( |) Z0 x; T0 H: v! _* }5 S
  18.    
    ) i. J7 G/ H9 P2 B' K3 u6 \
  19. class ImageHash {   
    % r5 A7 R) H' W( {  V+ @
  20.     % e3 E4 t0 y: w8 l- }& a
  21.    /**取样倍率 1~10   : f# \4 I  s  V# C3 L: |# S0 x# u
  22.     * @access public   
    & }) f2 Q. ~$ `6 }0 Z' R
  23.     * @staticvar int   
    / i2 @; e# X* [8 X
  24.     * */    2 E9 _  z6 ?6 n% v
  25.    public static $rate = 2;    1 ?1 `( Y* u; T9 l  w# {! c$ `1 O
  26.     ( @4 \4 B' u8 Z
  27.    /**相似度允许值 0~64   " Y- Q" C/ O# v; ?7 C) H6 W
  28.     * @access public   $ j! ]4 X) @. B% ~4 Z
  29.     * @staticvar int     x" K& F* b, i
  30.     * */    3 U* V1 ?# O, k. B  u/ @
  31.    public static $similarity = 80;    5 E$ V7 ~# x, z% D+ ~- }3 M
  32.    
    6 q" S# T4 L7 n; K+ G
  33.    /**图片类型对应的开启函数   + ~# g- f. [7 q9 G! f. Q( M" ]$ u( ?
  34.     * @access private   
    , i+ b$ z3 ~( ]; m9 W" P
  35.     * @staticvar string   
    ' M$ d6 ~# V+ j" w+ }( h8 t9 \3 U
  36.     * */   
    ' E0 O2 K* [3 Y4 O% k1 P
  37.    private static $_createFunc = array(   
    $ t8 `; M9 E( d3 U' o8 v9 o
  38.        IMAGETYPE_GIF   =>'imageCreateFromGIF',   
    * A! f' n- p. K( l) u% h2 a
  39.        IMAGETYPE_JPEG  =>'imageCreateFromJPEG',    " U: D: T' J, f" ]
  40.        IMAGETYPE_PNG   =>'imageCreateFromPNG',    % I1 Z) V/ J7 z, l1 j
  41.        IMAGETYPE_BMP   =>'imageCreateFromBMP',    1 c+ ~9 c/ \! @, s/ G
  42.        IMAGETYPE_WBMP  =>'imageCreateFromWBMP',   
    ) J6 u* C9 p# I2 j0 _3 m" s" w5 O
  43.        IMAGETYPE_XBM   =>'imageCreateFromXBM',   
    " z, L- g2 I- F
  44.    );   
    6 H1 K- U2 a( L6 M& j& Y- Z
  45.     4 p/ B5 d7 ?5 j1 T8 t
  46.     ; H/ v/ Q1 _7 f- Z+ k
  47.    /**从文件建立图片   
    & o4 t% Q- X( X' F; w
  48.     * @param string $filePath 文件地址路径   
    ; r' O- \8 O+ Q7 T9 K4 L" [; n  G1 L
  49.     * @return resource 当成功开启图片则传递图片 resource ID,失败则是 false   1 D/ r5 s0 w5 R7 p
  50.     * */   
    / K0 j& D; j* F; }$ D
  51.    public static function createImage($filePath){    & ?/ v0 R4 S  E
  52.        if(!file_exists($filePath)){ return false; }   
    1 g4 Y+ ^( q) U1 r! M
  53.     2 L0 v9 @% G8 C/ p" h) g: Q
  54.        /*判断文件类型是否可以开启*/   
    " ^$ K8 ^+ {' @1 I9 b' u+ y# ~, T
  55.        $type = exif_imagetype($filePath);    7 }+ V$ N, [5 V/ h: |" e
  56.        if(!array_key_exists($type,self::$_createFunc)){ return false; }    3 q' f  R/ J5 k! W# P" K
  57.     1 q; \5 ~$ x" ]3 J/ a
  58.        $func = self::$_createFunc[$type];    . `! {$ z8 t5 w& n% I# I
  59.        if(!function_exists($func)){ return false; }    9 Z9 P4 v+ Y7 q& R+ y, ^: l
  60.    
    $ H7 p, v5 F, R% z) L: m. |
  61.        return $func($filePath);    7 |, e5 ~9 O, n
  62.    }   
    : h* |8 ]* m8 p2 A
  63.    
    7 @1 a( m3 r1 s, n, G0 `* ]+ j
  64.     # c; ~/ n1 _; G  v0 j
  65.    /**hash 图片   
    ) c% s( L; U  V& F  t4 ?
  66.     * @param resource $src 图片 resource ID   2 u' \) }# Z/ r# D7 ~0 @2 s) F
  67.     * @return string 图片 hash 值,失败则是 false   * b$ r8 p7 O) S3 V
  68.     * */   
    * r* C& C8 Q* V3 x( u0 @6 x
  69.    public static function hashImage($src){    1 b1 T: {( ~* d' s, ~
  70.        if(!$src){ return false; }    5 U: `8 x( R. l) m! @5 Q4 q
  71.     ' c, [  e* V$ G* K( u0 {& B3 z
  72.        /*缩小图片尺寸*/    ) I6 M5 J& D3 R* d. @+ l4 a# G
  73.        $delta = 8 * self::$rate;   
    ( [7 N: o' ^, {) x: K5 a
  74.        $img = imageCreateTrueColor($delta,$delta);   
    3 g( g  x( F) p  w* k3 Y
  75.        imageCopyResized($img,$src, 0,0,0,0, $delta,$delta,imagesX($src),imagesY($src));   
    8 `9 e6 t1 A; |3 D! l3 ?4 I/ J- y
  76.    
    # Y+ O: W: L3 x( K' \; {# o
  77.        /*计算图片灰阶值*/   
    ; q9 f* s8 g) d) D! a* ?9 j
  78.        $grayArray = array();    9 b6 d* Q7 k+ C4 Z! e- u
  79.        for ($y=0; $y<$delta; $y++){    & I( t6 F0 s) `( B% P) s3 T1 @
  80.            for ($x=0; $x<$delta; $x++){      M- v/ d) S! e6 I
  81.                $rgb = imagecolorat($img,$x,$y);    % j6 s  O2 V; d4 Z2 T$ V7 B" X
  82.                $col = imagecolorsforindex($img, $rgb);    " y& D1 A$ \' Q: t! g# I
  83.                $gray = intval(($col['red']+$col['green']+$col['blue'])/3)& 0xFF;   
    $ [5 M! e2 C; r" @) d
  84.    
    2 ?/ N9 ~/ w7 X. @8 o" f' x
  85.                $grayArray[] = $gray;   
    ; f4 `; c" c8 E$ @" Z
  86.            }   
    ' E* ^2 @  g4 y8 R  g% F. [
  87.        }    # m' K3 k$ H( I0 w
  88.        imagedestroy($img);   
    : W* X+ D6 K4 i  S1 T
  89.    
    3 a1 k5 I7 _  x! B( l# w0 Z7 L8 v
  90.        /*计算所有像素的灰阶平均值*/    & @. R1 f( s- n7 N+ _' b
  91.        $average = array_sum($grayArray)/count($grayArray);   
    & b8 t3 ?" q. x4 i" ]8 i; P' j2 h- S
  92.     ! k# Z# V( {6 k+ X+ |
  93.        /*计算 hash 值*/    + _# n" Q) O8 j% x6 ~0 I- w
  94.        $hashStr = '';   
    ; ]9 W3 Q( }1 c4 v! o3 w8 a5 g3 @
  95.        foreach ($grayArray as $gray){    $ E0 V/ g! d; k+ s
  96.            $hashStr .= ($gray>=$average) ? '1' : '0';   
    7 A: M) s  U; F+ u% Y8 B- }
  97.        }   
    + ^' K! H2 U; s% t7 ?2 a
  98.     ! d$ M  G9 ^/ w5 U
  99.        return $hashStr;    + z$ x5 C* W( B
  100.    }    + q: n" ]1 V% R4 R+ V
  101.     3 S8 R9 C2 F7 p1 q* a% @
  102.    
    - K6 Y+ a# P! }
  103.    /**hash 图片文件   
    * a1 n0 V/ H" p* |
  104.     * @param string $filePath 文件地址路径   3 `# B8 i) u# T$ Q+ e. e# v
  105.     * @return string 图片 hash 值,失败则是 false   $ V  \  O, Q# L' U
  106.     * */    4 j4 h8 p# r' D! @
  107.    public static function hashImageFile($filePath){    ; \5 g% |: O9 s6 d! V: n; \/ ^- l9 h2 q
  108.        $src = self::createImage($filePath);   
    6 k5 R# ^2 x1 @4 u8 j
  109.        $hashStr = self::hashImage($src);   
    / w2 W- L0 C- A# R% X8 v7 O
  110.        imagedestroy($src);   
    ' \& C# C- M+ {
  111.     * j  ~1 K% H/ t6 o
  112.        return $hashStr;    0 Y: k" e; u+ q# G; U
  113.    }    7 ?# w; n* @/ v( _5 A  l
  114.     9 r# |0 |! c" x' _, ~0 v" I
  115.    
    ; J  Y3 y$ @! [
  116.    /**比较两个 hash 值,是不是相似   
    # ~4 P! B( ~, {! ]! W% m
  117.     * @param string $aHash A图片的 hash 值     ]2 e$ N) c4 g9 U, D9 A
  118.     * @param string $bHash B图片的 hash 值   
    # o8 W1 w/ n8 h* J% V6 ?
  119.     * @return bool 当图片相似则传递 true,否则是 false   
    % T/ @) K/ I$ i* \
  120.     * */   
    # C* o& w7 {+ q
  121.    public static function isHashSimilar($aHash, $bHash){   
    4 \& N: {, a8 T- _5 H9 D+ o9 v- ?
  122.        $aL = strlen($aHash); $bL = strlen($bHash);    ; O* s6 x, L2 v% {4 s* S/ C. ^
  123.        if ($aL !== $bL){ return false; }   
    5 ^9 b5 X5 H8 K8 f! z  x/ E
  124.     ; p) J7 j/ z( P  Y( p0 M& V3 l- Z
  125.        /*计算容许落差的数量*/   
    * f% r$ @8 b1 d5 G5 S
  126.        $allowGap = $aL*(100-self::$similarity)/100;   
    ' ]1 W8 N  r) s2 J
  127.    
    # `7 {2 h3 f; N) }* N; X& q
  128.        /*计算两个 hash 值的汉明距离*/   
    0 R8 S( K# ]! ], |) i
  129.        $distance = 0;    ( w% X5 C/ c4 T2 R. Z/ g
  130.        for($i=0; $i<$aL; $i++){    ( P5 J4 v7 e( l
  131.            if ($aHash{$i} !== $bHash{$i}){ $distance++; }   
    1 `7 U, H# M( v
  132.        }   
    % y0 Z; {, ^* i9 g6 J
  133.    
    . g' ^1 S) B% A/ W4 ?9 x5 L1 [5 g
  134.        return ($distance<=$allowGap) ? true : false;    # U' i( O! x6 H7 [! J
  135.    }    3 P7 w! e$ ]3 t$ v
  136.    
    2 [4 l# C  z; T* r2 t
  137.     9 c- P5 L! ?' M8 M' t# c$ ?
  138.    /**比较两个图片文件,是不是相似   % B6 v1 a: X$ E
  139.     * @param string $aHash A图片的路径   4 v" x/ f+ n5 }1 N
  140.     * @param string $bHash B图片的路径   . T2 G, V' j6 R  y
  141.     * @return bool 当图片相似则传递 true,否则是 false   
    & A; z0 r) E/ q2 l+ d5 K: K! ^# O/ q  I
  142.     * */   
    0 L% H+ A- ]( E# u3 o
  143.    public static function isImageFileSimilar($aPath, $bPath){    % A: q  @: G2 S$ Y
  144.        $aHash = ImageHash::hashImageFile($aPath);   
      C) l. {# ?3 v9 @
  145.        $bHash = ImageHash::hashImageFile($bPath);   
    & M/ P( i9 O& z0 B4 W- v
  146.        return ImageHash::isHashSimilar($aHash, $bHash);   
    5 ^& x0 `! {( Q7 s  h2 q
  147.    }   
    " g) `4 x( {- h( T( v+ v3 _& u
  148.    
    ; `; H. I2 v5 R% m& W2 t1 [
  149. }! U- c+ t* p- y: H) ^
复制代码
; H% o, ^3 }5 M; l$ k, o- o
: s0 A  I& e2 w3 {1 g
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2024-12-23 07:47 , Processed in 0.110455 second(s), 21 queries .

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