Algorithm 用于创建颜色控制盘的函数

Algorithm 用于创建颜色控制盘的函数,algorithm,language-agnostic,colors,color-space,Algorithm,Language Agnostic,Colors,Color Space,这是我已经伪解决了很多次,从来没有找到一个解决方案 问题是要找到一种方法来生成N颜色,在N是一个参数的情况下,这种颜色尽可能可区分。我读到过一些人眼无法区分少于4个值的地方。所以这是需要记住的。以下算法无法对此进行补偿 我不确定这是否正是您想要的,但这是随机生成非重复颜色值的一种方法: (注意,前面的伪代码不一致) //输入的颜色为0-255[R、G、B] 颜色=[]//保存要使用的最终颜色 rand=新随机数(); //假设n小于16777216 随机发生器(int n){ while(len

这是我已经伪解决了很多次,从来没有找到一个解决方案


问题是要找到一种方法来生成
N
颜色,在
N
是一个参数的情况下,这种颜色尽可能可区分。

我读到过一些人眼无法区分少于4个值的地方。所以这是需要记住的。以下算法无法对此进行补偿

我不确定这是否正是您想要的,但这是随机生成非重复颜色值的一种方法:

(注意,前面的伪代码不一致)

//输入的颜色为0-255[R、G、B]
颜色=[]//保存要使用的最终颜色
rand=新随机数();
//假设n小于16777216
随机发生器(int n){
while(len(颜色)
为了获得更好的可见性,可以对此进行优化的一种方法是比较每个新颜色与阵列中所有颜色之间的距离:

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);
}
用于颜色为的项目{
itemSq=(项[0]^2+项[1]^2+项[2]^2])^(.5);
tempSq=(临时[0]^2+临时[1]^2+临时[2]^2])^(.5);
dist=itemSq-tempSq;
dist=abs(dist);
}
//数字可以是您选择的距离。
如果距离<数字且温度不在颜色中{
颜色。附加(临时);
}
但这种方法会大大降低算法的速度


另一种方法是消除随机性,系统地检查每4个值,并在上面的示例中向数组添加颜色。

这不是设置颜色顺序的一个因素吗

如果你使用Dillie Os的想法,你需要尽可能多地混合颜色。 0 64 128 256是从一个到下一个。但轮子上的0 256 64 128会更“分开”


这有意义吗?

关于这一点,我的第一个想法是“如何在空间中生成N个向量,使彼此之间的距离最大化。”

您可以看到RGB(或在颜色空间中形成基础的任何其他比例)只是矢量。看一看。一旦你有了一组间距最大化的向量,你就可以把它们保存在一个哈希表中或是以后用的东西中,然后对它们进行随机旋转,得到你想要的彼此间距最大的所有颜色

进一步考虑这个问题,最好以线性方式映射颜色,可能是(0,0,0)→ (255255)按字典顺序排列,然后均匀分布

我真的不知道这会有多好,但应该是因为,让我们说:

n = 10
我们知道我们有16777216种颜色(256^3)


我们可以使用查找字典索引颜色。。您可能需要编辑算法以避免溢出,并可能添加一些小的速度改进。

最好在“感知一致”的颜色空间中找到最大距离的颜色,例如CIELAB(使用L*、a*、b*坐标之间的欧几里德距离作为距离度量)然后转换到您选择的颜色空间。通过调整颜色空间以近似人类视觉系统中的非线性来实现感知一致性。

一些相关资源:

-设计为在地图上使用时可最大程度区分的颜色集


-描述在hcl颜色空间中生成良好(即最大可分辨)颜色集的一组算法的技术报告。

以下是一些代码,用于在指定亮度的HSL色轮周围均匀分配RGB颜色

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;
}
类颜色选择器
{
公众:
无效拾取(向量和v拾取的向量,整数计数,整数亮度=50);
私人:
DWORD HSL2RGB(内部h、内部s、内部v);
无符号字符TORG1(浮点rm1、浮点rm2、浮点rh);
};
/**
围绕HSL色轮均匀分配RGB颜色
@param[out]v_拾取RGB格式的颜色向量
@参数[in]计数所需的颜色数
@参数[in]亮0为全黑,100为全白,默认为50
基于图3http://epub.wu-wien.ac.at/dyn/virlib/wp/eng/mediate/epub-wu-01_c87.pdf?ID=epub-wu-01_c87
*/
void cColor Picker::Pick(向量&v_picked_cols,int count,int bright)
{
v_picked_cols.clear();
对于(int k_色调=0;k_色调<360;k_色调+=360/计数)
v_拾取颜色。向后推(HSL2RGB(k_色调,100,明亮));
}
/**
将HSL转换为RGB
基于http://www.codeguru.com/code/legacy/gdi/colorapp_src.zip
*/
DWORD cColorPicker::HSL2RGB(整数h、整数s、整数l)
{
DWORD ret=0;
无符号字符r,g,b;
浮动饱和=s/100.0f;
浮动亮度=l/100.f;
浮动色调=(浮动)h;
如果(饱和度==0.0)
{
r=g=b=无符号字符(亮度*255.0);
}
其他的
{
浮动rm1、rm2;
如果(亮度8,
(myCols[k]&0xFF));
返回0;
}
函数随机颜色($i=null,$n=10,$sat=0.5,$br=0.7){
$i=is_null($i)?mt_rand(0,$n):$i;
$rgb=hsv2rgb(数组($i*(360/$n),$sat,$br));
对于($i=0;$i要实现“最可分辨”,我们需要使用除RGB之外的感知颜色空间,如Lab(或任何其他感知线性颜色空间)。此外,我们可以量化此空间以减小空间大小

使用所有可能的量化输入生成完整的3D空间,并使用
K=N
运行K-means算法。生成的中心/“means”应该彼此之间最容易区分。

您能解释一下在这种情况下“i”是什么吗?问题是问N个数字。在
random_color()上,“i”参数是什么
$i
是生成色调的“种子”,应该是0到
$n
之间的数字,如果未输入种子(NULL),函数将随机选取一个。
$
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;
}
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] 
    } 
}