रैखिक बनाम गैर-रैखिक आरजीबी अंतरिक्ष में रंगों के साथ काम करते समय व्यावहारिक अंतर क्या हैं?


88

एक रैखिक आरजीबी अंतरिक्ष की मूल संपत्ति क्या है और गैर-रैखिक एक की मौलिक संपत्ति क्या है? जब उन 8 (या अधिक) बिट्स में प्रत्येक चैनल के अंदर के मूल्यों के बारे में बात करते हैं, तो क्या बदलता है?

ओपनजीएल में, रंग 3 + 1 मान हैं, और इसके साथ मेरा मतलब है आरजीबी + अल्फा, प्रत्येक चैनल के लिए 8 बिट आरक्षित है, और यह वह हिस्सा है जो मुझे स्पष्ट रूप से मिलता है।

लेकिन जब गामा सुधार की बात आती है, तो मुझे नहीं लगता कि गैर-रैखिक आरजीबी अंतरिक्ष में काम करने का क्या प्रभाव है।

चूंकि मुझे पता है कि फोटो-संपादन के लिए ग्राफिक सॉफ़्टवेयर में वक्र का उपयोग कैसे किया जाता है, इसलिए मेरा स्पष्टीकरण है कि रैखिक आरजीबी अंतरिक्ष में आप मान लेते हैं जैसे कि वे हैं, कोई हेरफेर नहीं और कोई गणित फ़ंक्शन संलग्न नहीं है, इसके बजाय जब यह गैर-रैखिक प्रत्येक है चैनल आमतौर पर एक क्लासिक पावर फ़ंक्शन व्यवहार के बाद विकसित होता है।

यहां तक ​​कि अगर मैं इस स्पष्टीकरण को वास्तविक के रूप में लेता हूं, तो मुझे अभी भी वह नहीं मिलता है जो एक वास्तविक रैखिक स्थान है, क्योंकि गणना के बाद सभी गैर-रेखीय आरजीबी रिक्त स्थान रैखिक हो जाते हैं और सबसे महत्वपूर्ण मुझे वह हिस्सा नहीं मिलता है जहां एक गैर -लाइन रंग का स्थान मानव आंख के लिए अधिक उपयुक्त है क्योंकि अंत में सभी आरजीबी रिक्त स्थान रैखिक हैं जो मैं समझता हूं।


एक व्यावहारिक नोट पर, आप एसवीजी में अपने रंग स्थान के रूप में या तो रैखिक या मानक आरजीबी निर्दिष्ट कर सकते हैं और मुझे नहीं पता कि इसका क्या प्रभाव है, इस तथ्य के अलावा कि यह महत्वपूर्ण प्रतीत होता है :-)
माइकल मुल्नी

@MichaelMullany यह लीनियर चीज़ वास्तविक विशिष्ट गुणवत्ता की तुलना में उपयोगकर्ता के लिए एक संकेत की तरह दिखती है।
केन

कुछ ऐसा है जिसने मेरी मदद की: मुझे लगता है कि यह एक गणित शिक्षक था जिसने मुझसे कहा था "जब आप रैखिक सुनते हैं तो थिंक लाइन"। यकीन नहीं अगर यह किसी भी मदद करता है, लेकिन मेरे लिए, यह "ओह हाँ!" पल
जो प्लांट

जवाबों:


229

मान लें कि आप RGB रंगों के साथ काम कर रहे हैं: प्रत्येक रंग को तीन तीव्रता या चमक के साथ दर्शाया गया है । आपको "रैखिक RGB" और "sRGB" के बीच चयन करना है। अभी के लिए, हम तीन अलग-अलग तीव्रता को अनदेखा करके चीजों को सरल करेंगे, और मान लें कि आपके पास बस एक तीव्रता है: अर्थात, आप केवल ग्रे के रंगों के साथ काम कर रहे हैं।

एक रैखिक रंग-स्थान में, आपके द्वारा संग्रहित संख्याओं और उनके द्वारा प्रदर्शित तीव्रता के बीच का संबंध रैखिक होता है। व्यावहारिक रूप से, इसका मतलब है कि यदि आप संख्या को दोगुना करते हैं, तो आप तीव्रता (ग्रे की लपट) को दोगुना करते हैं। यदि आप दो तीव्रता को एक साथ जोड़ना चाहते हैं (क्योंकि आप दो प्रकाश स्रोतों के योगदान के आधार पर तीव्रता की गणना कर रहे हैं, या क्योंकि आप एक अपारदर्शी वस्तु के ऊपर एक पारदर्शी वस्तु जोड़ रहे हैं), तो आप इसे केवल जोड़कर कर सकते हैं एक साथ दो नंबर। यदि आप किसी भी तरह के 2 डी सम्मिश्रण या 3 डी छायांकन, या लगभग किसी भी छवि प्रसंस्करण कर रहे हैं, तो आप एक रैखिक रंग-स्थान में अपनी तीव्रता चाहते हैं, इसलिए आप तीव्रता पर समान प्रभाव डालने के लिए बस जोड़, घटा, गुणा और भाग कर सकते हैं। अधिकांश रंग-प्रसंस्करण और रेंडरिंग एल्गोरिदम केवल रैखिक आरजीबी के साथ सही परिणाम देते हैं, जब तक कि आप हर चीज में अतिरिक्त भार नहीं जोड़ते हैं।

यह वास्तव में आसान लगता है, लेकिन एक समस्या है। प्रकाश के प्रति मानव की संवेदनशीलता उच्च तीव्रता की तुलना में कम तीव्रता पर महीन होती है। यह कहना है, यदि आप उन सभी तीव्रता की सूची बनाते हैं जो आप भेद कर सकते हैं, तो प्रकाश की तुलना में अधिक अंधेरे हैं। इसे दूसरे तरीके से रखने के लिए, आप ग्रे के हल्के रंगों के अलावा ग्रे के हल्के रंगों को बेहतर बता सकते हैं। विशेष रूप से, यदि आप अपनी तीव्रता का प्रतिनिधित्व करने के लिए 8 बिट्स का उपयोग कर रहे हैं, और आप इसे रैखिक रंग-स्थान में करते हैं, तो आप बहुत सारे लाइट शेड्स के साथ समाप्त होंगे, और पर्याप्त डार्क शेड्स नहीं। आप अपने अंधेरे क्षेत्रों में बैंडिंग करते हैं, जबकि आपके प्रकाश क्षेत्रों में, आप सफेद के विभिन्न रंगों पर बिट्स को बर्बाद कर रहे हैं जो उपयोगकर्ता अलग नहीं कर सकता है।

इस समस्या से बचने के लिए, और उन 8 बिट्स का सबसे अच्छा उपयोग करने के लिए, हम sRGB का उपयोग करते हैं । SRGB मानक आपको अपने रंगों को गैर-रैखिक बनाने के लिए उपयोग करने के लिए एक वक्र बताता है। नीचे की तरफ कर्व है, इसलिए आपके पास अधिक गहरे रंग के ग्रे, और सबसे ऊपर स्टिपर है, इसलिए आपके पास कम प्रकाश ग्रिड हैं। यदि आप संख्या को दोगुना करते हैं, तो आप तीव्रता को दोगुना करते हैं। इसका मतलब है कि यदि आप sRGB रंगों को एक साथ जोड़ते हैं, तो आप एक परिणाम के साथ समाप्त होते हैं जो हल्का होना चाहिए। इन दिनों, अधिकांश मॉनिटर अपने इनपुट रंगों की व्याख्या sRGB के रूप में करते हैं। इसलिए, जब आप स्क्रीन पर एक रंग डाल रहे हों, या इसे 8-बिट-प्रति-चैनल बनावट में संग्रहीत कर रहे हों , तो इसे sRGB के रूप में संग्रहीत करें , इसलिए आप उन 8 बिट्स का सबसे अच्छा उपयोग करते हैं।

आप देखेंगे कि अब हमें एक समस्या है: हम चाहते हैं कि हमारे रंग रैखिक स्थान पर संसाधित हों, लेकिन sRGB में संग्रहीत हैं। इसका मतलब है कि आप पढ़ने पर sRGB-to-रैखिक रूपांतरण कर रहे हैं, और लिखने पर रैखिक-से-sRGB रूपांतरण कर रहे हैं। जैसा कि हमने पहले ही कहा है कि रैखिक 8-बिट तीव्रता में पर्याप्त अंधेरा नहीं है, यह समस्या पैदा करेगा, इसलिए एक और व्यावहारिक नियम है: यदि आप इसे से बच सकते हैं तो 8-बिट रैखिक रंगों का उपयोग न करें । इस नियम का पालन करना पारंपरिक हो रहा है कि 8-बिट रंग हमेशा sRGB होते हैं, इसलिए आप अपनी sRGB-से-रैखिक रूपांतरण उसी समय करते हैं, जब आपकी तीव्रता 8 से 16 बिट्स तक बढ़ जाती है, या पूर्णांक से फ्लोटिंग-पॉइंट तक; इसी तरह, जब आपने अपना फ़्लोटिंग-पॉइंट प्रोसेसिंग समाप्त कर लिया है, तो आप sRGB में कनवर्ट करने के साथ-साथ 8 बिट तक संकीर्ण होते हैं। यदि आप इन नियमों का पालन करते हैं,

जब आप एक sRGB छवि पढ़ रहे हों, और आप रेखीय तीव्रता चाहते हैं, तो इस सूत्र को प्रत्येक तीव्रता पर लागू करें:

float s = read_channel();
float linear;
if (s <= 0.04045) linear = s / 12.92;
else linear = pow((s + 0.055) / 1.055, 2.4);

दूसरे रास्ते पर जाने पर, जब आप किसी छवि को sRGB के रूप में लिखना चाहते हैं, तो इस सूत्र को प्रत्येक रैखिक तीव्रता पर लागू करें:

float linear = do_processing();
float s;
if (linear <= 0.0031308) s = linear * 12.92;
else s = 1.055 * pow(linear, 1.0/2.4) - 0.055; ( Edited: The previous version is -0.55 )

दोनों ही मामलों में, फ़्लोटिंग-पॉइंट का मान 0 से 1 तक होता है, इसलिए यदि आप 8-बिट पूर्णांक पढ़ रहे हैं, जिसे आप 255 से विभाजित करना चाहते हैं, और यदि आप 8-बिट पूर्णांक लिख रहे हैं, तो आप 255 से गुणा करना चाहते हैं अंत में, उसी तरह जो आप आमतौर पर करेंगे। बस आपको sRGB के साथ काम करने की जानकारी होनी चाहिए।

अब तक, मैंने केवल एक ही तीव्रता से निपटा है, लेकिन रंगों के साथ चतुर चीजें हैं। मानव आंख अलग-अलग चिह्नों की तुलना में अलग-अलग चमक को बता सकती है (तकनीकी रूप से, इसमें क्रोमिनेंस की तुलना में बेहतर ल्यूमिनेन्स रिज़ॉल्यूशन है), इसलिए आप टिंट से अलग चमक को संग्रहीत करके अपने 24 बिट्स का और भी बेहतर उपयोग कर सकते हैं। यह वही है जो YUV, YCrCb इत्यादि का प्रतिनिधित्व करने की कोशिश करता है। वाई चैनल रंग की समग्र लपट है, और अन्य दो चैनलों की तुलना में अधिक बिट्स (या अधिक स्थानिक रिज़ॉल्यूशन) का उपयोग करता है। इस तरह, आपको (हमेशा) आरजीबी तीव्रता के साथ एक वक्र लगाने की आवश्यकता नहीं है। YUV एक रैखिक रंग-स्थान है, इसलिए यदि आप Y चैनल में संख्या को दोगुना करते हैं, तो आप रंग की चमक को दोगुना कर देते हैं, लेकिन आप YUV रंगों को एक साथ जोड़ या गुणा नहीं कर सकते हैं जैसे आप RGB रंगों के साथ कर सकते हैं, इसलिए यह '

मुझे लगता है कि आपके सवाल का जवाब है, इसलिए मैं एक त्वरित ऐतिहासिक नोट के साथ समाप्त करूंगा। SRGB से पहले, पुराने CRT में एक गैर-रैखिकता का उपयोग किया जाता था। यदि आप एक पिक्सेल के लिए वोल्टेज को दोगुना करते हैं, तो आप तीव्रता को दोगुना से अधिक करेंगे। प्रत्येक मॉनिटर के लिए कितना अधिक भिन्न था, और इस पैरामीटर को गामा कहा जाता था । यह व्यवहार उपयोगी था क्योंकि इसका मतलब था कि आप रोशनी की तुलना में अधिक अंधेरा पा सकते हैं, लेकिन इसका मतलब यह भी है कि आप यह नहीं बता सकते कि आपके रंग उपयोगकर्ता के सीआरटी पर कितने उज्ज्वल होंगे, जब तक कि आप इसे पहले कैलिब्रेट नहीं करते। गामा सुधारआप (शायद रैखिक) के साथ शुरू होने वाले रंगों को बदलने और उपयोगकर्ता के सीआरटी के गामा के लिए उन्हें बदलने का मतलब है। OpenGL इस युग से आता है, यही कारण है कि इसका sRGB व्यवहार कभी-कभी थोड़ा भ्रमित होता है। लेकिन GPU विक्रेता अब मेरे द्वारा ऊपर बताए गए अधिवेशन के साथ काम करते हैं: जब आप किसी बनावट या फ्रेम-बफ़र में 8-बिट की तीव्रता का भंडारण कर रहे होते हैं, तो यह sRGB होता है, और जब आप रंगों को संसाधित कर रहे होते हैं, तो यह रैखिक होता है। उदाहरण के लिए, एक OpenGL ES 3.0, प्रत्येक फ्रेमबफ़र और बनावट में एक "sRGB ध्वज" होता है जिसे आप पढ़ते और लिखते समय स्वचालित रूपांतरण को सक्षम कर सकते हैं। आपको स्पष्ट रूप से sRGB रूपांतरण या गामा सुधार बिल्कुल करने की आवश्यकता नहीं है।


6
अद्भुत जवाब, धन्यवाद, यह हमेशा आश्चर्यजनक है कि चीजों को समझाया गया है, मैं केवल एक किताब या एक संसाधन के लिए पूछूंगा कि आपकी राय में इस विषय के लिए पर्याप्त अच्छा होगा, रंग रिक्त स्थान, और रूपांतरण sRGB करने के लिए उपयोग किए जाने वाले सूत्र क्या हैं <-> रैखिक या वह कार्य क्या है जो इस व्यवहार को अनुमानित कर सकता है।
केन

मुझे डर है कि मुझे किसी अच्छी किताबों या संसाधनों का पता नहीं है। विकिपीडिया पृष्ठ व्यापक है, और सभी सफेद बिंदु और कैसे छोटे सरगम (जो मैं उल्लेख नहीं किया है, जैसा कि ज्यादातर लोगों को इसके बारे में पता करने की जरूरत नहीं है) के बारे में सामान भी शामिल है, लेकिन यह है कि यह थोड़ा अभेद्य बना देता है ।
डैन हुल्मे



1

मैं "मानव रंग पहचान विशेषज्ञ" नहीं हूं, लेकिन मैं YUV-> आरजीबी रूपांतरण पर इसी तरह की बात कर चुका हूं। आर / जी / बी चैनलों के लिए अलग-अलग वजन हैं, इसलिए यदि आप स्रोत रंग को एक्स द्वारा बदलते हैं, तो आरजीबी मान अलग-अलग मात्रा में बदलते हैं।

जैसा कि कहा गया है, मैं एक विशेषज्ञ नहीं हूँ, वैसे भी, मुझे लगता है, यदि आप कुछ रंग-सही परिवर्तन करना चाहते हैं, तो आपको इसे YUV स्पेस में करना चाहिए, फिर इसे RGB में कनवर्ट करें (या RGB पर गणितीय रूप से समतुल्य ऑपरेशन करें, सावधान रहें डेटा हानि)। इसके अलावा, मुझे यकीन नहीं है कि YUV रंगों का सबसे अच्छा मूल प्रतिनिधित्व है, लेकिन वीडियो कैमरे उस प्रारूप को प्रदान करते हैं, यही वह जगह है जहां मैंने इस मुद्दे को पूरा किया है।

यहाँ जादू YUV-> आरजीबी फार्मूला है जिसमें गुप्त संख्याएँ शामिल हैं: http://www.fourcc.org/fccyvrgb.php


1
RGB <-> YUV रूपांतरण और पीछे के बारे में सावधान रहें। मुझे यकीन नहीं है कि यह हर मामले में है, लेकिन YUV रंग स्थान कभी-कभी 24-बिट आरजीबी में 0-255 के बजाय 16-235 की सीमा में परिवर्तित हो जाता है। इसलिए, जब भी आप एक कलरस्पेस रूपांतरण करते हैं, तो आप हर बार डेटा खो सकते हैं। अधिकांश लोग एक ही रंग के स्थान के भीतर रखने के लिए कहते हैं यदि आप इसे मदद कर सकते हैं।
जो प्लांट
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.