Как создать контрастные цвета? - PullRequest
6 голосов
/ 30 марта 2011

Мое приложение содержит линейный график, который может отображать 20 или более наборов данных одновременно, но обычно оно отображает менее 5. Я бы хотел, чтобы каждый набор данных имел уникальный цвет.

В настоящее время я делаю это:

setHsl(i * 255.0 / session->getNumDataSets(), 255, 128);

Это работает, но имеет недостаток, что два последовательных набора данных будут иметь очень похожие цвета.Мне бы хотелось, чтобы каждый сгенерированный цвет был как можно более контрастным по сравнению со всеми предыдущими сгенерированными цветами.

Как лучше создать цвета?

Вот моя вторая попытка:

double pos = 0;
if (wheel.size() == 0)
{
    wheel.append(0.0);
    wheel.append(1.0);
}
else
{
    double gap = 0;
    double hi = 0;
    double lo = 0;

    for (int i = 0; i < wheel.size() - 1; i++)
    {
        double g = wheel[i + 1] - wheel[i];
        if (g > gap)
        {
            gap = g;
            lo = wheel[i];
            hi = wheel[i + 1];
        }
    }

    pos = (hi - lo) / 2.0 + lo;

    wheel.append(pos);
    qSort(wheel);
}

QColor c;
c.setHsl(pos * 255.0, 255, 128);
return c.toRgb();

Моя идея состоит в том, что первый цвет - это позиция 0 наЦветовое колесо.Затем для каждого следующего цвета я обхожу цветовое колесо, ища самый большой разрыв между цветами, и как только я его нашел, я вставляю новый цвет в этот разрыв.Кажется, он работает лучше, но все еще не идеально, поскольку, как только промежутки становятся маленькими, последовательные цвета снова становятся похожими.

Ответы [ 4 ]

5 голосов
/ 30 марта 2011

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

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

Если у вас может быть более 20 наборов данных, я думаю, что будет очень трудно отличитьодин цвет, но цвета могут быть повторно использованы в сочетании с другим отличием, таким как пунктирные линии.

3 голосов
/ 30 марта 2011

Вы могли бы сделать что-то вроде:

int n = session->getNumDataSets();
setHsl( (((i%3) * n/3)+(i/3)) * 255.0 / n, 255, 128);

Я должен был бы перепроверить мою математику, но в основном она вращается через трети спектра.

2 голосов
/ 08 сентября 2011

Я использую следующую функцию в Java для создания равномерно распределенных цветов для разных наборов данных на графиках, сгенерированных Java. Это коротко и сладко:

/**
 * This function splits the red-green-blue colour wheel into n equally spaced divisions
 * and returns the colour from a particular division.
 * 
 * @param index The index of the colour to return, the range is 0 - (count-1)
 * @param count The number of divisions to split the HSV colour wheel into
 * @return A java.awt.Color object containing the colour.
 * @author HughesR
 */
public static Color getSpacedOutColour(int index, int count) {
    final float saturation = 0.95f; // Saturation
    final float brightness = 0.8f;  // Brightness
    float hue = (float)index / (float)count;
    return Color.getHSBColor(hue, saturation, brightness);
}
2 голосов
/ 31 марта 2011

Не используйте HSL. Недостатки в том, что цвета, которые «выглядят по-разному» численно в пространстве HSL (или так же плохо, HSV), в конечном итоге выглядят одинаково на ваш взгляд. Вместо этого используйте YUV (он же YCbCr). Основная идея YUV, если вы не знакомы, состоит в том, чтобы сделать линейное преобразование в координаты, где первая ось имеет интенсивность восприятия , что-то вроде:

Y = 0.3*R + 0.6*G + 0.1*B

(обычно используются более точные коэффициенты, но это простые, которые дают вам приблизительное представление о весах)

Затем вторую и третью оси просто выбирают в виде двух векторов в плоскости, ортогональной оси Y, часто приблизительно в «красном» и «синем» направлениях.

Обратите внимание, что, поскольку цвета ограничены кубом в координатах RGB, после выбора значения Y это накладывает ограничение на возможные значения U и V, которые остаются внутри поля. При Y = max U и V должны быть равны нулю. Так что просто выберите какое-нибудь значение Y промежуточной яркости, в котором вы много играете в U и V, а затем выберите N равномерно расположенных векторов в полярных координатах в плоскости UV.

...