문제

이것은 제가 여러 번 의사 해결을 해봤지만 아직 해결책을 찾지 못한 문제입니다.

문제는 생성 방법을 찾는 것입니다. N 가능한 한 구별할 수 있는 색상 N 매개변수입니다.

도움이 되었습니까?

해결책

이에 대한 나의 첫 번째 생각은 "서로의 거리를 최대화하는 공간에서 N개의 벡터를 생성하는 방법"이었습니다.

RGB(또는 색상 공간의 기초를 형성하는 데 사용하는 다른 스케일)가 단지 벡터라는 것을 알 수 있습니다.보세요 무작위 포인트 따기.서로 최대화되는 벡터 세트가 있으면 나중에 해시 테이블이나 다른 곳에 저장할 수 있으며 무작위 회전을 수행하여 서로 최대한 떨어져 있는 원하는 모든 색상을 얻을 수 있습니다!

이 문제를 좀 더 생각해 보면 색상을 (0,0,0) → (255,255,255) 사전순으로 선형 방식으로 매핑한 다음 고르게 분포시키는 것이 더 나을 것입니다.

이것이 얼마나 잘 작동할지는 모르겠지만, 이후에는 다음과 같이 말해야 합니다.

n = 10

우리는 16777216개의 색상(256^3)을 가지고 있다는 것을 알고 있습니다.

우리는 사용할 수 있습니다 버클 알고리즘 515 사전순으로 색인된 색상을 찾으려면\frac {\binom {256^3} {3}} {n} * i.오버플로를 방지하고 약간의 속도 향상을 추가하기 위해 알고리즘을 편집해야 할 수도 있습니다.

다른 팁

"지각적으로 균일한" 색상 공간에서 최대한 멀리 있는 색상을 찾는 것이 가장 좋습니다.CIELAB(L*, a*, b* 좌표 사이의 유클리드 거리를 거리 측정법으로 사용) 그런 다음 선택한 색상 공간으로 변환합니다.지각적 균일성은 인간 시각 시스템의 비선형성에 근접하도록 색 공간을 조정함으로써 달성됩니다.

일부 관련 리소스:

컬러브루어 - 지도에서 사용하기 위해 최대한 구별할 수 있도록 설계된 색상 세트입니다.

RGB랜드 탈출:통계 그래픽의 색상 선택 - 상품 생성을 위한 일련의 알고리즘을 설명하는 기술 보고서(예:최대로 구별 가능) 색상은 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;
}

색상을 설정하는 순서도 중요한 요소가 아닐까요?

Dillie-Os 아이디어를 사용하는 것처럼 색상을 최대한 혼합해야 합니다.0 64 128 256은 하나부터 다음까지입니다.그러나 바퀴의 0 256 64 128은 더 "떨어져" 있습니다.

이게 말이 돼?

나는 인간의 눈이 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개의 값을 모두 검토하고 위 예에서 배열에 색상을 추가하는 것입니다.

나는 이것이 오래된 게시물이라는 것을 알고 있지만 주제에 대한 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] 
    } 
}

따라서 $i가 색상을 식별하고, $n이 가능한 색상 수, $sat가 채도, $br이 밝기를 식별하는 Random_color() 함수를 호출하면 됩니다.

"가장 구별 가능한" 결과를 얻으려면 RGB가 아닌 Lab(또는 다른 지각 선형 색상 공간)과 같은 지각 색상 공간을 사용해야 합니다.또한, 이 공간을 양자화하여 공간의 크기를 줄일 수 있습니다.

가능한 모든 양자화된 항목으로 전체 3D 공간을 생성하고 다음을 사용하여 K-평균 알고리즘을 실행합니다. k=N.결과 중심/"수단"은 대략적으로 서로 가장 구별 가능해야 합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top