(Более) точное измерение динамического диапазона сенсора камеры
Вступление
Всем привет! В этом посте поговорим о том, как (более) точно измерять динамический диапазон сенсора камеры и что с этими замерами можно сделать.
Разумеется, я не являюсь специалистом по компьютерному зрению, программистом или статистиком, поэтому не стесняйтесь поправлять меня в комментариях, если я допускаю в этом посте ошибки. Здесь мой интерес был в основном направлен на повседневные и прикладные задачи, такие как фотография, но я считаю, что результат может быть полезен также и специалистам по компьютерному зрению.
Обновлено: после перевода поста на английский и публикации его на форуме DPReview, здесь были найдены ошибки. Я считаю важным это отметить здесь, а вот ссылка на саму тему
Существующая проблема
Динамический диапазон современных сенсоров изображения ограничен, мы не можем захватывать детали сразу в очень ярких светах и очень тёмных тенях без ухудшения качества изображения из-за шума. Вообще, шум, на мой взгляд, сегодня является самым ограничивающим фактором качества изображения. Чем темнее сцена, тем больше в тенях шума, который с затемнением всё больше и больше увеличивается по амплитуде и всё больше "съедает" детали, прежде всего у малоконтрастных объектов.
Зачем измерять динамический диапазон
Вообще, точные измерения динамического диапазона могут использоваться как фотографами (причём не только любителями, но и профессионалами), так и специалистами по компьютерному зрению с целью оценки какого-либо оборудования.
Во-первых, измерения помогут ответить на вопрос, какую камеру или сенсор выбрать для будущих задач или стоит ли совершать апгрейд - насколько преимущество будет заметно. Во-вторых, благодаря измерениям можно проанализировать существующую камеру или сенсор с целью поиска оптимальной стратегии экспонирования и постобработки, а также использовать данные для дальнейших исследований.
Как сейчас измеряется динамический диапазон сенсоров
В этой главе я использую метод и данные Билла Клэффа (Bill Claff) с сайта Photons to Photos.
Текущий метод измерения динамического диапазона начинается с построения графика соотношения сигнала к шуму для нужного ISO при разных значениях экспозиции, как показано на иллюстрации ниже:
Вообще, существуют инженерный и так называемый фотографический динамический диапазон. Вот что мистер Клэфф пишет относительно первого:
The low endpoint for Engineering Dynamic Range is determined by where the SNR curve crosses the value of 1.
Here is an extreme close-up of that area of the Photon Transfer Curve:
The ISO 100 line crosses 0 (the log2(1)) at 1.63 EV.
So Engineering Dynamic Range is 14.00 EV - 1.63 EV = 12.37 EV.
Or, if we use the White Level (from White Level), (14.00 EV - 0.11 EV) - 1.63 EV = 12.26 EV.
Для сравнения, вот определение так называемого фотографического динамического диапазона:
My definition of Photographic Dynamic Range is a low endpoint with an SNR of 20 when adjusted for the appropriate Circle Of Confusion (COC) for the sensor.
For the D300 the SNR values on this curve is for a 5.5 micron square photosite.
To correct for a COC of .022mm we are looking for a log2 SNR value of 2.49.
Here is an close-up of the area of the curve:
Note that the ISO 100 crosses 2.49 at 5.00 EV.
So Photographic Dynamic Range at ISO 100 is 14.00 EV - 5.00 EV = 9.00 EV.
Or, if we use the White Level (from White Level), (14.00 EV - 0.11 EV) - 5.00 EV = 8.89 EV.
Графики, полученные после таких измерений, можно найти здесь - Photographic Dynamic Range versus ISO Setting
Например, так выглядят данные для Pentax K-1:
Однако выбирать стратегию экспонирования лишь по этому графику - не лучшая идея, ведь некоторые камеры являются так называемыми ISO-less, то есть поднятие ISO в камере до захвата снимка не приведёт к улучшению шумных деталей в тенях, а лишь уничтожит детали в светах.
Поэтому также нужен другой график - вот такой - улучшение теней против значения ISO:
Действительно, выбранная камера оказалась ISO-less, то есть повышение ISO выше 100 не приведёт к улучшению деталей в тенях.
Для наглядности, вот два кадра с той же камеры от DPReview - один на ISO 3200 с осветлением на стоп, другой на ISO 100 с остветлением на 6 стопов:
Но это работает не для всех камер. Например, вот Canon 6D, тут поднятие ISO действительно улучшает тени:
Нельзя сказать, что только из-за этого камера обязательно лучше или хуже, но это влияет на выбор оптимальной стратегии экспонирования при съёмке.
Недостаток такого метода измерений
Проблема в таком классическом подходе появляется тогда, когда в камере используется шумодав. Да, это по прежнему сырые файлы, просто он может быть использован ещё до демозаика. Как видно на графике ниже, динамический диапазон резко взлетает на ISO 640:
Это совсем не значит, что качество изображения стало действительно лучше. Наоборот, шумодав мог уничтожить некоторые мелкие детали.
На графике улучшения теней всё ещё нагляднее - преимущество достигает почти 2 стопов:
На самом деле, как вы понимаете, в реальности всё будет не так классно. В этом и проблема классического способа замеров - алгоритмы DSP, такие как шумоподавление и восстановление деталей, можно лишь обнаружить (что и значат перевёрнутые треугольники на графике), но нельзя оценить их реальное влияние на качество изображения.
Более совершенный метод измерения динамического диапазона
Вы наверняка знаете библиотеку libraw и, возможно, даже пользуетесь ей. Разработчик этой библиотеки Алексей Тутубалин предложил свой вариант измерения динамического диапазона ещё в 2017 году. Он задался вопросом того, сколько реального разрешения остаётся на снимке вследствие воздействия шума - для этого Алексей использовал малоконтрастную повёрнутую мишень для тестирования разрешения. Повёрнута она была, чтобы усложнить работу DSP внутри камеры, если такие алгоритмы в ней имеются. Выглядело это вот так:
После серий снимков и анализа результатов в полуавтоматическом режиме был получен вот такой интересный график:
На мой взгляд, данные получились невероятно полезными и наглядными, но мне хотелось повторить результат, используя полностью автоматические замеры и метрики, при этом чтобы разработанный метод был доступен каждому в домашних условиях.
Предлагаемое решение
Я считаю, что разрешение нельзя тестировать с помощью специальных мишеней из-за возможных попыток читерства со стороны камеры. При этом мишень должна иметь разрешение, то есть детализацию, выше разрешения сенсора. Получается, нам нужна мишень с большим количеством мелких деталей, которые невозможно подделать - а тогда это просто шум. Но мы не можем взять обычный шум, ведь он будет уменьшаться по мере удаления камеры от мишени, поэтому нам нужен специальный, scale-invariant розовый шум.
Imatest продают такие мишени за $330:
Я же просто распечатал такой квадратик на обычном принтере на листочке A4.
К сожалению, у меня нет отдельной камеры, поэтому тестирование проводилось на обычном телефоне с сенсором SONY IMX686. Я использовал приложение FreeDCam, которым управлял через компьютер с помощью scrcpy, чтобы не двигать телефон между кадрами (в случае с реальной камерой её надо было бы поставить на штатив и так же дистанционно управлять с компьютера). После этого я сделал серии снимков получившейся мишени на разных ISO с разной экспозицией, от 1 до 12 стопов ниже насыщения сенсора (внимательные читатели заметят, что на самом деле линии на графике ниже обрываются раньше 12 стопов на ISO 3200 и 6400 - во FreeDCam просто нет настолько коротких значений выдержки). Полученные кадры были сконвертированы в линейный 16-битный TIFF без демозаика, но с балансом белого, который был применён через усиление каналов, а затем проанализированы относительно референсного кадра - 10 усреднённых кадров мишени, снятых на стоп ниже насыщения сенсора - аналог кадра на ISO 5 с идеальной экспозицией.
Получился вот такой график соотношения сигнал/шум:
В отличие от графика мистера Клэффа, этот график если не полностью, то хотя бы частично устойчив к DSP - прошу обратить внимание на нижние значения на ISO 3200 и 6400 - это, вероятно, шумодав. Хотя график не полностью избавлен от его влияния, улучшения относительно верхних значений не случилось, а значит полученные данные имеют более высокое качество, чем те, которые были бы получены стандартным способом. На самом деле, я тестировал конкретно свой телефон не с розовым шумом, поэтому реальный розовый шум (который можно сгенерировать, например, используя функции отсюда), вероятно, только улучшит результат.
Вместо построения графиков классическим способом, я решил пойти дальше и построить график как у Алексея Тутубалина, только, опять же, используя данные, полученные в полностью автоматическом режиме и, как я надеюсь, с большей точностью. Для этого я написал и использовал вот такую функцию numpy:
def find_real_resolution(image_resolution, ground_truth, noisy_image):
stock_contrast = np.max(ground_truth) / np.min(ground_truth)
noise = np.mean(np.abs(noisy_image - ground_truth))
real_contrast = (np.max(ground_truth) - noise) / (np.min(ground_truth) + noise)
contrast_change_coefficient = stock_contrast / real_contrast
real_resolution = image_resolution / contrast_change_coefficient
return real_resolution
Подробнее о ней
image_resolution
- разрешение всего кадра (так как в данном случае тестировалась лишь его обрезанная часть 100x100 пикселей), ground_truth
- референсное изображение, noisy_image
- тестируемое изображение из серии. Как вы понимаете, все кадры в сериях надо просто прогнать через эту функцию. Но что же она делает?
Давайте ещё раз посмотрим на мишень для тестирования разрешения:
В худшем случае шум уменьшит значение белого фона и увеличит значение чёрных линий, что приведёт к понижению контраста, а тогда и к падению разрешения для данной мишени. Поэтому я просто сначала нахожу "средний шум" каждого кадра (строка 2 внутри функции), после чего вычитаю его из точки белого референсного изображения и прибавляю к точке чёрного того же изображения (строка 3). Затем сравниваю (строка 4) исходную (строка 1) и новую (строка 3) контрастность, после чего просто делю (строка 5) всё разрешение кадра на данный коэффициент и получаю реальное разрешение.
Получился вот такой график:
Значения ниже 0 приведены лишь для наглядности.
Как и было сказано ранее, такой график можно использовать для сравнения двух сенсоров, чтобы понять, например, какой из них выбрать для определённых условий освещения. Или же можно исследовать график только этого сенсора для определения оптимальной стратегии экспонирования, а также разработки наилучших алгоритмов постобработки, например, того же шумоподавления.
Дальнейшее исследование
В качестве дальнейшей работы я бы хотел отметить следующие возможности:
Разделение фильтра Байера на каналы до анализа. Если пиксели автофокуса у камеры только, например, синие, интересно сравнить их с теми, у которых автофокуса нет (то есть, например, с одним из зелёных каналов)
Использование этого метода для несырых, обработанных изображений. Это будет полезно, если нужно не только визуально оценить работу алгоритмов шумоподавления при постобработке, но и узнать, сколько реальных деталей они оставляют. Это также может помочь при разработке каких-либо новых алгоритмов, связанных с восстановлением деталей и уменьшением шума, даже нейросетевых
Модификация метода с целью использования на видео - можно показывать новое изображение розового шума покадрово на высокогерцовом мониторе. Однако программа, проводящая анализ такого видео, должна знать, в какой момент какой кадр был показан - очевидно, для этого можно выводить какую-либо вспомогательную информацию (например, номер кадра, возможно, закодированный в QR-код) сбоку от основной мишени. Но в итоге такая система будет устойчива даже в временны́м методам шумоподавления, которые как раз используются на видео
Использование более точных вычислений, возможно, опирающихся на статистический анализ, для подсчёта реального разрешения
Использование различных метрик оценки качества изображения для представления результатов. Вот, например, SSIM:
На этом всё, спасибо, что прочитали!