Simple image comparison using php

    The algorithm is probably not new, and is not ideal , but, surprisingly, it works. No graphs or correlation.

    To begin with, it is worth noting that the comparison is very approximate (at least at this stage), at times two completely different photographs turn out to be similar to 60% percent, also hard modifications (rotations, inversion, cropping) are not taken into account - for this you need to bring and bring. For me personally, the most important thing were two parameters: speed , independence of image resolution and the ability to compare "images" directly in the database.

    Principle

    • Open source image
    • Scale it to the size of the mask (in my case it is 20 by 20, I do not need large sizes - the comparison is approximate, it is quite possible to make a mask and 10 by 10).
    • We calculate the main color of the mask.
    • We create an array where the value is a key of type af2 (1,2 - coordinates, as in a naval battle. 2 - discrepancy with the main brightness).
    • We generate a line - a key.
    • Compare two lines by relevance.

    The code


    In this case, the version that works through GD with PNG images is presented .
    //Генерация ключа-изображения
    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.

    * The similarity calculation function is approximate - it is better to perform this action on the base side.

    Examples


    image
    Surprisingly, 95% 87% similarity (with the addition of UPD-2)

    image
    52% similarity

    image
    28% similarity

    image
    100% similarity

    P.S


    All this is only approximate calculations, it is impossible to achieve a particularly advanced comparison in this way, but it will do for a quick selection from the database of similar images.

    PS Comments and advice are accepted.
    UPD Thanks MiniM - the code has been simplified.
    UPD-2 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 the point will be taken into account. Thus, the similarity in the first example will be 87% .
    UPD-3 Moved to php.

    Also popular now: