July 31st, 2013

medved

Компрессия RAW с потерями

Задумался тут о вопросе компрессии RAW файлов с потерями.
Исходно задача состоит в просмотре RAW файлов на планшетах - дивайсах достаточно слабомощных, ну и ограниченных по памяти. 20ти и более меговый файлы для планшета тяжеловаты.
С другой стороны возникает вопрос - а нужны ли эти RAW'ы вообще?
В подавляющем большинстве случаев, конечный результат все равно будет жопег, к тому же сильно меньше в плане многопиксельности.
Конечно у RAW файлов есть одно неубиваемое достоинство в сравнении с жопегами - 12/14 битный цвет. В силу этого, можно и цифровой баланс подкорректировать и экспозицию в широких пределах менять.
С другой стороны, тягать из-за этого 20+ меговые файлы не очень удобно.
Вопрос (риторический) - почему производители камер редко пользуют форматы поддерживающие 12-16 битное сжатие с потерями, например жопег2000 или что-то типа того?

Хотя жопег 2000 не решает проблему. Во-первых он довольно тормозной, скажем на планшете его юзать замучаешься. Во-вторых, RAW форматы обычно хранят данные не в RGB виде а в баеровском CFA, т.е. по одному цветному отсчетну на пиксель, ну и потом интерполируют оставшиеся.
Таким образом, получается, что скажем для 20 мегапиксельной картинки, в RAW'е хранится 20 млн 14битных семплов, ну и он занимает в сжатом виде в районе 20+ мегабайт. А если его отконвертировать в jpeg2000, то после интерполяции будет 60 млн 16битных значений, ну и в сжатом виде (без потерь) он будет занимать в районе 60 мегов, ну от силы 50 (jpeg2000 в лосслесс режиме дает сжатие в районе 2-2.5). TIFF конечно будет хуже, что-то типа 120 мегов, но в сравнении с RAW результат не радует.

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

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

Учет байеровской структуры делается просто. Алгоритмы сжатия с потерями первым этапом обычно трансформируют RGB в цветовое пространство с яркостным каналом, типа YCbCr или YUV. Так снижается коррелированность каналов, ибо мощность переходит в яркостный канал.
Ну а байеровская матрица обычно имеет удвоенное кол-во зеленых пикселей. Т.е. можно закодировать половину зеленых пикселей отдельным grayscale'ом, ну а оставшиеся как раз дадут RGB половинного разрешения. Точнее конечно нужно брать среднее между двумя зелеными пикселями, а отдельным greyscale'ом кодировать разницу между зелеными пикселями, для декорреляции.

Чтобы сохранить битность цвета, мне в голову пришло 4 варианта:
1 использовать 12 битный жопег. Правда, все-таки 14 бит это лучше чем 12. В теории, можно было бы сделать гамма-предыскажение, ну и тогда линейный 14 бит как раз бы превратился в примерно 12 бит гамма-предыскаженного. Но к сожеланию, это вариант затруднит последующую коррекцию экспозиции, ведь при гамма-предыскажении и уменьшении до 12 бит потеряются детали в светах. Если не менять экспозицию, то и похрен - глаз там как раз меньше чувствителен, но если сильно сдвинуть экспозицию в плюч, то света могут оказаться и тенями. Так что это не очень хороший вариант.
2 можно разбить 14бит на две части, т.е. отдельно кодировать старшие 8бит и 6 младших битов (либо 7 на 7). Вариант хотя и простой в реализации, но мне кажется не совсем удачным, ибо при сжатии с потерями будут херится детали в обоих изображениях. Кроме того, 8бит обычно гамма-предыскаженные, а в RAW обычно линейный значения. Т.е. вообще говоря можно сделать гамма-коррекцию в 8бит, и отдельно сжимать разницу между исходным и гамма-корректированным изображеним.
3 более хитрый вариант нежели в пункте два. Сначала сжимаем 8битное изображение обычным жопегом (гамма-корректированное или нет). Потом декодируем жопег, вычисляем разницу с исходным, ну и сжимаем эту разницу. В этом случае, детали фактически будут хериццо только при сжатии второго изорбражения, т.е. один источник искажений. Так что можно тоньше варьировать степень сжатия. Правда реализация довольно геморная. Впрочем, так как для сжатия жопега есть оптимизированные библиотеки, то вариант довольно интересный
4 использовать алгоритм для работы с 16ти битным цветом, типа того же жопег2000 или другой вариант. Этот вариант интерсен тем, что для быстрого декодирования картинок меньшего масштаба, все равно придется использовать вейвлетные преобразования.

Итого, надо:
1 бить изображение на тайлы
2 делать разные версии по разрешению, фактически вейвлеты в том или ином виде
3 делать декорреляцию байеровских каналов
4 решать проблему с 14ти битным цветом

Фактически, тут лучше всего подходят вейвлетные алгоритмы, ибо они это все и так делают. В идеале должен быть такой алгоритм (фактически жопег2000/PGF/ICER с вариациями):
1 считаем яркостный (усредненный) канал и три разностных, по той или иной схеме (лучше конечно обратимой и быстросчитаемой, т.е. коэффиценты степени двойки). На данном этапе у нас уже картинка половинного разрешения, ибо большее разрешение все равно получается интерполяцией (demosaicing).
2 разбиваем на тайлы
3 делаем вейвлетное преобразование, тут вобщем-то стандартный вариант - CDF 5/3, используемый в жопег2000 и PGF, ибо целочисленные коэффициенты, т.е. быстрее считать, а также обратимость (так как сжатие с потерями, то последнее некритично).
4 уменьшаем точность коэффициентов по той или иной схеме (лучше целочисленной опять-таки)
5 энтропийно сжимаем коэффициенты

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