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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2018-7-7 23:06:35 | 显示全部楼层 回帖奖励 |倒序浏览 |阅读模式
摘要: 本文讲的是分享一个PHP简易的图片相似度比较类, 由于相似图片搜索的php实现的 API 不怎么符合我的用途,所以我重新定义 API 的架构,改写成比较简单的函数方式,虽然还是用对象的方式包装。  代码如下 复制代码 <?php    /**   * 图
( Q( B- V8 z5 Z3 y. N( E" t3 J# f; y' _

1 t: u% _: C: w1 b5 A7 ^由于相似图片搜索的php实现的 API 不怎么符合我的用途,所以我重新定义 API 的架构,改写成比较简单的函数方式,虽然还是用对象的方式包装。
) c! e4 U6 {, O( e. x: m/ J
  1. <?php   
    5 R9 K3 l* F6 M" L
  2. /**   
    1 {7 S0 q4 W# k0 {+ d* X7 h
  3. * 图片相似度比较   
    6 m7 d; q( u9 d, N& Y4 n3 {5 D
  4. *   3 q1 B' ~3 Z( o: N6 K3 g" }* l
  5. * @version     $Id: ImageHash.php 4429 2012-04-17 13:20:31Z jax [        DISCUZ_CODE_1        ]nbsp;  ! d" z  z9 T& v
  6. * @author      jax.hu   & {( J- [, W$ g
  7. *   
    7 u* d( D( c. K- M
  8. * <code>   ) T$ w! g& M, @, X9 A
  9. *  //Sample_1   
    6 J; v9 B! s' `4 e  u5 a% P
  10. *  $aHash = ImageHash::hashImageFile('wsz.11.jpg');   / t) o: f  P: b3 ?' R
  11. *  $bHash = ImageHash::hashImageFile('wsz.12.jpg');   
    & X! u$ Z/ s6 |+ c" Y* y+ @. {
  12. *  var_dump(ImageHash::isHashSimilar($aHash, $bHash));   
    1 R3 Q  e% T/ w+ y) p# K$ W' \, m! z
  13. *   
    $ ?( p9 p# f, f1 m  ~: v4 }
  14. *  //Sample_2   
    3 t; _: R# K! r  z8 e' W1 g9 K
  15. *  var_dump(ImageHash::isImageFileSimilar('wsz.11.jpg', 'wsz.12.jpg'));   
    + g) a" x" ^5 I: i' _
  16. * </code>   
    5 l( l+ r$ }( j
  17. */   
    3 S$ R" g6 Q) E+ ~
  18.    
    0 u$ f/ [3 b: I" ^8 @4 a1 w
  19. class ImageHash {    / I  j3 V$ x( Q5 ~. I7 P& V5 ?& \- e: }
  20.    
    0 {, X  x  ?2 v
  21.    /**取样倍率 1~10   9 Z- ^4 P  c- f$ t
  22.     * @access public   
    % d# W$ h7 I7 \; Y
  23.     * @staticvar int   
    * v/ D# x) h4 J
  24.     * */    $ h8 r+ I2 ~4 u) ^6 f. \) e# a
  25.    public static $rate = 2;   
    0 i$ p4 o0 T, J) P( R
  26.    
    9 E; M/ Z% b1 g' p1 v. v0 ]: E# j
  27.    /**相似度允许值 0~64   / v5 o3 E# q6 h2 J  B( v5 W' o
  28.     * @access public   ; M5 N: H6 F2 y) M8 I/ N- g
  29.     * @staticvar int   
    / d! Q7 w, l+ d- ]# j  s
  30.     * */   
    " n. M9 o6 f1 Q& G, _
  31.    public static $similarity = 80;    7 T3 f* K( Y5 d3 f0 A: n7 a
  32.     " O: {) L! d8 P/ C7 t0 w4 Y% S
  33.    /**图片类型对应的开启函数   
    ' W/ L5 l( O, a# X1 w' G8 y
  34.     * @access private   
    % J6 d; {; R/ x1 J: j
  35.     * @staticvar string   - e6 m- I2 \  c; h" t' A
  36.     * */   
    - V+ o7 Y# _& w! R0 e# o
  37.    private static $_createFunc = array(      U7 t; ^: z0 i5 K* \5 P
  38.        IMAGETYPE_GIF   =>'imageCreateFromGIF',    ) ~3 t4 R$ H1 j8 [: Y6 m4 z8 s, E7 h3 I
  39.        IMAGETYPE_JPEG  =>'imageCreateFromJPEG',   
    $ r& S7 `: M2 E/ ^' W. Z' m6 w0 F6 |
  40.        IMAGETYPE_PNG   =>'imageCreateFromPNG',   
    & {' e; c  ~  T' t! W9 b
  41.        IMAGETYPE_BMP   =>'imageCreateFromBMP',   
    ; H* Z/ F! W, _2 ~( ^; I
  42.        IMAGETYPE_WBMP  =>'imageCreateFromWBMP',   
    : V, }* t8 r! h8 e, I) X
  43.        IMAGETYPE_XBM   =>'imageCreateFromXBM',   
    2 k3 s+ {' I4 ~0 N
  44.    );   
    $ J) |" S; E7 y" E" D9 \$ w+ O
  45.     7 L- o: Z/ x2 ]. a# _7 ^
  46.     ' j* x7 R3 Y0 \& c( E
  47.    /**从文件建立图片   3 [2 f+ |2 v0 d( a4 |* i
  48.     * @param string $filePath 文件地址路径   / T  p1 v4 O! B' t2 ]: B2 S7 t
  49.     * @return resource 当成功开启图片则传递图片 resource ID,失败则是 false   + O) L5 f# F' b% \: ~+ I& ?( @
  50.     * */   
    + s. {2 m! z% I* ^, Y: }7 T
  51.    public static function createImage($filePath){   
    & L* H/ H# `& ^3 n3 F* S$ `5 ]
  52.        if(!file_exists($filePath)){ return false; }    8 A7 z( v( C" m/ N7 l
  53.    
    ' @, x: d+ @6 \0 r! `
  54.        /*判断文件类型是否可以开启*/    ; v: q* S) ~  N: ]& @5 ?
  55.        $type = exif_imagetype($filePath);   
    6 Y+ g& y4 }% b8 v$ p) _: o2 T
  56.        if(!array_key_exists($type,self::$_createFunc)){ return false; }   
    : d) l1 W% |' \4 L, o
  57.     , x+ ], |  X2 P3 o% q5 ~! k' x& i
  58.        $func = self::$_createFunc[$type];   
    8 L5 L, m/ _3 m9 R' ?, c! x
  59.        if(!function_exists($func)){ return false; }   
    5 {' k- Q5 X! t
  60.     5 ?8 y1 @! @* E$ Q4 t) m  ]3 A/ v1 Z
  61.        return $func($filePath);   
    8 g5 [5 ?/ ]9 ?: T% o. o
  62.    }    7 @) G9 S: s; V3 g) n4 _& }7 }5 Y
  63.     4 ~0 c' x; w( L0 R- O/ c. u
  64.    
    5 f- c5 W- t- F! M1 {+ ~* H
  65.    /**hash 图片   
    3 ]4 t0 ]% U5 a7 i' q5 P
  66.     * @param resource $src 图片 resource ID   
    ' W1 r* q% K2 Z5 D
  67.     * @return string 图片 hash 值,失败则是 false   
    ; S, @# q( r8 J/ ?2 |( _: E, ]9 }
  68.     * */   
    4 @. P/ j+ M- L2 C, h
  69.    public static function hashImage($src){    ' P. ]/ z2 ~8 \& _5 f; i
  70.        if(!$src){ return false; }   
    6 J1 v/ ~/ b' `. U
  71.    
    : b5 v6 T0 J! i, V
  72.        /*缩小图片尺寸*/   
    . _# f! E1 V8 [8 {8 p7 M
  73.        $delta = 8 * self::$rate;   
    $ K8 v7 m  ?5 {. K9 A% g
  74.        $img = imageCreateTrueColor($delta,$delta);   
    + I4 M' ]* p# w2 t7 V) z
  75.        imageCopyResized($img,$src, 0,0,0,0, $delta,$delta,imagesX($src),imagesY($src));    8 k7 d) o' L. R- p1 U
  76.    
    8 g/ u2 Q2 H4 ?6 P: n* b& G0 @- l
  77.        /*计算图片灰阶值*/    : r% g6 @* r# Q* q0 e) y  I' @
  78.        $grayArray = array();   
    % f( E; c% a+ w" @2 h5 N9 a# m* T
  79.        for ($y=0; $y<$delta; $y++){   
    / M" u9 M) _2 u8 W
  80.            for ($x=0; $x<$delta; $x++){   
    8 F; J2 Z5 _" g
  81.                $rgb = imagecolorat($img,$x,$y);   
    ( z. |+ e, k' g! e
  82.                $col = imagecolorsforindex($img, $rgb);    6 F0 V; F9 N: ^
  83.                $gray = intval(($col['red']+$col['green']+$col['blue'])/3)& 0xFF;   
    3 ^" A2 o/ z; l* U
  84.     ! m$ d+ ?6 P' K
  85.                $grayArray[] = $gray;   
    2 c. a2 J! X: B- [" ?
  86.            }    1 i5 o, @8 j/ k7 G, M
  87.        }    # @" {2 e4 t- g& F
  88.        imagedestroy($img);    ( w& a; \! q; ]6 w
  89.     * u# O; r1 `! l: A* o
  90.        /*计算所有像素的灰阶平均值*/    % T. z' U, F+ @* t1 w
  91.        $average = array_sum($grayArray)/count($grayArray);   
    ( @  Z1 F0 k2 s8 }- @2 w
  92.    
    2 ~% ]2 P/ Z6 ^: C5 }. a4 _8 z
  93.        /*计算 hash 值*/    . o( [( e; W4 ~- P3 u
  94.        $hashStr = '';   
    2 J2 i1 ^; v( I3 k8 p" b4 o2 W
  95.        foreach ($grayArray as $gray){    1 O) N- r$ Q/ j: b/ U: C: ^
  96.            $hashStr .= ($gray>=$average) ? '1' : '0';    ! G& x2 H3 n# F, r2 z
  97.        }    * s% t3 |% |9 w3 ~" X
  98.    
    - f" F& q4 H5 U. D5 T
  99.        return $hashStr;    3 p2 Z! l- E) v# U# c( e% j
  100.    }    % F9 P1 X1 t; B
  101.     8 w* I( e  w3 ?: l" J
  102.    
    & Z$ S: P2 `8 x9 L* _1 W" p
  103.    /**hash 图片文件   ; z& G9 b( H! |* f' M
  104.     * @param string $filePath 文件地址路径   0 w0 \" Y+ P. {+ F* y3 `- M# L
  105.     * @return string 图片 hash 值,失败则是 false   0 d* f, v2 X- u( ]1 V$ e$ K
  106.     * */    ; ]/ e' b6 g# X- y' I
  107.    public static function hashImageFile($filePath){    " L' G: |7 J. w+ @, {7 @* v
  108.        $src = self::createImage($filePath);   
    5 D+ _2 v% f3 R, I# Y
  109.        $hashStr = self::hashImage($src);   
    ( X2 s0 ^/ s4 C* M% H
  110.        imagedestroy($src);    6 Z! w$ b4 Q& M
  111.    
    4 i* R9 e" S5 O$ n* i) n
  112.        return $hashStr;   
    + R" ~- r+ R6 ~9 ?. U) ?
  113.    }    ; c" @# u# T( H! u) B. `. l
  114.     6 @, c+ l  Y5 S/ c- a, J; A
  115.     5 Y, _) J5 b9 ^5 O% a* j( A
  116.    /**比较两个 hash 值,是不是相似   
    2 h1 p" E, b+ a6 R4 H$ l6 D6 S
  117.     * @param string $aHash A图片的 hash 值   8 l/ I3 C9 M/ ]: X, S- W# G
  118.     * @param string $bHash B图片的 hash 值   
    + U7 ^& e& @0 s% j
  119.     * @return bool 当图片相似则传递 true,否则是 false   
    . |3 r# ^4 z2 c6 f6 {* n% P7 R5 E, m
  120.     * */   
    ! U+ U; x1 B3 C
  121.    public static function isHashSimilar($aHash, $bHash){    3 v7 p( y; g- @" }  M9 B) p: H
  122.        $aL = strlen($aHash); $bL = strlen($bHash);   
    1 o5 F% r5 F* i4 V' \
  123.        if ($aL !== $bL){ return false; }   
    7 a9 q6 W" R7 [& L& ^) n8 S# l
  124.    
    ) ?8 n" t: R6 d
  125.        /*计算容许落差的数量*/    2 |9 g% ^, X: k) M& r' Q' v8 N) S
  126.        $allowGap = $aL*(100-self::$similarity)/100;    ! k9 C3 }" L4 y; O) v3 B/ E
  127.     3 `' z( i  V2 q1 ~0 b9 C; U$ V
  128.        /*计算两个 hash 值的汉明距离*/    ( O2 J8 M1 M& h% u
  129.        $distance = 0;    & I5 X2 _, ^7 t$ d" P2 }3 _
  130.        for($i=0; $i<$aL; $i++){    . w2 g1 H3 H' m' [. H
  131.            if ($aHash{$i} !== $bHash{$i}){ $distance++; }   
    % C1 g9 s2 s$ Y, j
  132.        }   
    + h) c4 W( }5 _/ \$ \9 Z/ Y
  133.    
    # ^* S/ d2 F1 g- n* V
  134.        return ($distance<=$allowGap) ? true : false;   
    0 ^' Z' ?$ ]6 {
  135.    }   
    - z( p) w" o  ?
  136.    
    6 {2 M2 p+ L8 M, u4 `( e1 L* `. m1 C/ ~
  137.     5 x6 L+ }, e6 w0 Z; E" H/ y
  138.    /**比较两个图片文件,是不是相似   
    # m* S. r" Y# Y
  139.     * @param string $aHash A图片的路径   + C$ o0 `4 i; |" {
  140.     * @param string $bHash B图片的路径   
    , R* j. X( s& ^) C5 w/ p% P# q
  141.     * @return bool 当图片相似则传递 true,否则是 false   4 j+ K9 x  t1 C) q3 j% f. F
  142.     * */   
    6 z/ o' z& S/ J1 T3 Y6 U
  143.    public static function isImageFileSimilar($aPath, $bPath){    , ?# E1 O4 f" b
  144.        $aHash = ImageHash::hashImageFile($aPath);    " ~2 M* S/ l* L4 ^$ I- X
  145.        $bHash = ImageHash::hashImageFile($bPath);   
    . q, i3 k  C) |
  146.        return ImageHash::isHashSimilar($aHash, $bHash);    ! E5 t0 [$ J6 l: T! y$ u8 y
  147.    }    # k7 j/ R! g) H4 D( L; h& U, ]- a
  148.    
    * H8 K5 O' w6 k1 j
  149. }" ~. g$ B9 B; T4 V" A& o
复制代码

" W# v9 g) d  o1 S* |: J
! U3 H' Q) o3 V- F$ y
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2024-5-17 12:04 , Processed in 0.116512 second(s), 19 queries .

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