Распознавание изображения по цветовому тону на PHP


Часто бывают ситуации когда необходимо определить цветовой тон изображения на PHP и в зависимости от результата определённым образом обработать картинку. Для этого я написал следующую функцию, которая определяет основной цвет изображения и подсчитывает процент этого цвета во всем изображении.

function dominant_color($img) {
if (trim($img)!='' AND file_exists($_SERVER['DOCUMENT_ROOT'].$img))    
    {
    $result_array = array();
    $return['max_count']=0;
    $return['max_rgb']='';  
    $return['all_px']=0;
    $return['proc']=0;  
        
    $type = getimagesize($_SERVER['DOCUMENT_ROOT'].$img);
    switch ($type['mime']) {
        case "image/jpeg":
        $im = imageCreateFromJPEG($_SERVER['DOCUMENT_ROOT'].$img);
        break;
        
        case "image/gif":
        $im = imageCreateFromGIF($_SERVER['DOCUMENT_ROOT'].$img);
        break;
        
        case "image/png":
        $im = imageCreateFromPNG($_SERVER['DOCUMENT_ROOT'].$img);
        break;
        
        default:
        die("<p style='color:red;'>Тип файла (".$img.") не распознан - " . $type['mime'] . "</p>");
        }
    $h = imagesx($im);
    $w = imagesy($im);
    $return['all_px'] = $h*$w;
    for ($i = 0; $i < $h; $i++)
        {
        for ($j = 0; $j < $w; $j++)
            {
            $rgb = imagecolorat($im, $i, $j);
        
            $r = ($rgb >> 16) & 0xFF;
            $g = ($rgb >> 8) & 0xFF;
            $b = $rgb & 0xFF;
        
            $color = "R-".$r.";G-".$g.";B-".$b;
            $result_array[$color]++;
            }
        }
    foreach ($result_array as $key => $value)
        {
        if ($value>$return['max_count'])
            {
            $return['max_count'] = $value;
            $return['max_rgb'] = $key;   
            }
        }
    $return['proc'] = round(($return['max_count']*100)/$return['all_px'], 0); 
      
    /*echo '<pre>';
    print_r($result_array);
    echo '</pre>'; */ 
   
    return $return;
    }
    else
    {
    die("<p>Файл не найден! ".$_SERVER['DOCUMENT_ROOT'].$img."</p>");
    }  
}

Разберём как она работает:

  1. Первым делом функция формирует дескриптор изображения для дальнейшей работы уже с этим дескриптором.
  2. Затем вычисляется ширина и высота изображения в пикселях, после чего перебираю в двух циклах все пиксели и сохраняю в массив цвет. Для удобства дальнейшей группировки результатов, элемент массива называю по цвету, а его значение присваиваю единице. Если такой цвет уже существует, то его значение увеличиваю на единицу (инкрементирую).
  3. В получившемся массиве я ищу максимальное значение, и сохраняю его цвет.
  4. На выходе я получаю: цвет, который чаще всего встречается, количество пикселей этого цвета, сколько всего пикселей, процент максимально часто встречающегося цвета к общему количеству пикселей.

На выходе получаем вот такой массив:

Array
(
    [max_count] => 11577
    [max_rgb] => R-239;G-225;B-198
    [all_px] => 90032
    [proc] => 13
)

Элементы этого массива я описал выше.

Используя данную функцию можно определить основной цвет изображения (цветовой тон). 

Также возможен поиск изображений по картинке. Для этого просто увеличиваем число для округления процента вхождения самого часто встречающегося цвета, и сравниваем всего лишь 2 параметра:

  • основной цвет вхождения
  • процент его вхождения

Результат конечно возможно не 100%-ый, но вполне приемлемый для поиска картинок. Таким образом возможно найти одинаковые картинки среди большого количества изображений используя всего лишь данные изображения - образца.

 


Тэги:

Комментарии: 4

Прокомментировать »

 
 
lutskboy
27.04.2014
 

привет. а как вытащить не одно значение наиболее часто всречающегося цвета, а несколько. например 10. я хочу потом по этим значениям искать картинки с похожими цветами. как на сайтах с обоями для рабочего стола. спасибо за ответ.

lavrik
28.04.2014
 

lutskboy, для вашей задачи пришлось модифицировать функцию. Посмотреть можете здесь: http://lavrik-v.ru/upload/userfiles/files/test.rar

lutskboy
28.04.2014
 

спасибо за быстрый ответ. скачал. буду тестировать.

lavrik
28.04.2014
 

Обращайтесь)))

 

Прокомментировать

 
 
Сообщение *
 
Проверочный код *
 
 
 
Яндекс.Метрика