Цветовые пространства, гамма и улучшение изображения

Цветовое пространство. Что ж, про RGB знают все: три значения, нормированные в диапазоне [0.0,1.0], которые имеют значение интенсивности цветовых компонентов Красный Зеленый Синий; эта интенсивность подразумевается как линейная, не так ли?

Гамма. Насколько я понимаю, гамма - это функция, которая сопоставляет компоненты цвета RGB с другим значением. Погуглив по этому поводу, я видел линейные функции и нелинейные функции ... Линейные функции, кажется, масштабируют компоненты RGB, поэтому кажется, что они настраивают яркость изображения; нелинейные функции, кажется, «распаковывают» более темные / более светлые компоненты.

Теперь я начинаю реализовывать программу просмотра изображений, которая будет отображать различные форматы изображений в виде текстуры. Я хотел бы изменить гамму этих изображений, поэтому я должен создать фрагментный шейдер и запустить текстурированный четырехугольник. Хорошо, но как мне определить правильную гамма-коррекцию?

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

Сначала я определю гамма-рампу. Как я мог это определить? (аналитически или с использованием таблиц поиска)

Затем я подошел к вопросу о расширении OpenGL EXT_framebuffer_sRGB, которое кажется очень связанным с расширением EXT_texture_sRGB.

EXT_texture_sRGB представляет новый формат текстуры, который используется для линеаризации текстовых значений в линейное пространство RGB. (сноска 1) Таким образом, я знаю цветовое пространство sRGB и использую его как линейное цветовое пространство RGB.

Вместо этого расширение EXT_framebuffer_sRGB позволяет мне кодировать линейные значения RGB в фреймбуфер sRGB, не беспокоясь об этом.

...

Подождите, вся эта информация для чего? Если я могу использовать кадровый буфер sRGB и загружать текстуры sRGB, обрабатывать эти текстуры без преобразования sRGB ... зачем мне корректировать гамму?

Может все-таки гамму подправить хоть на sRGB буфере? Или мне лучше нет? А яркость и контраст: до или после гамма-коррекции?

Это много информации, я сейчас запутался. Надеюсь, что кто-то из вас сможет подробнее объяснить мне все эти концепции! Спасибо.

...

Есть еще вопрос. Если гамма устройства отличается от "стандартной" 2.2, как мне "накапливать" разные гамма-коррекции? Я не знаю, ясно ли: в случае, если значения RGB изображения уже скорректированы для монитора со значением гаммы 2,2, но монитор имеет значение гаммы 2,8, как мне исправить гамму?


(1) Вот отрывок, чтобы подчеркнуть, что я имею в виду:

Цветовое пространство sRGB основано на типичных (нелинейных) характеристиках монитора, ожидаемых в тускло освещенном офисе. Он был стандартизирован Международной электротехнической комиссией (МЭК) как IEC 61966-2-1. Цветовое пространство sRGB примерно соответствует гамма-коррекции 2,2.


Предоставляет ли это расширение какие-либо форматы кадрового буфера sRGB или гарантирует, что изображения, визуализированные с текстурами sRGB, будут «хорошо выглядеть» при выводе на устройство, поддерживающее цветовое пространство sRGB?

   RESOLVED:  No.

  Whether the displayed framebuffer is displayed to a monitor that
    faithfully reproduces the sRGB color space is beyond the scope
    of this extension.  This involves the gamma correction and color
    calibration of the physical display device.

    With this extension, artists can author content in an sRGB color
    space and provide that sRGB content for use as texture imagery
    that can be properly converted to linear RGB and filtered as part
    of texturing in a way that preserves the sRGB distribution of
    precision, but that does NOT mean sRGB pixels are output
    to the framebuffer.  Indeed, this extension provides texture
    formats that convert sRGB to linear RGB as part of filtering.

    With programmable shading, an application could perform a
    linear RGB to sRGB conversion just prior to emitting color
    values from the shader.  Even so, OpenGL blending (other than
    simple modulation) will perform linear math operations on values
    stored in a non-linear space which is technically incorrect for
    sRGB-encoded colors.

    One way to think about these sRGB texture formats is that they
    simply provide color components with a distribution of values
    distributed to favor precision towards 0 rather than evenly
    distributing the precision with conventional non-sRGB formats
    such as GL_RGB8.

person Luca    schedule 18.06.2011    source источник
comment
Я бы сказал, что буду выполнять рендеринг на мониторе, который не предназначен для потребителей, но на самом деле он специализируется на обработке изображений HDR. На данный момент у меня нет спецификации монитора, но я подозреваю, что буду применять гамма-коррекцию во время рендеринга.   -  person Luca    schedule 18.06.2011


Ответы (3)


К сожалению, OpenGL сам по себе не определяет цветовое пространство. Просто определено, что значения RGB, переданные в OpenGL, образуют линейное векторное пространство. Значения визуализированного буфера кадра затем отправляются на устройство отображения как есть. OpenGL просто передает значение.

Гамма обслуживает две цели:

  • Сенсорное восприятие нелинейно
  • В былые времена устройства отображения имели нелинейный отклик.

Гамма-коррекция используется для компенсации обоих.

Преобразование - это просто «линейное значение V в некоторую степень гаммы», то есть y (v) = v ^ gamma.

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

Долгое время типичное значение гаммы составляло 2,2. Однако это вызвало нежелательное квантование низких значений, поэтому Adobe представила новое цветовое пространство, называемое sRGB, которое имеет линейную часть для низких значений и функцию мощности с экспоненциальной ~ 2,3 для более высоких значений. Большинство устройств отображения в наши дни используют sRGB. Также большинство файлов изображений в наши дни имеют формат sRGB.

Итак, если у вас есть изображение sRGB и вы отображаете его как есть на устройстве отображения sRGB с линейной гамма-рампой, настроенной на устройстве (например, гамма видеодрайвера = 1), вы можете просто использовать текстурирование sRGB и кадровый буфер, а не делать этого. что-нибудь еще.

ИЗМЕНИТЬ из-за комментариев

Подведем итог:

  • Используйте буфер кадра ARB_framebuffer_sRGB, чтобы результаты линейной обработки OpenGL правильно преобразовывались в цвет с помощью драйвера http://www.opengl.org/registry/specs/ARB/framebuffer_sRGB.txt

  • Линеаризуйте все входные цвета в OpenGL

  • Текстуры в цветовом пространстве sRGB следует передавать через EXT_texture_sRGB http://www.opengl.org/registry/specs/EXT/texture_sRGB.txt

  • Не применяйте гамма-коррекцию выходных значений (буфер кадра в формате sRGB позаботится об этом)

Если ваша система не поддерживает кадровые буферы sRGB:

  • Установите линейную цветовую шкалу на вашем устройстве отображения.

  • создавать (линейные) объекты фреймбуфера до линейного рендеринга в объекте фреймбуфера. Использование FBO заключается в правильном смешивании, которое работает только в линейном цветовом пространстве.

  • нарисуйте окончательный результат рендеринга из FBO в окно с помощью фрагментного шейдера, который применяет желаемые корректировки цвета (гамма и другие).

person datenwolf    schedule 18.06.2011
comment
Действительно, драйвер OpenGL исправляет значения RGB фреймбуфера после того, как я его заменил? В этом случае, если я хочу применить гамма-коррекцию в своем шейдере только для своего приложения, я должен определять текущую настройку системы, не так ли? - person Luca; 18.06.2011
comment
@ Лука: В принципе, да. Однако вы столкнетесь с проблемой, заключающейся в том, что в OpenGL вы работаете в линейном цветовом пространстве (что вам и нужно), и любая гамма-коррекция сделает ваши цвета нелинейными. К сожалению, ваш графический драйвер предполагает, что входящие фрагменты являются линейными. И вот здесь начинаются проблемы: примененная коррекция может быть чем-то совершенно отличным от простой гамма-кривой. Например, ваше целевое устройство ожидает X'Y'Z ', и это настроено в драйвере. Тогда передача нелинейных значений испортит преобразование. - person datenwolf; 18.06.2011
comment
@Luca: Как правило, вы должны придерживаться линейных преобразований цвета; не только в OpenGL, но и во всех ситуациях. Если вам известны точные преобразования, применяемые драйвером и устройством отображения, вы можете принять их во внимание. Также некоторые драйверы дисплея (драйверы профессиональных видеокарт) предоставляют специальные конфигурации формата пикселей, при которых значения из приложения подаются непосредственно на устройство без промежуточной коррекции. Только в этом случае вы можете безопасно применять нелинейные преобразования, но тогда, конечно, придется делать все исправления самостоятельно. - person datenwolf; 18.06.2011
comment
@Luca: Итак, в заключение: линеаризуйте все, что вы передаете в OpenGL, используя какую-нибудь систему управления цветом (например, littleCMS); если ваши изображения sRGB, используйте текстурирование sRGB. А затем придерживайтесь линейной обработки цвета. Графический драйвер выполнит необходимые исправления для соответствия вашему устройству отображения. Так что не лги водителю. - person datenwolf; 18.06.2011
comment
Вот это да. Поэтому я должен проинструктировать драйвер о гамма-коррекции (я подозреваю, что использую SetDeviceGammaRamp или какую-то точку входа в драйвер). У вас есть указатель на эти форматы пикселей? Просто любопытство! - person Luca; 18.06.2011
comment
@Luca: Забудьте о коррекции гаммы на выходе. Вместо этого примените обратную гамма-коррекцию, которая будет линеаризовать данные изображения перед их передачей в OpenGL. Если ваше изображение имеет гамму, скажем, 2,6, примените гамму 1 / 2,6, а затем передайте ее в OpenGL. sRGB, к сожалению, немного неудобен для работы, простая гамма-коррекция не поможет. Вот тут-то и пригодится EXT_texture_sRGB. - person datenwolf; 18.06.2011
comment
@Luca: О, пожалуйста, прочтите статью, на которую ссылается @Bethor, это действительно жемчужина! - person datenwolf; 18.06.2011
comment
@datenwolf Вы можете проверить, правильно ли я понял? При использовании фреймбуфера sRGB значения сохраняются в самом пространстве sRGB, в то время как все задействованные операции будут автоматически преобразованы для выполнения в линейном пространстве. Это обеспечивает более высокое качество, чем ручной метод использования обычного линейного цветового буфера с последующей гамма-коррекцией (с шейдером) при постобработке. Поскольку линейные операции фреймбуфера sRGB будут выполняться с полной точностью на оборудовании, тогда как ручной метод усекает значения до 8 линейных битов на каждом проходе. - person Steven Lu; 27.02.2012
comment
@StevenLu: Нет, нет снижения качества, так как в шейдере все значения могут храниться и вычисляться как значения с плавающей запятой с более чем 8 битами. Но использование sRGB-текстур и кадровых буферов может привести к повышению производительности благодаря оптимизации, встроенной в драйвер. Но вы правы в том, что цвета остаются в пространстве sRGB и линеаризуются только при сэмплировании и смешивании и делинеаризуются, когда фрагменты переносятся на экран. - person datenwolf; 27.02.2012

Подождите, вся эта информация для чего? Если я могу использовать кадровый буфер sRGB и загружать текстуры sRGB, обрабатывать эти текстуры без преобразования sRGB ... зачем мне корректировать гамму?

Как правило, нет. Текстурирование sRGB и фреймбуферы предназначены для того, чтобы вам не приходилось вручную выполнять гамма-коррекцию. Чтение из текстур sRGB преобразуется в линейное цветовое пространство, а запись в буфер кадра sRGB принимает линейные значения RGB и преобразует их в значения sRGB. Все это происходит автоматически и, точнее, бесплатно с точки зрения производительности.

Единственный раз, когда вам нужно будет выполнить гамма-коррекцию, это если гамма монитора не соответствует гамма-аппроксимации sRGB, равной 2,2. Редко бывает монитор, который делает это.

Ваши текстуры не должны находиться в цветовом пространстве sRGB. Однако большинство приложений для создания изображений сохраняют изображения в sRGB и работают с цветами в sRGB, поэтому большая часть ваших текстур уже находится в sRGB, хотите вы их или нет. Функция текстуры sRGB просто позволяет вам фактически получить правильные значения цвета, а не значения цвета, которые вы получали до сих пор.

А яркость и контраст: до или после гамма-коррекции?

Я не знаю, что вы имеете в виду под яркостью и контрастом. Это должно быть установлено монитором, а не вашим приложением. Но практически все математические операции, которые вы захотите проделать с данными изображения, должны выполняться в линейном цветовом пространстве. Следовательно, если вам дано изображение в цветовом пространстве sRGB, вам необходимо линеаризовать его, прежде чем вы сможете делать с ним какие-либо математические вычисления. Функция текстуры sRGB делает это бесплатно, вместо того, чтобы выполнять сложные вычисления шейдеров.

person Nicol Bolas    schedule 18.06.2011
comment
Как узнать, действительно ли функция загрузчика изображений дает мне значения sRGB или уже скорректированные значения RGB? (Да, слишком широкое выражение, т.е. установить jpeglib и openexr в качестве загрузчиков изображений). - person Luca; 18.06.2011
comment
@Luca OpenEXR предназначен для изображений с плавающей запятой. Они должны быть в линейном цветовом пространстве, и sRGB в любом случае не разрешен для изображений с плавающей запятой. Формат JPEG имеет цветовые профили, которые определяют цветовое пространство данных, но sRGB здесь довольно распространен. Точно так же в PNG может быть встроена информация о цветовом профиле. - person Nicol Bolas; 18.06.2011
comment
Правда, OpenEXR должен быть линейным. К сожалению, некоторые программы генерируют нелинейный OpenEXR. Так что в случае сомнений проверьте его еще раз. - person datenwolf; 19.06.2011

RGB

RGB: три значения, нормализованные в диапазоне [0.0,1.0], которые имеют значение интенсивности цветовых компонентов Красный Зеленый Синий; эта интенсивность подразумевается как линейная, не так ли?

Нет. Значения RGB являются бессмысленными числами, если не определено их отношение к конкретному пространству / кодировке. Они могут быть линейными, гамма-кодированными, логарифмическими или использовать составную кривую передачи, такую ​​как спецификации Rec709 и sRGB.

Кроме того, они соотносятся с их основными цветами и точкой белого, как определено в цветовом пространстве, поэтому, например, # 00FF00 в sRGB отличается от цвета # 00FF00 в DCI-P3.

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

sRGB - это стандартное цветовое пространство RGB по умолчанию для Интернета и вычислений общего назначения. Это связано с Rec709, стандартным цветовым пространством для HDTV.

ГАММА или КРИВАЯ ПЕРЕДАЧИ

Гамма. Насколько я понимаю, гамма - это функция, которая сопоставляет компоненты цвета RGB с другим значением.

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

Перед цифровым форматом гамма также использовалась в системе вещания NTSC, которая подавляла кажущийся шум в сигнале, аналогично тому, как гамма изображения предотвращает появление артефактов "полосатости" изображения с 8 битами на канал.

Сначала я определю гамма-рампу. Как я мог это определить? (аналитически или с использованием таблиц поиска)

Гамма КРИВАЯ. Гамма-кривая sRGB легко доступна. Вот ссылка на Википедию для перехода от sRGB к линейному. Вы также можете использовать «упрощенный» метод, который просто использует кривую экспоненты 2,2:

linearVideo = sRGBvideo^2.2 и упрощенное обратное, чтобы вернуться к sRGB:

sRGBvideo = linearVideo^0.4545

Использование упрощенной версии приведет к некоторым незначительным гамма-ошибкам, рекомендуется использовать «правильную» кривую для критических операций или в тех случаях, когда изображение будет «округляться» несколько раз.

Есть еще вопрос. Если гамма устройства отличается от "стандартной" 2.2, как мне "накапливать" разные гамма-коррекции? Я не знаю, ясно ли: в случае, если значения RGB изображения уже скорректированы для монитора со значением гаммы 2,2, но монитор имеет значение гаммы 2,8, как мне исправить гамму?

2,8 ??? Что это за монитор? PAL? Это необычно - хотя в спецификации PAL сказано, что версия 2.8 непрактична. Мониторы обычно имеют размер от 2,3 до 2,5 в зависимости от того, как они настроены. Регулируя уровень черного и контраст (уровень белого), вы, по сути, настраиваете воспринимаемую гамму в соответствии со средой просмотра (комнатное освещение).

Просто к вашему сведению, в то время как «сигнал» sRGB имеет закодированную гамму 1 / 2,2, монитор обычно добавляет экспоненту около 1,1.

Для Rec709 закодированный сигнал имеет эффективную гамму около 1 / 1,9 иш, но монитор в эталонной среде просмотра составляет около 2,4

В обоих случаях имеется преднамеренное усиление гаммы системы.

Если вы хотите закодировать изображение с гаммой для дисплея 2,8 и вам не нужно никакого системного усиления гаммы, тогда показатель степени равен 1 / 2,8.

«Наивысшая» гамма, обычно используемая для цифрового кино (а также Rec2020), составляет 2,6. Для тех из вас, кто думает о PAL & 2.8, я рекомендую вам прочитать Poynton на эту тему:

НАСТОЯТЕЛЬНО РЕКОМЕНДУЕМЫЕ ЧТЕНИЯ

FAQ по гамме Чарльза Пойнтона легко читается и полностью описывает эти проблемы и их важность в конвейере изображений. . Также прочтите его FAQ по цвету по той же ссылке.

НЕСКОЛЬКО СЛОВ О LINEAR vs sRGB

Работа с изображениями в линейном рабочем пространстве обычно идеальна, поскольку не только упрощает математику, но и имитирует свет в реальном мире. Свет в мире работает линейно (аддитивно). Но для линейной работы нужна адекватная битовая глубина, а 8 бит недостаточно.

Человеческое восприятие НЕ линейно. Гамма-кодирование изображения использует нелинейность, чтобы максимально использовать 8-битные контейнеры изображений. Когда вы переходите на линейный, ВАМ НУЖНО БОЛЬШЕ БИТ. 12 бит на канал считается минимумом, но 16-битное число с плавающей запятой - это минимум, "рекомендуемый передовой практикой" для линейных рабочих пространств.

При использовании текстур в среде линейного рендеринга эти текстуры необходимо преобразовать в линейное пространство (и часто с большей битовой глубиной). Хотя добавленные биты увеличивают пропускную способность данных, упрощенная математика часто позволяет ускорить вычисления.

sRGB - это пространство, НАЗЫВАЕМОЕ ДИСПЛЕЕМ, оно предназначено для ЦЕЛЕЙ ДИСПЛЕЯ и для хранения изображений в компактном состоянии «готово к отображению». Черный - 0, белый - 255, а передаточная кривая близка к 1 / 2.2.

sRGB основан на Rec709 (HDTV) и использует идентичные основные цвета и точку белого. Но кривая передачи и кодировка данных разные. Rec709 предназначен для отображения на мониторе с более высокой гаммой в затемненной гостиной и кодирует черный цвет на 16 и белый на 235.

person Myndex    schedule 30.04.2019