The algorithm may not be new, and is
not ideal , but, surprisingly, it works. No graphs and correlations.
To begin with, it is worth noting that the comparison is very approximate (at least at this stage), from time to time two completely different photos turn out to be similar by 60%, and also hard modifications (turns, inversion, cropping) are not taken into account - for this you need to bring and bring. For me personally, two parameters turned out to be the most important:
speed ,
independence from image resolution and the ability to compare “images” right in the database.
Principle
- Open the original image
- Scale it to the size of the mask (in my case it’s 20 by 20, I don’t need big sizes - a comparison is approximate, it’s quite possible to make a mask and 10 by 10).
- Calculate the main color of the mask.
- We create an array, where the value is a key of type af2 (1,2 is the coordinates, as in naval combat. 2 is the discrepancy with the main brightness).
- We generate a string - a key.
- Compare two lines by relevance.
Code
In this case, there is a version that works through GD with
PNG images.
// -
function getimageid($image)
{
//
$size=getimagesize($image);
//
$image=imagecreatefrompng($image);
//
$zone=imagecreate(20,20);
//
imagecopyresized($zone,$image,0,0,0,0,20,20,$size[0],$size[1]);
//
$colormap=array();
//
$average=0;
//
$result=array();
//
for ($x=0;$x<20;$x++)
for ($y=0;$y<20;$y++)
{
$color=imagecolorat($zone,$x,$y);
$color=imagecolorsforindex($zone,$color);
// Ryotsuke
$colormap[$x][$y]= 0.212671 * $color[ 'red' ] + 0.715160 * $color[ 'green' ] + 0.072169 * $color[ 'blue' ];
$average += $colormap[$x][$y];
}
//
$average /= 400;
//
for ($x=0;$x<20;$x++)
for ($y=0;$y<20;$y++)
$result[]=($x<10?$x:chr($x+97)).($y<10?$y:chr($y+97)).round(2*$colormap[$x][$y]/$average);
//
return join( ' ' ,$result);
}
* This source code was highlighted with Source Code Highlighter .
// ""
function imagediff($image,$desc)
{
$image=explode( ' ' ,$image);
$desc=explode( ' ' ,$desc);
$result=0;
foreach ($image as $bit)
if (in_array($bit,$desc))
$result++;
return $result/((count($image)+count($desc))/2);
}
* This source code was highlighted with Source Code Highlighter .
* similarity counting function is approximate - it is better to perform this action on the side of the base.
Examples

Surprisingly,
95% 87% similarity (with the addition of UPD-2)
')
52% similarity
28% similarity
100% similarityP.S
All this is only an approximate calculation, it is not possible to achieve a particularly advanced comparison in this way, but it will come down for a quick sample from the database of similar images.
PS Comments and advice accepted.
UPD Thanks
MiniM - the code is simplified.
UPD-2 A small addition:
//
for ($x=0;$x<20;$x++)
for ($y=0;$y<20;$y++)
$result[]=($x<10?$x:chr($x+97)).($y<10?$y:chr($y+97)).($colormap[$x][$y]==0? '0' :round(2*($colormap[$x][$y]>$average?$colormap[$x][$y]/$average:-1*$average/$colormap[$x][$y])));
* This source code was highlighted with Source Code Highlighter .
After that, the decrease in brightness at a point will be taken into account. Thus, the similarity in the first example will be
87% .
UPD-3 Migrated to php.