当前位置: 首页 > news >正文

【PHP】对比两张图片的相似度

目录

一、需求

二、相似度算法

三、示例

1、差异值哈希

2、均值哈希

四、计算结果

1、差异值哈希

2、均值哈希


一、需求

给出两张图片,对比这两张图片的相似度,如果相似度大于设定的某个阈值(比如说大于80),就可以判断两张图片是类似的,如果小于某个阈值说明两张图片差异较大。

下面的示例使用的是ThinkPHP5。

二、相似度算法

下面介绍两种计算相似度的方法,一种是差异值哈希,一种是均值哈希。

1、差异值哈希

  • 将图片缩小为8*8的尺寸
  • 将小图片变为灰度图像
  • 计算每个像素的灰度的差值
  • 将两个图片的指纹依次进行比较

2、均值哈希

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

两种算法均是先把图片缩小,变成灰度图像,差异值哈希是计算每个像素的灰度差值,再将两张图片依次进行比较,均值哈希算法是计算每个像素的灰度平均值,再与平均值作比较,再将两张图片的指纹依次对比

三、示例

1、差异值哈希

<?php
namespace app\index\controller;
use think\Controller;/* 差异值哈希* 1.将图片缩小为8*8的尺寸* 2.将小图片变为灰度图像* 3.计算每个像素的灰度的差值* 4.将两个图片的指纹依次进行比较* */class ImgCompareDHASH extends Controller
{//正方形图片public $width = 8;public $height = 8;public $scalar = 8;/*** 主方法 - 对比两张图片,得到相似度  -- 步骤4*/public function compare($img1, $img2){$hash1 = $this->gethash($img1);$hash2 = $this->gethash($img2);if(strlen($hash1) !== strlen($hash2)) {return false;}$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 真彩色图像  -- 步骤1* 返回一个图像标识符*/$new_img = imagecreatetruecolor($this->width, $this->height);   //获取图片宽和高list($ex_w, $ex_h) = getimagesize($url);// 获得图片文件的后缀名$name = pathinfo($url, PATHINFO_EXTENSION);$ex_img = call_user_func('imagecreatefrom'. ( $name == 'jpg' ? 'jpeg' : $name ) , $url);//调整图片尺寸 - 重采样拷贝部分图像并调整大小imagecopyresampled($new_img, $ex_img, 0, 0, 0, 0, $this->width, $this->height, $ex_w, $ex_h);//转换图片为灰度图  -- 步骤2imagefilter($new_img, 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($new_img, $i, $j) & 255;//记录每个点的像素值$pixels[] = $gray;     }}imagedestroy($new_img);// 计算所有像素的灰阶平均值  -- 步骤3   $average = intval(array_sum($pixels) / count($pixels));    //获取图片指纹$hashStr = '';    foreach ($pixels as $gray){    $hashStr .= ($gray >= $average) ? '1' : '0';}return $hashStr;}
}

2、均值哈希

<?php
namespace app\index\controller;
use think\Controller;/* 均值哈希* 1.将图片缩小为8*8的尺寸* 2.将小图片变为灰度图像* 3.计算每个像素的灰度平均值* 4.与平均值进行比较,大于等于为 1,小于为 0,得到指纹* 5.将两个图片的指纹依次进行比较,相同 count++  count越大,相似度越高* */class ImgCompareAVG extends Controller
{// 比较相似度  实现步骤5public 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;      // 相当于返回相似度}// 将图片文件返回为图像标识符 代表图片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 2imagedestroy($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;}}

四、计算结果

输入的两张图片

1、差异值哈希

2、均值哈希

这两种算法是通过计算汉明距离或相同位数来评估相似度,不能代表绝对的相似,但可作为参考,两种算法各有特点,其中差异值哈希计算的结果相对比较可靠。

http://www.xdnf.cn/news/1241677.html

相关文章:

  • WPF 按钮背景色渐变
  • 服务器的Mysql 集群技术
  • linux下docker安装ollama
  • Petalinux快捷下载
  • 部署 Kibana 8.2.2 可视化管理 Elasticsearch 8.2.2 集群
  • RabbitMQ--介绍
  • 【深度学习新浪潮】近三年零样本图像分类研发进展调研
  • 文件与目录操作命令
  • MySQL 基本操作入门指南
  • Apache IoTDB(3):时序数据库 IoTDB Docker部署实战
  • [GYCTF2020]FlaskApp
  • Nginx vs Spring Cloud Gateway:限流功能深度对比与实践指南
  • 直角坐标系里的四象限对NLP中的深层语义分析的积极影响和启示
  • spring boot开发中的资源处理等问题
  • 怎样推动AI技术在人机协同中的发展?
  • RTSP/RTMP播放器超低延迟实战:无人机远控视觉链路的工程实践
  • vue3+vue-flow制作简单可拖拽可增删改流程图
  • Qt 自动无法加载数据库为空
  • Go语言select
  • 开源的现代数据探索和可视化平台:Apache Superset 使用 Docker Compose
  • 笔记本电脑联想T14重启后无法识别外置红米屏幕
  • 如何手动打包 Linux(麒麟系统)的 Qt 程序
  • JVM学习专题(四)对象创建过程
  • 【Spring Boot 】Spring Boot + OpenAI API 万能集成模板,实现快速集成AI
  • sqli-labs通关笔记-第30关GET字符注入(WAF绕过 双引号闭合 手工注入+脚本注入两种方法)
  • AI Agents漏洞百出,恶意提示等安全缺陷令人担忧
  • 高防服务器租用的作用都有哪些?
  • 随笔之 ClickHouse 列式分析数据库安装注意事项及基准测试
  • 【BUUCTF系列】[SUCTF 2019]EasySQL1
  • 【论文简读】LongSplat