zoukankan      html  css  js  c++  java
  • php实现图片相似搜索

    本人qq群也有许多的技术文档,希望可以为你提供一些帮助(非技术的勿加)。

    QQ群:   281442983 (点击链接加入群:http://jq.qq.com/?_wv=1027&k=29LoD19)    QQ:1542385235

    几天前看到阮一峰的博客里写到关于相似图片搜索的原理, 里面介绍了Google相似图片搜索的大致原理,主要是从Neal Krawetz博士的LOOKS LIKE IT翻译而来。文章详细的介绍了相似图片搜索处理的相关步骤,并且给出了一个python的实现,由于我对PHP比较熟,所以写了个PHP的版本。
     
    图片相似搜索的简单原理
     
    根据文章里的描述,其实原理比较简单,大致有如下几个步骤:
     
    1、缩小尺寸。将图片缩小到8×8的尺寸,总共64个像素。这一步的作用是去除图片的细节,只保留结构、明暗等基本信息,摒弃不同尺寸、比例带来的图片差异。
     
    2、简化色彩。将缩小后的图片,转为64级灰度。也就是说,所有像素点总共只有64种颜色。
     
    3、计算平均值。计算所有64个像素的灰度平均值。
     
    4、比较像素的灰度。将每个像素的灰度,与平均值进行比较。大于或等于平均值,记为1;小于平均值,记为0。
     
    5、计算哈希值。将上一步的比较结果,组合在一起,就构成了一个64位的整数,这就是这张图片的指纹。组合的次序并不重要,只要保证所有图片都采用同样次序就行了。得到指纹以后,就可以对比不同的图片,看看64位中有多少位是不一样的。
     
    这种算法的优点是简单快速,不受图片大小缩放的影响,缺点是图片的内容不能变更。实际应用中,往往采用更强大的pHash算法和SIFT算法,它们能够识别图片的变形。只要变形程度不超过25%,它们就能匹配原图。
     
    图片相似搜索的PHP实现
     
    原文中给出了一个python版本的实现,代码只有53行。我写了个对应的PHP版本,由于直接是用类写的,所以代码有100行,具体如下:
     
    hash($f);
    }
    return $isString ? $result[0] : $result;
    }
    public function checkIsSimilarImg($imgHash, $otherImgHash){
    if (file_exists($imgHash) && file_exists($otherImgHash)){
    $imgHash = $this->run($imgHash);
    $otherImgHash = $this->run($otherImgHash);
    }
    if (strlen($imgHash) !== strlen($otherImgHash)) return false;
    $count = 0;
    $len = strlen($imgHash);
    for($i=0;$i<$len;$i++){
    if ($imgHash{$i} !== $otherImgHash{$i}){
    $count++;
    }
    }
    return $count <= (5 * $rate * $rate) ? true : false;
    }
    public function hash($file){
    if (!file_exists($file)){
    return false;
    }
    $height = 8 * $this->rate;
    $width = 8 * $this->rate;
    $img = imagecreatetruecolor($width, $height);
    list($w, $h) = getimagesize($file);
    $source = $this->createImg($file);
    imagecopyresampled($img, $source, 0, 0, 0, 0, $width, $height, $w, $h);
    $value = $this->getHashValue($img);
    imagedestroy($img);
    return $value;
    }
    public function getHashValue($img){
    $width = imagesx($img);
    $height = imagesy($img);
    $total = 0;
    $array = array();
    for ($y=0;$y<$height;$y++){
    for ($x=0;$x<$width;$x++){
    $gray = ( imagecolorat($img, $x, $y) >> 8 ) & 0xFF;
    if (!is_array($array[$y])){
    $array[$y] = array();
    }
    $array[$y][$x] = $gray;
    $total += $gray;
    }
    }
    $average = intval($total / (64 * $this->rate * $this->rate));
    $result = '';
    for ($y=0;$y<$height;$y++){
    for ($x=0;$x<$width;$x++){
    if ($array[$y][$x] >= $average){
    $result .= '1';
    }else{
    $result .= '0';
    }
    }
    }
    return $result;
    }
    public function createImg($file){
    $ext = $this->getFileExt($file);
    if ($ext === 'jpeg') $ext = 'jpg';
    $img = null;
    switch ($ext){
    case 'png' : $img = imagecreatefrompng($file);break;
    case 'jpg' : $img = imagecreatefromjpeg($file);break;
    case 'gif' : $img = imagecreatefromgif($file);
    }
    return $img;
    }
    public function getFileExt($file){
    $infos = explode('.', $file);
    $ext = strtolower($infos[count($infos) - 1]);
    return $ext;
    }
    }
    调用方式如下:
     
    require_once "Imghash.class.php";
    $instance = ImgHash::getInstance();
    $result = $instance->checkIsSimilarImg('chenyin/IMG_3214.png', 'chenyin/IMG_3212.JPG');
    如果$result值为true, 则表明2个图片相似,否则不相似。
     
     
     
    其他
     
    在实际的相似图片搜索中,算图片的指纹并不是难点,难点而是在怎么从海量的图片指纹里找出与之相似的指纹。

    个人公众号谢谢各位老铁支持

    本人qq群也有许多的技术文档,希望可以为你提供一些帮助(非技术的勿加)。

    QQ群:   281442983 (点击链接加入群:http://jq.qq.com/?_wv=1027&k=29LoD19)    QQ:1542385235

    我的淘宝店,可以进去逛逛噢:https://shop108912636.taobao.com/index.htm?spm=2013.1.w5001-7867000954.3.1d29318dPlLar7&scene=taobao_shop

  • 相关阅读:
    #在蓝懿学习iOS的日子#Day10
    #在蓝懿学习iOS的日子#Day9
    #在蓝懿学习iOS的日子#第三个练习日
    #在蓝懿学习iOS的日子#Day8
    WCF基础:绑定(二)
    WCF基础:绑定(三)
    WCF基础:绑定(一)
    MVC框架中的值提供机制(三)
    MVC框架中的值提供机制(二)
    MVC框架中的值提供机制(一)
  • 原文地址:https://www.cnblogs.com/piwefei/p/5354087.html
Copyright © 2011-2022 走看看