Подтвердить что ты не робот

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

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

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

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

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

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

4b9b3361

Ответ 1

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

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

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

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

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

Ответ 2

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

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

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