Pull to refresh

Определение доминирующих тонов на изображении

Algorithms *
Sandbox

Предыстория


Очень давно, когда мои познания в PHP были на уровне мат операций и вывода результатов, а нашел очень полезный класс, написанный Kalpeh Gamit, его сайт уже давно недоступен, поэтому, к сожалению контакты оставить не могу. Класс распространяется под именем GetImageColor и лицензией GPL 2.0.

Пользовался я этим классом частенько. Он принимает в качестве входного параметра изображение (только в формате JPEG, но за минуту дополняется всеми остальными), количество возвращаемых цветов и шаг обработки. Скрипт считывает цвет с фотографии с заданным шагом и заносит его в массив цветов. Итоговый массив отсортирован по вхождениям цветов и возвращается только заданное количество цветов.


Очень удобный скрипт для многих задач. Лично мне он нужен был в первой версии Фотокиоска, с помощью скрипта я определял однотоновые фотографии и не позволял их загружать на сервер (слишком темные, засвеченные итд). Позже в LetPrint я применял его для определения заполненности листа и цветности.

Сегодня увидел статью на Хабре: habrahabr.ru/blogs/web_design/136343


Заинтересовало вот что. У изображения выбраны не просто часто встречающиеся цвета, а доминирующие или контрастные тона. Вспомнив, что выдал бы тот класс, я понял, что необходимо другое решение.


Решение


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

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

Написать такой алгоритм было не трудно, но вот поиск похожих меня немного затормозил. Хотя я долго и не разбирался с ним, все же кустарное решение легко нашел.

Наш цвет состоит из трех компонент: R+G+B. Все эти значения от 0 до 255. Цвета 250,100,100 и 240,90,90 – подобны, но второй темнее первого, но тем не менее они подобны. Цвет 245,100,100 тоже подобен первым двум, но в меньшей степени. Собственно вот здесь и начинается погрешность. Первые два цвета подобны, но подобны и 255,255,255 и 0,0,0 и это сразу же отбрасывает черно-белые фотографии. Также из-за подобности первых двух и третьего, отбрасываются оттенки. Но мы готовы к таким жертвам.

Число подобия – |R-G|.|R-B|.|B-G|, также для внесения подобных оттенков сама разность тоже подвергается обработке dif = round(round(|R-G|/pogr)*pogr). Коэффициэнтом pogr мы вносим погрешность. К примеру, если pogr = 10, то цвета 254,180,35 и 234,163,19 подобны. Чем больше погрешность, тем больше подобных оттенков мы объеденим.

После необходимо учитывая вес цвета, сгладить массив в единый цвет. Имеем массив подобных цветов. У каждого 2 параметра – цвет и количество вхождений. Собственно сглаженный цвет будет состоять из R = СУММ(Ri*mi)/СУММ(mi), где mi — количество вхождений этого цвета, также и с остальными составляющими G и B. Это значит, что раз черный и белый у нас подобны, то в результате работы алгоритма мы получим серый, который может и не присутствовать на картинке, но который будет полностью отражать смешение черного и белого.

С полученным массивом, мы проделываем эти операции вновь и вновь, пока не добьемся результата. В какой-то момент алгоритм может просто застопориться, поэтому погрешность выборки подобных pogr с каждой итерацией возрастает.

Результат


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

Попробовать алгоритм в действии можно тут: blog.assorium.ru/jpeg
Сервер у меня слабый, поэтому попрошу сильно на него не давить. Ограничения: изображения в формате JPEG и весом не более 500 КБ.

Альтернативные методы решения


Самый простой способ решения этой задачи, это каталог тонов. Я где-то уже наталкивался на него. Там предлагались самый часто используемые и приятные тона. Каталог насчитывал несколько тысяч цветов, что вполне бы хватило для этого скрипта. Обработка в принципе остается той же, но при сглаживании в окончательный массив добавляется цвет из каталога, который подобен текущим и так до тех пор, пока не останется несколько цветов. Преимущество метода очевидно, Вы получите цвет, который сам по себе хорош и не будет резать глаз и при этом еще и будет отражать суть на картинке.

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

UPD_1 Среди загруженных фотографий немало обнаженных женщин. Зачем кому-то узнавать тона обнаженного тела?
UPD_2 4utep нашел готовое решение, но с помощью HSV и определенного набора цветов. ссылка
Push_Ok подсказал «формулу цветового отличия» утвержденную CIE. Возможно она улучшит определение подобных. Пока я не определял насколько. ссылка
UPD_3 За сутки было загружено более 1500 картинок. Спасибо хабраюзерам за эпичные картинки прошедших трех месяцев и немалое количество эротики. Среди картинок даже попались экземпляры, просящие инвайт. Очень меня обрадовал мой хостер. Сайт не упал ни разу и не тормозил.
Tags:
Hubs:
Total votes 53: ↑51 and ↓2 +49
Views 24K
Comments Comments 35