话不多说直接上代码
<?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; } }