Эмуляция длительности затвора на фотографиях RAW с помощью совмещения экспозиции

Итак, я занимаюсь этой проблемой уже около года и не могу ее решить. Я отказался от этого некоторое время назад, но теперь я исследовал и готов получить ответ.

Я пытаюсь имитировать длинную экспозицию, делая несколько фотографий в формате RAW и что-то делая со значениями фильтра Байера , чтобы получить эффект того, что затвор остается открытым так долго.

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

Например, если у меня есть три фотографии продолжительностью 1/3 секунды, сделанные без перемещения камеры, они должны хранить ту же информацию, что и фотография продолжительностью 1 секунда.

Проблема, с которой я сталкиваюсь, заключается в том, как я могу количественно оценить эту агрегацию. Я обнаружил, что многие различные методы терпят неудачу, и я не уверен, почему. Если я просто усредню несколько фотографий, я получу чертовски сильное шумоподавление . Так что приятно иметь эту часть. Позже я могу использовать Camera Raw, чтобы осветлить фотографию , и я получу близкое приближение к тому, что я получил бы с выдержкой в ​​1 секунду. Проблема в том, что я хочу сделать это на устройстве. В настоящее время я использую iPhone для тестирования, но я не думаю, что это имеет значение.

Текущая настройка и формула

Я использую три выдержки по 1/3 секунды, чтобы попытаться подделать 1-секундную фотографию. Моя текущая формула проста:

out_picture[x][y] = picture1[x][y] + picture2[x][y] + picture3[x][y]

Проблема в том, что это дает мне действительно розовые картинки, например:

JPEG-версия файла RAW

Я пробовал несколько различных вариантов приведенной выше формулы. Один из них, который я считал многообещающим, — это производная сигмовидной функции . Причина, по которой я использовал производную сигмоиды, заключается в том, что я провел тематическое исследование, в котором я изучал влияние окончательных выходных сигналов RGB в зависимости от значения ползунка «EV» в Photoshop Camera Raw и обнаружил сигмовидный шаблон. Вот как это выглядит, когда я рисую его для нескольких пикселей:

Может сигмоид?

Поэтому я подумал, что, возможно, производная сигмоиды (высокие изменения для средних значений, низкие изменения для низких и высоких значений фильтра) исправит ситуацию. Я нормализовал значения фильтра до диапазона 0-1, используя уровень черного камеры и максимальное значение бита. Я внес некоторые изменения в производную, чтобы она соответствовала диапазону значений 0-1, это функция, с которой я закончил. Затем я умножил на количество сделанных снимков, чтобы эмулировать EVслайдер в Camera Raw.

Вот формула для этого (на питоне):

def exposureAdjust(x):
   black_level = 528    ## iPhone RAW Photos have a black_level of 528
   max_pixel_value = 2**14 - 1    ## 14-bit depth
   normalized = (x - black_level)/max_pixel_value    ## now x is between [0,1]
   EV = num_pics    ## faking EV value
   adjustment = EV * (np.exp(-10 *(x - 0.25)))/(np.exp(-10*(x - 0.25)) + 1)^2

   return min(x * (1+adjustment), max_pixel_value)    ## Cap at 2**14 


num_pics = 3
out_picture[x][y] = picture1[x][y] + picture2[x][y] + picture3[x][y]
out_picture[x][y] = exposureAdjust(out_picture[x][y]/3)

Запустив эту формулу, я получаю аналогичный результат:

Все еще сломан


Заключение и наблюдения

Как видите, он все еще розоватый. Фотографии выше — это JPEG, да, но на самом деле я работаю с RAW. Мне просто нужно было загрузить их в формате JPEG, чтобы их можно было прикрепить.

Розовый бывает, когда не хватает зеленого. Камера имеет схему фильтра Байера RGGB, но я действительно не понимаю, как я мог получить этот эффект. У кого-нибудь есть идеи, что здесь виновато и как я могу настроить это программно. У меня настроен весь трубопровод. Мне нужна только формула, но почему-то она не работает. Я закодировал это на Python и Swift, и результаты такие же. Определенно есть проблема с формулой, использующей значения фильтра Байера RAW. Я думаю, что это крутой вызов, но я достиг предела своего ума в этом.

Есть идеи?


ОБНОВЛЕНИЕ: Вот результаты гистограммы для изображения до и послеexposureAdjust применения функции . Вроде зеленый канал нужно настроить по другому?

В вашем примере, что вы фотографируете? Он кажется очень темным и недоэкспонированным.
Подождите, вы работаете напрямую с необработанными значениями или с дебайеризованными данными?
@scottbb просто несколько кабелей на моем столе. Работа напрямую с необработанными значениями. Он намеренно темный и недоэкспонированный, чтобы моя длинная выдержка могла быть ярче. могу добавить фото получше
FWIW это именно то, что делает «Ночной режим» на последних версиях Android.
У вас есть рабочий код для правильного отображения одного изображения, сделанного со средней («правильной») экспозицией?
Так что да, мой код на самом деле работает, когда я просто вывожу среднее значение всех изображений (шум тоже уменьшается!). Я просто хочу сделать его ярче. Я также понял, что мой код не отражает то, что я передаю в функцию ExpoAdjust среднее значение , а не сумму.
Я думаю, у вас неправильное представление о стеке: не недоэкспонируйте каждый отдельный снимок в стеке, ожидая существенно увеличить экспозицию при постобработке. Используйте полный диапазон вашей камеры для каждого снимка и просто усредняйте снимки вместе.
Черт возьми... Я идиот. Это имеет смысл, это дает мне возможность работать сейчас. Однако из любопытства я хотел бы решить эту проблему. Пойду какое-то время читать.

Ответы (2)

Наблюдения:

  1. Вы суммируете значения каждого пикселя, но ваша exposureAdjust()функция предполагает, что после обработки каждый пиксель будет находиться в диапазоне [0, 1). Это неправильно. Предположим, что значение пикселя в каждом из 3 входных изображений составляет, скажем, 50% полной шкалы (таким образом, 2 · 13 = 8192). Суммируя это трижды, получаем 3 * 8192 = 24 576. Тогда результат после normalized = (x - black_level)/max_pixel_valueбудет около 1,47, определенно не нормализованный до менее 1.

  2. Удалите сигмовидную adjustment =линию, пока не разберетесь с остальной логикой (например, выше). Вот график вашей сигмовидной функции:

    введите описание изображения здесь

    Обратите внимание, что для значений x выше примерно 0,4 увеличение x дает быстро меньшие значения y (ваше «скорректированное» значение. Для сравнения, нескорректированное значение должно соответствовать линейному графику y = x на графике.

  3. Для нормализации (при условии правильно ограниченных входных данных [0, ]) вам, вероятно , также max_pixel_value - 1следует уменьшить знаменатель на (т. е. ). Если вы этого не сделаете, то ваши нормализованные значения находятся в диапазоне [0, ~ 0,969) (точнее, (2 13 - 511) / (2 14 - 1)).black_levelnormalized = (x - black_level)/(max_pixel_value - black_level)

1. Первый блок кода был просто пробным. Я на 100% согласен с тем, что тот не был нормализован должным образом, я просто хотел показать, как неправильно нормализованный ввод дал тот же результат.
2. Причина, по которой я хотел иметь эту функцию, заключалась в том, что я думал, что существует некоторая нелинейность в том, как масштабируются значения Байера. y=x был бы идеальным, но я подумал, что, возможно, причина проблемы в том, что темные пиксели (0-0,5) недостаточно масштабируются.
3. Конечно, это справедливое замечание, это точно ошибка в моих расчетах. К сожалению, я не думаю, что это решит проблему :/

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

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

В этой статье о Uni-WB содержится много информации о методах коррекции необработанных данных и поправочных коэффициентах WB. http://www.guillermoluijk.com/tutorial/uniwb/index_en.htm

Данные RAW применяются непосредственно из фотографий, снятых с камеры, и никогда не проходят через ACR. Вы правы в том, что с каналами определенно что-то не так, так как вот результаты до и после функции ExposureAdjustment. Очевидно, что на красный и синий каналы воздействуют совершенно по-разному.
Вы заявили, что придумали сигмовидную коррекцию, основанную на том, что вы наблюдали с помощью Photoshop Camera Raw... к этому наблюдению применялась коррекция баланса белого. Какую программу вы сейчас используете для рендеринга обработанных необработанных данных? Насколько я знаю, единственная программа, которая может отображать необработанный файл без применения поправок WB, — это DCRAW; может RawDigger.