@voral рациональное зерно в этом есть. Но что, если у нас (условно, два цвета и 10 градаций) Код (Text): $rangeR1 = [0,1,2,3,4]; $rangeG1 = [5,6,7,8,9]; $rangeR2 = [5,6,7,8,9]; $rangeG2 = [0,1,2,3,4]; $pixelColor = ['R' => 4, 'G' => 2]; пиксель не вписывается полностью ни в один диапазон. А задача требует отнести 100% пикселей в ту или иную сторону. --- Добавлено --- вот в этом примере, очевидно, цвет более красный, чем зеленый. Достаточно ли в такой ситуации опираться на бОльшее значение?
Мне кажется тут надо уходить от этих диапазонов. Они же какие то средне потолочные не привязанные к конкретной картинке (или их надо создавать так, чтобы они охватывали весь диапазон. Тут, мне кажется, надо копать в следующем направлении: Читаем пиксели и для каждого сразу определяем диапазон при попадании в который другой цвет считается похожим. Потом надо из этих диапазонов создать нечто типа "тепловой карты". И уже на ней искать значимые диапазоны. Конечно это идея-сырец... надо смотреть на примере
именно так я и хочу сделать ) вот думаю, как именно реализовать... --- Добавлено --- @voral динамические диапазоны не подойдут:
На уровне бреда. Трехмерный массив. Каждый уровень это канал. Тип значений integer. 256 * 256 * 256 элементов считываем пиксели, каждый анализируем и добавляем 1 в соответствующий элемент массива, Для удобства, кстати, можно одномерный - просто индекс это цвет. --- Добавлено --- А ну тогда вообще не нужна дельта -вычисяем процент: "на сколько текущий цвет похож на заданный цвет" . И относим к тому цвету для которого процент больше.... % так же вычисляется отдельно по компонентам --- Добавлено --- Если имеем ситуацию: Эталонные группы FF0000, 00FF00, 0000FF и цвет 00FFFF.Цвет в равной степени относится к двум эталонам. В этом случае каждой группе добавлять по полбалла --- Добавлено --- Кстати..... А если вообще поступить так: вычисляем весовую долю одного пиксела. (100 / количество пикселов). Вычисляем процент на сколько каждый пиксел похож на каждый эталон и, с учетом весового коэффициента, добавляем к каждому эталону. --- Добавлено --- Например: имеем картинку 10 х 10 пиксеей. Т.е. всего 100 пикселей. Каждый пиксел весит 1%. Имеем три эталонных цвета. Каждый пиксел распределяет свой процент по этим эталонам пропорционально степени похожести (по составляющим)... Т.е. в итоге сумма эталонов 100%...
мы тут пытаемся решить задачу минимальной кровью сервера)) 256 на 256 на 256 - это первое, что приходит в голову, но это массив из 16 777 216 элементов)) человек не различает цвета с такой точностью и такая нагрузка не нужна.
Можно и уменьшить количество цветов. Для пиксела вычисляем диапазон. И смотрим на какой цвете в массиве он похож больше всего. И добавляем туда. Впрочем второму (с весовымикоэффициентами) варианту массив совсем не нужен --- Добавлено --- Правда у него есть другая проблема - она озвучена по ссылке, что дал @Sail. Лучше из RGB перейти в Lab --- Добавлено --- Кстати, по ссылке метод интереснее там считается расстояние между точками в трех мерном пространстве (звучит это проще, чем сравнивать отдельные составляющие), но распределять все равно надо на все опорные цвета, т.к. расстояние может получиться одинаковым
Конвертирование RGB -> Lab https://gist.github.com/manojpandey/f5ece715132c572c80421febebaf66ae правда на питоне, но все понятно
Так не получается) При округлении до целых процентов и при наличии 512 диапазонов (кол-во диапазонов настраивается) в простенькой картинке набегает 7 % пикселей, которых меньше 0,5 % (при округлении получаем 0)
@voral, немного можно упростить Ваш вариант используя каналы RGB как координаты в 3х-мерном пространстве двух векторов. Отличия в цвете - длина вектора разницы исходных векторов. Но в итоге подсчет оттенков надо производить не в RGB, а в Lab или подобном пространстве, чтобы исключить яркость из расчетов.
Ага, собственно я даже накидал именно так примерчик для себя. Правда в RGB... Время "перекура" вышло --- Добавлено --- При чем, на мой взгляд надо делать так. В три этапа. Если четкое попадание в цвет - отдаем полный вес, если есть несколько цветов попадающих в зону погрешности и несколько расположенных дальше то распределяем вес пропорционально по вошедшим в погрешность. Если не один не попал в погрешность - пропорционально.. (это если надо обязательно все распределить) --- Добавлено --- Единственное - потом вчитался в задачу и понял что делаю фигню. По этому переключился на другой вариант (правда кушающий память) - прохожусь по всей картинки и все цвета заношу в массив. Цвет ключ, значение количество точных совпадений. Затем сортировка массива от самых редких до самых популярных.... И начиная с начала переносить цвета в более подходящие. Чтоб в итоге свести палитру к необходимому количеству.
Соглашаясь выполнить эту работу, автор кода передаёт мне имущественные права: «Исключительное право (имущественное право) на программу первоначально возникает у её автора (авторов) . Это исключительное право может быть передано автором другому лицу по договору или перейти к другим лицам по иным основаниям, предусмотренным законодательством.» — Программы для ЭВМ как объект авторского права --- Добавлено --- true color (24 bit) потенциально даёт вам 16 млн цветов. имейте это в виду, когда планируете "занести в массив цветов".
Класс я написал. Было интересно решить эту задачу. Напишу док и выложу на гитхаб. И пользуйся на здоровье ты и все, кто хочет. Будет приятно быть полезным. А 20 $ могу принять в качестве благодарности. Но если нет, то и ладно. Я бы взял за этот код (если бы делал на заказ) минимум 100, а может и больше.
Короче писал док и меня осинило. У меня был обычный двумерный массив цветовых диапазонов. И каждый пиксель сравнивался со всеми диапазонами. Ну можно было поставить breack, если диапазон нашелся. Но всё равно процесс это довольно долгий, если нужна высокая точность. Так вот о чем я: Можно же организовать массив так, чтобы поиск был очень быстрым. Если говорить о кубике, то если мы знаем, что в этой плоскости нет нашего цвета, то нам и не нужно перебирать все точки этой плоскости. Ищем сразу нужную плоскость, а в ней сразу нужный отрезок, и затем нужную точку. Короче релиз откладывается)
Пипец как просто всё, вот что значит выспаться на выходных. --- Добавлено --- Если проканает, то это реально на $20, ну и еще $2000 за ноу-хау :-D
прикол как раз в том, чтобы найти простое решение для сложной задачи. у тебя профессиональная деформация ценностей. Ты неделю килишовал в голове задачу и вот придумал решение.
Новый вариант готов По сравнению с предыдущей версией он просто мега быстрый и кушает фулАшДи за 40 сек на моём компе. На работе на восьмиядерном I7 кушал за 20сек) И это при шаге между цветами в 8 бит. Такая точность не нужна вообще и дробит картинку на кучу цветов. Под линуксом будет работать еще быстрее (наверное). Вот про эту картинку говорю: Спойлер: IMG Всё, что нужно знать о классе: 1. Свойство step - шаг между цветами. Чем он больше, тем точность ниже. Слишком высокая точность тоже ни к чему. Поиграйся на картинках и поймешь о чем я. step должен быть равен одному из значений (технически): 4, 8, 16, 32, 64, 128. 2. Пользоваться очень просто: PHP: $obj = new image_colors_proportions(); $proportions = $obj->getProportions('куть/к/картинке.jpg'); Получишь массив цветов, отсортированных по убыванию. Выведи и всё поймёшь. Тип картинки определяется сам. Поддерживаются jpg, png и gif. Поддержку можешь добавить в методе getImg(). 3. Методом $obj->viewColors(); можешь вывести все опорные цвета для текущего шага. Код можно улучшить, но я уже от него устал) Надеюсь, класс будет полезным.
тут еще интересное примечание. а у такой картинки должен ли фон идти в зачет: Даже точнее если бы фон был белый. Должен ли этот белый считаться преобладающим.
@TeslaFeo крутяг! Я придумал другой метод. Но пока залип на генерации палитры. Хочу уменьшить количество цветов )
@[vs] у меня кол-во цветов уменьшается увеличением шага. посмотри метод getRanges. Больше всего похожи цвета, если все три канала увеличить или уменьшить на одинаковое кол-во бит. Поэтому диапазон формируется из начального цвета, и цвета, у которого все три канала больше на величину step - 1 ( - 1 - чтобы диапазоны не пересекались ) и середина диапазона - начало диапазона + (step / 2). Потом я организовал быстрый поиск по ключам и края диапазонов стали не нужны) теперь они не сравниваются ни с чем) --- Добавлено --- будет интересно)