Как определить прелбладающий цвет изображения?
например цвета
123 456 789 , и больше всего цвета 7, поссчитать +-1
тогда если усреднить получим
222 555 888
тк все 7-ки стали 8-ками выдаем что преобладает 7 цвет. в принципе +-1 не нарушено, но если нужен точный результат не катит
сортировать можно например по одной составляющей, если есть несколько одинаков значений одной тогда по второй, потом третьей. (может лучше построить дерево)
потом какже как ищется медиана в обычном массиве - проходим интервалом в 2*д (д - наша точность) по первой составляющей , подсчитываем кол-во цветов в этом интервале , в которых вторая и третья составляющие попадают в ±, записываем куданить максимальную сумму цветов в диапазоне и номер этого максимального диапазона. после прохода всего массива/дерева имея список нужных цветов несложно определить который из них центр (наверно лучше нри проходах сделать интервал чуть больше 2*д, и лишние цвета отбросить на этом последнем этапе)
решение довольно громоздкое и медленное.. походу.. но должно работать . корректно.
Оцениваем долю составляющего цвета в триаде RGB. В случае, если составляющая превышает определенный порог по отношению к другим основным цветам (к примеру R:150, G:10, B:10), то засчитываем этот пиксел как соответствующий нашим требованиям.
В конце, оцениваем общую долю отобранных пикселей к общему числу пикселей составляющих рисунок. Естественно и тут используем некое пороговое значение.
Наиболее простая как мне кажется реализация тут получается для оценки основных цветов. Т.е. чистого красного, зеленого и синего.
Для оценки содержания скажем желтого или оранжевого, скорей всего придется делать оценочное сравнение с заданным цветом т.е. берем наш цвет в формате RGB и сравниваем с целевым пикселем, с определенным допуском отклонения от оригинала.
Для чего нужно усреднение? Если говорить о фотографиях в формате JPEG, то в среднем там можно насчитать от 40 до 180 тысяч уникальных цветов (только что проверил по своему архиву). Если фотография состоит всего из 6 миллионов пикселей, то пикселей, окрашенных в доминирующий цвет, окажется не так уж и много - порядка тысяч. В то же время достаточно просто посмотреть на фотографию и уже можно без большого труда сказать, какой цвет действительно преобладает. Поэтому слишком большая точность не нужна. Я думаю, достаточно округлить значение в каждом канале до ближайшего десятка. Заодно это может уменьшит влияние шума на точность определения цвета. на сложность самой сортировки это не повлияет, однако поиск доминирующего цвета в отсортированном массиве пройдёт быстрее.
Но мне кажется, что задачу можно решить элегантней. А что там матстатистика говорит о способах отыскания моды? Специальные учёные по-любому изобрели качественный метод. И, кстати, как там работает кодек BMP при конверсии растровых рисунков в палитровые?
Конечно для приблизительного можно использовать.
Меня вот что смущает. Что такое RGB±10 ??
ето (R±10 and G±10 and B±10) или (abs(R-r) + abs(G-g) + abs(B-b)) <= 10 ??
Теоретически улучшенный метод: делаем сетку {4 ^ 3} и распределяем по ней возможные цвета. Если цвет совпадает с цветом, соответствующим узлу сетки - добавляем цвет в этот узел. Если плавает "где-то между" соседними - добавляем ещё и в соседние. Для каждого узла с количеством цветов, соответствующим максимальному, повторяем разбиение { 4 ^ 3 } (остальные выбрасываем) и так до достижения нужной точности. Мэджик 4 может быть другим, главное чтоб было больше двух. Оно позволяет добиться оптимального баланса зависимости объёма выделяемой памяти от размера картинки (чем больше изображение, тем больше это число). Последний шаг - вычисление наиболее вероятного точного значения среди найденных приблизительных аналогично высказыванию в первом абзаце.
Можно скомбинироавть с первым, двухшаговым методом: создавать сетку {((256 + точность - 1) / точность) ^ 3}, в узлах по-прежнему хранить количества, а не сами цвета, но ввести фишку с соседними узлами. Вотрой шаг (вычисление точного значения) так же, как и в первом методе, будет использовать весь исходный массив. Что и когда лучше - надо выводить.
В частности, каков будет преобладающий цвет на картинке из 30% красного, 30% оранжевого и 40% зелеого? Красно-оранжевый или зеленый?
Если нам задана (или вычислена) некоторая погрешность, мы можем разбить цветовой куб на зоны, размеры которых примерно соответствуют величине погрешности (например на 10 частей при 10% и 20 частей при 5%) по каждой из цветовых координат.
При 10% получаем примерно 1000 зон (цвет трехмерен).
Далее оцениваем, по сколько в среднем пикселей попадет в одну зону. Например, для рисунка 320х240 - примерно 77 штук. Если это число оказалось меньше нескольких единиц (например 4), вряд ли задача в такой постановке разрешима.
Далее мы выделяем зоны скопления цветов. Обозначив их границы примерно, можно разделить окрестности раниц на более подробные подзоны - для более точного опрелеления. Находим самую представительную зону скопления и принимаем решение о том, как будем вычислять средний по зоне цвет - как максимально удаленный от границ зоны либо как средневзвешенное значение по пикселям, входящим в зону.
Для полноты следует ОПРЕДЕЛИТЬ преобладающий цвет как среднее арифметическое значение цветов пикселей картинки.
Если тупо уменьшить размер картинки до размера 1х1, то она получается примерно того цвета, который преобладает.
опять на примере японского флага - он станет розовый, хотя преобладает белый, а Український прапор буде зелений, хоче там його і близько не лежало
в данном случае
тоесть тот которым окрашено больше пикселей
ну флаг конечно это крайность. думаю на практику надо просто выдать какого цвета больше - если одинаково то либо вывести тот который по if'ам раньше/пожже, либо просто табличкой "пятерку лучших"
ето (R±10 and G±10 and B±10) или (abs(R-r) + abs(G-g) + abs(B-b)) <= 10 ??
Поскольку я так и не понял что такое RGB±10 припускаю что ето (R±10 and G±10 and B±10). Тоесть есть у нас куб RGB в нем есть точка соответствующая некому цвету, а допустимые отклонения лежат в кубе со стороной 21. Также припускаю что розмер куба RGB 256*256*256.
Вот бежим по картинке и щитаем в куб сколько у нас какого цвета. Пощитали. Дальше задача найти такой подкуб со стороной 21 сума елементов которого наибольшая. Извените за розсусоливание, я для ясности вещей.
Как найти максимальний подкуб.
первый шаг. Формируем куб 256*256*(256-21). В каждом его елементе сума елементов первоначального куба от x, y, z до x, y, z + 21. Делается такое за один проход по изначальному кубу.
Дальше из нового куба формируем куб 256*(256-21)*(256-21) где сума щитается от x, y, z до x, y + 21, z из предыдущего куба.Здесь в каждом елементе будет сума цветов уже не в столбце а в площадке 21*21. Дальше похожим образом получаем куб (256-21)*(256-21)*(256-21) где в каждом елементе сума цвеов которые попадают в куб 21*21*21 начинающийся в x, y, z.
В последнем кубе нужно найти максимум.
Тут также есть прикол. Припустим вся картинка окрашена в один цвет. Тогда у нас будет 21*21*21 кубов с максимальной сумой. Но ета проблема легко решается.
Итого сложность O( 256*256*256 )
Спорный вопрос. Смутно представляю себе как можно легко уточнять результат после того как цвета искаверкаем запихая их в меньшый куб.
Врезультате получаем гиморой с контролем пропущеных значений по каждой оси (а ето нам нужно для контроля отклонения цвета), который кажысь схавает секономленое время и усложнит алгоритм.
Я предложыл общее решение. Конечно с учетом спецыфики фходных данных его можно усовершенствовать. Вопрос в том стоит ли :)
ИМХО, в идеале следовало бы вообще округлять до наиболее часто встречающегося значения, тогда доминирующий цвет нашёлся бы наиболее точно.