Каковы практические различия при работе с цветами в линейном и нелинейном пространстве RGB?



Что является основным свойством линейного пространства RGB и что является фундаментальным свойством нелинейного? Когда речь идет о значениях внутри каждого канала в этих 8 (или более) битах, что меняется?



в OpenGL цвета имеют значения 3+1, и с этим я имею в виду RGB+alpha, с 8 битами, зарезервированными для каждого канала, и это та часть, которую я получаю четко.



но когда дело доходит до гамма-коррекции, я не понимаю, каков эффект работы в нелинейном пространстве RGB есть.





даже если я возьму это объяснение как реальное, я все еще не понимаю, что такое реальное линейное пространство, потому что после вычисления все нелинейные пространства RGB становится линейным и, самое главное, я не получаю ту часть, где нелинейное цветовое пространство более подходит для человеческого глаза, потому что в конце концов все пространства RGB линейны для того, что я понимаю.

703   2  

2 ответов:

допустим, вы работаете с цветами RGB: каждый цвет представлен тремя света или яркости. Вы должны выбрать между "линейным RGB"и " sRGB". На данный момент мы упростим ситуацию, игнорируя три разных интенсивности, и предположим, что у вас есть только одна интенсивность: то есть вы имеете дело только с оттенками серого.

в линейном цветовом пространстве отношение между хранящимися числами и интенсивностями, которые они представляют, линейно. Практически это означает, что если вы удвоите число, вы удвоите интенсивность (яркость серого). Если вы хотите добавить две интенсивности вместе (потому что вы вычисляете интенсивность на основе вклада двух источников света или потому что вы добавляете прозрачный объект поверх непрозрачного объекта), вы можете сделать это, просто добавив два числа вместе. если вы делаете любой вид 2D смешивания или 3D затенения, или почти любой обработки изображений, то вы хотите, чтобы ваши интенсивности в линейном цветовом пространстве, так что вы можете просто складывать, вычитать, умножать и делить числа, чтобы иметь тот же эффект на интенсивность. Большинство алгоритмов обработки и рендеринга цветов дают правильные результаты только с линейным RGB, если вы не добавляете дополнительные веса ко всему.

это звучит очень просто, но есть проблема. Чувствительность человеческого глаза к свету тоньше при низкой интенсивности, чем при высокой. То есть, если вы составите список всех интенсивностей, которые вы можете различают, что темных больше, чем светлых. Другими словами, вы можете отличить темные оттенки серого друг от друга лучше, чем вы можете со светлыми оттенками серого. В частности, если вы используете 8 бит для представления своей интенсивности, и вы делаете это в линейном цветовом пространстве, вы получите слишком много светлых оттенков и недостаточно темных оттенков. Вы получаете полосу в темных областях, в то время как в светлых областях вы тратите биты на разные оттенки почти белого, которые пользователь не может сказать отдельно.

чтобы избежать этой проблемы и наилучшим образом использовать эти 8 бит, мы, как правило, используем sRGB. Стандарт sRGB сообщает вам кривую для использования, чтобы сделать ваши цвета нелинейными. Кривая более мелкая внизу, поэтому у вас может быть больше темных серых, и круче вверху, поэтому у вас меньше светлых серых. Если вы удвоите число, вы более чем удвоите интенсивность. Это означает, что если вы добавите цвета sRGB вместе, вы получите результат, который будет светлее, чем должен быть. В наши дни большинство мониторов интерпретируют свои входные цвета как sRGB. Итак,когда вы помещаете цвет на экран или сохраняете его в 8-битной текстуре на канал, храните его как sRGB, так что вы делаете лучшее использование этих 8 бит.

вы заметите, что теперь у нас есть проблема: мы хотим, чтобы наши цвета обрабатывались в линейном пространстве, но хранились в sRGB. Это означает, что вы в конечном итоге делает с sRGB в линейное преобразование на чтение, и линейная-в-преобразование цветового пространства sRGB при записи. Как мы уже говорили, линейный 8-битный интенсивности не хватает темноты, это вызовет проблемы, поэтому есть еще одно практическое правило:Не используйте 8-битные линейные цвета если вы можете избежать его. Это становится обычной следовать правилу, что 8-битный цвет всегда регу, так что вы вашего цветового пространства 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 )

в обоих случаях значение S с плавающей запятой колеблется от 0 до 1, поэтому, если Вы читаете 8-битные целые числа, которые вы хотите разделить на 255 во-первых, и если вы пишете 8-битные целые числа, которые вы хотите умножить на 255 в последний раз, так же, как обычно. Это все, что вам нужно знать, чтобы работать с sRGB.

Я думаю, что ответ на ваш вопрос, поэтому я закончу краткое историческая справка. Прежде чем sRGB, а старый ЭЛТ используется нелинейность, встроенные в них. Если бы вы удвоили напряжение для пикселя, вы бы более чем удвоили интенсивность. Насколько больше было разных для каждого монитора, и этот параметр назывался гамма. Это поведение было полезно, потому что это означало, что вы можете получить больше темных чем свет, но это также означало, что вы не могли бы сказать, насколько яркие ваши цвета будут на ЭЛТ пользователя, если вы не откалибровали его в первую очередь. гамма-коррекция означает преобразование цветов, с которых вы начинаете (возможно, линейное), и преобразование их для гаммы CRT пользователя. OpenGL происходит из этой эпохи, поэтому его поведение sRGB иногда немного сбивает с толку. Но поставщики GPU теперь склонны работать с соглашением, которое я описал выше: когда вы сохраняете 8-битную интенсивность в a текстура или фреймбуфер, это sRGB, и когда вы обрабатываете цвета, это линейно. Например, в OpenGL ES 3.0 каждый фреймбуфер и текстура имеют флаг sRGB, который можно включить, чтобы включить автоматическое преобразование при чтении и записи. Вам не нужно явно выполнять преобразование sRGB или гамма-коррекцию вообще.

Я не "эксперт по обнаружению цвета человека", но я встречал подобную вещь на преобразовании YUV->RGB. Существуют различные веса для каналов R/G/B, поэтому, если вы измените исходный цвет на x, значения RGB изменят другое количество.

Как уже было сказано, я не эксперт, во всяком случае, я думаю, что если вы хотите сделать какое-то цветокорректное преобразование, вы должны сделать это в пространстве YUV, а затем преобразовать его в RGB (или сделать математически эквивалентную операцию на RGB, остерегайтесь потери данных). Кроме того, я не уверен это YUV-лучшее родное представление цветов, но видеокамеры обеспечивают этот формат, вот где я встретил проблему.

вот волшебная формула YUV - > RGB с включенными секретными номерами:http://www.fourcc.org/fccyvrgb.php

Comments

    Ничего не найдено.