Как автоматически генерировать N "разных" цветов? - PullRequest
179 голосов
/ 22 января 2009

Я написал два метода ниже, чтобы автоматически выбрать N различных цветов. Он работает путем определения кусочно-линейной функции на кубе RGB. Преимущество этого состоит в том, что вы также можете получить прогрессивную шкалу, если вы этого хотите, но когда N становится большим, цвета могут начать выглядеть одинаково. Я также могу представить себе равномерное подразделение куба RGB на решетку и затем рисование точек. Кто-нибудь знает какие-либо другие методы? Я исключаю определение списка, а затем просто перебираю его. Я должен также сказать, что мне все равно, сталкиваются ли они или не выглядят красиво, они просто должны быть визуально различимы.

public static List<Color> pick(int num) {
    List<Color> colors = new ArrayList<Color>();
    if (num < 2)
        return colors;
    float dx = 1.0f / (float) (num - 1);
    for (int i = 0; i < num; i++) {
        colors.add(get(i * dx));
    }
    return colors;
}

public static Color get(float x) {
    float r = 0.0f;
    float g = 0.0f;
    float b = 1.0f;
    if (x >= 0.0f && x < 0.2f) {
        x = x / 0.2f;
        r = 0.0f;
        g = x;
        b = 1.0f;
    } else if (x >= 0.2f && x < 0.4f) {
        x = (x - 0.2f) / 0.2f;
        r = 0.0f;
        g = 1.0f;
        b = 1.0f - x;
    } else if (x >= 0.4f && x < 0.6f) {
        x = (x - 0.4f) / 0.2f;
        r = x;
        g = 1.0f;
        b = 0.0f;
    } else if (x >= 0.6f && x < 0.8f) {
        x = (x - 0.6f) / 0.2f;
        r = 1.0f;
        g = 1.0f - x;
        b = 0.0f;
    } else if (x >= 0.8f && x <= 1.0f) {
        x = (x - 0.8f) / 0.2f;
        r = 1.0f;
        g = 0.0f;
        b = x;
    }
    return new Color(r, g, b);
}

Ответы [ 13 ]

1 голос
/ 02 ноября 2016

Я написал пакет для R под названием qualpalr , который разработан специально для этой цели. Я рекомендую вам взглянуть на виньетка , чтобы узнать, как это работает, но я постараюсь обобщить основные моменты.

qualpalr берет спецификацию цветов в цветовом пространстве HSL (которое было описано ранее в этой теме), проецирует его в цветовое пространство DIN99d (которое является перцепционно однородным) и находит n, который максимизировать минимальное расстояние между ними.

# Create a palette of 4 colors of hues from 0 to 360, saturations between
# 0.1 and 0.5, and lightness from 0.6 to 0.85
pal <- qualpal(n = 4, list(h = c(0, 360), s = c(0.1, 0.5), l = c(0.6, 0.85)))

# Look at the colors in hex format
pal$hex
#> [1] "#6F75CE" "#CC6B76" "#CAC16A" "#76D0D0"

# Create a palette using one of the predefined color subspaces
pal2 <- qualpal(n = 4, colorspace = "pretty")

# Distance matrix of the DIN99d color differences
pal2$de_DIN99d
#>        #69A3CC #6ECC6E #CA6BC4
#> 6ECC6E      22                
#> CA6BC4      21      30        
#> CD976B      24      21      21

plot(pal2)

enter image description here

1 голос
/ 09 июля 2016

Это тривиально в MATLAB (есть команда hsv):

cmap = hsv(number_of_colors)
1 голос
/ 22 января 2009

Если N достаточно велико, вы получите несколько похожих цветов. В мире их так много.

Почему бы просто не распределить их равномерно по спектру, например:

IEnumerable<Color> CreateUniqueColors(int nColors)
{
    int subdivision = (int)Math.Floor(Math.Pow(nColors, 1/3d));
    for(int r = 0; r < 255; r += subdivision)
        for(int g = 0; g < 255; g += subdivision)
            for(int b = 0; b < 255; b += subdivision)
                yield return Color.FromArgb(r, g, b);
}

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

Я что-то понимаю?

...