Получение цветовой схемы из изображения

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

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

Может ли кто-нибудь здесь дать совет относительно того, как я мог бы создать программу, которая будет делать что-то похожее на программу выше, которая будет принимать изображение и выбирать пять лучших цветов, используемых в изображении?


person Mike B    schedule 11.01.2010    source источник
comment
serhio дал отличный отзыв об использовании миниатюрного изображения. Таким образом, время, необходимое для оценки изображения, будет быстро сокращено. +1   -  person Finglas    schedule 11.01.2010


Ответы (3)


Что ж ... Используйте уменьшенное изображение (16 x 16, 32 x 32 и т. Д.) И выберите из него цвета, например

обновленный код:

    private void button1_Click(object sender, EventArgs e)
    {
        int thumbSize = 32;
        Dictionary<Color, int> colors = new Dictionary<Color, int>();

        Bitmap thumbBmp = 
            new Bitmap(pictureBox1.BackgroundImage.GetThumbnailImage(
                thumbSize, thumbSize, ThumbnailCallback, IntPtr.Zero));

        //just for test
        pictureBox2.Image = thumbBmp;            

        for (int i = 0; i < thumbSize; i++)
        {
            for (int j = 0; j < thumbSize; j++)
            {
                Color col = thumbBmp.GetPixel(i, j);
                if (colors.ContainsKey(col))
                    colors[col]++;
                else
                    colors.Add(col, 1);
            }                
        }

        List<KeyValuePair<Color, int>> keyValueList = 
            new List<KeyValuePair<Color, int>>(colors);

        keyValueList.Sort(
            delegate(KeyValuePair<Color, int> firstPair,
            KeyValuePair<Color, int> nextPair)
            {
                return nextPair.Value.CompareTo(firstPair.Value);
            });

        string top10Colors = "";
        for (int i = 0; i < 10; i++)
        {
            top10Colors += string.Format("\n {0}. {1} > {2}",
                i, keyValueList[i].Key.ToString(), keyValueList[i].Value);
            flowLayoutPanel1.Controls[i].BackColor = keyValueList[i].Key;
        }
        MessageBox.Show("Top 10 Colors: " + top10Colors);
    }

    public bool ThumbnailCallback() { return false; }

http://lh3.ggpht.com/_1TPOP7DzY1E/S0uZ6GGD4oI/AAAAAAAAC5k/3Psp1cOCELY/s800/colors.png

person serhio    schedule 11.01.2010
comment
Это гениально! Никогда бы не подумал об этом. Я пока не могу проверить код, потому что мой ноутбук сломался, но я все равно приму ответ. Большое тебе спасибо! - person Mike B; 12.01.2010
comment
Эммм, блог, в котором было размещено изображение, не работал? Изображение больше не существует. Если он у вас все еще есть, вам следует подумать о его загрузке с помощью кнопки изображения в редакторе. - person Cole Johnson; 21.08.2013
comment
Разве это не избавит от высококонтрастных бликов только потому, что они не используются на большей части изображения? Я бы хотел что-то такое, что сохранит такие детали, а вместо этого отфильтрует слишком похожие цвета. - person Nyerguds; 10.04.2017

Как вы сказали, самый простой способ:

  • Считайте каждый пиксель и сохраните их в коллекции.

  • Пять основных используемых цветов будут наиболее часто встречающимися значениями.

Вот как я бы сначала попробовал что-то подобное.

Чтобы продолжить эту работу, вы можете использовать цветовые диапазоны, поэтому с помощью значений RGB (Red, Green, Blue) назначьте цвет с определенным приближением цвета.

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

Повторите то же самое для остальных пикселей.

Что касается масштабирования - на сайте-примере используются тусклые / яркие значения. Можно использовать простое значение шкалы. Рассмотрим средний красный цвет в RGB:

0.7, 0.0, 0.0

Вы можете масштабировать это, добавляя / умножая значение. Однако оставьте значения в пределах от 0 до 1. Насчет того, какое должно быть значение масштабирования, экспериментатор. Чем он выше, тем тусклее / ярче станет цвет.

person Finglas    schedule 11.01.2010
comment
Я должен добавить, что при использовании изображений BMP чтение в один пиксель и его обработка довольно просты, поэтому создание прототипа с использованием некоторых предложений, которые вы здесь получаете, должно быть вполне выполнимым. - person Finglas; 11.01.2010
comment
@Dockers, платформа - C # /. NET. Из-за этого все общие файлы имеют один API, GetPixel / SetPixel с X / Y. - person Dykam; 11.01.2010
comment
Однако GetPixel / SetPixel работает медленно. Я предпочитаю просто перебирать массив данных резервного копирования. - person Nyerguds; 10.04.2017

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

Но моя основная рекомендация - не использовать RGB (если только веб-сайт, который вы просматриваете, не имеет в основном простые цвета), а вместо этого используйте HSB. Компонент «H» (оттенок) даст вам лучшее представление об используемых цветах, независимо от того, насколько они яркие или темные.

person Padu Merloti    schedule 11.01.2010
comment
структура предоставляет .GetHue (), .GetSaturation () и .GetBrightness () для любого заданного объекта Color. Здесь есть очень хороший пост с подробностями: stackoverflow.com/questions/2942/hsl-in-net - person Padu Merloti; 11.01.2010