Функция для создания цветовых колес [закрыто]

Это то, что я много раз решал псевдорегулятором, и никогда так и не нашел решения.

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

1.08.2008 18:42:19
В последний раз я проверял, что JFreeChart имеет этот точный алгоритм и, поскольку он является открытым исходным кодом, вы можете проверить, что он делает. Я знаю, что цвета, которые я получаю, кажутся не случайно расположенными вдоль некоторого круга или сферы, а скорее выбираются более конкретно.
Kathy Van Stone 30.09.2009 18:00:26
8 ОТВЕТОВ
РЕШЕНИЕ

Моя первая мысль об этом: «Как создать N векторов в пространстве, которые максимизируют расстояние друг от друга».

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

Если больше думать об этой проблеме, было бы лучше отобразить цвета линейно, возможно, (0,0,0) → (255,255,255) лексикографически, а затем распределить их равномерно.

Я действительно не знаю, насколько хорошо это будет работать, но с тех пор, скажем так:

n = 10

мы знаем, что у нас 16777216 цветов (256 ^ 3).

Мы можем использовать Buckles Algorithm 515, чтобы найти лексикографически индексированный цвет. \ frac {\ binom {256 ^ 3} {3}} {n} * i, Вам, вероятно, придется отредактировать алгоритм, чтобы избежать переполнения и, возможно, добавить некоторые незначительные улучшения скорости.

24
30.05.2018 13:55:59
Это неверно, потому что цветовое пространство RGB не одинаково воспринимается
adrienlucca.wordpress.com 13.01.2015 17:24:11
Я согласен, что звучит логично. RGB в основном дает фиолетовые и оранжевые гибриды, а относительно редко - сине-зеленые гибриды ... цветовая гамма однородна от инфракрасного до темно-синего, поэтому приходится выбирать точки, расположенные на одинаковом расстоянии друг от друга. нужен алгоритм на основе радуги.
com.prehensible 14.09.2015 12:46:06
Пожалуйста, рассмотрите возможность голосования / следите за сайтом теории цвета StackExchange: area51.stackexchange.com/proposals/110687/color-theory
Adi Shavit 22.06.2017 08:14:49

Было бы лучше найти цвета, максимально удаленные в «перцепционно однородном» цветовом пространстве, например, CIELAB (используя евклидово расстояние между координатами L *, a *, b * в качестве метрики расстояния), а затем преобразовать в цветовое пространство по вашему выбору. Однородность восприятия достигается путем настройки цветового пространства для аппроксимации нелинейностей в зрительной системе человека.

18
30.01.2016 15:14:29
Это, вероятно, лучшее решение, так как оно довольно простое. Однако есть и другие формулы цветоразностных характеристик, такие как CIE2000 или даже CIECAM
adrienlucca.wordpress.com 13.01.2015 17:25:47

Некоторые связанные ресурсы:

ColorBrewer - Наборы цветов, разработанные таким образом, чтобы максимально различаться для использования на картах.

Выход из RGBland: выбор цветов для статистической графики - технический отчет, описывающий набор алгоритмов для генерации хороших (то есть максимально различимых) наборов цветов в цветовом пространстве hcl.

8
18.09.2008 16:01:24
Экранирование RGBland является обязательным для прочтения справочником для выбора воспринимаемых различимых цветовых палитр.
Drake Guan 19.07.2013 09:16:22

Вот некоторый код для равномерного распределения цветов RGB вокруг цветового круга HSL заданной яркости.

class cColorPicker
{
public:
    void Pick( vector<DWORD>&v_picked_cols, int count, int bright = 50 );
private:
    DWORD HSL2RGB( int h, int s, int v );
    unsigned char ToRGB1(float rm1, float rm2, float rh);
};
/**

  Evenly allocate RGB colors around HSL color wheel

  @param[out] v_picked_cols  a vector of colors in RGB format
  @param[in]  count   number of colors required
  @param[in]  bright  0 is all black, 100 is all white, defaults to 50

  based on Fig 3 of http://epub.wu-wien.ac.at/dyn/virlib/wp/eng/mediate/epub-wu-01_c87.pdf?ID=epub-wu-01_c87

*/

void cColorPicker::Pick( vector<DWORD>&v_picked_cols, int count, int bright )
{
    v_picked_cols.clear();
    for( int k_hue = 0; k_hue < 360; k_hue += 360/count )
        v_picked_cols.push_back( HSL2RGB( k_hue, 100, bright ) );
}
/**

  Convert HSL to RGB

  based on http://www.codeguru.com/code/legacy/gdi/colorapp_src.zip

*/

DWORD cColorPicker::HSL2RGB( int h, int s, int l )
{
    DWORD ret = 0;
    unsigned char r,g,b;

    float saturation = s / 100.0f;
    float luminance = l / 100.f;
    float hue = (float)h;

    if (saturation == 0.0) 
    {
      r = g = b = unsigned char(luminance * 255.0);
    }
    else
    {
      float rm1, rm2;

      if (luminance <= 0.5f) rm2 = luminance + luminance * saturation;  
      else                     rm2 = luminance + saturation - luminance * saturation;
      rm1 = 2.0f * luminance - rm2;   
      r   = ToRGB1(rm1, rm2, hue + 120.0f);   
      g = ToRGB1(rm1, rm2, hue);
      b  = ToRGB1(rm1, rm2, hue - 120.0f);
    }

    ret = ((DWORD)(((BYTE)(r)|((WORD)((BYTE)(g))<<8))|(((DWORD)(BYTE)(b))<<16)));

    return ret;
}


unsigned char cColorPicker::ToRGB1(float rm1, float rm2, float rh)
{
  if      (rh > 360.0f) rh -= 360.0f;
  else if (rh <   0.0f) rh += 360.0f;

  if      (rh <  60.0f) rm1 = rm1 + (rm2 - rm1) * rh / 60.0f;   
  else if (rh < 180.0f) rm1 = rm2;
  else if (rh < 240.0f) rm1 = rm1 + (rm2 - rm1) * (240.0f - rh) / 60.0f;      

  return static_cast<unsigned char>(rm1 * 255);
}

int _tmain(int argc, _TCHAR* argv[])
{
    vector<DWORD> myCols;
    cColorPicker colpick;
    colpick.Pick( myCols, 20 );
    for( int k = 0; k < (int)myCols.size(); k++ )
        printf("%d: %d %d %d\n", k+1,
        ( myCols[k] & 0xFF0000 ) >>16,
        ( myCols[k] & 0xFF00 ) >>8,
        ( myCols[k] & 0xFF ) );

    return 0;
}
7
30.04.2016 11:29:24
AFAIK, просто перенести код с C ++ на Java
ravenspoint 14.01.2013 13:29:53
не тогда, когда я не понимаю всех вещей, сдвигающих биты, между прочим: /
CodeGuy 15.01.2013 05:15:54
Я предоставил URL-адреса, которые ссылаются на объяснения того, что делает код.
ravenspoint 15.01.2013 12:39:41
Что если я хочу включить, чтобы цвета отличались от цвета фона, который я предоставляю?
CodeGuy 16.01.2013 04:58:39
Рассчитайте «расстояние» между сгенерированными цветами и цветом фона. Не используйте цвет, который ближе всего к вашему фону.
ravenspoint 16.01.2013 13:18:14

Разве это не тот фактор, в каком порядке вы устанавливаете цвета?

Например, если вы используете идею Дилли-Ос, вам нужно как можно больше смешивать цвета. 0 64 128 256 - от одного к другому. но 0 256 64 128 в колесе было бы более "врозь"

Имеет ли это смысл?

3
2.08.2008 18:16:07

Я читал где-то, что человеческий глаз не может различить менее 4 значений друг от друга. так что это что-то иметь в виду. Следующий алгоритм не компенсирует это.

Я не уверен, что это именно то, что вы хотите, но это один из способов случайного генерирования неповторяющихся значений цвета:

(будьте осторожны, непоследовательный псевдокод впереди)

//colors entered as 0-255 [R, G, B]
colors = []; //holds final colors to be used
rand = new Random();

//assumes n is less than 16,777,216
randomGen(int n){
   while (len(colors) < n){
      //generate a random number between 0,255 for each color
      newRed = rand.next(256);
      newGreen = rand.next(256);
      newBlue = rand.next(256);
      temp = [newRed, newGreen, newBlue];
      //only adds new colors to the array
      if temp not in colors {
         colors.append(temp);
      }
   }
}

Один из способов оптимизировать это для лучшей видимости - сравнить расстояние между каждым новым цветом и всеми цветами в массиве:

for item in color{
   itemSq = (item[0]^2 + item[1]^2 + item[2]^2])^(.5);
   tempSq = (temp[0]^2 + temp[1]^2 + temp[2]^2])^(.5);
   dist = itemSq - tempSq;
   dist = abs(dist);
}
//NUMBER can be your chosen distance apart.
if dist < NUMBER and temp not in colors {
   colors.append(temp);
}

Но такой подход значительно замедлит ваш алгоритм.

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

1
1.08.2008 19:36:46

Я знаю, что это старый пост, но я нашел его, когда искал решение PHP для этой темы, и, наконец, пришел с простым решением:

function random_color($i = null, $n = 10, $sat = .5, $br = .7) {
    $i = is_null($i) ? mt_rand(0,$n) : $i;
    $rgb = hsv2rgb(array($i*(360/$n), $sat, $br));
    for ($i=0 ; $i<=2 ; $i++) 
        $rgb[$i] = dechex(ceil($rgb[$i]));
    return implode('', $rgb);
}

function hsv2rgb($c) { 
    list($h,$s,$v)=$c; 
    if ($s==0) 
        return array($v,$v,$v); 
    else { 
        $h=($h%=360)/60; 
        $i=floor($h); 
        $f=$h-$i; 
        $q[0]=$q[1]=$v*(1-$s); 
        $q[2]=$v*(1-$s*(1-$f)); 
        $q[3]=$q[4]=$v; 
        $q[5]=$v*(1-$s*$f); 
        return(array($q[($i+4)%6]*255,$q[($i+2)%6]*255,$q[$i%6]*255)); //[1] 
    } 
}

Так что просто вызовите функцию random_color (), где $ i определяет цвет, $ n количество возможных цветов, $ sat насыщенность и $ br яркость.

1
19.10.2011 01:58:23
Можете ли вы объяснить, что такое «я» в данном случае? Вопрос задан для N номеров. Что такое параматер "я"?
CodeGuy 14.01.2013 07:39:16
On random_color(), $iэто «семя» для генерации оттенка, должно быть числом от 0 до $n, если вы не вводите seed (NULL), функция выбирает случайный. $nколичество возможных цветов для данной насыщенности и яркости, то есть количество цветов в палитре. Мы в основном разбиваем 360 градусов оттенков на $nи используем $iв качестве множителя. Другими словами, чем выше $n, тем больше цветов, чем ниже $n, тем меньше цветов, но больше разных. $iбудет определять цвет и всегда будет одинаковым, если вы продолжите использовать эту функцию. Надеюсь, это поможет.
Mauro 14.01.2013 18:35:21
Понимаю! Спасибо за объяснение. Еще одна вещь ... какие-либо предложения, что делать, если у меня есть цвет фона, и я хочу быть как можно дальше от этого для всех цветов?
CodeGuy 15.01.2013 05:16:45
Вам нужно добавить 180 градусов к оттенку вашего цвета, сохраняя насыщенность и ценность. Разместите новый вопрос для этого, вставьте ссылку сюда, и я объясню дальше!
Mauro 15.01.2013 16:37:28

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

Создайте полное трехмерное пространство со всеми возможными квантованными записями и запустите алгоритм K-средних с помощью k=N. Результирующие центры / «средства» должны быть примерно максимально различимы друг от друга.

0
7.02.2014 17:43:13