Advertisement
Guest User

comparison of images test multiple methods.

a guest
Mar 10th, 2014
111
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 14.37 KB | None | 0 0
  1. <?php
  2.  
  3. set_time_limit(0);
  4. error_reporting(E_ALL);
  5.  
  6. date_default_timezone_set("Europe/Amsterdam");
  7.  
  8. /*
  9. $image1 = new imagick("image1.png");
  10. $image2 = new imagick("image2.png");
  11.  
  12. $result = $image1->compareImages($image2, Imagick::METRIC_MEANSQUAREERROR);
  13. $result[0]->setImageFormat("png");
  14.  
  15. header("Content-Type: image/png");
  16. echo $result[0];
  17.  
  18. exit;
  19. */
  20. $enter = "\r\n";
  21.  
  22. class compareImages
  23. {
  24.     private function mimeType($i) {
  25.         /*returns array with mime type and if its jpg or png. Returns false if it isn't jpg or png*/
  26.         $mime = getimagesize($i);
  27.         $return = array($mime[0],$mime[1]);
  28.      
  29.         switch ($mime['mime']) {
  30.             case 'image/jpeg':
  31.                 $return[] = 'jpg';
  32.                 return $return;
  33.             case 'image/png':
  34.                 $return[] = 'png';
  35.                 return $return;
  36.             default:
  37.                 return false;
  38.         }
  39.     }  
  40.    
  41.     private function createImage($i) {
  42.         /*retuns image resource or false if its not jpg or png*/
  43.         $mime = $this->mimeType($i);
  44.      
  45.         if($mime[2] == 'jpg') {
  46.             return imagecreatefromjpeg ($i);
  47.         }
  48.         else if ($mime[2] == 'png')  {
  49.             return imagecreatefrompng ($i);
  50.         }
  51.         else {
  52.             return false;
  53.         }
  54.     }
  55.    
  56.     private function resizeImage($i,$source) {
  57.         /*resizes the image to a 8x8 squere and returns as image resource*/
  58.         $mime = $this->mimeType($source);
  59.      
  60.         $t = imagecreatetruecolor(8, 8);
  61.        
  62.         $source = $this->createImage($source);
  63.        
  64.         imagecopyresized($t, $source, 0, 0, 0, 0, 8, 8, $mime[0], $mime[1]);
  65.        
  66.         return $t;
  67.     }
  68.    
  69.     private function colorMeanValue($i) {
  70.         /*returns the mean value of the colors and the list of all pixel's colors*/
  71.         $colorList = array();
  72.         $colorSum = 0;
  73.         for($a = 0;$a<8;$a++) {
  74.             for($b = 0;$b<8;$b++) {
  75.                 $rgb = imagecolorat($i, $a, $b);
  76.                 $colorList[] = $rgb & 0xFF;
  77.                 $colorSum += $rgb & 0xFF;
  78.             }
  79.         }
  80.        
  81.         return array($colorSum/64,$colorList);
  82.     }
  83.    
  84.     private function bits($colorMean) {
  85.         /*returns an array with 1 and zeros. If a color is bigger than the mean value of colors it is 1*/
  86.         $bits = array();
  87.          
  88.         foreach($colorMean[1] as $color){$bits[]= ($color>=$colorMean[0])?1:0;}
  89.  
  90.         return $bits;
  91.     }
  92.    
  93.     public function compare($a,$b) {
  94.         /*main function. returns the hammering distance of two images' bit value*/
  95.         $i1 = $this->createImage($a);
  96.         $i2 = $this->createImage($b);
  97.        
  98.         if(!$i1 || !$i2){return false;}
  99.        
  100.         $i1 = $this->resizeImage($i1,$a);
  101.         $i2 = $this->resizeImage($i2,$b);
  102.        
  103.         imagefilter($i1, IMG_FILTER_GRAYSCALE);
  104.         imagefilter($i2, IMG_FILTER_GRAYSCALE);
  105.        
  106.         $colorMean1 = $this->colorMeanValue($i1);
  107.         $colorMean2 = $this->colorMeanValue($i2);
  108.        
  109.         $bits1 = $this->bits($colorMean1);
  110.         $bits2 = $this->bits($colorMean2);
  111.        
  112.         $hammeringDistance = 0;
  113.        
  114.         for($a = 0;$a<64;$a++) {
  115.        
  116.             if($bits1[$a] != $bits2[$a]) {
  117.                 $hammeringDistance++;
  118.             }
  119.         }
  120.          
  121.         return $hammeringDistance;
  122.     }
  123. }
  124.  
  125. class imagediff {
  126.     private $image1, $image2;
  127.     private $rectX, $rectY;
  128.     private $diference = array();
  129.     private $different_pixels = array();
  130.     private $image1src;
  131.     private $image2src;
  132.     private $rectZone;
  133.  
  134.     function __construct($img1, $img2, $rectX = 50, $rectY = 50) {
  135.         $this->image1['path'] = realpath($img1);
  136.         $this->image2['path'] = realpath($img2);
  137.         $this->image1src = $img1;
  138.         $this->image2src = $img2;
  139.         $this->rectX = $rectX;
  140.         $this->rectY = $rectY;
  141.          
  142.         if ($this->image1['path'] === false || $this->image2['path'] === false) {
  143.             throw new Exception('Image "' . htmlspecialchars($this->image1 ? $img2 : $img1) . '" not found!<br />');
  144.         }
  145.         else {
  146.             $this->image1['type'] = $this->imagetyte($this->image1['path']);
  147.             $this->image2['type'] = $this->imagetyte($this->image2['path']);
  148.         }
  149.     }
  150.  
  151.     private function imagetyte($imgname) {
  152.         $file_info = pathinfo($imgname);
  153.         if (!empty($file_info['extension'])) {
  154.             $filetype = strtolower($file_info['extension']);
  155.             $filetype = $filetype == 'jpg' ? 'jpeg' : $filetype;
  156.             $func = 'imagecreatefrom' . $filetype;
  157.             if (function_exists($func)) {
  158.                 return $filetype;
  159.             } else {
  160.                 throw new Exception('File type "' . htmlspecialchars($filetype) . '" not supported!<br />');
  161.             }
  162.         }
  163.         else {
  164.             throw new Exception('File type not supported! <br />');
  165.         }
  166.     }
  167.     public function createDiffImage($i1, $i2) {
  168.         /* http://www.phpied.com/image-diff/ */
  169.          
  170.         $this->rectZone[0] = $this->rectX;
  171.         $this->rectZone[1] = $this->rectY;
  172.          
  173.         list($src_W, $src_H) = getimagesize($i1);
  174.         $ratio_src = $src_W / $src_H;
  175.          
  176.         ($this->rectZone[0] / $this->rectZone[1] > $ratio_src) ? $this->rectZone[0] = $this->rectZone[1] * $ratio_src : $this->rectZone[1] = $this->rectZone[0] / $ratio_src;
  177.          
  178.         $i1 = @imagecreatefromjpeg($i1);
  179.         $i2 = @imagecreatefromjpeg($i2);
  180.          
  181.         $zone1 = imagecreate($this->rectZone[0], $this->rectZone[1]);
  182.         imagecopyresampled($zone1, $i1, 0, 0, 0, 0, $this->rectZone[0], $this->rectZone[1], $src_W, $src_H);
  183.         $zone2 = imagecreate($this->rectZone[0], $this->rectZone[1]);
  184.         imagecopyresampled($zone2, $i2, 0, 0, 0, 0, $this->rectZone[0], $this->rectZone[1], $src_W, $src_H);
  185.          
  186.         imagefilter($zone1, IMG_FILTER_GRAYSCALE);
  187.         imagefilter($zone2, IMG_FILTER_GRAYSCALE);
  188.         /*
  189.         $gaussian = array(array(1.0, 2.0, 1.0), array(2.0, 4.0, 2.0), array(1.0, 2.0, 1.0));
  190.         imageconvolution($zone1, $gaussian, 16, 0);
  191.         imageconvolution($zone2, $gaussian, 16, 0);
  192.         imagefilter($zone1,IMG_FILTER_PIXELATE,round($this->rectZone[0]/5,0));
  193.         imagefilter($zone2,IMG_FILTER_PIXELATE,round($this->rectZone[0]/5,0));
  194.         */
  195.          
  196.         $sx1 = imagesx($zone1);
  197.         $sy1 = imagesy($zone1);
  198.         $diffi = imagecreatetruecolor($sx1, $sy1);
  199.         $red = imagecolorallocate($diffi, 255, 0, 0);
  200.         imagefill($diffi, 0, 0, imagecolorallocate($diffi, 0, 0, 0));
  201.         $different_pixels = 0;
  202.          
  203.         $sumtotal = 0;
  204.          
  205.         for ($x = 0; $x < $sx1; $x++) {
  206.             for ($y = 0; $y < $sy1; $y++) {
  207.          
  208.                 $rgb1 = imagecolorat($zone1, $x, $y);
  209.                 $pix1 = imagecolorsforindex($zone1, $rgb1);
  210.          
  211.                 $rgb2 = imagecolorat($zone2, $x, $y);
  212.                 $pix2 = imagecolorsforindex($zone2, $rgb2);
  213.                  
  214.                 $mediapixels = pow($pix1['red']   - $pix2['red'], 2) +
  215.                                pow($pix1['green'] - $pix2['green'], 2) +
  216.                                pow($pix1['blue']  - $pix2['blue'], 2);
  217.                 $sumtotal = $sumtotal + $mediapixels;
  218.                 if ($mediapixels > 1500) {
  219.                     $different_pixels++;
  220.                     imagesetpixel($diffi, $x, $y, $red);
  221.                 }
  222.             }
  223.         }
  224.          
  225.         $total = $sx1 * $sy1;
  226.         $percent = number_format(100 * $different_pixels / $total, 2);
  227.          
  228.         array_push($this->different_pixels, $different_pixels, $percent, ($this->rectZone[0] * $this->rectZone[1]));
  229.         return $this->different_pixels;
  230.     }
  231.    
  232.     private function imagehex($image) {
  233.         error_reporting(0);
  234.         ini_set("gd.jpeg_ignore_warning", true);
  235.        
  236.         $this->rectZone[0] = $this->rectX;
  237.         $this->rectZone[1] = $this->rectY;
  238.         $size = getimagesize($image['path']);
  239.         $func = 'imagecreatefrom' . $image['type'];
  240.         $imageres = $func($image['path']);
  241.         $zone = imagecreate($this->rectZone[0], $this->rectZone[1]);
  242.         imagecopyresized($zone, $imageres, 0, 0, 0, 0, $this->rectZone[0], $this->rectZone[1], $size[0], $size[1]);
  243.         $colormap = array();
  244.         $average = 0;
  245.         $result = array();
  246.          
  247.         for ($x = 0; $x < $this->rectZone[0]; $x++) {
  248.             for ($y = 0; $y < $this->rectZone[1]; $y++) {
  249.                 $color = imagecolorat($zone, $x, $y);
  250.                 $color = imagecolorsforindex($zone, $color);
  251.                 $colormap[$x][$y] = 0.212671 * $color['red'] +
  252.                                     0.715160 * $color['green'] +
  253.                                     0.072169 * $color['blue'];
  254.                 $average += $colormap[$x][$y];
  255.             }
  256.         }
  257.  
  258.         $average /= ($this->rectZone[0] * $this->rectZone[1]);
  259.         for ($x = 0; $x < $this->rectZone[0]; $x++) {
  260.             for ($y = 0; $y < $this->rectZone[1]; $y++) {
  261.                 $result[] = ($x < 10 ? $x : chr($x + 97)) . ($y < 10 ? $y : chr($y + 97)) . round(2 * $colormap[$x][$y] / $average);
  262.             }
  263.         }
  264.          
  265.         return $result;
  266.     }
  267.  
  268.     public function diff() {
  269.         $hex1 = $this->imagehex($this->image1);
  270.         $hex2 = $this->imagehex($this->image2);
  271.         $result = (count($hex1) + count($hex2)) - count(array_diff($hex2, $hex1)) - ($this->rectZone[0] * $this->rectZone[1]);
  272.         return $result / ((count($hex1) + count($hex2)) / 2);
  273.     }    
  274. }
  275.  
  276. class imagediffOld
  277. {
  278.     private $image1;
  279.     private $image2;
  280.    
  281.     function  __construct($img1, $img2) {
  282.         $this->image1['path'] = realpath($img1);
  283.         $this->image2['path'] = realpath($img2);
  284.         if($this->image1['path'] === false || $this->image2['path'] === false) {
  285.             throw new Exception('Image "'.htmlspecialchars( $this->image1 ? $img2 : $img1 ).'" not found!');
  286.         }
  287.         else {
  288.             $this->image1['type'] = $this->imagetyte($this->image1['path']);
  289.             $this->image2['type'] = $this->imagetyte($this->image2['path']);
  290.         }
  291.     }
  292.  
  293.     private function imagetyte($imgname) {
  294.         $file_info = pathinfo($imgname);
  295.         if(!empty ($file_info['extension'])) {
  296.             $filetype = strtolower($file_info['extension']);
  297.             $filetype = $filetype == 'jpg' ? 'jpeg' : $filetype;
  298.             $func = 'imagecreatefrom' . $filetype;
  299.             if(function_exists($func)) {
  300.                 return $filetype;
  301.             }
  302.             else {
  303.                 throw new Exception('File type "'.htmlspecialchars( $filetype ).'" not supported!');
  304.             }
  305.         }
  306.         else {
  307.             throw new Exception('File type not supported!');
  308.         }
  309.     }
  310.  
  311.     private function imagehex($image) {
  312.         $size = getimagesize($image['path']);
  313.         $func = 'imagecreatefrom'.$image['type'];
  314.         $imageres = $func($image['path']);
  315.         $zone = imagecreate(20, 20);
  316.         imagecopyresized($zone, $imageres, 0, 0, 0, 0, 20, 20, $size[0], $size[1]);
  317.         $colormap = array();
  318.         $average = 0;
  319.         $result = array();
  320.         for($x=0; $x<20; $x++) {
  321.             for($y=0; $y<20; $y++) {
  322.                 $color = imagecolorat($zone, $x, $y);
  323.      
  324.                 $color = imagecolorsforindex($zone, $color);
  325.  
  326.                 $colormap[$x][$y]= 0.212671 * $color['red'] + 0.715160 * $color['green'] + 0.072169 * $color['blue'];
  327.                 $average += $colormap[$x][$y];
  328.             }
  329.         }
  330.         $average /= 400;
  331.         for($x=0; $x<20; $x++) {
  332.             for($y=0; $y<20; $y++) {
  333.                 $result[]=($x<10?$x:chr($x+97)) . ($y<10?$y:chr($y+97)) . round(2*$colormap[$x][$y]/$average);
  334.             }
  335.         }
  336.         return $result;
  337.     }
  338.  
  339.     public function diff() {
  340.         $hex1 = $this->imagehex($this->image1) ;
  341.         $hex2 = $this->imagehex($this->image2);
  342.         $result=(count($hex1) + count($hex2)) - count(array_diff($hex2,$hex1))-400;
  343.         return $result / ( ( count($hex1) + count($hex2) ) / 2 );
  344.     }
  345. }
  346.    
  347. $photos = glob("d:/photos/snapshots/20140301/*.jpg");
  348. usort($photos, function($a, $b) {
  349.     return strcmp($b, $a);
  350. });
  351. $current = array_shift($photos);
  352. $cnt = 0;
  353. echo '<table>';
  354. function microtime_float() {
  355.     list($usec, $sec) = explode(" ", microtime());
  356.     return ((float)$usec + (float)$sec);
  357. }
  358.  
  359. $best = array();
  360. $missed = array();
  361. foreach ($photos AS $next) {
  362.     $start = microtime_float();
  363.     $diff = new imagediff($current, $next, 64, 64, true);
  364.     $tmp = $diff->diff() * 100;
  365.     $endTime = microtime_float() - $start;
  366.     $cnt++;
  367.     $array = array();
  368.     $best_cur = 999;
  369.     $best_cur_id = 999;
  370.    
  371.     if ($tmp < 80) {
  372.         $comp = new compareImages();
  373.  
  374.         echo '<tr><td>' . $enter;
  375.         echo '<img src="file:///' . str_replace("\\", "/", $current) . '" width="256" height="256"></td><td><img src="file:///' . str_replace("\\", "/", $next) . '" width="256" height="256"></td><td>' . $enter;
  376.         echo 'Time: ' . date("H:i:s") . '<br />';
  377.         echo 'Item: ' . $cnt . $enter . '<br />';
  378.        
  379.         $tmp = number_format($tmp, 2);
  380.         $array[] = array($tmp, $endTime);
  381.        
  382.         $start = microtime_float();
  383.         $tmp = $comp->compare($current, $next);
  384.         $endTime = number_format(microtime_float() - $start,2);
  385.         $array[] = array($tmp, $endTime);
  386.        
  387.         $start = microtime_float();
  388.         $diffy = new imagediffOld($current, $next);
  389.         $tmp = ($diffy->diff() * 100);
  390.         $endTime = number_format(microtime_float() - $start,2);
  391.         $array[] = array($tmp, $endTime);
  392.        
  393.         $start = microtime_float();
  394.         $tmp = number_format(exec('"c:\Program Files\ImageMagick-6.8.8-Q16\compare.exe" -metric PSNR ' . $current . ' ' . $next . ' NULL: 2>&1'),2);
  395.         $endTime = number_format(microtime_float() - $start,2);
  396.         $array[] = array($tmp, $endTime);
  397.        
  398.         $start = microtime_float();
  399.         $tmp = number_format(exec('"c:\Program Files\ImageMagick-6.8.8-Q16\compare.exe" -metric NCC ' . $current . ' ' . $next . ' NULL: 2>&1'),2);
  400.         $endTime = number_format(microtime_float() - $start,2);
  401.         $array[] = array($tmp, $endTime);
  402.        
  403.         foreach ($array AS $k=>$v) {
  404.             if ($best_cur > $v[1]) { $best_cur = $v[1]; $best_cur_id = $k; }
  405.             echo $k . ': ' . $v[0] . ' (' . number_format($v[1], 2) . ')<br />';
  406.         }
  407.         $best[$best_cur_id]++;
  408. //        echo $current . ';' . '</td><td>';
  409. //        echo $next . ';' . $enter;
  410.         echo '</td></tr>';
  411.     }
  412.     else {
  413.         $missed[] = $next;
  414.     }
  415.     $current = $next;
  416.     flush();
  417. }
  418.  
  419. print_r($best);
  420. print_r($missed);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement