Рис. 1: фото на Nikon D610 с объективом AF-S 24-120mm f/4 и параметрами 24mm f/8 ISO100

Каковы базовые шаги рендера изображения формата RAW на низком уровне? В данной статье я опишу, что происходит «под капотом» конвертеров цифровой камеры, где необработанные данные превращаются в пригодное для просмотра изображение формата RAW – иногда этот процесс называют рендерингом. Для демонстрации преобразования информации с изображения на каждом шаге я буду использовать приведённую в начале статьи фотографию, сделанную на Nikon D610 с объективом AF-S 24-120mm f/4 и параметрами 24mm f/8 ISO100.

Рендеринг – это преобразование RAW и редактирование


Рендеринг можно разделить на два основных процесса: преобразование RAW и редактирование. Преобразование RAW необходимо для превращения необработанных данных изображения в стандартный формат, который понимают программы для редактирования и просмотра изображений, а также устройства для работы с ними. Обычно для этого используется колориметрическое цветовое пространство RGB типа Adobe или sRGB.

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

Пример чистого конвертера RAW – dcraw от Дэвида Коффина. Пример чистого редактора — Photoshop от Adobe. Большинство конвертеров RAW на самом деле сочетают в себе функции преобразования RAW с функциями редактора (к примеру, Capture NX, LR, C1).

7 шагов базового преобразования RAW


Граница того, где заканчивается конвертация и начинается редактирование, достаточно размыта, но, в зависимости от того, как их разделять, можно выделить всего 7 шагов в основном процессе преобразования файла RAW в стандартное колориметрическое цветовое пространство – к примеру, sRGB. Шаги не обязательно должны идти в таком порядке, однако следующая последовательность довольно логична.

  1. Загрузить линейные данные из файла RAW и вычесть уровни чёрного.
  2. Провести балансировку белого.
  3. Подправить линейную яркость.
  4. Обрезать данные изображения.
  5. Восстановить исходное изображение из мозаики (дебайеризация).
  6. Применить преобразования и коррекции цветов.
  7. Применить гамму.

В базовом преобразовании RAW процесс остаётся линейным до самого конца. В идеале кривая гаммы на последнем шаге исправляется устройством, выводящим изображение, поэтому система обработки изображения от начала и до конца – от момента, когда на матрицу падает свет, до момента, когда свет достигает глаз – примерно линейная. Если вам нужно «честно» отрендерить изображение, так, как оно попало на фотоматрицу – то это всё, что вам нужно от конвертера RAW.

+ Отображение тона: адаптация к динамическому диапазону устройства вывода


Однако, как мы увидим, базовое преобразование файлов RAW в существующих цифровых камерах почти никогда не даёт удовлетворительного результата, поскольку у большей части устройств вывода (фотобумага, мониторы) коэффициент контрастности уступает тому, который способны запечатлеть хорошие цифровые камеры. Поэтому практически необходимо провести коррекцию тонов, чтобы привести широкий динамический диапазон камеры к узкому динамическому диапазону устройства. Это может быть простая кривая контрастности – или более сложное отображение тона вместе с локальной и глобальной подстройкой теней, ярких участков, чёткости и т.п. (стандартные ползунки в коммерческих редакторах и ПО конвертеров). Обычно это делается при редактировании рендера – но если вы стремитесь получить «точный» цвет, в идеале отображение тона должно быть частью 6-го шага цветокоррекции во время конвертирования RAW (см. отличный сайт Алекса Торгера с описанием цветовых профилей).

После семи базовых шагов конвертирования можно переходить к редактору, с тем, чтобы объективно скорректировать несовершенства, выявленные в конкретном кадре и в конкретном выводе картинки на устройство вывода – а также сделать изображение субъективно более приятным глазу художника. К примеру, исправить дисторсию объектива и латеральную хроматическую аберрацию; применить уменьшение шума; применить фильтр увеличения резкости. Возможно, некоторые из этих функций лучше выполнять в линейном пространстве, перед определёнными шагами конвертирования RAW, но обычно они необязательны, и их можно точно так же сделать и в редакторе после рендеринга в гамма-пространстве.

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

1. Загрузить линейные данные из файла RAW и вычесть уровни чёрного


Первый шаг в преобразовании RAW – простая загрузка данных из файла RAW в память. Поскольку форматы RAW отличаются от камеры к камере, большинство конвертеров используют вариации программ LibRaw/dcraw с открытым кодом. Следующие команды для LibRaw или dcraw перепакуют RAW в линейный 16-битный TIF, который смогут прочесть приложения для обработки (Matlab, ImageJ, PS, и т.д.). Установка программы не требуется, нужно только, чтобы исполняемый файл был в переменной PATH или находился в той же директории.

unprocessed_raw -T  yourRawFile

или

dcraw -d -4 -T  yourRawFile

Если ваша фотоматрица хорошо спроектирована и находится в рамках спецификаций, записанные данные будут находиться в линейном соотношении с яркостью света, однако обычно они хранятся со смещением, зависящим от камеры и канала. Т.н. уровни чёрного имеют величины в несколько сотен или тысяч DN, и их нужно вычесть из оригинальных необработанных данных, чтобы нулевая интенсивность пикселей совпадала с нулевым количеством света. dcraw с приведённой выше командной строкой сделает это для вас (хотя и применит некие средние значения). При использовании unprocessed_raw вам нужно знать значение уровня чёрного для вашей камеры и вычесть его соответственно (или можно использовать параметр –B, который, правда, в текущей версии LibRaw, похоже, не поддерживается).

Оказывается, что Nikon вычитает уровни чёрного из каждого канала перед записью в файлы D610, поэтому для нашего справочного кадра любая из команд сработает. Я загрузил её командой dcraw -d -4 –T, которая также масштабирует данные до 16 бит (см. шаг 3 по коррекции яркости далее).

Загруженные на этой стадии данные просто представляют собой интенсивность «серой шкалы» изображения. Однако в них есть соответствие положению на матрице, связанное с определённым цветовым фильтром, под которым оно находится. В байеровских матрицах идут ряды перемежающихся красного с зелёным цветов – и зелёного с синим – как показано на картинке. Точный порядок определяется по первому квартету активной области матрицы – в данном случае это RGGB, однако возможны и три других варианта.


Рис 2: матрица цветного фильтра Байера: расположение RGGB.

Байеровская матрица для D610 имеет раскладку RGGB. Необработанные данные выглядят на этом этапе следующим образом, как недоэкспонированное чёрно-белое изображение:


Рис. 3: Шаг 1: линейное необработанное изображение с вычтенными уровнями чёрного. Должно выглядеть таким же ярким, как следующий рис. 4. Если нет – ваш браузер неправильно обрабатывает цвета (я использую Chrome, и он, очевидно, обрабатывает их неправильно).

Если фото чёрное, то ваш браузер не знает, как показывать правильно размеченные линейные данные. Интересно, что редактор WordPress показывает изображение верно, но после публикации в Chrome оно выглядит неправильно (примечание: к 2019 году это, наконец, исправили) [статья 2016 года / прим. перев.]. Вот, как должно выглядеть это изображение:


Рис. 4: то же фото, но в виде CFA grayscale

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

Изображение выглядит как полноценное чёрно-белое из-за малого размера, но на самом деле это не так: даже на одинаково освещённых участках видна пикселизация. Это происходит из-за того, что соседние цветовые фильтры, имея разную спектральную чувствительность, собирают разную информацию о цветах. Это легко видно при увеличении изображения. Вот как выглядит участок изображения сразу под карточкой WhiBal с увеличением до 600%:


Рис 5: CFA-пикселизация видна на равномерно серой карточке (сверху) и на окрашенных листьях.

2. Данные о балансе белого


Из-за спектрального распределения энергии источника света (в данном случае это частично закрытое облаками небо, свет которого проникает сквозь листву) и спектральной чувствительности фильтров, расположенных на матрице, различные цветные пиксели записывают пропорционально большие или меньшие значения даже при одном и том же освещении. Особенно это очевидно в нейтральных частях изображения, где, казалось бы, должны проявляться одинаковые средние значения по всем цветовым плоскостям. В данном случае на нейтрально серой карточке красные и синие пиксели записали значения в 48,8% и 75,4% от зелёного значения соответственно, поэтому они кажутся темнее.

Поэтому следующий шаг – применить баланс белого к линейным данным CFA, умножив каждый красный пиксель на 2,0493 (1/48,8%), а каждый синий – на 1,3256 (1/75,4%). В терминах Adobe мы получим чёрно-белое изображение, нейтральное относительно камеры. Тогда гарантированно, за исключением шума, все пиксели покажут одинаковые линейные значения на нейтральных частях изображения.


Рис. 6: после балансировки белого пикселизация серой карточки исчезает, но на цветных объектах она ещё видна.

Посмотрите, как исчезла пикселизация вверху изображения – для калибровки использовалась нейтрально серая карточка. Но, конечно, с цветных объектов пикселизация не исчезла: информация о цветах хранится в разности интенсивностей трёх каналов.

3. Корректировка линейной яркости


Большинство современных цифровых камер с заменяемыми объективами дают необработанные данные размерностью 12-14 линейных битов. Стандартная битовая глубина файлов (jpeg, TIFF, PNG) обычно задаётся в виде множителей 8, и любимой глубиной большинства редакторов сегодня являются 16 бит. Мы не можем просто взять 14-битные данные с вычтенным уровнем чёрного и сохранить их в 16 бит – всё попадёт в нижние 25% линейного диапазона и будет слишком тёмным. В идеале нам нужно обрезать данные после балансировки белого и вычитания чёрного, чтобы соответствовать обрезанным данным 16-битного файла, и соответствующим образом их масштабировать (см. шаг 4). Простой способ примерного приведения данных – просто умножить 14-битные данные на 4, масштабируя их до 16 бит. Именно это было сделано на шаге 1 после вычитания чёрного (dcraw -d -4 -T делает это автоматически, а с unprocessed_raw нужно будет сделать это вручную).

Говоря о масштабировании, мы можем также захотеть подправить нашу яркость. Этот шаг субъективен, и его, вероятно, не стоит делать, если вы гонитесь за «честным» рендером изображения, таким, какое оно получилось на матрице и записалось в файл RAW. Однако ни у кого не получается идеально выставить экспозицию, а разные камеры часто измеряют среднее серое в разных процентах от необработанных данных, поэтому полезно иметь возможность подправлять яркость. Поэтому у многих конвертеров относительные ползунки называются «коррекция экспозиции » или «компенсация экспозиции». В Adobe есть связанная с этим метка DNG, нормализующая экспонометр для разных камер, BaselineExposure. Для D610 она равняется 0,35 шага.

На мой вкус наше изображение темновато, и карточка WhiBal, которая должна иметь 50% отражающей способности, в полном масштабе даёт всего 17%. Линейная коррекция яркости – это умножение каждого пикселя в данных на константу. Если мы посчитаем, что на данном снимке не нужно сохранять самые яркие участки изображения яркостью выше 100% рассеянного белого света, то эта константа в данном примере будет равняться 50/17, примерно 1,5 шага коррекции. В данном случае я решил применить субъективно-консервативную коррекцию в +1,1 шага линейной яркости, умножив все данные в файле на 2,14, и получилось следующее:


Рис. 7: CFA-изображение после вычитания уровней чёрного, балансировки белого, обрезки, коррекции линейной яркости на 1,1 шаг

Уже лучше. Но, как вы можете видеть, расплачиваться за линейную коррекцию яркости приходится засветкой частей водопада. Тут приходят на помощь продвинутые ползунки нелинейного сжатия ярких участков и восстановления теней, имеющиеся в большинстве конвертеров RAW.

4. Убедиться в ровной обрезке данных по балансу белого


Если в необработанных данных изначально был обрезан зелёный канал, возможно, после применения множителей баланса белого придётся обрезать и два других до полного масштаба, чтобы исправить возникшую нелинейность. Полный масштаб показан на гистограммах ниже в виде нормализованного значения 1,0. Видно, что зелёный канал оригинальных необработанных данных был обрезан (из-за нагромождения значений), а другие – не были.


Рис. 8: Сверху вниз: гистограммы R, G, B после применения множителей баланса белого к необработанным данным, до обрезки. Обязательно обрезать все три до уровня меньшего из каналов, чтобы в ярких областях не появилось ложных цветов. Данные изображения отложены на отрезке 0-1, где 1 – полный масштаб.

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


Рис. 9: Слева: правильно обрезанное изображение после применения баланса белого. Справа: изображение не обрезано. Жёлтой стрелкой показана область, близкая к максимальной яркости, где неполная информация от цветовых каналов даёт розоватый оттенок.

Вместо обрезки можно было бы сделать определённые предположения о недостающих цветах и дополнить относительные данные. В продвинутых конвертерах RAW этим занимаются алгоритмы или ползунки с названиями типа «реконструкция ярких участков». Способов сделать это существует множество. К примеру, если не хватает всего одного канала, как в случае с зелёным от 1,0 до 1,2 на рис. 8, проще всего предположить, что яркие участки находятся в районе нейтрально белого цвета, а в необработанных данных изображения сделан правильный баланс белого. Тогда в любом квартете, где зелёный цвет будет обрезан, а два других не будут, то значение зелёного будет равняться среднему значению двух других каналов. Для данного снимка такая стратегия смогла бы реконструировать не более 1/4 шага в ярких участках (log2(1,2)). Затем потребовалось бы провести сжатие ярких участков и/или повторную нормализацию новой полной шкалы до 1,0.

5. Дебайеризация данных CFA


До сего момента CFA-изображение находилось на одной чёрно-белой плоскости, из-за чего цветные участки казались пикселизированными, как видно на рис. 6. Пришло время дебайеризации – разделения красных, зелёных и синих пикселей, показанных на рис. 2, на отдельные полноразмерные цветовые плоскости, путём аппроксимации отсутствующих данных (на рис. ниже они показаны в виде белых квадратов).


Рис. 10: дебайеризация – заполнение отсутствующих данных в каждой цветовой плоскости с использованием информации из всех трёх плоскостей.

На этом шаге можно использовать любой из большого количества продвинутых алгоритмов дебайеризации. Большинство из них работают очень хорошо, но некоторые получаются лучше других, в зависимости от ситуации. Некоторые конвертеры RAW типа открытых RawTherapee и dcraw предлагают пользователю выбрать алгоритм из списка. Большинство конвертеров не дают такой возможности, и используют один алгоритм дебайеризации. Знаете ли вы, какой алгоритм дебайеризации использует ваш любимый конвертер RAW?

В данном испытании я решил схитрить и просто сжать каждый квартет RGGB в единый пиксель RGB, оставив значения R и B для каждого квартета такими, какие они есть в необработанных данных, и усреднив G по двум (это эквивалентно режиму dcraw –h). Это алгоритм дебайеризации 2?2 по ближайшим соседям. Он даёт более удобное в работе изображение вдвое меньшего размера (по линейным измерениям, или вчетверо по площади).


Рис. 11: необработанное RGB-изображение после вычитания уровней чёрного, балансировки белого, обрезки, коррекции линейной яркости и дебайеризации 2?2 по ближайшим соседям (эквивалент dcraw –h).

На рис. 11 видно, что наши необработанные данные теперь представлены в RGB-формате с тремя полностью заполненными цветовыми плоскостями. Цвета такие, какие записала камера, показал браузер и монитор. Выглядят блекловато, но не сильно отличаются от оригинала. Оттенки хранятся не в стандартном RGB-пространстве, поэтому ПО и железо не всегда понимают, что с ними делать. Следующий шаг – преобразовать эти цвета в общепринятое колориметрическое стандартное цветовое пространство.

6. Преобразование и коррекция цветов


Это один из наименее интуитивно понятных но наиболее важных шагов, необходимых для получения готового изображения с приятными глазу цветами. Все производители ревностно хранят секреты своих цветовых фильтров в CFA их матриц, однако при наличии подходящего оборудования не так уж сложно вывести функции спектральной чувствительности. Примерное представление о функциях вашей камеры вы можете составить даже при помощи дешёвого спектрометра.

Вооружившись всем этим, а также сделав множество предположений по поводу типичных источников света, сцен и способов просмотра, можно сгенерировать компромиссную линейную матрицу, преобразующую цвет, полученный в CFA-изображении (таком, как показано на рис. 11), в стандартный цвет, который смогут распознать распространённые программы типа редакторов или браузеров, а также устройства типа дисплеев и принтеров.

К счастью для нас, измерением и расчётом этих матриц занимается несколько прекрасных лабораторий – а потом они выкладывают расчёты в открытый доступ. К примеру, DXOmark.com выпускает матрицы для преобразования данных из необработанного фото после балансировки белого в sRGB для двух источников для любой камеры из их базы данных. Вот, например, их матрица для Nikon D610 и стандартного источника света D50:


Рис 12: цветовая матрица от DXO lab для источника света D50: от данных, прошедших балансировку белого и дебайеризации к sRGB.

Какая из компромиссных матриц будет лучшей, зависит от спектрального распределения энергии источника света в момент снятия кадра, поэтому реальную матрицу обычно интерполируют на основе парочки ссылок. В мире Adobe сегодня это стандартные источники света A и D65, отвечающие за предельные варианты типичного освещения в повседневной фотографии, от лампы накаливания до дневной тени и съёмки в помещении. Затем преобразованные данные адаптируются к источнику света, соответствующему итоговому цветовому пространству – для sRGB это, например, D65. В итоге получается некая матрица, как, например, та, что показана на рис. 12. Потом остаётся просто перемножить её на RGB-значения каждого дебайеризованного пикселя после шага 5.

В спецификации своего DNG Converter Adobe советует более гибкий процесс. Вместо прямого перехода от CFA камеры к колориметрическому цветовому пространству Adobe сначала преобразует данные в цветовое пространство Profile Connection (XYZ D50), умножая данные после балансировки белого и дебайеризации на интерполированную линейную прямую матрицу [forward matrix], а потом уже приходит в итоговое цветовое пространство типа sRGB. Иногда Adobe также применяет дополнительную нелинейную цветовую коррекцию с использованием специальных профилей в XYZ (на языке DNG это HSV-коррекции через ProPhoto RGB, HueSatMap и LookTable).

Прямые матрицы камеры, сделавшей снимок, записываются в каждый DNG-файл, хвала Adobe. Я скачал оттуда матрицы для D610, а матрицы XYZD50 -> sRGBD65 с сайта Брюса Линдблума, и получил итоговое изображение:


Рис. 13: «Честно» сконвертированное изображение. Необработанные данные, вычтены уровни чёрного, произведена балансировка белого, обрезка, подправлена яркость, дебайеризация через ближайшего соседа 2?2, цвет подкорректирован и преобразован в цветовое пространство sRGB.

Теперь цвета такие, какие ожидают встретить программы и устройства в цветовое пространство sRGB. Если вам интересно, то данное изображение практически идентично тому, что выдаёт конвертер необработанных данных Capture NX-D от Nikon с профилем Flat. Однако выглядит оно не очень резко из-за плохой контрастности наших мониторов (см. Отображение тона).

7. Применение гаммы


Последний шаг зависит от выбранного цветового пространства. Gamma для пространства sRGB равна около 2,2. Я отмечаю это особо только для того, чтобы показать, что на этом этапе процесс рендеринга становится нелинейным. С этого момента изображение приведено к колориметрическому гамма цветовому пространству, и его можно как загружать в любимый редактор, так и выводить на экран. В теории все предыдущие шаги были линейными, то есть легко обратимыми.

+ Отображение тона


В 2016 году почти всегда требуется ещё и коррекция тона, чтобы выбрать, как именно втиснуть большой динамический диапазон камеры в небольшой диапазон отображающего устройства. К примеру, в зависимости от вашей устойчивости к шуму, динамический диапазон моего D610 имеет 12 шагов, при том, что у моего совсем неплохого монитора коэффициент контрастности равен 500:1, или порядка 9 шагов. Это значит, что три нижних шага с камеры не будут видны на мониторе из-за его подсветки.

Кривая RGB субъективно перераспределит тона по диапазону, так, чтобы некоторые тени стали виднее за счёт некоторых самых ярких участков (поэтому эту кривую называют «градационной кривой»). На момент написания статьи такую кривую обычно применяет Adobe в ACR/LR во время рендеринга перед тем, как показать изображение в первый раз:


Рис. 14: градационная кривая применяемая ACR/LR ближе к концу процесса рендеринга в Process Version 3 (2012-2016). Горизонтальная ось нелинейна.

В данном случае я её не использовал. Я просто применил кривую увеличения контраста и добавил немного резкости в Photoshop CS5 к рис. 13, чтобы получить итоговое изображение:


Рис. 15: Итоговое sRGB изображение. Изначально необработанные данные, вычтены уровни чёрного, произведена балансировка белого, обрезка, подправлена яркость, проведена дебайеризация, цвет подкорректирован, применена градационная кривая

Конечно, применение кривой контраста на позднем этапе меняет хроматичность и насыщенность цветов, однако именно это происходит, когда вы применяете эти подстройки гамма-RGB пространстве после рендера изображения. Исторически так всё происходило в фотоаппаратах, и так всё происходит в популярных конвертерах RAW – такова процедура, и к такому мы с годами привыкли. Альтернативной для достижения «точности» цветопередачи будет использовать цветовой профиль с сайта Торгера, и уже не трогать тона.

Подытожим


Итак, для базовой конвертации RAW с линейной подстройкой яркости и цветов требуется:

  1. Загрузить линейные данные из файла RAW и вычесть уровни чёрного.
  2. Провести балансировку белого.
  3. Подправить линейную яркость.
  4. Обрезать данные изображения.
  5. Провести дебайеризацию.
  6. Применить преобразования и коррекции цветов.
  7. Применить гамму.

И всё – покров тайны с конвертертации необработанных данных сорван.

Скрипты для Matlab для получения изображений, приведённых в этой статье, можно скачать по ссылке. 7 базовых шагов отмечены жёлтым:

s = raw2RGB(‘DSC_4022’ , ‘ROI’ , 1.1)

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