Сравните 2 изображения в php
Сравнивать 2 изображения, чтобы увидеть, являются ли они одинаковыми файлами, легко, выкинули файлы MD5, но возможно или даже правдоподобно определить, совпадают ли 2 изображения, используя PHP GD, чтобы получить разницу двух изображений. Если мы найдем разницу между двумя значениями, и все они будут белыми (то есть предположим, что они белые или даже черные), то мы бы теперь знали, что это одна и та же фотография?
Также примечание: я хотел бы знать, возможно ли получить 2 изображения одинакового размера для создания эффекта "луковой кожи", 50% прозрачности на 1 и 50% на другом.
10 ответов
ImageMagick предлагает различные инструменты, которые вы можете использовать для этого, через расширение PHP ImageMagick.
http://www.php.net/manual/en/function.imagick-compareimages.php
Самая большая проблема заключается в том, что документация для этой библиотеки практически не существует, поэтому будет много проб и ошибок.
$md5image1 = md5(file_get_contents($image1));
$md5image2 = md5(file_get_contents($image2));
if ($md5image1 == $md5image2) {
}
libpuzzle - это расширение PHP, которое может сравнивать изображения.
Аналогичный вопрос был задан в этой теме Stackru, и я разработал что-то для себя. Размещение здесь, чтобы оно могло помочь другим.
Он берет два (или более изображения) и дает вам возможность проверить разницу между ними. Варианты, такие как разрешение, чтобы использовать, и строгость.
Я также написал более подробный пост в блоге.
Я закодировал своего рода метод сравнения среднеквадратических ошибок, используя графическую библиотеку GD, уже включенную в PHP.
Я беспокоился о времени, поэтому включил несколько вариантов, например:
- Масштабирование изображений перед сравнением.
- Использование только одного канала RGB вместо воспринимаемой яркости изображения.
- Вычислите линейную разницу ошибок вместо MSE.
Но, видя результаты, если вы выполняете массовые операции, возможно, лучше всего жестко запрограммировать параметры, чтобы избежать накладных расходов на условные строки.
Это код, с некоторым испытанием и эталоном:
<?php
define('FILENAME1','./image1.png');
define('FILENAME2','./image2.png');
define('OUTEXT','png'); //Output extension
/**
* Calculate an arbitrary metric of difference between images
*
* @param resource(gd) $img1 First image
* @param resource(gd) $img2 Second image
* @param int $resX Scaled width resolution
* @param int $resY Scaled height resolution
* @param int $pow Mean square error if 2, but could be another power
* @param string $channel RGB channel or 'all' for perceived luminance
*
* @return float the calculated metric
*/
function diff($img1,$img2,$resX=false,$resY=false,$pow='2',$channel='all'){
//Scaling to image 1 size for default
if(!$resX||!$resY){
$resX=imagesx($img1); //width
$resY=imagesy($img2); //height
}
//Use imagescale() function to scale the images
$thumb1=imagescale($img1,$resX,$resY);
$thumb2=imagescale($img2,$resX,$resY);
//Sum of errors
$sum=0;
for($x=0;$x<$resX;++$x){
for($y=0;$y<$resY;++$y){
//Read pixel bytes
$bytes1=imagecolorat($thumb1,$x,$y);
$bytes2=imagecolorat($thumb2,$x,$y);
//Split the channel values from bytes
$colors1=imagecolorsforindex($thumb1,$bytes1);
$colors2=imagecolorsforindex($thumb2,$bytes2);
//Choose image channel
if($channel=='all'){
//Perceived luminance
$value1=sqrt(0.2126*$colors1['red']**2+0.7152*$colors1['green']**2+ 0.0722*$colors1['blue']**2);
$value2=sqrt(0.2126*$colors2['red']**2+0.7152*$colors2['green']**2+ 0.0722*$colors2['blue']**2);
}else{
//RGB channel
$value1=$colors1[$channel];
$value2=$colors2[$channel];
}
$sum+=abs($value1-$value2)**$pow;
}
}
//Return mean of the error sum
return $sum/($resX*$resY);
}
//Show image in HTML
function imgdraw($imgobj){
//Choose function
$image="image".OUTEXT;
//Capture the image data stream
ob_start();
$image($imgobj);
$data = ob_get_clean();
//Create and HTML img
echo '<img src="data:image/png;base64,'.base64_encode($data).'" />';
}
//Load an image
function loadimg($filename){
//Get filename extension
$ext=substr($filename,strrpos($filename,'.')+1);
//Create image object
$imagecreate="imagecreatefrom$ext";
return $imagecreate($filename);
}
//Test
$img1=loadimg(FILENAME1);
$img2=loadimg(FILENAME2);
if( !$img1 || !$img2){
//Problem reading the files
die("Error loading image files");
}else{
imgdraw($img1);
imgdraw($img2);
}
//Times for 133x144 pixels png images
echo "<p>original size MSE perceived luminance: ".diff($img1,$img2)."</p>";
//time: 0.2281 seconds.
echo "<p>original size MSE green channel: ".diff($img1,$img2,false,false,2,'green')."</p>";
//time: 0.1364 seconds.
echo "<p>original size linear perceived luminance: ".diff($img1,$img2,false,false,1)."</p>";
//time: 0.1920 seconds.
echo "<p>original size linear green channel: ".diff($img1,$img2,false,false,1,'green')."</p>";
//time: 0.1351 seconds.
echo "<p>64x64 MSE perceived luminance: ".diff($img1,$img2,64,64)."</p>";
//time: 0.0431 seconds.
echo "<p>64x64 MSE green channel: ".diff($img1,$img2,64,64,2,'green')."</p>";
//time: 0.0293 seconds.
echo "<p>64x64 linear perceived luminance: ".diff($img1,$img2,64,64,1)."</p>";
//time: 0.0423 seconds.
echo "<p>64x64 linear green channel: ".diff($img1,$img2,64,64,1,'green')."</p>";
//time: 0.0293 seconds.
echo "<p>16x16 MSE perceived luminance: ".diff($img1,$img2,16,16)."</p>";
//time: 0.0028 seconds.
echo "<p>16x16 MSE green channel: ".diff($img1,$img2,16,16,2,'green')."</p>";
//time: 0.0027 seconds.
echo "<p>16x16 linear perceived luminance: ".diff($img1,$img2,16,16,1)."</p>";
//time: 0.0027 seconds.
echo "<p>16x16 linear green channel: ".diff($img1,$img2,16,16,1,'green')."</p>";
//time: 0.0018 seconds.
?>
Функция сравнения изображений в PHP с библиотекой GD http://www.robert-lerner.com/imagecompare.php
Если вы сравниваете только два файла, то хеширование данных, а затем сравнение - идеальное решение. Если вы сравниваете большое количество файлов, то лучше сначала отсортировать их по размеру, а затем сравнивать только с одинаковым размером.
Мне пришлось дедуплицировать набор изображений JPEG, где разница между двумя пиксельными изображениями была одинаковой:
- разные метаданные, например изображения имели разные IFD0:ModifyDate
- различные двоичные данные, например, изображения были сжаты без потерь с помощью другого программного обеспечения
Решение, которое я использовал, было следующим:
- открыть изображение с помощью
createimagefromjpeg
функция - сохранить изображение в формате GD2, используя
imagegd2
- сравнить версии GD2, используя сопоставление хешей или сравнение строк
Не уверен, что это так просто, и решение выходит, но, вероятно, вы можете получить представление об обнаружении изображения из:
Распознавание лиц с помощью PHP
Фильтр обнаженных изображений (класс)
Если вы используете PHP 8.1 или выше, вы можете использовать для этого библиотеку https://github.com/sapientpro/image-comparator:
$comparator = new SapientPro\ImageComparator\ImageComparator();
$similarity = $imageComparator->compare('your-images/your-image1.jpg', 'your-images/your-image12.jpg');
echo $similarity; // 82.3