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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

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

% u. A, ~1 P( H9 I% q: `6 H! h
8 m# t' L( x/ t9 x
由于相似图片搜索的php实现的 API 不怎么符合我的用途,所以我重新定义 API 的架构,改写成比较简单的函数方式,虽然还是用对象的方式包装。

/ X0 M1 x- }$ n* h9 p# s
  1. <?php      k6 K' B! P% k; r. Q3 ~* Y
  2. /**   
    8 U4 F% {" w7 [: x: f$ r% L
  3. * 图片相似度比较   " S8 y9 A7 n; L8 g. f6 m- b
  4. *   ( L! R( ?. Z% x, u, `
  5. * @version     $Id: ImageHash.php 4429 2012-04-17 13:20:31Z jax [        DISCUZ_CODE_1        ]nbsp;  ; Q8 B& z# n' b: \* W2 g3 T
  6. * @author      jax.hu   1 ^' K/ w7 V. `" a
  7. *   / `2 k3 s% ]5 t) k+ r( ?* F: r  S
  8. * <code>   5 j& G" q. o. f
  9. *  //Sample_1   1 Z5 r2 a: h$ P
  10. *  $aHash = ImageHash::hashImageFile('wsz.11.jpg');   & \7 I- K' b- o' g( R- O4 m; N
  11. *  $bHash = ImageHash::hashImageFile('wsz.12.jpg');   
    ) {" {- N" l- x. i/ A: k
  12. *  var_dump(ImageHash::isHashSimilar($aHash, $bHash));   $ j/ m# K7 Y' {" s# P
  13. *   8 t" Z3 D# g6 S1 c. C4 ]' T  a
  14. *  //Sample_2   & |9 ~; e+ t& W  v9 k
  15. *  var_dump(ImageHash::isImageFileSimilar('wsz.11.jpg', 'wsz.12.jpg'));   ( H* o& l1 y4 z6 Q" k
  16. * </code>   
    ( F' F/ V8 u% c. o
  17. */    3 G. b3 [# R* u5 [' O
  18.    
    " I$ Z2 C. M4 {2 D8 G3 k( X
  19. class ImageHash {    . T" z+ j# Q1 O. T: b6 C
  20.    
    0 G% q/ N! [) \
  21.    /**取样倍率 1~10   
    7 `8 B/ J7 u0 u$ s) q' M
  22.     * @access public   5 m, r5 h- S. A8 L, ~% P" S; Q( l
  23.     * @staticvar int     n) R" ]& U; `3 g& a: F
  24.     * */    # g2 w# h, Q+ Y8 u$ l" [8 g
  25.    public static $rate = 2;    - |' |( K' a" ^8 Q# C. H* T/ b
  26.     + Z2 f( k; B/ ]2 j3 o! ?
  27.    /**相似度允许值 0~64   ! \+ s! S* G; M) ^$ d+ m! I
  28.     * @access public   
    ( M8 D- _1 [3 y  B# l
  29.     * @staticvar int   8 J( \1 P0 f  H1 U
  30.     * */   
    / N) C8 z7 y/ e: h" I- X2 ?* R/ o
  31.    public static $similarity = 80;      @, ~8 Z. m4 C! z
  32.    
    / Y# H% M% f4 g6 k. a
  33.    /**图片类型对应的开启函数   
    0 L5 P& V7 D+ e1 X/ w# @
  34.     * @access private   
    ; W" q, r# O) n' N# p' b
  35.     * @staticvar string   
    . \3 H; P3 ]) Z) X% K
  36.     * */    ; q/ q7 n1 H# p6 Z/ T
  37.    private static $_createFunc = array(    7 y. g/ r4 B% ]+ _
  38.        IMAGETYPE_GIF   =>'imageCreateFromGIF',    , k6 q7 }' |7 x" ^* Z7 t0 I
  39.        IMAGETYPE_JPEG  =>'imageCreateFromJPEG',    5 \$ h$ r, d4 _1 ~
  40.        IMAGETYPE_PNG   =>'imageCreateFromPNG',    7 U5 L7 C$ P: S* L2 h
  41.        IMAGETYPE_BMP   =>'imageCreateFromBMP',   
    0 x# _% y2 `5 c' q: E
  42.        IMAGETYPE_WBMP  =>'imageCreateFromWBMP',    ( ^4 O! A& W! E, {
  43.        IMAGETYPE_XBM   =>'imageCreateFromXBM',    , e9 v4 l- [0 a
  44.    );   
    5 S2 m# n9 Z: [# z
  45.    
    0 c* D  `! D" A
  46.    
    - U. W/ @, a7 Q8 z2 a! l( Q
  47.    /**从文件建立图片   
    / U) K2 s- v2 M8 E  r  o1 F6 y: {
  48.     * @param string $filePath 文件地址路径   
    9 F/ F$ D4 \$ }( w' Z; G9 @
  49.     * @return resource 当成功开启图片则传递图片 resource ID,失败则是 false   2 u7 o, @1 \) J& R
  50.     * */    5 n9 d! N' a: R6 K3 x& M- `
  51.    public static function createImage($filePath){   
    % O# b  ^, G/ d: T+ d
  52.        if(!file_exists($filePath)){ return false; }    1 u4 o# e, s0 V
  53.     5 L: y! a0 {) z, Y. I7 J! W
  54.        /*判断文件类型是否可以开启*/   
    # q; R) N6 ^; j! A' A
  55.        $type = exif_imagetype($filePath);    0 n. N+ w) X1 y! m* h
  56.        if(!array_key_exists($type,self::$_createFunc)){ return false; }    ' u4 o' T1 P4 z  K
  57.    
    1 x; d4 P, N" G
  58.        $func = self::$_createFunc[$type];    2 w8 k- ]' G6 m
  59.        if(!function_exists($func)){ return false; }   
    ! T# E/ o% F" v; B
  60.    
    / n5 u% T' _$ T4 U3 V
  61.        return $func($filePath);   
      O& n* @8 I1 B3 l) I' J
  62.    }   
    4 N' s+ ]; v2 x- F
  63.     1 C! n0 a0 W- z- p# W+ z! c
  64.    
    ! m9 c6 ?/ x, {
  65.    /**hash 图片   % }  ?1 x$ x8 k4 _% c
  66.     * @param resource $src 图片 resource ID   ( {( A8 B4 p0 U
  67.     * @return string 图片 hash 值,失败则是 false   ) y  E8 K/ q" v: E6 i- o
  68.     * */   
    " w4 {3 _. I, f9 T( _; Y
  69.    public static function hashImage($src){    9 G! U6 \# _- h: Z- x
  70.        if(!$src){ return false; }   
    , Z3 J; B. a9 H" n9 N0 Z- j; _
  71.     2 D% x1 k/ E0 |: l7 s
  72.        /*缩小图片尺寸*/    0 Y. u' ?; ?' y9 o* A
  73.        $delta = 8 * self::$rate;   
    ! }+ Y: B: f" o) I% y; w. c: N
  74.        $img = imageCreateTrueColor($delta,$delta);    0 A5 \7 x1 L$ T( H1 c
  75.        imageCopyResized($img,$src, 0,0,0,0, $delta,$delta,imagesX($src),imagesY($src));   
    5 E" o; W' L! x! ?# j' ^) a
  76.     " J* g% h4 ^2 z* |4 N$ R
  77.        /*计算图片灰阶值*/    / F. _6 _% \* S. f$ {
  78.        $grayArray = array();    ( D: T9 M; a1 w! S& ]7 h6 B
  79.        for ($y=0; $y<$delta; $y++){   
    ) g- y9 V7 ], D& b# I: ]. \; J' C
  80.            for ($x=0; $x<$delta; $x++){    ! a. e6 r6 O4 U  k( w, T2 E) A
  81.                $rgb = imagecolorat($img,$x,$y);   
    4 C+ u" N& l3 R( e) A1 X
  82.                $col = imagecolorsforindex($img, $rgb);    + u2 m1 p  U  C( ^$ v7 F" ~  N; f
  83.                $gray = intval(($col['red']+$col['green']+$col['blue'])/3)& 0xFF;   
    1 O# i, f1 c  A$ a) u5 W, j6 S5 r/ p: x
  84.    
    0 D4 Y: t6 x# x7 j& y
  85.                $grayArray[] = $gray;      z0 j& y- M, e+ X. c! y% {# W) j; @
  86.            }    ) _  {. k; b, \. j
  87.        }    ; k$ I/ \/ |( n6 y9 |* Q! w- ^
  88.        imagedestroy($img);   
    6 ]. V, `8 I. b4 O# N+ O
  89.    
    ' P5 B6 m$ s1 s- j2 ~
  90.        /*计算所有像素的灰阶平均值*/   
    * k' T8 U; L) U# L
  91.        $average = array_sum($grayArray)/count($grayArray);   
    9 T" t0 P4 }0 P# d3 t% I
  92.     9 [6 j  R6 I( h) r# C0 C
  93.        /*计算 hash 值*/    2 @6 n0 m8 J. a2 m. C" c
  94.        $hashStr = '';   
    7 b! S! v! I: G
  95.        foreach ($grayArray as $gray){    8 G# R4 ~1 K1 B& p5 V
  96.            $hashStr .= ($gray>=$average) ? '1' : '0';    : J* l# e5 X; }
  97.        }    + s. x7 i. H5 W% F) G+ y' p
  98.    
    * U9 t8 p4 Q! K( E4 Y
  99.        return $hashStr;   
    3 Y' I9 b. ?( J2 P  g% ]$ \
  100.    }    8 Q* Z4 G7 `1 `/ b/ O" e8 ?
  101.     - [" s& V# n1 K
  102.     & S9 a' b  S; _$ o9 @
  103.    /**hash 图片文件   , N" ^. a% w- Z3 y3 i0 u
  104.     * @param string $filePath 文件地址路径   * O) D$ }5 Q- O& g7 a
  105.     * @return string 图片 hash 值,失败则是 false   
    6 U% z, F* P3 u
  106.     * */    4 z- G+ u9 K1 E$ @
  107.    public static function hashImageFile($filePath){      B8 f) w* Z  Q& f9 J$ }9 m
  108.        $src = self::createImage($filePath);   
    ! w6 d. a# r7 d) L
  109.        $hashStr = self::hashImage($src);    0 N3 W! o4 I- [: S- e
  110.        imagedestroy($src);    ( K" u* ^7 i! M# `" s
  111.    
    + {: f: C+ E; @1 _) O
  112.        return $hashStr;    ( ]8 r, w: ^/ {5 ?$ C/ |3 p
  113.    }    2 f' T8 [# C0 k
  114.     & p; S/ I1 C7 v  O& r' F
  115.    
    7 E; v- M- f/ I( e
  116.    /**比较两个 hash 值,是不是相似   
    / g" [. u& Q& t0 _8 `' H
  117.     * @param string $aHash A图片的 hash 值   
    & e: r- w& i: C
  118.     * @param string $bHash B图片的 hash 值   + ~. O1 {2 m0 l" u$ d, E7 A2 P
  119.     * @return bool 当图片相似则传递 true,否则是 false   
    9 m/ r( F/ h( T& a7 o2 g
  120.     * */   
    - T; Q( R, ~. C: v, I
  121.    public static function isHashSimilar($aHash, $bHash){   
    $ N- c) F% p9 J6 U! A
  122.        $aL = strlen($aHash); $bL = strlen($bHash);   
    8 U* V* n" r& J1 g5 _1 o5 o+ q
  123.        if ($aL !== $bL){ return false; }   
    ' c9 H2 c$ J  |+ B
  124.     & H6 X# `& o. w# b$ ~
  125.        /*计算容许落差的数量*/   
    / G& |3 Y9 f% o( Y
  126.        $allowGap = $aL*(100-self::$similarity)/100;    , ~* u6 A' X% s( N- O
  127.    
    1 L9 j. l! [8 D  v3 g4 V- K* b; F
  128.        /*计算两个 hash 值的汉明距离*/    * B0 `7 M) a3 r
  129.        $distance = 0;    ) Q& M+ F  |5 o  u9 t- E1 M0 h* v
  130.        for($i=0; $i<$aL; $i++){    & n' m0 I& b+ Y
  131.            if ($aHash{$i} !== $bHash{$i}){ $distance++; }    ) o# L- ^, A8 Q! E* q
  132.        }   
    ' Y/ p; A# ?$ c& y* U$ w6 U+ x
  133.     . w- u9 q! O1 E1 _4 q' t/ _
  134.        return ($distance<=$allowGap) ? true : false;    2 z3 k  Y  V" v
  135.    }   
    2 L  Q! \9 T  x) G  e8 }* ]
  136.    
    ) B: z+ |7 f! f: b8 n
  137.     # w) s4 Y5 y" e7 U2 M
  138.    /**比较两个图片文件,是不是相似   0 d5 B% W+ F8 @7 h: w
  139.     * @param string $aHash A图片的路径   
    4 N4 U7 y, e  [
  140.     * @param string $bHash B图片的路径   
    1 V& M1 E4 f& [. V( b$ A
  141.     * @return bool 当图片相似则传递 true,否则是 false   
    9 F: r* V; |+ B
  142.     * */   
    # x; w3 L7 x* r
  143.    public static function isImageFileSimilar($aPath, $bPath){   
    2 |; P" H! v1 t0 O2 I
  144.        $aHash = ImageHash::hashImageFile($aPath);   
    ( Y9 a) @) d4 i4 y; l& L$ [1 @
  145.        $bHash = ImageHash::hashImageFile($bPath);    " d+ G1 ]8 v5 h! F1 ^+ B: D5 S7 C
  146.        return ImageHash::isHashSimilar($aHash, $bHash);    ( Q; ?5 o! p7 r3 I8 q
  147.    }    : O- g: e1 t: y1 c
  148.    
    . _' R+ _) Q5 j7 D* W1 l0 T4 h& E
  149. }
    ; D( ~  b# S- s5 x
复制代码

0 }5 i  [7 n4 e& O  Z  m" V) D
. b: N* |" u- L4 w
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2024-12-23 01:44 , Processed in 0.112566 second(s), 20 queries .

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