Advertisement

PHP比较两张图片的相似度(感知哈希算法 均值哈希)

阅读量:

一、算法原理步骤

将图片转化为8*8的缩略图,根据算法得到这64个像素的哈希值,一次比较两幅图的哈希值,哈希值不一样 count++,若count>=10则不相似,count<=5为最相似(下面的代码中我把哈希值相同的进行count++操作,count越大则相似度越大)
步骤:

  • 1.将图片缩小为8*8的尺寸
  • 2.将小图片变为灰度图像
  • 3.计算每个像素的灰度平均值
  • 4.与平均值进行比较,大于等于为 1,小于为 0,得到指纹
  • 5.将两个图片的指纹依次进行比较,相同 count++ count越大,相似度越高

二、先了解后面用到的函数

pathinfo()
返回值 :数组
以数组形式显示文件信息
在这里插入图片描述
PATHINFO_DIRNAME - 只返回 路径
PATHINFO_BASENAME - 只返回 文件名
PATHINFO_EXTENSION - 只返回 后缀名
PATHINFO_FILENAME - 只返回 不包含后缀名的文件名
eg.
在这里插入图片描述
call_user_func()
回调函数
返回值:回调函数的返回值
eg.
在这里插入图片描述
imagecreatetruecolor()
新建图像
返回值:true || false
在这里插入图片描述
getimagesize()
获得图片信息
返回值:数组
eg.
在这里插入图片描述
在这里插入图片描述
list()
将值赋给list中的参数
返回值:数组
eg.
在这里插入图片描述
imagecopyresampled()
将原图变为目标图
返回值:true || false
在这里插入图片描述
imagedestroy()
销毁图片

imagecolorat()
获得该点像素的颜色索引值
返回值:该点的RGB
在这里插入图片描述
intval()
获取整数值
返回值:int
eg.
在这里插入图片描述

三、代码

复制代码
    <?php
    /* 均值哈希
     * 1.将图片缩小为8*8的尺寸
     * 2.将小图片变为灰度图像
     * 3.计算每个像素的灰度平均值
     * 4.与平均值进行比较,大于等于为 1,小于为 0,得到指纹
     * 5.将两个图片的指纹依次进行比较,相同 count++  count越大,相似度越高
     * */
    
    class img_compare{
    
    // 比较相似度  实现步骤5
    public function compare($img1,$img2){
        static $self;
        if(!$self) $self = new static;
        $hash1 = $self->gethash($img1);
        $hash2 = $self->gethash($img2);
        if(strlen($hash1) !== strlen($hash2)) return false;
        $count = 0;
        $len = strlen($hash1);
        for($i = 0; $i < $len; $i++){
            if($hash1[$i] == $hash2[$i]){
                $count++;
            }
        }
    
        //return $count <= 10 ? true : false;   直接返回是否相似
        return $count;      // 相当于返回相似度
    
    }
    
    // 将图片文件返回为图像标识符 代表图片
    public function getimg($url){
        $name = pathinfo($url,PATHINFO_EXTENSION);    // 获得图片文件的后缀名
        $img = call_user_func('imagecreatefrom'. ( $name == 'jpg' ? 'jpeg' : $name ) , $url);   // 由文件创建图片
        return $img;
    }
    
    // 获得图片指纹
    public function gethash($url){
    
        $array = array();
        $total = 0;
    
        $new_img = imagecreatetruecolor(8,8);   // 建立一个 8*8 的黑色图像
        list($ex_w,$ex_h) = getimagesize($url);  // 将获得的图像长宽赋值给 $ex_w  $ex_h
        $ex_img = $this->getimg($url);  //  获得图片
        imagecopyresampled($new_img, $ex_img,0,0,0,0,8,8,$ex_w,$ex_h);  //  实现步骤 1 2
        imagedestroy($ex_img);   // 销毁原图
    
        for($i=0;$i<8;$i++){
            for($j=0;$j<8;$j++){
                $gray = (imagecolorat($new_img, $j, $i) >> 8) & 0xFF;     // 获得每个位置像素的索引值   0xFF  1111 1111
                $array[$i][$j] = $gray;     // 记录每个点的像素值
                $total += $gray;    // 计算总和
            }
        }
    
        imagedestroy($new_img);
        $average = intval($total / (8 * 8 * 2));   // 平均值  实现步骤3
        $hash = '';
        for($i=0;$i<8;$i++){
            for($j=0;$j<8;$j++){
                $hash .= ($array[$i][$j] >= $average) ? '1' : '0';    // 实现步骤4
            }
        }
    
        return$hash;
    }
    }
    
    /*$img = new img_compare();
    $count = $img->compare('images/arrow.png','images/abc.jpg');
    echo $count;  */

全部评论 (0)

还没有任何评论哟~