JuangaCovas.info

La página personal de Juan Gabriel Covas

Herramientas de usuario

Herramientas del sitio


personal:codigo:image-compare

PHP: Cómo saber si dos imágenes son prácticamente iguales

Quick and dirty image comparison, does the job (tested on personal project).

Code from PHPClasses by Ákos Nikházy

Usage example

$compare_obj = new compareImages();
$compare_res = $compare_obj->compare('filea', 'fileb');
if ($compare_res < 10) { // almost identical images
  [...]
}

compareImages class

/*
	two images are almost the same when the hammered distance is less than 10
	try it with images like this:
		1. the example images
		2. two complatly different image
		3. the same image (returned number should be 0)
		4. the same image but with different size, even different aspect ratio (returned number should be 0)
	you will see how the returned number will represent the similarity of the images.
	$class = new compareImages;
	echo $class->compare('1.jpg','2.jpg');
*/
class compareImages
{
	private function mimeType($i)
	{
		/*returns array with mime type and if its jpg or png. Returns false if it isn't jpg or png*/
		$mime = getimagesize($i);
		$return = array($mime[0],$mime[1]);
		switch ($mime['mime'])
		{
			case 'image/jpeg':
				$return[] = 'jpg';
				return $return;
			case 'image/png':
				$return[] = 'png';
				return $return;
			default:
				return false;
		}
	}
	private function createImage($i)
	{
		/*retuns image resource or false if its not jpg or png*/
		$mime = $this->mimeType($i);
		if($mime[2] == 'jpg')
		{
			return imagecreatefromjpeg ($i);
		}
		else if ($mime[2] == 'png')
		{
			return imagecreatefrompng ($i);
		}
		else
		{
			return false;
		}
	}
	private function resizeImage($i,$source)
	{
		/*resizes the image to a 8x8 squere and returns as image resource*/
		$mime = $this->mimeType($source);
		$t = imagecreatetruecolor(8, 8);
		$source = $this->createImage($source);
		imagecopyresized($t, $source, 0, 0, 0, 0, 8, 8, $mime[0], $mime[1]);
		return $t;
	}
	private function colorMeanValue($i)
	{
		/*returns the mean value of the colors and the list of all pixel's colors*/
		$colorList = array();
		$colorSum = 0;
		for($a = 0;$a<8;$a++)
		{
			for($b = 0;$b<8;$b++)
			{
				$rgb = imagecolorat($i, $a, $b);
				$colorList[] = $rgb & 0xFF;
				$colorSum += $rgb & 0xFF;
			}
		}
		return array($colorSum/64,$colorList);
	}
	private function bits($colorMean)
	{
		/*returns an array with 1 and zeros. If a color is bigger than the mean value of colors it is 1*/
		$bits = array();
		foreach($colorMean[1] as $color){$bits[]= ($color>=$colorMean[0])?1:0;}
		return $bits;
	}
	public function compare($a,$b)
	{
		/*main function. returns the hammering distance of two images' bit value*/
		$i1 = $this->createImage($a);
		$i2 = $this->createImage($b);
		if(!$i1 || !$i2){return false;}
		$i1 = $this->resizeImage($i1,$a);
		$i2 = $this->resizeImage($i2,$b);
		imagefilter($i1, IMG_FILTER_GRAYSCALE);
		imagefilter($i2, IMG_FILTER_GRAYSCALE);
		$colorMean1 = $this->colorMeanValue($i1);
		$colorMean2 = $this->colorMeanValue($i2);
		$bits1 = $this->bits($colorMean1);
		$bits2 = $this->bits($colorMean2);
		$hammeringDistance = 0;
		for($a = 0;$a<64;$a++)
		{
			if($bits1[$a] != $bits2[$a])
			{
				$hammeringDistance++;
			}
		}
		return $hammeringDistance;
	}
}

~~DISCUSSION|Comentarios~~

personal/codigo/image-compare.txt · Última modificación: 10/07/2020 17:50 por Juanga Covas