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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2018-7-7 23:06:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
摘要: 本文讲的是分享一个PHP简易的图片相似度比较类, 由于相似图片搜索的php实现的 API 不怎么符合我的用途,所以我重新定义 API 的架构,改写成比较简单的函数方式,虽然还是用对象的方式包装。  代码如下 复制代码 <?php    /**   * 图5 d2 a2 y# e4 B' f3 T. O: k$ }
: }5 t& H3 n0 N0 J2 ~* X

- {$ |$ }- O& `  G4 o1 ?' r: G由于相似图片搜索的php实现的 API 不怎么符合我的用途,所以我重新定义 API 的架构,改写成比较简单的函数方式,虽然还是用对象的方式包装。

! d0 {$ |# a+ x7 X3 F
  1. <?php   
    ' O2 z  y% x9 w8 ~- b% y, ^" H7 @, r; i
  2. /**     y6 o! @5 ^: e, W3 S4 y& G, L- j4 H
  3. * 图片相似度比较   
      Z  W9 m' Q. e
  4. *   : b" z0 k& c+ T- z, j4 v
  5. * @version     $Id: ImageHash.php 4429 2012-04-17 13:20:31Z jax [        DISCUZ_CODE_1        ]nbsp;  ' r2 t8 o+ a* l& L
  6. * @author      jax.hu   
    / {4 v% D. z, A; N3 _
  7. *   : L$ G9 ~9 i# K* T$ ]& i1 \( Q
  8. * <code>   
    " k' V& @* @4 c
  9. *  //Sample_1   0 T6 M- D& v* \- ~) p7 V/ @% G
  10. *  $aHash = ImageHash::hashImageFile('wsz.11.jpg');   + m! w# N+ h- |# Q; `! g
  11. *  $bHash = ImageHash::hashImageFile('wsz.12.jpg');   
    ; l  C* o; I3 x2 q0 }* j
  12. *  var_dump(ImageHash::isHashSimilar($aHash, $bHash));   2 P' O6 ^% [  ^" |/ p9 p! [! T
  13. *   
    ; u' l/ u4 T9 o0 f+ m
  14. *  //Sample_2   
    * I( R/ j( I: P4 a4 Q  y
  15. *  var_dump(ImageHash::isImageFileSimilar('wsz.11.jpg', 'wsz.12.jpg'));   " o" r# m3 B; t8 c& O! z# A
  16. * </code>   : b0 A" j1 K' [- v& O9 Q
  17. */      b* a' ~2 c( U, C" [, N0 n
  18.     " I8 r( Y3 o) Y  r6 H$ p2 o' T) j
  19. class ImageHash {   
    ( Z1 W9 `2 r/ N) i$ p$ _
  20.     : w, C6 _: y, y8 z/ T7 s
  21.    /**取样倍率 1~10   
    0 p# O) \! W% q8 M2 ~
  22.     * @access public   9 q# S8 X6 r: }/ }
  23.     * @staticvar int   
    - m5 ]& e% o# h  K/ ?, m! C
  24.     * */      G, a% j# G( I7 L! P! K8 K! c7 }
  25.    public static $rate = 2;    5 H2 J- h" g8 x" |  ?' G6 W# v% w1 J
  26.     9 b+ r. _% h0 Z$ i, l  T
  27.    /**相似度允许值 0~64   % q9 I* }2 r+ N; j! t$ ?( ]
  28.     * @access public   ( A9 E* s2 k* e, ?+ n- j9 @
  29.     * @staticvar int   
    # S* T+ v/ @2 s5 ?% N
  30.     * */    / L4 ]  t2 W# K6 ?. r9 f& U' S6 O
  31.    public static $similarity = 80;   
    # J% k, h: n3 ^8 Z) X9 W
  32.     ! j& F$ q$ h& a3 [- a+ n  m, J
  33.    /**图片类型对应的开启函数   
    1 C7 t5 @. Z: h1 @
  34.     * @access private   
    1 U" a: Y9 B, N9 }& S5 N, F4 J
  35.     * @staticvar string   - d8 |1 |* B% P5 p4 [* {; N
  36.     * */   
    . i& l* b: z! q' G9 w9 [9 A" @( i
  37.    private static $_createFunc = array(   
    0 ]" ?( T  `8 u# O
  38.        IMAGETYPE_GIF   =>'imageCreateFromGIF',   
    ( @! w. q  y; L! g" W' G% U/ G
  39.        IMAGETYPE_JPEG  =>'imageCreateFromJPEG',    % z$ O$ U$ H- s! Z
  40.        IMAGETYPE_PNG   =>'imageCreateFromPNG',   
    / f" t$ Y: {% Z5 t
  41.        IMAGETYPE_BMP   =>'imageCreateFromBMP',    1 g! p+ z% l6 H6 R: V$ [+ @/ @2 X) G
  42.        IMAGETYPE_WBMP  =>'imageCreateFromWBMP',   
    ( }5 Y; ~) K, Y& {
  43.        IMAGETYPE_XBM   =>'imageCreateFromXBM',    2 q( I: C* |  e6 q2 V" F( P' \
  44.    );   
    ( O0 O' I5 n  v* d# K, B
  45.     5 i/ ?+ M0 \3 w: d
  46.     8 |- O9 u7 n, H
  47.    /**从文件建立图片   
    ( s& G6 X7 T7 A
  48.     * @param string $filePath 文件地址路径   7 v& R7 a9 Y9 \7 x) n
  49.     * @return resource 当成功开启图片则传递图片 resource ID,失败则是 false   
    ' |; v7 i3 C: I# p2 w; Q3 D) y4 l; L
  50.     * */   
    ' C4 m2 T3 P9 X) R1 v/ C5 v
  51.    public static function createImage($filePath){   
    - G8 Y& Z: l- H" u' _
  52.        if(!file_exists($filePath)){ return false; }   
    $ K2 ~* D) o, w
  53.    
    . K7 I) Z0 x2 p1 W+ O
  54.        /*判断文件类型是否可以开启*/    $ M+ A) ^! N' O. W8 ]
  55.        $type = exif_imagetype($filePath);   
      w- X' v; q0 N* ?
  56.        if(!array_key_exists($type,self::$_createFunc)){ return false; }   
    ) L7 q. Q* c! g7 o' d. O
  57.    
    4 T+ C, J$ [6 B1 W
  58.        $func = self::$_createFunc[$type];   
    6 ~# l; a! I& d6 X# _, a. G' F/ T
  59.        if(!function_exists($func)){ return false; }   
    * h. V; f) {: u
  60.    
    , i: _7 i1 K( Y
  61.        return $func($filePath);    3 u- l: r/ D  b! M6 J; P
  62.    }    9 }) d/ k- q, A) X
  63.    
    + a& m: E+ ?' N' o2 q! v- _( |' _
  64.     4 j, t/ i' Z& E5 [, Y( [
  65.    /**hash 图片   
    ! g; n4 N3 r  j  z2 M
  66.     * @param resource $src 图片 resource ID   1 T+ B0 {4 D4 }3 U/ M
  67.     * @return string 图片 hash 值,失败则是 false   + r5 j8 J3 U7 D9 [/ D6 D" J
  68.     * */    ) W8 G0 l* h8 g
  69.    public static function hashImage($src){    % q' i! O' D" E
  70.        if(!$src){ return false; }   
    3 ^6 B) p6 L$ ~$ g# A
  71.     % B( W9 A+ z# o; v
  72.        /*缩小图片尺寸*/   
    % [$ u2 U& n/ @4 e  p2 x
  73.        $delta = 8 * self::$rate;    ( x# C# d5 T9 t/ x4 @
  74.        $img = imageCreateTrueColor($delta,$delta);   
    . M2 b9 k6 z6 s9 o& `
  75.        imageCopyResized($img,$src, 0,0,0,0, $delta,$delta,imagesX($src),imagesY($src));   
      u. J& }) D' ~; I' `; i
  76.    
    ! S! k6 t" J1 I3 {. R
  77.        /*计算图片灰阶值*/   
      t5 g" k9 c: g9 j" p
  78.        $grayArray = array();   
    0 h* a! ?- o  _1 \  G, j$ A* p
  79.        for ($y=0; $y<$delta; $y++){    7 ?0 L% S9 d; Y! L* Z9 _1 [! Y
  80.            for ($x=0; $x<$delta; $x++){    , l; M, C5 ^1 k' y  K
  81.                $rgb = imagecolorat($img,$x,$y);    # \8 a* l" A) @9 ?  D) b" E. f
  82.                $col = imagecolorsforindex($img, $rgb);    " z: v2 v* \. Z" C3 N
  83.                $gray = intval(($col['red']+$col['green']+$col['blue'])/3)& 0xFF;   
    - o, \/ w2 c& e" Q/ Z
  84.    
    2 ~" S* d: C$ B7 x" N$ v
  85.                $grayArray[] = $gray;    ' h  e+ h3 i8 i5 R
  86.            }    - D/ Y" Q  s4 `
  87.        }   
    # l. V3 r+ e% z3 f* P. }& Q
  88.        imagedestroy($img);    9 l0 @5 Q8 Q: x4 m! v6 Q
  89.     ' o) C7 F( s) J& b2 z  G1 ]
  90.        /*计算所有像素的灰阶平均值*/   
      c- M& s, M! e' @- Z
  91.        $average = array_sum($grayArray)/count($grayArray);    $ X7 r( h1 t- ^- }7 ~9 G
  92.    
    ; X* y( n0 j0 ]7 t
  93.        /*计算 hash 值*/   
    . Q4 Z! |5 W2 P0 w  e  o" r$ S8 Q
  94.        $hashStr = '';    / J9 D1 |9 e, f9 r
  95.        foreach ($grayArray as $gray){    ; D  j* ~# p% J
  96.            $hashStr .= ($gray>=$average) ? '1' : '0';    2 u- I* n* D7 ?( V& _
  97.        }    2 V% L; W9 W/ B- A" Q
  98.       r. G4 g' R% z$ k
  99.        return $hashStr;   
    / P2 B4 ]0 p% I6 D8 V. e( H' a6 e
  100.    }   
    % p3 H1 Z0 o2 A4 e/ \
  101.     8 Y5 \* b& V) k* G' }6 e" H
  102.    
    / ~* W. X2 n/ ?
  103.    /**hash 图片文件   
    ; L4 b$ N& P$ l$ u* I; p  W& Z
  104.     * @param string $filePath 文件地址路径   
    7 n6 y+ j9 J7 O! C& b2 P
  105.     * @return string 图片 hash 值,失败则是 false   
    9 ^  w8 ]! F2 z" K- X
  106.     * */   
    . O+ W9 T+ K; l( S" C
  107.    public static function hashImageFile($filePath){    % n% E0 J& o$ z& O  S
  108.        $src = self::createImage($filePath);    6 L* _" w" S: G! o" |
  109.        $hashStr = self::hashImage($src);   
    . a* O9 L- G! Q3 e0 J4 P
  110.        imagedestroy($src);    $ X" u4 B( \( C" t4 b4 {7 [
  111.     4 M% O. E8 |4 j
  112.        return $hashStr;   
    1 {% O. J9 y2 u' @5 b8 r2 n1 R
  113.    }    . L/ X+ F  k& N4 E3 V" k. s" w$ u
  114.     + J4 ]+ z, ~/ R2 R6 a
  115.    
    ) h. x. R5 G% x8 C. f' v( b1 ]+ w- ]
  116.    /**比较两个 hash 值,是不是相似   2 [. c! y+ l6 ^- z( D$ V  U  j( _
  117.     * @param string $aHash A图片的 hash 值   
    8 D9 o% ]$ q+ n  \0 A1 u( D8 {$ s
  118.     * @param string $bHash B图片的 hash 值   
    1 u9 z. D. f5 Y
  119.     * @return bool 当图片相似则传递 true,否则是 false   $ N! U& q  {" j: P
  120.     * */   
    , r% o- M" p4 g) w: C* N  J" v
  121.    public static function isHashSimilar($aHash, $bHash){   
    , O) c8 v: H+ r3 M4 a; j; w; _3 U
  122.        $aL = strlen($aHash); $bL = strlen($bHash);   
    9 s: M3 o1 s7 c) U
  123.        if ($aL !== $bL){ return false; }    $ z0 v3 M8 L) C& @5 L* C" J- q: S
  124.     # m+ C" K! v2 N# ]+ I) z
  125.        /*计算容许落差的数量*/    - N9 C! [+ {4 \
  126.        $allowGap = $aL*(100-self::$similarity)/100;   
    2 w6 u7 q! X0 m
  127.     4 g. c' ~2 M8 Z9 R
  128.        /*计算两个 hash 值的汉明距离*/   
    % |( j( Z7 z1 E5 s) |& I
  129.        $distance = 0;   
    $ Y7 q9 ]- r" z( `+ @
  130.        for($i=0; $i<$aL; $i++){    ' [2 W3 c$ I; ]. d
  131.            if ($aHash{$i} !== $bHash{$i}){ $distance++; }   
    ; r5 q0 a5 q9 A  U9 b7 T1 X; G
  132.        }   
    * u: x4 T, J) O
  133.     ( F! M& `' V- _( f
  134.        return ($distance<=$allowGap) ? true : false;    $ v' I2 w, h( x. I
  135.    }    ( E1 f9 {  j4 I& r. L
  136.    
    4 v# C, f$ L1 f7 E# A3 R4 ^" X" b
  137.    
    - U1 ~0 c/ K6 r8 O0 Z
  138.    /**比较两个图片文件,是不是相似   
    1 ?1 {# T* R* ]) J3 |* m
  139.     * @param string $aHash A图片的路径   7 F- O2 o) U( t7 P
  140.     * @param string $bHash B图片的路径   
    - i+ J7 V' S% B; K% J, a# n8 B1 V
  141.     * @return bool 当图片相似则传递 true,否则是 false   
    / E9 z: J9 m; ]9 t  W2 K& H
  142.     * */      r, |& A" N- ]& j. g
  143.    public static function isImageFileSimilar($aPath, $bPath){   
    9 y# `9 s- t2 s# f+ g( L3 Q
  144.        $aHash = ImageHash::hashImageFile($aPath);    5 ~) p5 r% B, {, A
  145.        $bHash = ImageHash::hashImageFile($bPath);   
    ' s% v; g8 p" q
  146.        return ImageHash::isHashSimilar($aHash, $bHash);   
    ) _" s2 _5 `1 q& s5 ~
  147.    }   
    ' J% Y8 {/ u+ K: a5 a
  148.    
    & ?( m& A& `: T9 a- P7 s3 c1 H$ ^
  149. }; q0 J  l6 |( E; a( ^
复制代码
; V5 J& v* P* S9 \
' m3 {# k! ]+ z9 Z( ]) C
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-4-30 23:30 , Processed in 0.074325 second(s), 19 queries .

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