Image Comparison Function in PHP with GD Library

March 24, 2011
This function compares two images to find the percentage of differing pixels, and returns an array with the results. Does not use pattern recognition, good uses are comparing two frames from a webcam for differences with some resistance to signal interference, bad uses are trying to see how similar to pictures are of the same item at different light levels, angels, perspectives, etc.

Download Original
  1. <?php
  2. /**
  3. * Image Comparing Function (C)2011 Robert Lerner, All Rights Reserved
  4. * $image1 STRING/RESOURCE Filepath and name to PNG or passed image resource handle
  5. * $image2 STRING/RESOURCE Filepath and name to PNG or passed image resource handle
  6. * $RTolerance INTEGER (0-/+255) Red Integer Color Deviation before channel flag thrown
  7. * $GTolerance INTEGER (0-/+255) Green Integer Color Deviation before channel flag thrown
  8. * $BTolerance INTEGER (0-/+255) Blue Integer Color Deviation before channel flag thrown
  9. * $WarningTolerance INTEGER (0-100) Percentage of channel differences before warning returned
  10. * $ErrorTolerance INTEGER (0-100) Percentage of channel difference before error returned
  11.  
  12. */
  13. function imageCompare($image1, $image2, $RTolerance=0, $GTolerance=0, $BTolerance=0, $WarningTolerance=1, $ErrorTolerance=5)
  14. {
  15. if (is_resource($image1))
  16. $im = $image1;
  17. else
  18. if (!$im = imagecreatefrompng($image1))
  19. trigger_error("Image 1 could not be opened",E_USER_ERROR);
  20.  
  21. if (is_resource($image2))
  22. $im2 = $image2;
  23. else
  24. if (!$im2 = imagecreatefrompng($image2))
  25. trigger_error("Image 2 could not be opened",E_USER_ERROR);
  26.  
  27.  
  28.  
  29. $OutOfSpec = 0;
  30.  
  31. if (imagesx($im)!=imagesx($im2))
  32. die("Width does not match.");
  33. if (imagesy($im)!=imagesy($im2))
  34. die("Height does not match.");
  35.  
  36.  
  37. //By columns
  38. for ($width=0;$width<=imagesx($im)-1;$width++)
  39. {
  40. for ($height=0;$height<=imagesy($im)-1;$height++)
  41. {
  42. $rgb = imagecolorat($im, $width, $height);
  43. $r1 = ($rgb >> 16) & 0xFF;
  44. $g1 = ($rgb >> 8) & 0xFF;
  45. $b1 = $rgb & 0xFF;
  46.  
  47. $rgb = imagecolorat($im2, $width, $height);
  48. $r2 = ($rgb >> 16) & 0xFF;
  49. $g2 = ($rgb >> 8) & 0xFF;
  50. $b2 = $rgb & 0xFF;
  51.  
  52. if (!($r1>=$r2-$RTolerance && $r1<=$r2+$RTolerance))
  53. $OutOfSpec++;
  54.  
  55. if (!($g1>=$g2-$GTolerance && $g1<=$g2+$GTolerance))
  56. $OutOfSpec++;
  57.  
  58. if (!($b1>=$b2-$BTolerance && $b1<=$b2+$BTolerance))
  59. $OutOfSpec++;
  60.  
  61.  
  62. }
  63. }
  64. $TotalPixelsWithColors = (imagesx($im)*imagesy($im))*3;
  65.  
  66. $RET['PixelsByColors'] = $TotalPixelsWithColors;
  67. $RET['PixelsOutOfSpec'] = $OutOfSpec;
  68.  
  69. if ($OutOfSpec!=0 && $TotalPixelsWithColors!=0)
  70. {
  71. $PercentOut = ($OutOfSpec/$TotalPixelsWithColors)*100;
  72. $RET['PercentDifference']=$PercentOut;
  73. if ($PercentOut>=$WarningTolerance) //difference triggers WARNINGTOLERANCE%
  74. $RET['WarningLevel']=TRUE;
  75. if ($PercentOut>=$ErrorTolerance) //difference triggers ERRORTOLERANCE%
  76. $RET['ErrorLevel']=TRUE;
  77. }
  78.  
  79. RETURN $RET;
  80. }


Use:


$diff = imageCompare("c:/building.png","c:/building2.png",5,5,5,1,5);
echo "<pre>";
print_r($diff);


Using these images:


Building 1 Building 2

Returns:


Array
(
     [PixelsByColors] => 19608
     [PixelsOutOfSpec] => 224
     [PercentDifference] => 1.1423908608731
     [WarningLevel] => 1
)


Interpretation of Results:


PixelsByColors = Pixel Count * 3 (for R, G, and B)
PixelsOutOfSpec = (If a pixel varies outside of xTolerance, for each red, green, and blue. Where x = R/G/B) If any channel exceeds the threshhold, this number is incremented.
PercentDifference = PixelsOutOfSpec/PixelsByColors*100
WarningLevel = TRUE (or 1) if level exceeds prescribed level
ErrorLevel = TRUE (or 1) if level exceeds prescribed level


Comment


Name:

Posted: Saturday, June 18, 2011 at 1:53:18 AM
By: Mangesh
thank you for the code..

I wish to grab the pixel location where the difference is..
how do i do that?
Posted: Friday, May 4, 2012 at 8:00:29 AM
By: R. Mattu
Great!

It works for me. Thanks for posting the script.