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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2018-7-7 23:06:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
摘要: 本文讲的是分享一个PHP简易的图片相似度比较类, 由于相似图片搜索的php实现的 API 不怎么符合我的用途,所以我重新定义 API 的架构,改写成比较简单的函数方式,虽然还是用对象的方式包装。  代码如下 复制代码 <?php    /**   * 图
# d4 s# n* [2 C9 l( ]. w; B5 p& p  M; F& A, R. i- @+ z
" ]9 j  U" ^5 \1 T9 l& O; C! s
由于相似图片搜索的php实现的 API 不怎么符合我的用途,所以我重新定义 API 的架构,改写成比较简单的函数方式,虽然还是用对象的方式包装。
" D% l- d+ \; N% w
  1. <?php    # v7 u/ f! U5 O/ I/ q7 A5 [1 n
  2. /**   2 g: l9 U( v: T+ B7 S
  3. * 图片相似度比较   
    " @% l% [6 l+ v( D3 ^. i5 {
  4. *   
    0 H8 z0 I8 n3 w7 n' X' F+ ^) P
  5. * @version     $Id: ImageHash.php 4429 2012-04-17 13:20:31Z jax [        DISCUZ_CODE_1        ]nbsp;  ) ~( M* Z9 E. R' N4 C
  6. * @author      jax.hu   
    3 Z& a) ^4 Z& ]* t' E6 ]3 b
  7. *   
    0 ~* G1 i' r7 @( x8 H+ t
  8. * <code>   9 y, B6 X6 y/ l
  9. *  //Sample_1   % I3 M$ a4 T2 n8 j9 }
  10. *  $aHash = ImageHash::hashImageFile('wsz.11.jpg');   
    ' t* E* w5 g, Z6 Y" j
  11. *  $bHash = ImageHash::hashImageFile('wsz.12.jpg');   
    . e% S% x( r0 c' y7 Q# ?
  12. *  var_dump(ImageHash::isHashSimilar($aHash, $bHash));   
      N& o% W8 N# c0 e
  13. *   
    7 I% ^! b' \. U+ q
  14. *  //Sample_2   + q" t6 s5 C2 N; i
  15. *  var_dump(ImageHash::isImageFileSimilar('wsz.11.jpg', 'wsz.12.jpg'));   
    / x; j$ a& k2 D
  16. * </code>   8 E& z8 J9 H& e* c& h. T8 E$ I1 G
  17. */    , f# u0 }9 V! Z+ x7 c3 e: n$ v) s
  18.    
    3 {+ k- x; P  R+ F+ k
  19. class ImageHash {    7 Y; Y6 T0 h- E8 M6 ^  r' Q- x
  20.    
    8 e% n! ?% H4 g, I) ^! k" V
  21.    /**取样倍率 1~10   
    1 t5 r3 H& A* |& o! x' w# F  r% \# f
  22.     * @access public   $ l# G: J4 c6 e4 U  S$ _$ \
  23.     * @staticvar int   
    9 O6 ~" w! r4 l6 h5 H
  24.     * */   
    4 j* q) O; A* ]( p4 Z# m: c
  25.    public static $rate = 2;    ; _* v/ K! E% }9 u# k: Z. g5 w
  26.     ! z) N8 m; s( `8 s# Q4 v
  27.    /**相似度允许值 0~64   
    5 L; u4 K. U; J9 x+ a6 w6 S
  28.     * @access public   
    1 M( U0 ^5 x; z! o0 ?
  29.     * @staticvar int   ( i" D( R0 o9 O- m" V, a/ T
  30.     * */    9 b1 p$ @! b9 Z: I' g
  31.    public static $similarity = 80;   
    1 B& L7 ?9 T& \5 x/ s$ N
  32.    
    3 u4 [& K( c6 L* x8 P+ P, ]2 A
  33.    /**图片类型对应的开启函数   / A* |9 d- Z+ W+ m* P$ \  f4 M
  34.     * @access private   $ s% f) E+ A5 l( I$ G
  35.     * @staticvar string   5 b- J) P# G2 O
  36.     * */    8 M: o% d+ K; g: @  \: \( L& s- ~
  37.    private static $_createFunc = array(      ~3 j: ~* d+ J: b
  38.        IMAGETYPE_GIF   =>'imageCreateFromGIF',    6 Q# o+ p7 M  S9 O" {
  39.        IMAGETYPE_JPEG  =>'imageCreateFromJPEG',   
    # Q* b7 m- r. v1 Q$ e" k
  40.        IMAGETYPE_PNG   =>'imageCreateFromPNG',    ( x8 q1 K0 ]4 V. t7 {
  41.        IMAGETYPE_BMP   =>'imageCreateFromBMP',    # m, D7 ?# B- l) B2 b1 [% H
  42.        IMAGETYPE_WBMP  =>'imageCreateFromWBMP',   
    - k& E7 o; v, m7 P$ X$ \- M' T
  43.        IMAGETYPE_XBM   =>'imageCreateFromXBM',    4 W) Q, e2 Q: b, S3 y# {
  44.    );    $ V/ x6 B1 m' {/ V2 [2 g% |
  45.    
    $ Z: Z* n! E% u& s. x! T
  46.    
    0 u9 i  d8 w7 F4 Y+ l- B
  47.    /**从文件建立图片   
    3 Q& G2 C7 Y$ V, q5 S, w1 R1 q/ t
  48.     * @param string $filePath 文件地址路径   % k& [) ~' U8 p& n& V1 d* ?) `
  49.     * @return resource 当成功开启图片则传递图片 resource ID,失败则是 false   " H3 w8 z! J* D9 I* z7 F4 X
  50.     * */   
    3 Q" ~; Z' g) f' M3 l
  51.    public static function createImage($filePath){    0 y6 M  c, y' x' U& K' r0 b
  52.        if(!file_exists($filePath)){ return false; }    # S% i4 R/ F4 ]+ ~; ^( x
  53.     , ?$ |4 _+ I: A4 e
  54.        /*判断文件类型是否可以开启*/   
    " A* ?8 O+ @& G2 F# E
  55.        $type = exif_imagetype($filePath);   
    / v! [1 W: F. a3 ~
  56.        if(!array_key_exists($type,self::$_createFunc)){ return false; }    & Y4 ]. p' I8 N7 x  h) H
  57.     ' {( }  }1 c* e
  58.        $func = self::$_createFunc[$type];   
    * B4 P$ I, Z- h8 g2 L0 q
  59.        if(!function_exists($func)){ return false; }    6 f/ U2 J8 f4 t8 x5 ^# O
  60.    
    # K! {, t% O, N0 W
  61.        return $func($filePath);   
      W! l" Q+ }* M" T0 W+ W$ n
  62.    }    . P, i- n! V$ {( F( o/ x/ P
  63.     - R" G2 s8 e6 Z5 h2 C5 B( [" B/ Q
  64.    
    ) m' U) A4 n& ]5 W; l
  65.    /**hash 图片   # A/ r( Y3 ?% n
  66.     * @param resource $src 图片 resource ID   
    0 y  D7 ~/ L) F: I
  67.     * @return string 图片 hash 值,失败则是 false   - [& U6 n# N8 _- ]# Y, n' ~
  68.     * */    8 i8 o" \" F' B& {7 H; l% `4 g
  69.    public static function hashImage($src){    $ M) d: H5 D- b* h) \
  70.        if(!$src){ return false; }   
    + p" e- Q. l. j; q
  71.    
    ; P) r9 m9 ]8 q+ N$ S' `+ O. W! p
  72.        /*缩小图片尺寸*/    2 }9 k0 p5 d. Y  {4 y* p
  73.        $delta = 8 * self::$rate;   
    - z2 M* P& ?4 N+ b# D# P( h
  74.        $img = imageCreateTrueColor($delta,$delta);   
    ; W# }  B; i& e; b1 Y
  75.        imageCopyResized($img,$src, 0,0,0,0, $delta,$delta,imagesX($src),imagesY($src));    : ^8 h, S  B4 W/ a1 Q* s
  76.    
    4 M1 _) v4 Q: H' Y& B- P2 p3 @
  77.        /*计算图片灰阶值*/    $ |5 G! n. w9 q' B6 x3 x
  78.        $grayArray = array();    2 K) m) m# m: h) `
  79.        for ($y=0; $y<$delta; $y++){    2 ~' a, _4 F7 H/ h
  80.            for ($x=0; $x<$delta; $x++){    - Z% w, E0 l" x( L0 V
  81.                $rgb = imagecolorat($img,$x,$y);   
    - A% `+ T( m" U3 G/ N1 O
  82.                $col = imagecolorsforindex($img, $rgb);    & n7 Y9 e7 {8 L& r* [1 p
  83.                $gray = intval(($col['red']+$col['green']+$col['blue'])/3)& 0xFF;   
    1 |: S5 W, M. j* K+ R5 N) Q( l9 m6 e
  84.    
      Q8 |) ^8 w4 T8 q
  85.                $grayArray[] = $gray;    & B1 K* r- e- D% l/ `
  86.            }   
    - u3 o# `$ f, u( ?( c
  87.        }   
    + r( n% s; m! R" |: b
  88.        imagedestroy($img);   
    . l* n! l# ]5 q* M
  89.    
    - R1 j3 i! c  v9 W0 {! U+ c2 w! w
  90.        /*计算所有像素的灰阶平均值*/      q0 i! k; `: X% ~% n3 D& W( s
  91.        $average = array_sum($grayArray)/count($grayArray);   
    7 o1 P* l7 x9 ?* C  k2 Y
  92.     . l. x, n5 O7 r' B/ G
  93.        /*计算 hash 值*/    $ C/ Z& P& N, }( Z1 }
  94.        $hashStr = '';   
    7 G3 e  h; V/ s0 n; |, f
  95.        foreach ($grayArray as $gray){   
    # w  k  O8 F3 N: q4 k% p
  96.            $hashStr .= ($gray>=$average) ? '1' : '0';   
    - I" H$ s. V7 t, m
  97.        }    5 F7 \+ y) K  W1 p
  98.    
    5 b" A# F  X3 [- d3 f
  99.        return $hashStr;   
    6 \! O* V3 i; U  S$ Y# ^  L
  100.    }   
    / n5 m" }+ k" E
  101.     8 G- x# c' l8 G
  102.    
    8 P  A9 R" l8 t! L( a- I+ n
  103.    /**hash 图片文件   
    5 c) [# h* }, R3 V' G8 d5 q
  104.     * @param string $filePath 文件地址路径   2 k  K9 m. {0 }
  105.     * @return string 图片 hash 值,失败则是 false   
    4 o* g6 @  K& {4 ^# E
  106.     * */   
    - Q: Z8 l. ~6 J" y% @( q8 j
  107.    public static function hashImageFile($filePath){    - L) z; k' U! r
  108.        $src = self::createImage($filePath);    + b0 F9 I: g1 W: z% `7 ^
  109.        $hashStr = self::hashImage($src);   
    & u; k" R7 y5 D" n- ~/ Z
  110.        imagedestroy($src);    6 a4 v/ a+ l, T* ^# j
  111.    
    2 {8 W' H9 Q9 ?9 O3 G/ U( k  ?7 _
  112.        return $hashStr;      C8 {: W9 [/ z& x* o5 W0 c
  113.    }   
    1 p" t1 U0 I% Z; Y( I9 A1 i
  114.     ! T8 Z* k! q1 v
  115.    
    1 `* `3 j) ]8 X* A- I
  116.    /**比较两个 hash 值,是不是相似   . t$ b; n0 c; {  r' ?; G
  117.     * @param string $aHash A图片的 hash 值   ( D# L- m2 \: \! S+ e! H, w
  118.     * @param string $bHash B图片的 hash 值   
    0 B6 y" t9 s: C8 e. ^; G9 E$ ^4 ^+ O
  119.     * @return bool 当图片相似则传递 true,否则是 false   
    4 P0 D& w) V6 H1 J* k" S
  120.     * */    " s( n! K4 u- i: {! B
  121.    public static function isHashSimilar($aHash, $bHash){   
    4 D2 \. B$ k3 n
  122.        $aL = strlen($aHash); $bL = strlen($bHash);    9 L1 U  t) W2 T8 t) ?  a
  123.        if ($aL !== $bL){ return false; }   
    9 l# v) A$ X& P; `. X
  124.    
    ( R+ Z7 ^0 P5 s$ k
  125.        /*计算容许落差的数量*/    6 W1 n& M, I. J& m5 X1 a9 s  o
  126.        $allowGap = $aL*(100-self::$similarity)/100;    & c# i# R/ u' \* K
  127.     * r: W# |8 V, u' ?- a- G2 t
  128.        /*计算两个 hash 值的汉明距离*/    : V# ?, h5 t7 ~
  129.        $distance = 0;    ; [* S* W& R) s4 U  {
  130.        for($i=0; $i<$aL; $i++){    / f6 K0 @0 V8 Q3 M! z
  131.            if ($aHash{$i} !== $bHash{$i}){ $distance++; }    6 t9 n. z5 `. D
  132.        }   
    # S6 T# a0 ^" p) j/ Y
  133.     * ?+ F  A" w/ g1 h! J: r
  134.        return ($distance<=$allowGap) ? true : false;    / x( h  X3 s( q  K9 k
  135.    }    & ?8 K- b8 o. q! j2 t
  136.    
    0 l2 n% r# Z! K
  137.    
    3 G0 j( A( i3 x; T( G" X( S6 R
  138.    /**比较两个图片文件,是不是相似   
    3 I0 o" S+ r5 Y. Z' \* w
  139.     * @param string $aHash A图片的路径   
    / c0 }) ^# c7 f3 C0 r3 X- p& M
  140.     * @param string $bHash B图片的路径   
    9 [% h& T- h* g. [
  141.     * @return bool 当图片相似则传递 true,否则是 false   3 A8 h0 V8 k% A+ ^0 o7 K
  142.     * */    7 b* k& O& i& o( B4 d
  143.    public static function isImageFileSimilar($aPath, $bPath){    1 I0 ?. `; [) l2 D) X2 y6 ^3 @
  144.        $aHash = ImageHash::hashImageFile($aPath);    * }2 X5 ]9 ?; C! {/ a6 s
  145.        $bHash = ImageHash::hashImageFile($bPath);   
    ; u$ t2 _" {" A+ S/ [
  146.        return ImageHash::isHashSimilar($aHash, $bHash);    - a1 I+ a1 P# ?3 f
  147.    }    1 o1 @/ S; v9 P( d" b- g5 J  z
  148.     * `8 Y# ~" P) y+ |0 F# k+ w
  149. }9 O! i4 ^" _9 I" b1 g" X
复制代码

0 h) u* O  F; `0 |" z; b% r  D, d8 b4 O
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-1-30 15:04 , Processed in 0.054385 second(s), 19 queries .

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