Задача алгоритма: создать цветовую схему из изображения - PullRequest
52 голосов
/ 10 июля 2009

Фон

Итак, я работаю над новой версией веб-приложения. И мы обнаружили, что наши пользователи одержимы ленивостью. Действительно ленивый. На самом деле, чем больше мы делаем для них работы, тем больше они любят обслуживание. Часть существующего приложения требует от пользователя выбора цветовой схемы для использования. Тем не менее, у нас есть изображение (скриншот сайта пользователя), так почему же мы не можем просто насытить их лень и сделать это для них? Ответ: Мы можем, и это будет забавное упражнение по программированию! :)

Проблема

Для данного изображения как создать соответствующую цветовую схему? Другими словами, как выбрать основные цвета X на изображении (где X определяется веб-приложением). Изображение, используемое в нашей конкретной ситуации, представляет собой скриншот веб-сайта пользователя, сделанный в полном разрешении (например, 1280x1024). ( Примечание: Пожалуйста, просто опишите свой алгоритм - нет необходимости размещать реальный псевдокод.)

Бонусные баллы (уличные кредитные баллы, а не фактические SO баллы) для:

  • Описание простого, но эффективного алгоритма. Код - это то, как мы создаем - делайте его простым и красивым.
  • Позволяет пользователю настраивать цветовую схему в соответствии с различными «настроениями», такими как «Красочный», «Яркий», «Приглушенный», «Глубокий» и т. Д. (Как Кулер )
  • Описание метода надежного определения основного текста цвета, используемого на снимке экрана веб-сайта (вероятно, потребуется отдельный, отдельный, алгоритм).

Вдохновение

Существует несколько сайтов, которые выполняют аналогичную функцию. Не стесняйтесь проверить их и спросите себя: «Как бы я продублировал это? Как я мог бы улучшить это?»

Ответы [ 11 ]

26 голосов
/ 10 июля 2009
  1. Чтобы найти основные цвета X, закройте приложение. Запустите цветную гистограмму на изображении. Верхние цвета X на гистограмме - это тема. Редактировать: если используются градиенты, вам нужно выбрать различные «пики» цветов; то есть, вы можете иметь целую кучу цветов прямо вокруг «оранжевого», если оранжевый является одним из основных цветов, используемых в градиентах. По сути, просто установите определенное расстояние между вашими цветами, выбранными из гистограммы.

  2. Настройка цветовой схемы лучше всего сделать в пространстве HSV; преобразуйте свои цвета в пространство HSV, и если пользователи хотят, чтобы он был «ярче», увеличьте значение, если они хотят, чтобы он был более «ярким», увеличьте насыщенность и т. д.

  3. Определение цвета текста лучше всего сделать, охарактеризовав области высокой изменчивости (высокая частота в пространстве Фурье). В этих областях у вас должно быть либо: два цвета, текст и фон, и в этом случае ваш текст является менее используемым цветом; или у вас будет несколько цветов, цвета текста и фонового изображения, и в этом случае цвет текста будет наиболее распространенным.

8 голосов
/ 21 октября 2013

Вы можете взглянуть на:

https://github.com/dcollien/Dreamcoat

, что делает это в CoffeeScript (грамотный кофе, поэтому он хорошо документирован)

Демо здесь: http://dcollien.github.io/Dreamcoat/test.html

У него есть как подход квантования цвета, так и подход KMeans, которые объединены.

7 голосов
/ 13 ноября 2010

Я делаю это, чтобы найти палитру, используемую для изображений (иллюстраций).

  1. Я начинаю с imagemagick и изменяю размер большого изображения до работоспособного размера (то есть 400 пикселей по наибольшему размеру). Это на самом деле помогает преобразовать едва различимые локальные цветовые различия в меньшее количество пикселей со средним из этих цветов.

  2. Прокрутка каждого пикселя, присутствующего в измененном размере, чтение значений RGB для каждого пикселя, преобразование RGB в HSB и сохранение значений HSB в массив.

  3. Для каждого найденного цвета пикселя я делю диапазон оттенков (0,255) на 16, диапазон насыщенности (0,100) на 10 и диапазон яркости (0,100) на 10. Округляем результат вверх или вниз до целое число. Это помогает группировать пиксели в категории похожих цветов.

    Таким образом, пиксель с HSB 223,64,76 будет в категории 14,6,8

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

    Выберите, чтобы разделить HSB на более тонкие деления, если вы хотите лучше воспроизводить цвета из категорий. то есть. разделите каждый H, S, B на 8,5,5 вместо 16,10,10.

  4. Подсчитайте наиболее распространенные цветовые категории, сортируйте и отображайте. Я отбрасываю категории цветов с очень небольшим количеством пикселей.

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

По большей части HTML-страница, вероятно, имеет больше пикселей, которые точно соответствуют определенному значению цвета (т. Е. Цвет фона, цвет текста и т. Д. Все будут одинакового цвета, где бы они ни появлялись.)

6 голосов
/ 25 марта 2013

Квантование цвета - это тот же процесс, который используется для выбора палитры для низкоцветных GIF-изображений. Чтобы получить цветовую палитру из фотографического изображения, я использовал Nick Rabinowitz ’ quantize.js , основанный на MMCQ (модифицированный медианный срез) Leptonica.

meemoo screen shot Онлайн веб-приложение , о .

5 голосов
/ 10 июля 2009
  1. Разделите изображение экрана на сетку из r-многих прямоугольников в n на m «сетке», каждый из которых имеет ширину (общая ширина / n) и высоту (общая высота / м).

    1a. Присвойте вес громким областям экрана, таким как область слева от центра.

    1b. Для каждого прямоугольника назначьте пиксели в пространство ( цвет , частота )

  2. Для каждого прямоугольника R, распределение частоты f_R и вес W_R:

    2a. Определите i -й цвет схемы (например, i = 1 <-> цвет фона) путем сканирования «верхней частоты», «второй частоты» ( то есть f_R [] я,:]) для каждого блока.

    2b. Для каждого i , поместите его в таблицу результатов ( color_i , оценка ), где оценка = f_R [ i , "частота" ] * W_R

    2в. Лучшим бомбардиром для каждого i будет i -й цвет схемы.

Теоретически, если у вас много "синий на белом" или "красный на черном", вы должны получить белый основной, синий вторичный или черный основной, например, красный вторичный.

Для вашего цвета текста, либо основывайте его непосредственно на расчете по цвету фона, либо выбирайте вторичный цвет, и, если V-разница HSV слишком мала, основывайте цвет на цвете вычисленной схемы, но увеличивайте V значение.

псевдокод:

float[][] weights = 
    { { 1.0, 3.0, 5.0, 5.0, 3.0, 1.0, 1.0, 1.0, 1.0 },
      { 2.0, 6.0, 7.0, 7.0, 6.0, 2.0, 3.0, 3.0, 2.0 },
      { 2.0, 8.0, 9.0, 9.0, 7.0, 3.0, 6.0, 6.0, 3.0 },
      { 2.0, 8.0, 9.0, 9.0, 7.0, 2.0, 3.0, 3.0, 2.0 },
      { 2.0, 7.0, 9.0, 9.0, 7.0, 2.0, 1.0, 1.0, 1.0 },
      { 2.0, 6.0, 7.0, 7.0, 6.0, 2.0, 3.0, 3.0, 1.0 },
      { 1.0, 3.0, 5.0, 5.0, 3.0, 2.0, 6.0, 6.0, 2.0 },
      { 1.0, 1.0, 2.0, 2.0, 1.0, 2.0, 6.0, 6.0, 2.0 },
      { 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 3.0, 3.0, 1.0 } };

// Leave the following implementations to the imagination:
void DivideImageIntoRegions( Image originalImage, out Image[][] regions );
void GetNthMostCommonColorInRegion( Image region, int n, out Color color );
TKey FindMaximum<TKey, TValue>( Map<TKey, TValue> map );

// The method:
Color[] GetPrimaryScheme( Image image, int ncolors, int M = 9, int N = 9 )
{
    Color[] scheme = new Color[ncolors];
    Image[][] regions = new Image[M][N];

    DivideImageIntoRegions( image, regions );

    for( int i = 0; i < ncolors; i++ )
    {
        Map<Color, float> colorScores = new Map<Color, float>();

        for( int m = 0; m < M; m++ )
        for( int n = 0; n < N; n++ )
        {
            Color theColor;
            GetNthMostCommonColorInRegion( region, i, theColor );

            if( colorScores[theColor] == null )
            { colorScores[theColor] = 0; }

            colorScores[theColor] += weights[m][n];
        }

        scheme[i] = FindMaximum( colorScores );
    }

    return scheme;
}

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

            if( theColor != null )
                continue;

            if( colorScores[theColor] == null )
            { colorScores[theColor] = 0; }

            colorScores[theColor] += weights[m][n];
        }
4 голосов
/ 10 июля 2009

Название нужного вам типа алгоритма: Квантование цвета .

К сожалению, у меня нет исходного кода для вас, но я уверен, что поиск в Google может что-то поднять.

В частности, Д-р. Статья в журнале Добба на эту тему кажется многообещающей.

2 голосов
/ 10 июля 2009

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

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

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

2 голосов
/ 10 июля 2009

Как и в случае решения McWafflestix, необходимо будет изменить специфику, но мой общий подход будет ...

(я согласен, что HSV - правильное место)

  1. Возьмите гистограмму изображения, отфильтруйте ее, чтобы сгладить шум, и найдите наивысший балл, где V и S находятся в (возможно, динамической) гамме возможных «предметных» цветов. Красная птица на голубом небе потребует, чтобы мы были достаточно умны, чтобы основывать нашу схему не на синем, а на красном. Для этого могут потребоваться некоторые предположения о композиции фотографий, например, анализ «по центру кадра» и «правило третей» может дать вам вероятность того, что цвет будет релевантным. В любом случае, это наш базовый цвет.

  2. Вдоль линий Кулера вычислите цвета, дополняющие основу, перемещаясь вокруг цветового круга. Дополнительные очки за просчитанный комплимент, если он также появился на гистограмме с шага 1.

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

1 голос
/ 07 декабря 2016

Ниже приведены некоторые предложения и обсуждение различных подходов для создания цветовой схемы из изображения:

Во-первых, вставьте / разместите ваши пиксели в некотором цветовом пространстве. Это может быть RGB, HSL или другое цветовое пространство. Затем вы можете использовать одно из следующих действий для создания цветовой схемы:

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

  2. Median Cut или какой-либо другой метод разделения пространства - Это хорошее улучшение по сравнению с # 1, поскольку оно разделит пространство, посмотрев на данные.

  3. Кластеризация пикселей - Кластеризация пикселей в группы с использованием одного из многих методов кластеризации (k-средних, среднее смещение и т. Д.). Затем усредните пиксели в каждой группе для создания цветовой схемы.

Я написал более подробный пост о трех вышеупомянутых подходах здесь

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

1 голос
/ 17 мая 2012

Я немного опоздал с этим, но я бы реализовал Карту Кохонена (http://en.wikipedia.org/wiki/Self-organizing_map) в трехмерном цветовом пространстве. Число точек на карте было бы числом отдельных цветов, которые вы хотели для своей палитры, затем натренируйте свою карту, используя все пиксели на изображении. Я сам не пробовал, но уверен, что кто-то уже подумал об этом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...