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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2018-7-7 23:06:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
摘要: 本文讲的是分享一个PHP简易的图片相似度比较类, 由于相似图片搜索的php实现的 API 不怎么符合我的用途,所以我重新定义 API 的架构,改写成比较简单的函数方式,虽然还是用对象的方式包装。  代码如下 复制代码 <?php    /**   * 图
& m4 F8 h' O# |7 v8 d4 {( @4 @& F9 Z3 y
$ |# P2 G# f$ B" C2 m
由于相似图片搜索的php实现的 API 不怎么符合我的用途,所以我重新定义 API 的架构,改写成比较简单的函数方式,虽然还是用对象的方式包装。
- w6 H1 b- _  n9 @! U
  1. <?php   
    2 b  U' S% u4 ~. x0 E1 |$ ?# k
  2. /**   ! s$ x2 F% l  V. Q" |4 l
  3. * 图片相似度比较   ) i/ u6 F+ C4 w' z
  4. *   ' F$ c+ Q: r2 `
  5. * @version     $Id: ImageHash.php 4429 2012-04-17 13:20:31Z jax [        DISCUZ_CODE_1        ]nbsp;  0 T) ~" o9 {% x; {4 f& W# G2 d
  6. * @author      jax.hu   7 F* N/ U" T/ V& v5 t' r7 o
  7. *   7 [$ Q: g  Z4 Q( w( P% t
  8. * <code>   7 M  E& `" U4 O# o, K4 a  Q. r. a& b
  9. *  //Sample_1   - n4 C* e) l  A; q
  10. *  $aHash = ImageHash::hashImageFile('wsz.11.jpg');     ^2 @* m& K: K
  11. *  $bHash = ImageHash::hashImageFile('wsz.12.jpg');   * k* w0 x- l0 Y7 p$ i1 E4 E
  12. *  var_dump(ImageHash::isHashSimilar($aHash, $bHash));   ' ]+ |4 T- R, ~
  13. *   
    " b. B3 j% X0 K8 T) B
  14. *  //Sample_2   
    6 u# U+ U) n4 Y/ v: f
  15. *  var_dump(ImageHash::isImageFileSimilar('wsz.11.jpg', 'wsz.12.jpg'));   ) v; L3 _# N* d- Y
  16. * </code>   # e! t4 o8 c: Y1 p  Z6 X( d
  17. */   
    % ^0 }: ~/ [  A6 U0 z# V* E/ O8 Q
  18.     ( n, ]; Y0 D6 r' h1 y6 J
  19. class ImageHash {    - V2 k( k9 N) H3 m* e( q3 ~
  20.    
    ( Y- H& {% E/ R2 W. b. n
  21.    /**取样倍率 1~10   
    # Q) n+ D- o6 E& M& x5 y
  22.     * @access public   
    6 A- Y. v5 Y# Y/ ?
  23.     * @staticvar int   ; F3 S9 M  j' j% C7 ]- ?8 I
  24.     * */   
    * k. K' a) b7 @! d$ E: \. T! }
  25.    public static $rate = 2;   
    , p% `! o" A$ ]
  26.     " ~2 N+ C- A5 ?6 v& k8 s. X
  27.    /**相似度允许值 0~64   / [+ h" C6 R7 [  N
  28.     * @access public   
    / Q* D! u! v. n
  29.     * @staticvar int   
    ; K; |; ?& q7 @4 x! j
  30.     * */    ( k$ H5 a  ]1 e6 S
  31.    public static $similarity = 80;    - p( G" M- S( s4 i! {1 s
  32.     0 u: G* e$ {* R% u6 ~" }
  33.    /**图片类型对应的开启函数   
    & m. e2 }' D7 U: C* h
  34.     * @access private   
    8 K) b' o8 {8 R; d. {/ w8 A, q
  35.     * @staticvar string   : N- J3 h& Y+ f  u; H' F6 g5 Y, s
  36.     * */   
    8 {. ^7 e. O. S% ^$ t, F
  37.    private static $_createFunc = array(    9 z9 J$ M% H/ B
  38.        IMAGETYPE_GIF   =>'imageCreateFromGIF',    " X- x8 }3 T& t8 A7 J
  39.        IMAGETYPE_JPEG  =>'imageCreateFromJPEG',    ; U- y! n7 x9 o- i( W
  40.        IMAGETYPE_PNG   =>'imageCreateFromPNG',   
    : \1 u  n( ?: F  v8 V
  41.        IMAGETYPE_BMP   =>'imageCreateFromBMP',   
    * B( `! w- ~7 G: H0 @: r6 r
  42.        IMAGETYPE_WBMP  =>'imageCreateFromWBMP',    ( q9 u! i8 Y- l- G( f
  43.        IMAGETYPE_XBM   =>'imageCreateFromXBM',    ; ?, K% |9 r3 R# @
  44.    );   
    7 B& x9 y, ?- X$ t. H
  45.    
    5 d) q5 V- C2 W6 @; {4 F4 U
  46.    
    / u' L  y+ q  Q) H+ k9 A9 G
  47.    /**从文件建立图片   $ f5 x6 z- t& A
  48.     * @param string $filePath 文件地址路径   
    0 F5 V4 ~+ i  C; J0 T  j
  49.     * @return resource 当成功开启图片则传递图片 resource ID,失败则是 false   
    # Q; b0 u$ r7 B
  50.     * */   
    7 b9 v, G* c) l* T5 r4 P
  51.    public static function createImage($filePath){   
    - I$ g1 ~: W' k& u& m* `9 [) Q
  52.        if(!file_exists($filePath)){ return false; }   
    / D& W; Y# m% b+ v- N+ }6 A
  53.    
    ; B" U" _" Y+ C% N; l
  54.        /*判断文件类型是否可以开启*/   
    . Y% ~! b8 y3 _# r) {
  55.        $type = exif_imagetype($filePath);   
    : A5 L, v# O' G7 Z6 t
  56.        if(!array_key_exists($type,self::$_createFunc)){ return false; }   
    7 L7 W- W' k6 C% F$ V+ F! ^, i
  57.     4 d0 S) R0 |% Z( S1 j
  58.        $func = self::$_createFunc[$type];    7 _' y, A# w$ ]& x$ @. S/ B
  59.        if(!function_exists($func)){ return false; }    + `3 W! H. l  C8 m, P
  60.    
    ( N1 s  _* q& D- m+ N
  61.        return $func($filePath);    & f7 O6 Z: R3 W  f
  62.    }   
    . b: T6 s4 f( @
  63.     : r+ {. z1 ]0 K6 _7 k" u
  64.     0 s: d$ z6 B4 ?7 n/ `8 [
  65.    /**hash 图片   . S# ?  u; W7 P0 q  N4 I
  66.     * @param resource $src 图片 resource ID   
    4 s) W/ |" [/ \6 D- @2 {7 N- K
  67.     * @return string 图片 hash 值,失败则是 false   7 O: N3 H' I/ H/ v# B2 b
  68.     * */   
    % [. l8 x: d0 s: |6 e5 g
  69.    public static function hashImage($src){    2 \! a. q: \- }& C2 s1 c; k# Z
  70.        if(!$src){ return false; }   
    - M0 I! _% j9 h, Z) K6 M  p6 r
  71.     # ~9 S% c" ^$ O% W& z( |
  72.        /*缩小图片尺寸*/    ( o. ~( d+ P9 r2 n4 Z, x& d
  73.        $delta = 8 * self::$rate;   
    ) B* w! k* [) ?1 _. o" k
  74.        $img = imageCreateTrueColor($delta,$delta);    9 E6 }2 c3 Y6 z, G' r7 N. T
  75.        imageCopyResized($img,$src, 0,0,0,0, $delta,$delta,imagesX($src),imagesY($src));   
    ) u4 n7 {, M1 a$ B0 N6 j+ G3 V2 c
  76.     5 x% ~5 s% d0 ?% @
  77.        /*计算图片灰阶值*/    " f8 I$ q* l* m! p% K# E! G
  78.        $grayArray = array();    % h* N% W7 l2 h. h9 d+ H
  79.        for ($y=0; $y<$delta; $y++){    ! e8 I, g: K  `/ Y! c
  80.            for ($x=0; $x<$delta; $x++){   
    9 h* G/ A/ P" A8 t. q4 M
  81.                $rgb = imagecolorat($img,$x,$y);    4 @& F/ d) `& Q" ^! Z- S; V9 ]
  82.                $col = imagecolorsforindex($img, $rgb);    & I/ c8 l6 n' x) {: O3 e. w% K
  83.                $gray = intval(($col['red']+$col['green']+$col['blue'])/3)& 0xFF;    ( {& n, b) t$ C  A
  84.    
    7 u. f. i- A7 l3 @, n
  85.                $grayArray[] = $gray;   
    & c& B& |9 L- z9 ~; D. P
  86.            }   
    / d/ i: n/ z: a0 b+ ]9 v$ E
  87.        }   
    7 k  e1 h. a& ^" q# s9 P& p( w
  88.        imagedestroy($img);   
    $ ~: p9 I6 ]/ L% H( |9 N
  89.     $ T2 u; I3 D$ ^
  90.        /*计算所有像素的灰阶平均值*/    0 U7 T/ Y# j1 h4 o+ h) B- @
  91.        $average = array_sum($grayArray)/count($grayArray);   
    9 C7 ]7 V$ y" i7 V6 y, L7 h+ `
  92.     8 L7 S4 s: ^% C1 |, _5 ]) C2 P
  93.        /*计算 hash 值*/    5 Y" r4 F. r) t1 ~4 e1 J2 s$ p
  94.        $hashStr = '';   
    # k1 o" `5 ^5 @) o6 e8 j- f; U
  95.        foreach ($grayArray as $gray){   
    8 j5 x' c0 r( U3 m6 D& D
  96.            $hashStr .= ($gray>=$average) ? '1' : '0';    7 y% O" v& a$ t! Q" S6 J8 z, D
  97.        }    8 G' x& q  G. Z9 Y
  98.     / U6 ^1 d  y. x7 R! O
  99.        return $hashStr;   
    * W. @6 W& E/ i
  100.    }   
    : G8 R; o, ]2 _& {- s
  101.    
    : b  _8 M) r) a& K5 P& m, v
  102.    
    ; b- v& H- w# H, n: H
  103.    /**hash 图片文件   8 o6 V* o+ L3 m: v. O8 l" ^4 v
  104.     * @param string $filePath 文件地址路径   
    3 N; T' }2 x2 ?! Q! `/ g
  105.     * @return string 图片 hash 值,失败则是 false   : ]3 y# J) z' Q) Q- Z
  106.     * */    0 w. Q" a$ I8 L# r, f2 x8 X, a9 l
  107.    public static function hashImageFile($filePath){    % Z; p7 l# u1 k' T( @; t
  108.        $src = self::createImage($filePath);   
    4 z3 I: i" o, v8 o
  109.        $hashStr = self::hashImage($src);   
    4 W0 i. C# K9 _& H  q5 X5 Q
  110.        imagedestroy($src);    " {- Y2 Y8 @5 U- i
  111.     $ o* {3 r3 S1 g0 i- y
  112.        return $hashStr;    4 [; y+ p) a0 W; Z' }7 Y* T0 f
  113.    }    % `% P% S$ c8 A$ d5 j( [7 Y
  114.    
      m6 Y# ]$ @2 {" e
  115.       |" s3 ~, l" A+ X8 Y0 h
  116.    /**比较两个 hash 值,是不是相似   # e% a7 D1 y5 P7 m
  117.     * @param string $aHash A图片的 hash 值   
    , ^. P  n: Y  f( V: @( H4 p
  118.     * @param string $bHash B图片的 hash 值   
    3 {. D) a3 b) J
  119.     * @return bool 当图片相似则传递 true,否则是 false   , ]# }1 z7 G( @  Z
  120.     * */   
    - x/ h2 B5 k4 V+ l7 Y- f
  121.    public static function isHashSimilar($aHash, $bHash){    5 @. ~& _/ E4 \
  122.        $aL = strlen($aHash); $bL = strlen($bHash);    3 F5 A( r# _( s0 m- Z
  123.        if ($aL !== $bL){ return false; }    " v; F& P1 @5 Y$ L
  124.    
    . J/ _2 o9 G, q. c* w  y: |$ S9 v
  125.        /*计算容许落差的数量*/    " F' d  x+ }; l" a
  126.        $allowGap = $aL*(100-self::$similarity)/100;    , E/ q1 s4 b6 p0 Y
  127.     7 m2 L- L/ h4 @( L( Z4 F+ f& R, W
  128.        /*计算两个 hash 值的汉明距离*/   
    * @) O8 F  T: @  w) P. x, C4 }
  129.        $distance = 0;    3 d3 A  u; N3 T( c7 N9 [; Y1 L; u
  130.        for($i=0; $i<$aL; $i++){    6 u3 p' N# s. o$ F; f0 H& Z
  131.            if ($aHash{$i} !== $bHash{$i}){ $distance++; }   
    % g; E! t' V% E; H% ~1 n
  132.        }   
    4 j& z0 _# X# U2 a) y3 x
  133.    
    ) q: [/ j' c- z/ s) Q
  134.        return ($distance<=$allowGap) ? true : false;    7 e4 b/ h& K8 k- _; V8 \' O' u& U; }
  135.    }    8 ?# I4 K, u0 Z) u' i+ ~6 _. j9 t
  136.     ) Q4 n& V" L- n  r+ }9 I3 O: q
  137.     % n, }8 S  G' N) ?; u$ f
  138.    /**比较两个图片文件,是不是相似   
    + H! @0 K1 a! G2 e$ l
  139.     * @param string $aHash A图片的路径   
    5 \8 I6 ]( d1 z) m
  140.     * @param string $bHash B图片的路径   " ~5 f. s8 B7 c+ L/ v
  141.     * @return bool 当图片相似则传递 true,否则是 false   0 B  Z0 n$ j! ]1 i7 M+ O
  142.     * */    # Y' b0 A8 Y3 m; R( \! s
  143.    public static function isImageFileSimilar($aPath, $bPath){    ; a2 |; ^0 n5 F6 P- e
  144.        $aHash = ImageHash::hashImageFile($aPath);   
    6 p: S% f! T* ]8 z: m8 _
  145.        $bHash = ImageHash::hashImageFile($bPath);    ! A* o+ d3 R* o6 h
  146.        return ImageHash::isHashSimilar($aHash, $bHash);    % X* G& ?" k/ Y" z8 F4 N4 _
  147.    }   
    " W3 u% D5 D6 s
  148.    
    / R. t$ C7 i6 E, y, ?8 ^5 `6 k4 v
  149. }6 Y; P5 O  b' N& {7 f4 u# O
复制代码

( q1 u/ J4 `3 R$ T
2 d& B' m( j, E$ I- d/ k/ Z; D
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-6-4 09:34 , Processed in 0.054202 second(s), 19 queries .

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