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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2018-7-7 23:06:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
摘要: 本文讲的是分享一个PHP简易的图片相似度比较类, 由于相似图片搜索的php实现的 API 不怎么符合我的用途,所以我重新定义 API 的架构,改写成比较简单的函数方式,虽然还是用对象的方式包装。  代码如下 复制代码 <?php    /**   * 图
0 J( u% f; _& U: r. E
( R2 V$ O' V, \. R/ D: ~

6 X. D: ~( Y, J7 w; X, ~8 i7 Y由于相似图片搜索的php实现的 API 不怎么符合我的用途,所以我重新定义 API 的架构,改写成比较简单的函数方式,虽然还是用对象的方式包装。
9 B6 B6 c2 ]5 F) s& q7 P
  1. <?php   
    8 }$ P9 \7 o% p: y
  2. /**   
    5 w5 Y6 x0 }5 E; P4 b/ M" W7 K
  3. * 图片相似度比较   4 y1 k  \' K: i( e1 i
  4. *   * I$ J. i/ Q' ?4 f% |8 u
  5. * @version     $Id: ImageHash.php 4429 2012-04-17 13:20:31Z jax [        DISCUZ_CODE_1        ]nbsp;  0 V" G, K3 _$ R+ z/ c
  6. * @author      jax.hu   4 p9 O9 E0 @. W* a& a
  7. *   
    8 T( y% [% U! a
  8. * <code>   3 w7 N* f; ]6 i' J( z: x0 n  g
  9. *  //Sample_1   
      @  s$ s( }- \2 Y  S
  10. *  $aHash = ImageHash::hashImageFile('wsz.11.jpg');   % `* e* r" E$ I
  11. *  $bHash = ImageHash::hashImageFile('wsz.12.jpg');   ' z- r% _( Q! L2 l+ k# ~
  12. *  var_dump(ImageHash::isHashSimilar($aHash, $bHash));   
    / c9 {, E  l3 n, e5 C9 a
  13. *   3 X' l% a" Q0 ~
  14. *  //Sample_2   7 X4 b- C6 E# v! Q5 R3 D  h/ c
  15. *  var_dump(ImageHash::isImageFileSimilar('wsz.11.jpg', 'wsz.12.jpg'));   
    9 [+ d4 H! J& P) ~7 s! Z
  16. * </code>   
    : F3 v/ @! l, o7 m2 h
  17. */    ( V0 I8 u/ w0 A/ y! X2 h: Z! w  d% f
  18.     1 t# |1 Q. a) n, n8 F, F
  19. class ImageHash {   
    7 J! @& G" P" y
  20.     8 y7 k4 a. K$ d7 S% F% X& X" l6 @
  21.    /**取样倍率 1~10   4 q2 T1 l- m& g, p* U7 B
  22.     * @access public   
    " M. k5 H$ k( a" P  B! X; h
  23.     * @staticvar int   ! ?, N+ @- F5 B6 k
  24.     * */   
    ( c9 n' }" D5 M6 F6 T
  25.    public static $rate = 2;    ) A6 M; d: B% j4 V
  26.     9 z8 e( _  @1 s& f+ K  Q
  27.    /**相似度允许值 0~64   . ]# T: |: t' q6 e& ?5 T
  28.     * @access public   * t/ p- c1 `/ r7 I. p* Z9 x* \
  29.     * @staticvar int   ! p. e  E$ D9 L8 v/ T+ g# f' n* h
  30.     * */   
    $ r, M4 u$ C) E7 P. c: {: O
  31.    public static $similarity = 80;   
    " u% Q( O/ `  d3 |* }7 S) C
  32.    
    ' k2 ?2 |$ u0 y. f0 x, r  Y
  33.    /**图片类型对应的开启函数   
    2 E' ?0 F& y, e& e0 X* {0 J9 z  h% c
  34.     * @access private   
    . u4 u- N, p' o& ]- Q; H/ y
  35.     * @staticvar string   * {% a/ u& c# `' v/ H
  36.     * */   
    5 w$ @1 ]5 \; F' d$ x2 _
  37.    private static $_createFunc = array(    3 L% P4 N. t4 {) C' j* S' J
  38.        IMAGETYPE_GIF   =>'imageCreateFromGIF',   
    ! k3 `8 E% Q8 e+ C- @6 b- R8 `
  39.        IMAGETYPE_JPEG  =>'imageCreateFromJPEG',    ( C/ g7 t1 Q( Y- M+ @; b9 S
  40.        IMAGETYPE_PNG   =>'imageCreateFromPNG',   
    * M; I, W) `" Q& j& }. X
  41.        IMAGETYPE_BMP   =>'imageCreateFromBMP',   
    . w7 x6 j* P; p* W6 ]- t" Q; p
  42.        IMAGETYPE_WBMP  =>'imageCreateFromWBMP',   
    , B/ W/ h) L6 e# ^+ N
  43.        IMAGETYPE_XBM   =>'imageCreateFromXBM',   
      P/ A$ H7 Z/ l' v' c, U
  44.    );   
    ' \3 m% r/ }, g5 l! R: u& x( {* G1 n
  45.    
    , h% ?( p& ^' R
  46.     9 j$ ^& ]. o( b/ @0 w3 I
  47.    /**从文件建立图片   ( X- h" l: }( H" {4 X' o; o/ d0 J
  48.     * @param string $filePath 文件地址路径   
    ' B4 t+ i3 z  x$ |) d
  49.     * @return resource 当成功开启图片则传递图片 resource ID,失败则是 false   - Y3 H; _9 w* p  S
  50.     * */    . b. @- t; ^, r' C
  51.    public static function createImage($filePath){   
    ) ^5 S' O; M7 {/ Z
  52.        if(!file_exists($filePath)){ return false; }   
    1 o9 i) j" E, i* S* X! X. ?
  53.     ( f" L' H1 e% G. ^0 j6 b
  54.        /*判断文件类型是否可以开启*/    . t6 l9 i! Y; b. q4 N$ q7 E
  55.        $type = exif_imagetype($filePath);   
      _2 j* |5 c' l/ f4 {' Y
  56.        if(!array_key_exists($type,self::$_createFunc)){ return false; }   
    . N; o- W( s7 L8 B, \: Z3 a* P
  57.    
    1 u+ o$ Z6 k8 n" w7 H* X
  58.        $func = self::$_createFunc[$type];    , g6 H$ V9 V1 p4 D3 [; W) a. o3 u# x
  59.        if(!function_exists($func)){ return false; }   
    , _/ ?, c4 @# T: R) {
  60.    
    3 ]$ j7 y3 G+ A1 w3 |
  61.        return $func($filePath);    & r9 p3 A6 T: V  f: b- J3 i
  62.    }    6 y, z: ?. e- v; u; m
  63.     . \/ u, q2 U4 L  l1 L. M
  64.     9 p' ?" x8 l1 d9 U( K- p4 V+ P0 q
  65.    /**hash 图片   
    6 t2 Q6 O7 U/ S6 {3 C
  66.     * @param resource $src 图片 resource ID   
    - ^2 `: y7 U! m7 I8 M$ A# Q! n3 j
  67.     * @return string 图片 hash 值,失败则是 false   
    ( p1 g  m! N- l1 r4 j6 _# T; X& ^
  68.     * */    1 t( ~. _/ \) c, k# I% p9 O
  69.    public static function hashImage($src){    ; E7 b8 s/ u; v- Y* U+ @
  70.        if(!$src){ return false; }   
    ! z) s! L" [) T% v1 I" M- A2 C
  71.     $ B7 H9 D; T& p1 [( S. J
  72.        /*缩小图片尺寸*/    7 q3 ^  j2 b' U6 Z
  73.        $delta = 8 * self::$rate;   
    5 r+ J4 p# F+ U9 Y  g
  74.        $img = imageCreateTrueColor($delta,$delta);   
    ; P3 C9 U2 I/ h5 i
  75.        imageCopyResized($img,$src, 0,0,0,0, $delta,$delta,imagesX($src),imagesY($src));   
    3 {' I4 ?& n& _# }1 a" r2 n8 g
  76.    
    , U/ G5 i) ^# i) T1 ]
  77.        /*计算图片灰阶值*/    . L- U2 T& A- n  {3 F6 a
  78.        $grayArray = array();   
    , p; l# @: G3 L( [& x. g7 ~, ~5 U
  79.        for ($y=0; $y<$delta; $y++){   
    9 V; U# W$ d( X) ~7 d. w, e
  80.            for ($x=0; $x<$delta; $x++){    ' F6 Y7 ^2 w- V
  81.                $rgb = imagecolorat($img,$x,$y);   
    + E. g- |# C) x' y- z! U. U0 ~& [: f
  82.                $col = imagecolorsforindex($img, $rgb);   
    % _; z5 X. C+ ?0 y( _
  83.                $gray = intval(($col['red']+$col['green']+$col['blue'])/3)& 0xFF;    $ D  y: m% k: V3 i; z. a3 }
  84.     3 Y( I( d  R* }+ J( y8 h
  85.                $grayArray[] = $gray;    . i0 d$ \( o6 [( @/ ?
  86.            }    , |' A5 V: M! ^
  87.        }   
    & T. w" Z- r" Q' X8 A/ Y
  88.        imagedestroy($img);   
    : R5 M4 {- I+ v- r8 ]
  89.    
    0 |8 m6 P$ v" @5 s8 g5 N/ M' \
  90.        /*计算所有像素的灰阶平均值*/   
    % C' A  |  b- t$ G: |
  91.        $average = array_sum($grayArray)/count($grayArray);   
    - M0 }: M9 R7 p5 R' Q6 Q: f  d) P: A
  92.     " x) }# m$ F: C4 e0 e5 q% }7 C. R
  93.        /*计算 hash 值*/   
    ! q! `! z* A7 G, z7 y$ |
  94.        $hashStr = '';    : c4 K6 [& h. m4 Y
  95.        foreach ($grayArray as $gray){    0 X5 F9 r2 |- {" F: B1 u+ C6 C
  96.            $hashStr .= ($gray>=$average) ? '1' : '0';   
    ) {' q: n9 A" J$ m7 }4 X4 R0 v
  97.        }    * f/ l' q% x2 _2 z+ Z2 b
  98.     1 E0 z1 ]0 N, g! T( T# ~
  99.        return $hashStr;    ' G# ^: t* X+ L. {0 u
  100.    }    ( S+ N' z# A  C% P$ m
  101.     " X3 f* i* q! d; }0 r0 L/ K
  102.     4 m- K) N; Z& j* B; |  c
  103.    /**hash 图片文件   
    1 L. x6 e* E1 {( s
  104.     * @param string $filePath 文件地址路径   0 m. I; D! M* A- E
  105.     * @return string 图片 hash 值,失败则是 false   
    3 d. G& B; V7 E4 I  S% s( i
  106.     * */    8 Z1 U: n( ^( J. k2 l4 }
  107.    public static function hashImageFile($filePath){    " c2 p4 n# M: y" s" E0 H5 b
  108.        $src = self::createImage($filePath);   
    6 q" n) E  @0 S
  109.        $hashStr = self::hashImage($src);    # W" e" G' o0 v7 h4 m. S; K
  110.        imagedestroy($src);   
      `3 A8 n" W: e: z1 h
  111.    
    3 B3 q" l: D+ f8 j% d4 T
  112.        return $hashStr;   
    7 p2 N% V- k: }/ B1 `2 \/ M2 o
  113.    }    8 a+ W5 W  k0 ^; K
  114.    
    % G$ {8 d  E! W; {* F
  115.    
    : E2 f. l4 C3 M( L7 ~  b! i# U7 p
  116.    /**比较两个 hash 值,是不是相似   , N- b- d$ N9 t9 v1 s2 g$ Q1 V
  117.     * @param string $aHash A图片的 hash 值   
    / `% R- L% m- ~. j/ V( }
  118.     * @param string $bHash B图片的 hash 值   
    ) s3 T: k, K( k
  119.     * @return bool 当图片相似则传递 true,否则是 false   . V7 [+ X+ O: N0 Z
  120.     * */   
    ; S* Z$ j1 \, }- t! S
  121.    public static function isHashSimilar($aHash, $bHash){    " I0 L7 B6 x# ]
  122.        $aL = strlen($aHash); $bL = strlen($bHash);   
    6 f0 s; ]1 V- D: Q
  123.        if ($aL !== $bL){ return false; }    . k( a( z+ |- W' a' {
  124.     $ G2 l* H7 a& k
  125.        /*计算容许落差的数量*/   
    - O& m3 w. e+ M
  126.        $allowGap = $aL*(100-self::$similarity)/100;   
    ! J3 ?/ Q. y) ^
  127.    
    ) Q, f/ s$ N3 ]5 B' L, x0 a
  128.        /*计算两个 hash 值的汉明距离*/    8 w2 u% G' v2 e: I
  129.        $distance = 0;   
    3 y6 j& y. J, M9 A3 N
  130.        for($i=0; $i<$aL; $i++){    1 l- p4 `+ ^6 G. h) Q0 W& @7 C
  131.            if ($aHash{$i} !== $bHash{$i}){ $distance++; }    % f; m5 _1 T( t% n7 j) h- _7 N$ d
  132.        }    . O! w9 B5 |1 A: H$ e: v& N4 P
  133.     : V% x7 k# B0 ]# w. R3 u, a* N
  134.        return ($distance<=$allowGap) ? true : false;   
    8 J$ w( K' T' Y1 i  m
  135.    }   
    ( Q# N- O1 C6 d( a& h6 x
  136.     8 N0 U( ?" m$ V7 N, O; `1 {
  137.     8 R* `3 V+ |7 o8 f/ H# w
  138.    /**比较两个图片文件,是不是相似   
    1 i/ K2 _9 E4 ?" p4 _
  139.     * @param string $aHash A图片的路径   
    * a" x1 R* t4 K8 Z* F9 z
  140.     * @param string $bHash B图片的路径     h. z  Z5 Z+ A1 [8 [0 X. i
  141.     * @return bool 当图片相似则传递 true,否则是 false   
    0 H; }, _9 ~$ Y' R3 {
  142.     * */    ; s4 m5 c: ~4 r' N
  143.    public static function isImageFileSimilar($aPath, $bPath){    : _: Z4 `4 ?" C$ p9 U9 z$ P
  144.        $aHash = ImageHash::hashImageFile($aPath);   
    ; B! ~. A+ ~  l4 B1 E& k
  145.        $bHash = ImageHash::hashImageFile($bPath);   
    7 _! b. Q; z% u9 _/ p0 F8 j
  146.        return ImageHash::isHashSimilar($aHash, $bHash);    6 h3 E' W) l# @
  147.    }    5 q" f: }. @1 o- H
  148.     " R4 Z' q8 _" ~
  149. }( r6 D8 ^) z6 I$ G6 @& Z* J! `( f$ m
复制代码
# i/ K4 Q% C9 t* \+ `: d
; Y! i, h' Q' o5 n4 ]
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-3-16 18:41 , Processed in 0.056619 second(s), 19 queries .

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