2008-08-01 13 views
61

यह ऐसा कुछ है जिसे मैंने कई बार छद्म हल किया है और कभी भी समाधान नहीं मिला है। वह मेरे साथ फंस गया है। समस्या N रंगों को उत्पन्न करने के तरीके के साथ आना है, जो संभवतः यथासंभव भिन्न हैं जहां N एक पैरामीटर है।रंग पहियों बनाने के लिए फ़ंक्शन

+0

अंतिम मैं जाँच की [JFreeChart] (http://www.jfree.org/jfreechart/) इस सटीक एल्गोरिथ्म है और के रूप में यह खुला स्रोत है आप यह क्या करता है की जाँच कर सकते हैं। मुझे पता है कि मुझे लगता है कि रंग कुछ सर्कल या गोलाकार के साथ यादृच्छिक रूप से दूरी नहीं लगते हैं, बल्कि अधिक विशेष रूप से चुना जाता है। –

उत्तर

22

इस पर मेरा पहला विचार यह है कि "एक अंतरिक्ष में एन वैक्टर कैसे उत्पन्न करते हैं जो एक-दूसरे से दूरी को अधिकतम करते हैं।" आप देख सकते हैं कि आरजीबी (या कोई अन्य स्केल जो आप उपयोग करते हैं जो कलर स्पेस में आधार बनाता है) केवल वैक्टर हैं। Random Point Picking पर एक नज़र डालें। आशा है कि यह आपके लिए एक अच्छी शुरुआत है! एक बार जब आपके पास वेक्टरों का एक सेट होता है जो एक भाग को अधिकतम कर देते हैं, तो आप उन्हें हैश टेबल या बाद में कुछ में सहेज सकते हैं, और केवल उन सभी रंगों को प्राप्त करने के लिए यादृच्छिक रोटेशन कर सकते हैं जो अधिकतम एक-दूसरे से अलग हैं!

संपादित करें: इस समस्या के बारे में अधिक सोच रही थी, यह बेहतर होगा एक रेखीय मनोर में रंग मैप करने के लिए, संभवतः (0,0,0) -> (255,255,255) कोषगत, और फिर उन्हें समान रूप से वितरित करें। मैं वास्तव में नहीं जानता कि यह कितना अच्छा काम करेगा, लेकिन इसे तब से कहना चाहिए:

एन = 10 हम जानते हैं कि हमारे पास 16777216 रंग (256^3) हैं। हम लेक्सिकोोग्राफिक रूप से अनुक्रमित रंग को खोजने के लिए buckles algorithm 515 का उपयोग कर सकते हैं। \frac {\binom {256^3} {3}} {n} * i। अतिप्रवाह से बचने के लिए आपको शायद एल्गोरिदम संपादित करना होगा और शायद कुछ मामूली गति सुधार जोड़ें।

+1

यह गलत है क्योंकि आरजीबी रंग स्थान अवधारणात्मक रूप से समान नहीं है –

+0

मैं सहमत हूं कि तार्किक लगता है। आरजीबी ज्यादातर बैंगनी और नारंगी संकर बनाता है और अपेक्षाकृत दुर्लभ नीले हरे संकर बनाता है ... रंग का स्तर इन्फ्रा लाल से गहरे नीले रंग के समान होता है, इसलिए इसके साथ समान बिंदुओं को चुनना होता है। इंद्रधनुष आधारित अलगो की जरूरत है। –

+0

/upvoting पर विचार करें StackExchange रंग सिद्धांत साइट निम्नलिखित: https://area51.stackexchange.com/proposals/110687/color-theory –

1

मैंने कहीं पढ़ा है मानव आंख 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); 
} 

लेकिन इस दृष्टिकोण significa हैं अपने एल्गोरिदम को धीमा कर दें।

एक और तरीका यादृच्छिकता को स्क्रैप करना और व्यवस्थित रूप से प्रत्येक 4 मानों के माध्यम से जाना और उपर्युक्त उदाहरण में एक सरणी में रंग जोड़ना होगा।

3

क्या यह एक कारक भी नहीं है जिससे आप रंग स्थापित कर सकें?

यदि आप डिली-ओस विचार का उपयोग करते हैं तो आपको जितना संभव हो सके रंगों को मिश्रण करने की आवश्यकता है। 0 64 128 256 एक से दूसरे तक है। लेकिन एक व्हील में 0 256 64 128 अधिक "अलग" होगा

क्या यह समझ में आता है?

17

रंगों को "अवधारणात्मक वर्दी" रंगस्थान में अधिकतम दूरी से ढूंढना सबसे अच्छा होगा, उदाहरण के लिए CIELAB (एल *, ए *, बी * आपके दूरी मीट्रिक के रूप में निर्देशांक के बीच यूक्लिडियन दूरी का उपयोग करके) और फिर अपनी पसंद के रंगस्थान में कनवर्ट करना। मानवीय दृश्य प्रणाली में गैर-रैखिकता का अनुमान लगाने के लिए रंगस्थान को ट्विक करके अवधारणात्मक एकरूपता प्राप्त की जाती है।

+0

यह शायद सबसे अच्छा समाधान के रूप में यह काफी सरल है। लेकिन वहाँ पर विचार करने के लिए अन्य रंग-अंतर सूत्र, CIE2000 या यहाँ तक कि CIECAM –

7

कुछ संबंधित संसाधन:

ColorBrewer - नक्शे पर उपयोग के लिए अधिकतम साफ़ करने के लिए डिज़ाइन रंग के सेट।

Escaping RGBland: Selecting Colors for Statistical Graphics - एचसीएल रंग अंतरिक्ष में अच्छे (यानी अधिकतम अंतर करने योग्य) रंग सेट बनाने के लिए एल्गोरिदम के एक सेट का वर्णन करने वाली एक तकनीकी रिपोर्ट।

+1

बचने RGBland की तरह बहुत जरूरी perceptually अलग पहचाना रंग पट्टियाँ चुनने के लिए संदर्भ को पढ़ने के लिए है। – Drake

6

यहाँ निर्दिष्ट चमक के एचएसएल रंग चक्र के चारों ओर समान रूप से आरजीबी रंग आवंटित करने के लिए कुछ कोड है।

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; 
} 
+2

AFAIK यह सी ++ से जावा – ravenspoint

+0

से पोर्ट कोड के लिए सीधा है, जब मैं अन्य चीजों के साथ सभी बिट स्थानांतरण सामग्री को समझ नहीं पा रहा हूं:/ – CodeGuy

+0

मैंने यूआरएल प्रदान किए हैं जो कोड के स्पष्टीकरण से लिंक करते हैं। – ravenspoint

1

मैं इस एक पुरानी पोस्ट है, लेकिन मैं इसे थोड़ी देर के विषय के लिए एक 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() फ़ंक्शन जहां फोन $ मैं रंग की पहचान करता हूं, $ n संभावित रंगों की संख्या, $ संतृप्ति बैठता है और चमकती है।

+0

क्या आप इस मामले में "i" क्या समझा सकते हैं? प्रश्न एन संख्या के लिए पूछा गया। "मैं" पैरामीटर क्या है? – CodeGuy

+0

'random_color()' पर, 'i i' रंग उत्पन्न करने के लिए" बीज "है, यदि आप कोई बीज (NULL) इनपुट करते हैं, तो 0 से' n n 'तक की संख्या होनी चाहिए, फ़ंक्शन एक यादृच्छिक चुनता है। '$ n' किसी दिए गए संतृप्ति और चमक के लिए संभव रंगों की मात्रा है यानी पैलेट में रंगों की संख्या। हम मूल रूप से 360 ह्यू डिग्री को '$ n' में विभाजित कर रहे हैं और गुणक के रूप में' $ i' का उपयोग कर रहे हैं। दूसरे शब्दों में, उच्च '$ n' आपको अधिक रंग देगा, कम' $ n' आपको कम रंग देगा लेकिन एक दूसरे के लिए अधिक अलग होगा। 'i i' रंग की पहचान करेगा और यदि आप इस फ़ंक्शन का उपयोग करते रहेंगे तो हमेशा वही रहेगा। मुझे आशा है कि वह मदद करेंगे। – Mauro

+0

मैं देखता हूँ! स्पष्टीकरण के लिए धन्यवाद। एक और बात ... अगर मेरे पास पृष्ठभूमि रंग है तो क्या करना है और मैं सभी रंगों के लिए जितना संभव हो उससे दूर रहना चाहता हूं? – CodeGuy

0

प्राप्त करने के लिए "सबसे अलग पहचाना" हम एक अवधारणात्मक रंग (या किसी अन्य perceptually रैखिक रंग अंतरिक्ष) लैब की तरह अंतरिक्ष और नहीं आरजीबी प्रयोग करना होगा। इसके अलावा, हम अंतरिक्ष के आकार को कम करने के लिए इस जगह को माप सकते हैं।

सभी संभव मात्रा निर्धारित प्रविष्टियों के साथ पूर्ण 3 डी अंतरिक्ष उत्पन्न और चलाने k=N साथ कश्मीर का मतलब है एल्गोरिथ्म। परिणामी केंद्र/"साधन" एक-दूसरे से लगभग सबसे अलग-अलग होना चाहिए।

संबंधित मुद्दे