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)
还没有任何评论哟~
