Blog. Just Blog

Определение основного цвета изображения на PHP

Версия для печати Добавить в Избранное Отправить на E-Mail | Категория: Web-мастеру и не только | Автор: ManHunter
В различных поисковых системах есть возможность поиска изображения по цвету, например, "только синие" или "только зеленые". Естественно, это не означает стопроцентную синюю или зеленую заливку, а определяет преобладающий цвет картинки. Такой цвет называется основным. Алгоритм поиска основного цвета очень простой: надо просто подсчитать суммарные значения по каждому из каналов RGB для каждого пиксела изображения, а затем разделить полученные значения на общее количество пикселов. На PHP это реализуется примерно так:
  1. // Файл для определения основного цвета
  2. $im=ImageCreateFromJPEG('test.jpg');
  3.  
  4. $total_R=0;
  5. $total_G=0;
  6. $total_B=0;
  7.  
  8. // Размеры изображения
  9. $width=ImageSX($im);
  10. $height=ImageSY($im);
  11.  
  12. // Подсчитать суммарные значения по RGB
  13. for ($x=0$x<$width$x++) {
  14.     for ($y=0$y<$height$y++) {
  15.         $rgb=ImageColorAt($im,$x,$y);
  16.         $total_R+=($rgb>>16) & 0xFF;
  17.         $total_G+=($rgb>>8) & 0xFF;
  18.         $total_B+=$rgb 0xFF;
  19.     }
  20. }
  21.  
  22. // Прибраться за собой
  23. ImageDestroy($im);
  24.  
  25. // Определение значений RGB основного цвета
  26. $avg_R=round($total_R/$width/$height);
  27. $avg_G=round($total_G/$width/$height);
  28. $avg_B=round($total_B/$width/$height);
Код минимально необходимый, никаких проверок на наличие файла или корректность его внутреннего формата не производится, это вы можете сделать самостоятельно. После выполнения кода получаются три значения каналов RGB основного цвета изображения.

Для очень больших изображений можно применить следующий алгоритм определения основного цвета. Изображение сжимается штатными средствами PHP до размера 1х1 пиксель, основным цветом будет являться цвет этого пиксела.
  1. // Файл для определения основного цвета
  2. $im=ImageCreateFromJPEG('test.jpg');
  3.  
  4. // Размеры изображения
  5. $width=ImageSX($im);
  6. $height=ImageSY($im);
  7.  
  8. // Сжать изображение до 1x1
  9. $dst=ImageCreateTrueColor(1,1);
  10. ImageCopyResampled($dst,$im,0,0,0,0,1,1,$width,$height);
  11.  
  12. // Получить основной цвет
  13. $rgb=ImageColorAt($dst,0,0);
  14. $avg_R=($rgb >> 16) & 0xFF;
  15. $avg_G=($rgb >> 8) & 0xFF;
  16. $avg_B=$rgb 0xFF;
  17.  
  18. imageDestroy($im);
  19. imageDestroy($dst);
Основной цвет изображения определен, но использовать его для поиска изображений по критерию "цвет" пока не получится, так как слишком большой разброс значений. Надо преобразовать значение "оттенок красного" или "оттенок желтого" в абсолютно красный или абсолютно желтый, для этого удобнее всего перевести RGB в HSV и проанализировать цветовой тон (Hue), насыщенность (Saturation) и яркость (Value).
  1. // Перевести RGB в HSV
  2. $R=($avg_R/255);
  3. $G=($avg_G/255);
  4. $B=($avg_B/255);
  5.  
  6. $maxRGB=max(array($R$G$B));
  7. $minRGB=min(array($R$G$B));
  8. $delta=$maxRGB-$minRGB;
  9.  
  10. // Цветовой тон
  11. if ($delta!=0) {
  12.     if ($maxRGB==$R) {
  13.         $h=(($G-$B)/$delta);
  14.     }
  15.     elseif ($maxRGB==$G) {
  16.         $h=2+($B-$R)/$delta;
  17.     }
  18.     elseif ($maxRGB==$B) {
  19.         $h=4+($R-$G)/$delta;
  20.     }
  21.     $hue=round($h*60);
  22.     if ($hue<0) { $hue+=360; }
  23. }
  24. else {
  25.     $hue=0;
  26. }
  27.  
  28. // Насыщенность
  29. if ($maxRGB!=0) {
  30.     $saturation=round($delta/$maxRGB*100);
  31. }
  32. else {
  33.     $saturation=0;
  34. }
  35.  
  36. // Яркость
  37. $value=round($maxRGB*100);
Получив значение цветового тона, яркости и насыщенности, открываем любую программу или сайт для работы со шкалой HSV. Выбирая различные цвета, определяем граничные значения тона, насыщенности и яркости, и устанавливаем в скрипте, какому абсолютному цвету соответствует тот или иной интервал или комбинация значений. Например, для своих задач я определил следующие соответствия:
  1. // Яркость меньше 30%
  2. if ($value<30) {
  3.     // Черный
  4.     $color='#000000';
  5. }
  6. // Яркость больше 85% и насыщенность меньше 15%
  7. elseif ($value>85 && $saturation<15) {
  8.     // Белый
  9.     $color='#FFFFFF';
  10. }
  11. // Насыщенность меньше 25%
  12. elseif ($saturation<25) {
  13.     // Серый
  14.     $color='#909090';
  15. }
  16. // Определить цвет по цветовому тону
  17. else {
  18.     // Красный
  19.     if ($hue>320 || $hue<=40) {
  20.         $color='#FF0000';
  21.     }
  22.     // Розовый
  23.     elseif ($hue>260 && $hue<=320) {
  24.         $color='#FF00FF';
  25.     }
  26.     // Синий
  27.     elseif ($hue>190 && $hue<=260) {
  28.         $color='#0000FF';
  29.     }
  30.     // Голубой
  31.     elseif ($hue>175 && $hue<=190) {
  32.         $color='#00FFFF';
  33.     }
  34.     // Зеленый
  35.     elseif ($hue>70 && $hue<=175) {
  36.         $color='#00FF00';
  37.     }
  38.     // Желтый
  39.     else {
  40.         $color='#FFFF00';
  41.     }
  42. }
Теперь можно точно сказать, какого цвета картинка. Где это можно использовать? Про поиск изображений по абсолютным цветам я уже упомянул. А основной цвет хорошо использовать для отрисовки рамки или фона изображения, чтобы добиться наиболее удачного их сочетания. Наверняка найдутся и другие применения.

Поделиться ссылкой ВКонтакте
Просмотров: 8993 | Комментариев: 4

Метки: PHP, графика
Внимание! Статья опубликована больше года назад, информация могла устареть!

Комментарии

Отзывы посетителей сайта о статье
ManHunter (09.06.2016 в 20:02):
Цитататакое вряд ли возможно?

Да тоже можно, если поискать :) Например, https://html2canvas.hertzen.com
Скриншотилка на чистом JS. Она же на гитхабе: https://github.com/niklasvh/html2canvas
DiPrm (09.06.2016 в 09:14):
Ок. Действительно так быстрее, удобнее. Но картинку приходится загружать предварительно. А если зайти на страницу и запустить JS скрипт с целью получить цвет элемента контента страницы - такое вряд ли возможно?
ManHunter (09.06.2016 в 08:49):
На JS это сделать гораздо удобнее, canvas и все такое прочее. И работать такая реализация будет быстрее. Вот, например: http://easy-code.ru/lesson/htm...color-picker
DiPrm (09.06.2016 в 08:45):
Хороший пример, натолкнул на мысль, что можно сделать свой online colorPicker, передавая посредством AJAX на клиентской части координаты пикселя  картинки, предварительно загрузив ее на страницу.

Добавить комментарий

Заполните форму для добавления комментария
Имя*:
Текст комментария (не более 2000 символов)*:

*Все поля обязательны для заполнения.
Комментарии, содержащие рекламу, ненормативную лексику, оскорбления и т.п., а также флуд и сообщения не по теме, будут удаляться. Нарушителям может быть заблокирован доступ к сайту.
Наверх
Powered by PCL's Speckled Band Engine 0.2 RC3
© ManHunter / PCL, 2008-2024
При использовании материалов ссылка на сайт обязательна
Время генерации: 0.07 сек. / MySQL: 2 (0.0056 сек.) / Память: 4.5 Mb
Наверх