PHP实现搜索相似图片
作者:hebedich 发布时间:2024-05-03 15:52:53
标签:php,图片,相似度
感知哈希算法
count < =5 匹配最相似
count > 10 两张不同的图片
var_dump(ImageHash::run(‘./1.png', ‘./psb.jpg'));
<?php
class ImageHash {
const FILE_NOT_FOUND = '-1';
const FILE_EXTNAME_ILLEGAL = '-2';
private function __construct() {}
public static function run($src1, $src2) {
static $self;
if(!$self) $self = new static;
if(!is_file($src1) || !is_file($src2)) exit(self::FILE_NOT_FOUND);
$hash1 = $self->getHashValue($src1);
$hash2 = $self->getHashValue($src2);
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;
}
public function getImage($file) {
$extname = pathinfo($file, PATHINFO_EXTENSION);
if(!in_array($extname, ['jpg','jpeg','png','gif'])) exit(self::FILE_EXTNAME_ILLEGAL);
$img = call_user_func('imagecreatefrom'. ( $extname == 'jpg' ? 'jpeg' : $extname ) , $file);
return $img;
}
public function getHashValue($file) {
$w = 8;
$h = 8;
$img = imagecreatetruecolor($w, $h);
list($src_w, $src_h) = getimagesize($file);
$src = $this->getImage($file);
imagecopyresampled($img, $src, 0, 0, 0, 0, $w, $h, $src_w, $src_h);
imagedestroy($src);
$total = 0;
$array = array();
for( $y = 0; $y < $h; $y++) {
for ($x = 0; $x < $w; $x++) {
$gray = (imagecolorat($img, $x, $y) >> 8) & 0xFF;
if(!isset($array[$y])) $array[$y] = array();
$array[$y][$x] = $gray;
$total += $gray;
}
}
imagedestroy($img);
$average = intval($total / ($w * $h * 2));
$hash = '';
for($y = 0; $y < $h; $y++) {
for($x = 0; $x < $w; $x++) {
$hash .= ($array[$y][$x] >= $average) ? '1' : '0';
}
}
var_dump($hash);
return $hash;
}
}
var_dump(ImageHash::run('./1.png', './psb.jpg'));
方法二:
hash($f);
}
return $isString ? $result[0] : $result;
}
public function checkIsSimilarImg($imgHash, $otherImgHash){
if (file_exists($imgHash) && file_exists($otherImgHash)){
$imgHash = $this->run($imgHash);
$otherImgHash = $this->run($otherImgHash);
}
if (strlen($imgHash) !== strlen($otherImgHash)) return false;
$count = 0;
$len = strlen($imgHash);
for($i=0;$i<$len;$i++){
if ($imgHash{$i} !== $otherImgHash{$i}){
$count++;
}
}
return $count <= (5 * $rate * $rate) ? true : false;
}
public function hash($file){
if (!file_exists($file)){
return false;
}
$height = 8 * $this->rate;
$width = 8 * $this->rate;
$img = imagecreatetruecolor($width, $height);
list($w, $h) = getimagesize($file);
$source = $this->createImg($file);
imagecopyresampled($img, $source, 0, 0, 0, 0, $width, $height, $w, $h);
$value = $this->getHashValue($img);
imagedestroy($img);
return $value;
}
public function getHashValue($img){
$width = imagesx($img);
$height = imagesy($img);
$total = 0;
$array = array();
for ($y=0;$y<$height;$y++){
for ($x=0;$x<$width;$x++){
$gray = ( imagecolorat($img, $x, $y) >> 8 ) & 0xFF;
if (!is_array($array[$y])){
$array[$y] = array();
}
$array[$y][$x] = $gray;
$total += $gray;
}
}
$average = intval($total / (64 * $this->rate * $this->rate));
$result = '';
for ($y=0;$y<$height;$y++){
for ($x=0;$x<$width;$x++){
if ($array[$y][$x] >= $average){
$result .= '1';
}else{
$result .= '0';
}
}
}
return $result;
}
public function createImg($file){
$ext = $this->getFileExt($file);
if ($ext === 'jpeg') $ext = 'jpg';
$img = null;
switch ($ext){
case 'png' : $img = imagecreatefrompng($file);break;
case 'jpg' : $img = imagecreatefromjpeg($file);break;
case 'gif' : $img = imagecreatefromgif($file);
}
return $img;
}
public function getFileExt($file){
$infos = explode('.', $file);
$ext = strtolower($infos[count($infos) - 1]);
return $ext;
}
}
调用方式如下:
require_once "Imghash.class.php";
$instance = ImgHash::getInstance();
$result = $instance->checkIsSimilarImg('chenyin/IMG_3214.png', 'chenyin/IMG_3212.JPG');
如果$result值为true, 则表明2个图片相似,否则不相似。


猜你喜欢
- 以下所描述无理论依据,纯属经验谈。MySQL使用4.1以上版本,管他是什么字符集,一律使用默认。不用去设置MySQL。然后举个使用GB231
- 1、subprocess这个模块来产生子进程,并且可以连接到子进程的标准输入、输出、错误中,还可以获得子进程的返回值。2、subproces
- 大家好,并发编程 今天开始进入第二篇。今天的内容会比较基础,主要是为了让新手也能无障碍地阅读,所以还是要再巩固下基础。学完了基础,你们也就能
- editTable.js 提供编辑表格当前行、添加一行、删除当前行的操作,其中可以设置参数,如:operatePos 用于设置放置操作的列,
- 今天是 Firefox3的2008下载日 ,这就意味着Firefox3正式发布了。Firefox3有众多的改进和新功能,我最关注的功能之一是
- 之前,我曾转过一个单元测试框架系列的文章,里面介绍了 unittest、nose/nose2 与 pytest 这三个最受人欢迎的 Pyth
- 一 什么是WebsocketWebSocket是一种在单个TCP连接上进行全双工通信的协议WebSocket使得客户端和服务器之间的数据交换
- 本文以实例形式讲述了使用DataSet Datatable更新数据库的三种实现方法,包括CommandBuilder 方法、DataAdap
- python的版本及依赖的库的安装#版本python 3.7.1pip install pywin32==224pip install nu
- 其实要将MSSQL数据库的数据导出为.sql格式的文件很简单,微软的SQL Server 2008已经拥有了这一功能具体可以查看这篇文章。今
- 随着传统的数据库、计算机网络和数字通信技术的飞速发展,以数据分布存储和分布处理为主要特征的分布式数据库系统的研究和开发越来越受到人们的关注。
- 在深度学习中,经常需要动态调整学习率,以达到更好地训练效果,本文纪录在pytorch中的实现方法,其优化器实例为SGD优化器,其他如Adam
- 前言因为一些懂得都懂的原因,我的父母对于我电脑上的文件内容特别感兴趣。为了防止信息泄露,我连夜用Python做了一个文件加密器,防止我的重要
- 1、golang中获取请求接口中数据(GET)方式一: API参数 ctx.Param(name string)或者ctx.Params.B
- 有时候想要把几张图放在一起plot,比较好对比,subplot和subplots都可以实现,具体对比可以查看参考博文。这里用matplotl
- 前言在最一开始,我的B站收藏一直是存放在默认收藏夹中,但是随着视频收藏的越来越多,没有分类的视频放在一起,想在众多视频中找到想要的视频非常困
- pandas基于numpy,所以其中的空值nan和numpy.nan是等价的。numpy中的nan并不是空对象,其实际上是numpy.flo
- 一.问题描述python 中使用open打开某个文件写入时,往往会发现需要写入的文件不在同级目录下。这样就需要根据文件的路径来找到并打开。但
- 引言安装或者更新完pytorch后,运行不了,显示错误:(base) xu@xusu:~$ pythonPython 3.7.1 (defa
- 本文实例讲述了python字典序问题,分享给大家供大家参考。具体如下:问题描述:将字母从左向右的次序与字母表中的次序相同,且每个字符最大出现