На Хабре у меня уже было две статьи (1 и 2), обе они касались реализации быстрого сжатия изображений по алгоритму JPEG на CUDA. Теперь я бы хотел рассказать о другой, гораздо более масштабной задаче — как мы сделали конвертер и видео плеер для серий DNG изображений на CUDA. При этом мы получили очень высокую скорость работы, потому что вся обработка исходных данных в формате DNG теперь выполняется на видеокарте NVIDIA.


Исходное изображение в формате DNG взято с сайта blackmagicdesign.com

Несмотря на то, что в мире уже есть очень большое количество конвертеров RAW, которые работают с форматом DNG, мы решили сделать ещё один, но очень быстрый, который можно было бы использовать в том числе для отбраковки и сортировки. Видео плееры DNG тоже есть, но обычно они работают с уменьшенным разрешением, поэтому просмотреть только что отснятый в формате DNG материал на полном разрешении — это проблема. С помощью нашего конвертера мы сделали попытку обработать картинки настолько быстро, чтобы уметь просматривать серии DNG изображений в реальном времени и при полном разрешении. Естественно, что кроме скорости необходимо было получить приемлемое качество обработки и шумоподавления, и мне кажется, что нам это удалось.

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

Условие задачи: на достаточно быстром SSD лежит серия изображений в формате DNG (все кадры сжаты) с разрешением до 4К или 4.6К (например, как у последних моделей видеокамер URSA или URSA mini от компании BlackMagic Design) и нужно в реальном времени их прочитать, декодировать, сделать всю необходимую обработку и плавно вывести видео на монитор с заданной частотой в диапазоне 24-30 кадров в секунду на полном разрешении (без использования proxies, т.е. уменьшенных копий).

Мы довольно давно занимаемся разработкой алгоритмов и программного обеспечения для обработки изображений и видео на CUDA, поэтому в нашем распоряжении был собственный быстрый SDK, в котором мы реализовали весь необходимый функционал для работы с RAW данными от видеокамер. В итоге вся схема обработки изображений в настоящее время выглядит примерно следующим образом:

1. Многопоточное чтение DNG файлов с SSD
2. Парсинг DNG файлов, получение тайлов
3. Многопоточное декодирование DNG изображений
4. Пересылка декодированных изображений в видеокарту
5. Кроп для DNG
6. Линеаризация исходных данных, приведение их к 16 битам
7. Применение уровней белого и чёрного
8. Баланс белого
9. Экспокоррекция
10. Шумодав до дебайера
11. Дебайер (демозаик)
12. Шумодав после дебайера
13. Цветовые преобразования, температура и тинт
14. Кривые и уровни в RGB
15. Кривые и уровни в HSV
16. Кроп и ресайз (для заданного зума)
17. Резкость
18. Наложение профиля монитора и гаммы
19. Преобразование данных к 8 битам на канал
20. Копирование данных из памяти CUDA в текстуру OpenGL с последующим выводом на монитор после получения V-Sync
21. Вычисление и вывод на монитор гистограмм и парадов для каждого кадра

Как видно из описания, внутренний формат представления данных — 16 бит на канал. Это не так плохо, как может показаться на первый взгляд. Все участки кода, где очень важна точность, считаются во float (шумодав, ресайз, шарп), а финальный результат обработки каждой стадии сохраняется в 16 битах. Многие дебайеры представляют из себя целочисленные алгоритмы, поэтому для них 16 бит в самый раз, но некоторые стадии всё равно приходится делать во float. Также иногда мы объединяем соседние стадии обработки, например, баланс белого и экспокоррекцию, что уменьшает количество промежуточных округлений. Мы визуально сравнивали результаты с 32-битной реализацией и существенной разницы не обнаружили. Нам кажется, что это вызвано относительно небольшим количеством промежуточных стадий обработки в нашем софте.

Несколько слов хотелось бы сказать и о дебайерах, т. е. об алгоритмах демозаики. Очень часто в конвертерах для уменьшения времени вычислений используют билинейный алгоритм или его аналоги, ведь это один из самых быстрых вариантов. Действительно, на CPU это так, но если посмотреть на качество восстановленной картинки с точки зрения пикового отношения сигнал-шум (PSNR), то для стандартного набора изображений Кодака, используемого для тестирования дебайеров, у билинейного алгоритма получается менее 31 дБ. Алгоритмы дебайеров HQLI и DFPD из нашей программы дают 36 дБ и 39 дБ на этом же наборе кадров. Поскольку производительность дебайера на GPU во много раз выше, чем на CPU, то нет необходимости в билинейном дебайере и можно использовать более качественные алгоритмы. Когда мы делали кодек JPEG на видеокарте, мы измеряли PSNR в зависимости от коэффициента качества для разных дебайеров и получили интересный результат: низкий PSNR финальной картинки определяется именно билинейным дебайером, а не артефактами джипега при качестве не менее 75%. Резюме простое: если требуется качество, то билинейный дебайер лучше не использовать. Понятно, что метрика PSNR (как SSIM и остальные) достаточно условна, но это объективный критерий, который работает в большинстве случаев, хоть и не всегда.

Мы в ближайшее время должны завершить разработку нового алгоритма дебайера для GPU, который даёт PSNR 40.7 дБ на наборе Кодака. Версия на CPU уже готова и тестовое приложение с командной строкой лежит в открытом доступе. С его помощью можно протестировать все наши алгоритмы дебайеров и сравнить их.

Новый алгоритм дебайера называется MG (multiple gradients), он сделан нами, в других RAW конвертерах его нет.

Реализация такой общей схемы обработки для 10/12/14-битных исходных данных в формате DNG в реальном времени с частотой кадров в диапазоне 24-30 к/с для разрешений от 2К до 4К, требует тщательной оптимизации каждого алгоритма. При этом необходимо добиться максимально возможной скорости работы SSD, CPU и GPU. Если производительность одного из этих трёх компонент железа будет недостаточной, то реального времени не получится. Для разрешений 4К-4.6К мы достигли скорости обработки быстрее реального времени при использовании видеокарт NVIDIA GeForce GTX 980 и 1080.

На хорошем железе наш плеер DNG работает плавно, изображение можно масштабировать на весь экран. Аппаратный ресайз в OpenGL отключен, потому что в нём по умолчанию стоит билинейный алгоритм ресайза, который даёт значительные артефакты, особенно при уменьшении. Для решения этой проблемы мы всегда делаем ресайз на CUDA по алгоритму Ланцоша и передаём в OpenGL уже готовую картинку, размеры которой совпадают с размером окна. При этом мы получаем дополнительную задержку по времени, но качество картинки улучшается.

image
Изображение в формате DNG взято с этого сайта, оператор Джо Броули, тестовые снимки BlackMagic Ursa Mini 4.6K.

Для сохранения результатов в произвольный контейнер, можно использовать внешний FFmpeg, который пользователь должен установить самостоятельно, и его можно запустить из нашей программы с заданной командной строкой. Таким образом, например, с помощью внешнего FFmpeg можно сжать выходные данные в 10-битный 444 ProRes и сохранить их в контейнер MOV. Без помощи FFmpeg программа сама может сохранять обработанные кадры в виде серии 16-битных изображений в формате TIFF или 8/12-битных JPEG, а цветовой профиль встраивается в заголовок каждого кадра.

Таким же образом можно обрабатывать и фотографии. Но поскольку в фото есть очень много разных закрытых форматов, то для полноценной работы нужно будет подключить libraw, а пока есть только варианты с предварительной конвертацией исходных данных в DNG с помощью Adobe DNG Converter. Наша программа изначально не была ориентирована на фото, поэтому многих важных фич не хватает. В нашем SDK, на базе которого сделан софт, часть нужного функционала уже реализована, так что, возможно, быстрый конвертер для фото мы тоже сделаем. В этом случае пакетная обработка фотографий должна получиться очень быстрой, ведь и в джипег мы сжимаем на видеокарте. На хорошей карточке время обработки одной 50-МПикс картинки получается меньше, чем время загрузки изображения с SSD. Но для работы с такими большими файлами нужен GPU с памятью не менее 8 ГБайт.

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

Мы знаем о существовании Adobe Premiere Pro 2015, BlackMagic DaVinci Resolve 12 и о многих других универсальных профессиональных решениях из этой области, в том числе и на видеокартах. Нашей задачей было не создание конкурента программам для файл-менеджмента, нелинейного монтажа, грейдинга и компрессии с помощью монтажных кодеков — в этих областях существующие решения и так неплохо справляются с имеющимися задачами, хотя и тут есть простор для ускорения и улучшения. Мы сделали решение для очень быстрой и достаточно качественной обработки данных на видеокарте и пользователи могут оценить, что у нас получилось.

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

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

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

Перспективным вариантом для развития этого направления является создание плагинов к Adobe Premiere Pro и After Effects. В этом случае можно будет совместить нашу скорость и качество обработки с возможностью сохранения результатов с помощью разнообразных монтажных кодеков без использования FFmpeg. Такие плагины можно будет использовать и вместо монтажного кодека, чтобы в реальном времени делать из DNG готовые обработанные кадры с разрешением 16 бит на канал и передавать их напрямую в After Effects, тогда стадия декодирования из ProRes не потребуется.

Мы также работаем над ещё одним интересным аспектом этого проекта — делаем быстрый кодек JPEG2000 на видеокарте, чтобы использовать его в качестве монтажного кодека. Такой кодек сможет работать с 16-битными данными в реальном времени, что обеспечит более высокое качество по сравнению с другими монтажными кодеками. Даже сжатие 10/12-битных данных может быть сделано с лучшим качеством, чем это делается сейчас. Такой кодек JPEG2000 сможет работать в реальном времени и даст более высокое качество по сравнению с широко используемыми ProRes, DNxHD, DNxHR. В настоящее время такой кодек JPEG2000 на CPU уже есть в составе Adobe Premiere Pro, но он очень медленный, поэтому в практическом плане от него пользы мало. Быстрый кодек JPEG2000 всё кардинально изменит и позволит улучшить качество промежуточных материалов для последующего монтажа.

Мы продолжаем работу над улучшением качества обработки изображений, и в ближайшее время ожидается релиз нового дебайера MG, который должен быть не хуже, чем у Adobe Camera Raw (с нашей точки зрения дебайер из ACR очень хорош). А наш дебайер DFPD в текущем релизе явно лучше, чем у Adobe Premiere Pro 2015. В нашей бесплатной версии есть шумодавы до дебайера и после дебайера, но этого нет в бесплатной версии DaVinci Resolve, а у Premiere Pro собственного шумодава в реальном времени нет даже в платной версии. У каждой программы есть свои плюсы и минусы, так что сравнивать можно много и долго, но в итоге всё равно каждый находит для себя инструмент, отвечающий собственным потребностям и задачам.

Бесплатную демо-версию программы для Windows-7/8/10 (64 бит) можно загрузить отсюда, а тестовую серию CinemaDNG изображений можно взять здесь. Также программа может работать с видео от Canon 5D Mark III с альтернативной прошивкой Magic Lantern после конвертации MLV в DNG.

Буду признателен за замечания по качеству и скорости представленного решения. Ещё раз хочу напомнить, что программа работает только с видеокартами NVIDIA, причём для работы с 4К изображениями формата DNG желательно иметь не менее 2 ГБайт памяти на GPU. К сожалению, на видеокартах AMD и Intel программа работать не будет. И если почти вся память видеокарты NVIDIA занята другими приложениями, то тоже увы. Для достижения высокой скорости обработки нужны быстрые SSD, CPU и GPU.
Поделиться с друзьями
-->

Комментарии (11)


  1. AndreyDmitriev
    04.08.2016 22:35

    Быстрый J2K кодек — это интересно. Любопытно, какую производительность вы ожидаете получить? У меня вот уже довольно давно висит задачка по сжатию потока шестнадцатибитных картинок. Грубо говоря есть самодельная железка (PCI плата), которая подгоняет нам видео в виде потока картинок (технически на каждый фрейм вызывается callback с указателем на буфер), в настоящий момент до 96 MB в секунду (4096x4096/16 bit/3 FPS, либо 1024x1024/16 bit@30FPS — это стало быть 60 мегабайт в секунду). Требуется сжимать это видео с настраиваемой потерей качества и писать в контейнер, который затем можно будет воспроизводить самописным плейером (ну и в плеере само собой зуммирование, останов, интерактивный маппинг 16 бит на 8, либо на 10 бит если монитор поддерживает и т.д.). Вот как бы вы подошли к решению этой задачки (в той перспективе, что железка PCI скоро заменится на PCIe и скорость возрастёт до 320 MB/s)?


    1. fyodorser
      04.08.2016 23:03

      Мы тоже считаем, что это очень интересно, хотя скорость на порядок ниже, чем у обычного JPEG. В настоящее время для 24-битных картинок 4К для кодоблока 32х32 и при сжатии в JPEG2000 в 12 раз получена производительность кодирования 1200 МБайт/с на видеокарте GeForce GTX 1080. По запросу в гугле «jpeg2000 benchmarks gpu» можете найти наши графики и таблицы с более подробной информацией по бенчмаркам. К сожалению, декодер JPEG2000 пока не готов. Для решения задач такого типа у нас есть SDK для CUDA, в котором все упомянутые функции есть, в том числе зум (ресайз), луты для маппинга и пр. Статья как раз про решение на базе этого SDK.


  1. VaalKIA
    04.08.2016 23:43

    Для решения этой проблемы мы всегда делаем ресайз на CUDA по алгоритму Ланцоша

    Можно подробней, в инете сразу начинают грузить: «разреженные матрицы… бла-бла… методы итерирования подпространств»…
    Почему от АМД отказались? Там же и единая память Mantle и теперь уже SSD прикрутили и по производительности всё довольно неплохо.


    1. fyodorser
      05.08.2016 00:10

      Алгоритм Ланцоша даёт более высокое качество ресайза. Визуально гораздо лучше, чем используемый по умолчанию в OpenGL билинейный алгоритм. Все формулы есть в вики.
      Мы не отказывались от AMD, мы работаем с видеокартами NVIDIA. А единая память — это проблема для быстрых приложений, потому что при выходе за пределы памяти GPU получаем сильное падение производительности. Карточки у AMD быстрые. Жаль, что нельзя взять и перенести код из CUDA в OpenCL. Можно лишь заново всё переписать, практически с нуля.


      1. Paul_Nice
        05.08.2016 00:57

        Подскажите, а слой совместимости пригоден для облегчения этих задач?
        https://github.com/GPUOpen-ProfessionalCompute-Tools/HIP
        За статью спасибо.


        1. fyodorser
          05.08.2016 12:55

          Проблема в том, чтобы не просто код запустить на другом GPU. Основная задача — как это сделать оптимально. Для несложных алгоритмов это может быть просто, а для алгоритмов типа нашего дебайера, вейвлетного шумодава или кодека JPEG это, по всей видимости, невозможно.
          Например, у NVIDIA и AMD разные по длине вектора. У NVIDIA это warp и он состоит из 32 элементов, а у AMD это wavefront и он состоит из 64 элементов. Это базовое отличие, которое приводит к серьёзным модификациям алгоритмов. Кроме того есть и другие отличия в микроархитектурах (размер разделяемой памяти, количество регистров и т.д.), поэтому сильно оптимизированные алгоритмы, использующие все особенности архитектуры, просто не смогут работать, так что их придётся сильно модифицировать.


  1. fyodorser
    05.08.2016 00:32

    Спасибо за тесты и за комментарии. Действительно, пока при просмотре из Проводника приходится открывать и закрывать приложение, но это поправим в следующей версии. Для сравнения, насколько мы знаем, ни Премьер, ни Давинчи так работать не могут, а это их большой минус при решении задачи по сортировке и отбраковке снятого материала.
    Что касается размещения окон для отдельных модулей, то все они настраиваемые, поэтому можно их разместить разными способами. По умолчанию предлагается наш вариант, но он не является обязательным.
    Работа по разработке идёт, через пару месяцев будут новые модули и улучшенный интерфейс. Спасибо за замечания.
    Мы рассматриваем возможность поддержки формата MLV из Magic Lantern. Возможно, в этом году это решение уже будет готово.
    Про опечатки в написании английских слов пожалуйста напишите сюда или в личку.


  1. Arkkotangens
    05.08.2016 00:32

    Это очень круто. Аналоги для просмотра dng есть, но если эта программа станет плагином к премьеру или афтеру, она может стать вполне востребованной. Пока что работать с raw материалами с третьего марка не особо удобно. Если честно, не знаю, как обычно просматривают материалы владельцы Blackmagic, запускают ли резолв каждый раз, когда надо просто проверить материалы.
    Дебайер ACR действительно крайне хорош и немного выигрывает у резолва, но для риалтайма приходится прогружать таймлайн, а это весьма долго.

    Беглый тест — 120-140 fps на 980 Ti (Full HD cdng 16 bit с третьего марка), жесткий диск HGST HUH728060ALE604, примерно 200 МБ/с на чтение.

    Выбитые хайлайтсы становятся розовыми. При снижении white level до 32к этот эффект исчезает. (оказалось, не везде)
    Такое раньше было с некоторыми программами для дебайера материалов третьего марка, со временем как-то вылечили.

    Возможно, не разобрался, но импорт материалов пока что достаточно неудобный. Если загружать папку через контекстное меню в проводнике, открывается новая версия программы, а не добавляется запись в существующую.
    Идеальным был бы вариант drag-n-drop'а папки через проводник напрямую в окно project, чтобы для каждого клипа в рамках одного проекта была отдельная строка.

    Добавление всех DNG из папки при создании нового проекта почему-то не сработало.

    Не очень понятно, почему вкладки Places и File System разделены, если работают в связке — то, что выбрано в Places, появляется в File System. Причем по умолчанию они были отключены при первом запуске. Возможно, лучше убрать иные, более продвинутые опции обработки или метаданных, а вот их оставить, так как загрузка и просмотр материалов все-таки на первом месте.

    Из File System хотелось бы более простой импорт папок с их конвертацией в клипы, как это работает в резолве. Пока что приходится выделять все файлы и добавлять их вручную. Ну и огромное количество отдельных файлов в одной папке крайне неудобно. Так как программа все-таки нацелена на видеофайлы, а не на фото, то нужды в списке отдельных кадров нет. Ну и конечно же система работы с таймлайном в данном случае опять же весьма неудобна, так как все файлы при добавлении, скажем, at end, превращаются в одну большую колбасу, где приходится вручную искать начало и конец каждого файла.

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

    Попробуйте насытить интерфейс теми решениями, которые облегчают работу с мониторингом материалов. Например, при двойном нажатии левой кнопки мыши на картинку она устанавливается на масштаб в 100%, а при следующем двойном нажатии возвращается на пользовательское значение — часто приходится мониторить реальную картинку на предмет шума или banding. Аналогичное решение есть в программе mocha, только через хоткеи.

    Достаточно много опечаток в написании английских слов.

    Свяжитесь с ребятами из Magic Lantern, если еще не сделали это, конечно. Они всегда запускают публичные обсуждения и тестирование.
    Спасибо!


    1. fyodorser
      05.08.2016 12:59

      Ответ написал чуть выше.


  1. DrummerZi
    05.08.2016 16:59

    Здравствуйте, я пока не очень разобрался с этой программой, почему то у меня 4к рав от бм4к 9фпс показывает, как и в давинчи, разницы не заметил.видеокарта у меня gtx 680 4gb, двух процессорный по 2 гб… и описании увидел, что можно делать кроп, я так и не нашел эту функцию… и было бы супер.если бы создали группу вконтакте, там удобнее было бы следить за новостями… спасибо.


  1. fyodorser
    05.08.2016 17:08

    Чтобы получить 25 к/с на 4К, нужны быстрые SSD, CPU, GPU. Значение 9 фпс может быть из-за того, что это HDD, хотя скорости карточки 680 можеть не хватать. Пожалуйста попробуйте быстрый SSD, если это возможно. Или пришлите пару кадров DNG, мы посмотрим в чём может быть дело. Функции ресайза и кропа на GPU есть, но они пока не выведены наружу, скоро это будет.
    Группа вконтакте есть — vk.com/fastcinemadng