判断两张图片的相似性(可用来实现根据缩略图查找原图功能)
话不多说直接上代码
<?php
//引入图片相似度计算类
include_once "./imageDHASH.php";
$img = new ImgCompareDHASH();
//计算两个图片相似性 - 返回相似度百分比
$count1 = $img->ComparePic('./images/pic1.jpg','./images/pic2.png');
echo '相似度:'.$count1."%\n";
imageDHASH类代码如下:
<?php
/* 差异值哈希
* 1.将图片缩小为8*8的尺寸(这里把传来的图片全部转成统一大小)
* 2.将第一步转换的图片再次转换为灰度图像
* 3.计算每个像素的灰度的差值(如果大于平均值就取1,否则取0),得到图片指纹
* 4.然后对比两个图片的指纹依次进行比较,数字相同多的即为相似度较高
* */
class ImgCompareDHASH{
//设定需要转换的图片尺寸
public $width = 8;
public $height = 8;
public $scalar = 8;
/**
* 主方法 - 对比两张图片,得到相似度
*/
public function ComparePic($img1, $img2){
//获得img1的指纹
$hash1 = $this->getHash($img1);
//获得img2的指纹
$hash2 = $this->getHash($img2);
//对比长度
if(strlen($hash1) !== strlen($hash2)) {
return false;
}
//计算汉明距离(可参考我另一篇文章[《计算两数的汉明距离》](https://www.imooc.com/article/317960))
$result = $this->hd($hash1, $hash2);
//计算相似度
$result_percent = ($result / ($this->scalar * $this->scalar)) * 100;
//返回相似度
return $result_percent;
}
/**
* 计算汉明距离
*/
public function hd($h1, $h2)
{
$len = strlen($h1);
$dist = 0;
for ($i = 0;$i < $len; $i++) {
if ( $h1[$i] == $h2[$i] )
$dist++;
}
return $dist;
}
// 获得图片指纹
public function getHash($url){
/**
* 新建一个 width * height 真彩色图像
* 返回一个图像标识符
*/
$im = imagecreatetruecolor($this->width, $this->height);
//获取图片宽和高
list($ex_w, $ex_h) = getimagesize($url);
// 获得图片文件的后缀名
$name = pathinfo($url, PATHINFO_EXTENSION);
/**
* 根据扩展名判断使用什么方法进行处理
* [PHP图像处理集合函数](https://www.php.net/manual/zh/book.image.php)
* $allowedTypes = array(
* 1, // [] gif
* 2, // [] jpg
* 3, // [] png
* 6 // [] bmp
* );
*
* switch ($type) {
* case 1 :
* $im = imageCreateFromGif($filepath);
* break;
* case 2 :
* $im = imageCreateFromJpeg($filepath);
* break;
* case 3 :
* $im = imageCreateFromPng($filepath);
* break;
* case 6 :
* $im = imageCreateFromBmp($filepath);
* break;
* }
*/
$ex_img = call_user_func('imagecreatefrom'. ( $name == 'jpg' ? 'jpeg' : $name ) , $url);
//重采样拷贝部分图像并调整大小(把原图进行采样,然后给到$im,变换图片大小)
imagecopyresampled($im, $ex_img, 0, 0, 0, 0, $this->width, $this->height, $ex_w, $ex_h);
//对图像使用过滤器 - 转换图片为灰度图
imagefilter($im, IMG_FILTER_GRAYSCALE);
//销毁缓存
imagedestroy($ex_img);
//记录每个像素值
$pixels = [];
for($i = 0; $i < $this->scalar; $i++){
for($j = 0; $j < $this->scalar; $j++){
/**
* 获得每个位置像素的索引值
* 0xFF:表示16进制 相当于 十进制 的 255
* 1111 1111
* 计算图片灰度值
*/
$gray = ImageColorAt($im, $i, $j) & 255;
//记录每个点的像素值
$pixels[] = $gray;
}
}
//销毁缓存
imagedestroy($im);
/*计算所有像素的灰阶平均值*/
$average = intval(array_sum($pixels) / count($pixels));
//获取图片指纹
$hashStr = '';
foreach ($pixels as $gray){
$hashStr .= ($gray >= $average) ? '1' : '0';
}
return $hashStr;
}
}
效果如下:
以上程序测试用图如下
点击查看更多内容
1人点赞
评论
共同学习,写下你的评论
评论加载中...
作者其他优质文章
正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦