อะไรคือความแตกต่างในทางปฏิบัติเมื่อทำงานกับสีในพื้นที่ RGB เชิงเส้นกับที่ไม่ใช่เชิงเส้น


91

คุณสมบัติพื้นฐานของพื้นที่ RGB เชิงเส้นคืออะไรและคุณสมบัติพื้นฐานของ non-linear คืออะไร? เมื่อพูดถึงค่าภายในแต่ละช่องใน 8 บิต (หรือมากกว่า) เหล่านั้นมีอะไรเปลี่ยนแปลงบ้าง?

ใน OpenGL สีคือ 3 + 1 ค่าและด้วยสิ่งนี้ฉันหมายถึง RGB + alpha โดยสงวนไว้ 8 บิตสำหรับแต่ละช่องและนี่คือส่วนที่ฉันได้รับอย่างชัดเจน

แต่เมื่อพูดถึงการแก้ไขแกมมาฉันไม่ได้รับผลกระทบของการทำงานในพื้นที่ RGB ที่ไม่ใช่เชิงเส้น

เนื่องจากฉันรู้วิธีใช้เส้นโค้งในซอฟต์แวร์กราฟิกสำหรับการแก้ไขภาพคำอธิบายของฉันก็คือในช่องว่าง RGB เชิงเส้นคุณรับค่าตามที่เป็นอยู่โดยไม่มีการปรับแต่งและไม่มีฟังก์ชันทางคณิตศาสตร์ที่แนบมาแทนเมื่อมันไม่ใช่เชิงเส้น โดยปกติช่องสัญญาณจะวิวัฒนาการตามพฤติกรรมของฟังก์ชันกำลังแบบคลาสสิก

แม้ว่าฉันจะใช้คำอธิบายนี้เป็นของจริง แต่ฉันก็ยังไม่เข้าใจว่าสเปซเชิงเส้นที่แท้จริงคืออะไรเพราะหลังจากคำนวณช่องว่าง RGB ที่ไม่ใช่เชิงเส้นทั้งหมดจะกลายเป็นเส้นตรงและที่สำคัญที่สุดฉันไม่ได้รับส่วนที่ไม่ใช่ - ปริภูมิสีเชิงเส้นเหมาะกับสายตามนุษย์มากกว่าเพราะในที่สุดช่องว่าง RGB ทั้งหมดจะเป็นเส้นตรงตามที่ฉันเข้าใจ


ในข้อควรปฏิบัติคุณสามารถระบุ RGB เชิงเส้นหรือมาตรฐานเป็นพื้นที่สีของคุณใน SVG และฉันไม่รู้ว่าเอฟเฟกต์คืออะไรนอกเหนือจากความจริงที่ว่าสิ่งนี้ดูเหมือนจะสำคัญ :-)
Michael Mullany

@MichaelMull สิ่งที่เป็นเส้นตรงนี้ดูเหมือนคำใบ้สำหรับผู้ใช้มากกว่าคุณภาพที่โดดเด่นจริงๆ
Ken

สิ่งที่ช่วยฉัน: ฉันคิดว่าเป็นครูคณิตศาสตร์ที่บอกฉันว่า "คิดเส้นเมื่อคุณได้ยินเชิงเส้น" ไม่แน่ใจว่าสิ่งนี้ช่วยได้หรือไม่ แต่สำหรับฉันมันคือ "โอ้ใช่!" ช่วงเวลา
Joe Plante

การอ่านที่เกี่ยวข้องเกี่ยวกับ Gamma: ฉันจำเป็นต้อง gamma แก้ไขเอาต์พุตสีสุดท้ายหรือไม่?
legends2k

คำตอบ:


236

สมมติว่าคุณกำลังทำงานกับสี RGB: แต่ละสีจะแสดงด้วยความเข้มหรือความสว่างสามระดับ คุณต้องเลือกระหว่าง "linear RGB" และ "sRGB" สำหรับตอนนี้เราจะลดความซับซ้อนของสิ่งต่าง ๆ โดยมองข้ามความเข้มที่แตกต่างกันสามระดับและสมมติว่าคุณมีความเข้มเดียวนั่นคือคุณกำลังจัดการกับเฉดสีเทา

ในปริภูมิสีเชิงเส้นความสัมพันธ์ระหว่างตัวเลขที่คุณจัดเก็บและความเข้มที่แสดงเป็นเส้นตรง ในทางปฏิบัติหมายความว่าถ้าคุณเพิ่มจำนวนเป็นสองเท่าคุณจะเพิ่มความเข้มเป็นสองเท่า (ความสว่างของสีเทา) หากคุณต้องการเพิ่มความเข้มสองค่าเข้าด้วยกัน (เนื่องจากคุณกำลังคำนวณความเข้มจากการมีส่วนร่วมของแหล่งกำเนิดแสงสองแหล่งหรือเนื่องจากคุณกำลังเพิ่มวัตถุโปร่งใสที่ด้านบนของวัตถุทึบแสง) คุณสามารถทำได้โดยเพิ่ม สองตัวเลขด้วยกัน หากคุณกำลังทำการผสม 2D หรือแรเงา 3D หรือการประมวลผลภาพเกือบทุกประเภทคุณต้องการความเข้มของคุณในพื้นที่สีเชิงเส้นคุณจึงสามารถบวกลบคูณหารตัวเลขเพื่อให้มีผลเหมือนกันกับความเข้ม อัลกอริธึมการประมวลผลและการแสดงสีส่วนใหญ่จะให้ผลลัพธ์ที่ถูกต้องกับ RGB เชิงเส้นเท่านั้นเว้นแต่คุณจะเพิ่มน้ำหนักพิเศษให้กับทุกอย่าง

ฟังดูง่าย แต่มีปัญหา ความไวต่อแสงของดวงตามนุษย์นั้นละเอียดกว่าที่ความเข้มต่ำกว่าความเข้มสูง กล่าวคือถ้าคุณสร้างรายการความเข้มทั้งหมดที่คุณสามารถแยกแยะได้มีความมืดมากกว่าความสว่าง หากต้องการกล่าวอีกนัยหนึ่งคุณสามารถแยกเฉดสีเทาเข้มออกจากกันได้ดีกว่าที่คุณทำได้ด้วยเฉดสีเทาอ่อน โดยเฉพาะอย่างยิ่งถ้าคุณใช้ 8 บิตเพื่อแสดงความเข้มของคุณและคุณทำสิ่งนี้ในพื้นที่สีเชิงเส้นคุณจะได้เฉดสีอ่อนมากเกินไปและมีเฉดสีเข้มไม่เพียงพอ คุณได้รับแถบในบริเวณที่มืดของคุณในขณะที่อยู่ในบริเวณที่มีแสงของคุณคุณกำลังเสียบิตไปกับเฉดสีใกล้ขาวที่แตกต่างกันซึ่งผู้ใช้ไม่สามารถแยกออกจากกันได้

เพื่อหลีกเลี่ยงปัญหานี้และทำให้การใช้งานที่ดีที่สุดของผู้ที่ 8 บิตเรามักจะใช้sRGB มาตรฐาน sRGB บอกเส้นโค้งที่จะใช้เพื่อให้สีของคุณไม่เป็นเส้นตรง เส้นโค้งจะตื้นกว่าที่ด้านล่างคุณจึงมีสีเทาเข้มได้มากกว่าและด้านบนชันกว่าคุณจึงมีสีเทาอ่อนน้อยลง หากคุณเพิ่มจำนวนขึ้นเป็นสองเท่าคุณจะมีความเข้มมากกว่าสองเท่า ซึ่งหมายความว่าหากคุณเพิ่มสี sRGB เข้าด้วยกันคุณจะได้ผลลัพธ์ที่เบากว่าที่ควรจะเป็น ทุกวันนี้จอภาพส่วนใหญ่ตีความสีที่ป้อนเป็น sRGB ดังนั้นเมื่อคุณใส่สีบนหน้าจอหรือเก็บไว้ในพื้นผิว 8 บิตต่อช่องให้จัดเก็บเป็น sRGBดังนั้นคุณจึงใช้ประโยชน์จาก 8 บิตเหล่านั้นให้เกิดประโยชน์สูงสุด

คุณจะสังเกตเห็นว่าตอนนี้เรามีปัญหา: เราต้องการให้สีของเราประมวลผลในพื้นที่เชิงเส้น แต่เก็บไว้ใน sRGB ซึ่งหมายความว่าคุณจะทำการแปลง sRGB เป็นเชิงเส้นในการอ่านและการแปลง linear-to-sRGB ในการเขียน ดังที่เราได้กล่าวไปแล้วว่าความเข้มเชิงเส้น 8 บิตไม่มีความมืดเพียงพอสิ่งนี้จะทำให้เกิดปัญหาดังนั้นจึงมีกฎที่ใช้ได้จริงอีกข้อหนึ่งคืออย่าใช้สีเชิงเส้น 8 บิตหากคุณสามารถหลีกเลี่ยงได้ มันกลายเป็นเรื่องธรรมดาที่จะปฏิบัติตามกฎที่ว่าสี 8 บิตจะเป็น sRGB เสมอดังนั้นคุณจึงทำการแปลง sRGB เป็นเชิงเส้นในเวลาเดียวกันกับการขยายความเข้มจาก 8 เป็น 16 บิตหรือจากจำนวนเต็มเป็นทศนิยม ในทำนองเดียวกันเมื่อคุณประมวลผลทศนิยมเสร็จแล้วคุณจะ จำกัด ให้แคบลงเหลือ 8 บิตในเวลาเดียวกันกับการแปลงเป็น sRGB หากคุณปฏิบัติตามกฎเหล่านี้

เมื่อคุณอ่านภาพ 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 และอื่น ๆ พยายามทำ ช่อง Y คือความสว่างโดยรวมของสีและใช้บิตมากกว่า (หรือมีความละเอียดเชิงพื้นที่มากกว่า) มากกว่าอีกสองช่อง ด้วยวิธีนี้คุณไม่จำเป็นต้องใช้เส้นโค้งเช่นเดียวกับที่คุณทำกับความเข้ม RGB YUV เป็นช่องว่างสีเชิงเส้นดังนั้นหากคุณเพิ่มจำนวนเป็นสองเท่าในช่อง Y คุณจะมีความสว่างของสีเป็นสองเท่า แต่คุณไม่สามารถเพิ่มหรือคูณสี YUV เข้าด้วยกันได้เหมือนที่คุณทำได้ด้วยสี RGB ดังนั้น

ฉันคิดว่าตอบคำถามของคุณได้ดังนั้นฉันจะปิดท้ายด้วยบันทึกประวัติศาสตร์สั้น ๆ ก่อนหน้า sRGB CRT แบบเก่าเคยมีความไม่เป็นเชิงเส้นในตัว หากคุณเพิ่มแรงดันไฟฟ้าเป็นสองเท่าสำหรับพิกเซลคุณจะมีความเข้มมากกว่าสองเท่า วิธีการมากขึ้นแตกต่างกันสำหรับแต่ละตรวจสอบและพารามิเตอร์นี้ถูกเรียกว่ารังสีแกมมา พฤติกรรมนี้มีประโยชน์เพราะหมายความว่าคุณอาจมืดมากกว่าแสง แต่ก็หมายความว่าคุณไม่สามารถบอกได้ว่าสีของคุณจะสว่างแค่ไหนใน CRT ของผู้ใช้เว้นแต่คุณจะปรับเทียบก่อน การแก้ไขแกมมาหมายถึงการเปลี่ยนสีที่คุณเริ่มต้นด้วย (อาจเป็นเชิงเส้น) และเปลี่ยนเป็นแกมมาของ CRT ของผู้ใช้ OpenGL มาจากยุคนี้ซึ่งเป็นสาเหตุที่ทำให้พฤติกรรม sRGB บางครั้งสับสนเล็กน้อย แต่ตอนนี้ผู้จำหน่าย GPU มักจะทำงานร่วมกับรูปแบบที่ฉันอธิบายไว้ข้างต้นนั่นคือเมื่อคุณจัดเก็บความเข้ม 8 บิตในพื้นผิวหรือเฟรมบัฟเฟอร์จะเป็น sRGB และเมื่อคุณประมวลผลสีจะเป็นแบบเส้นตรง ตัวอย่างเช่น OpenGL ES 3.0 แต่ละเฟรมบัฟเฟอร์และพื้นผิวมี "แฟล็ก sRGB" ที่คุณสามารถเปิดเพื่อเปิดใช้งานการแปลงอัตโนมัติเมื่ออ่านและเขียน คุณไม่จำเป็นต้องทำการแปลง sRGB หรือแก้ไขแกมม่าอย่างชัดเจนเลย


6
คำตอบที่น่าอัศจรรย์ขอบคุณมันน่าทึ่งเสมอที่ได้เห็นสิ่งต่าง ๆ อธิบายฉันจะขอเพียงหนังสือหรือแหล่งข้อมูลที่ในความคิดของคุณจะดีพอสำหรับหัวข้อนี้ช่องว่างสีและสูตรที่ใช้ในการแปลง sRGB คืออะไร <-> เชิงเส้นหรืออะไรคือฟังก์ชันที่สามารถประมาณพฤติกรรมนี้ได้
Ken

ฉันกลัวว่าจะไม่รู้หนังสือหรือแหล่งข้อมูลดีๆ หน้าวิกิพีเดียจะครอบคลุมและรวมถึงทุกสิ่งที่เกี่ยวกับสีขาวจุดและวิธีการขนาดเล็กโทนเสียงดนตรีคือ (ซึ่งผมไม่ได้กล่าวถึงเป็นคนส่วนใหญ่ไม่จำเป็นต้องรู้เกี่ยวกับมัน) แต่ที่ทำให้มันเป็นที่น่าพิศวงบิต .
Dan Hulme



1

ฉันไม่ใช่ "ผู้เชี่ยวชาญด้านการตรวจจับสีของมนุษย์" แต่ฉันได้พบกับสิ่งที่คล้ายกันในการแปลง YUV-> RGB มีน้ำหนักที่แตกต่างกันสำหรับแชนเนล R / G / B ดังนั้นหากคุณเปลี่ยนสีต้นทางด้วย x ค่า RGB จะเปลี่ยนปริมาณที่แตกต่างกัน

อย่างที่บอกว่าฉันไม่ใช่ผู้เชี่ยวชาญ แต่ฉันคิดว่าถ้าคุณต้องการแปลงสีให้ถูกต้องคุณควรทำในพื้นที่ YUV จากนั้นแปลงเป็น RGB (หรือทำการดำเนินการที่เทียบเท่าทางคณิตศาสตร์บน RGB โปรดระวัง ข้อมูลสูญหาย) นอกจากนี้ฉันไม่แน่ใจว่า YUV เป็นตัวแทนของสีที่ดีที่สุด แต่กล้องวิดีโอให้รูปแบบนั้นนั่นคือสิ่งที่ฉันพบปัญหา

นี่คือสูตรมายากล YUV-> RGB พร้อมตัวเลขลับ: http://www.fourcc.org/fccyvrgb.php


1
ระวังการแปลง RGB <-> YUV และย้อนกลับ ฉันไม่แน่ใจว่าเป็นเช่นนี้ในทุกกรณีหรือไม่ แต่บางครั้งพื้นที่สี YUV จะแปลงเป็นช่วง 16-235 แทนที่จะเป็น 0-255 ใน RGB 24 บิต ดังนั้นคุณอาจสูญเสียข้อมูลทุกครั้งที่คุณทำการแปลงสี คนส่วนใหญ่มักจะบอกว่าให้เก็บไว้ในพื้นที่สีเดียวกันถ้าคุณสามารถช่วยได้
Joe Plante
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.