Показать сообщение отдельно
Старый 30.07.2008, 15:10   #16
Polad
Кинооператор
Медаль пользователю. ЗОЛОТО Любитель
Аватар для Polad
Регистрация: 30.03.2007
Адрес: Тридевятое царство
Сообщения: 267
Репутация: 41
16. Компенсация движения

Оценка движения и его компенсация — сложный способ повышения качества обработки при понижении шума, деинтерлейсе, изменении частоты (а в кодировщиках в MPEG эта информация используется для повышения степени сжатия).
Рассмотрим случай проводки камеры (панорамирования) при съемке и ее влияние на динамическое понижение шума. При этом все объекты в соседних кадрах не совпадают по расположению, поэтому глупый алгоритм фильтрации (усреднения) даст призраки по всему кадру, а умный алгоритм будет вынужден уменьшить степень фильтрации также почти по всему кадру. Если мы сдвинули бы предыдущий кадр на величину перемещения камеры, то почти все объекты совпали бы, и эффективность понижения шума значительно увеличилась.
Такое глобальное движение (смещение, зум, вращение) позволяет оценить и компенсировать плагин DePan (разработчик "Fizick"), который включает функцию-сервер оценки движения DepanEstimate, производящую клип в специальном формате со вставленными в первые строки данными о движении, и несколько функций-клиентов, использующих эти данные для компенсации.
#Пример скрипта 16.1
# Шумоподавление с компенсацией глобального движения
LoadPlugin("Depan.dll")
LoadPlugin("DeGrainMedian.dll")
AviSource("test.avi")
AssumeTFF() # для аналогового чересстрочного видео
SeparateFields()
M=DepanEstimate(trust=3) # спецклип M с данными по движению
DepanInterleave(data=M, prev=1, next=1) # утроенное число кадров
DeGrainMedian() # некоторый шумопонижающий фильтр
Selectevery(3,1) # выделим из каждых трех один кадр
Weave()
В скрипте использована функция DePanInterleave, которая для каждого текущего кадра подает на выход тройку похожих кадров: скомпенсированный по движению вперед предыдущий, текущий и скомпенсированный по движению назад последующий. Совместно с последующей прореживающей командой SelectEvery, они образуют как бы скобки (обкладки), внутри которых пишем временной (пространственно-временной) фильтр. Отметим, что такая обработка не имеет смысла с чисто пространственными фильтрами, для них компенсация не нужна, их можно указать до утроения. Еще обратим внимание, что для некоторых временных фильтров, с большим временным радиусом (больше одного кадра), нужно соответственно увеличить число компенсированных кадров в группе (параметрами prev, next), и соответственно изменить параметры SelectEvery. В частности, при последовательном применении двух временных фильтров их радиусы складываются.
#Пример скрипта 16.2
# Шумоподавление двумя фильтрами
# с компенсацией глобального движения
LoadPlugin("Depan.dll")
LoadPlugin("DeGrainMedian.dll")
LoadPlugin("FFT3DFilter.dll")
AviSource("test.avi")
AssumeTFF() # для аналогового чересстрочного видео
SeparateFields()
M = DepanEstimate(trust=3)
# получен спецклип M с данными по движению
DepanInterleave(data=M, prev=2, next=2)
# упятеренное число кадров, временной радиус фильтров равен 2
DeGrainMedian() # некоторый временной фильтр
FFT3DFilter() # второй временной фильтр
Selectevery(5,2) # выделим из каждых пяти второй кадр с 0
Weave()
Способ обработки чересстрочного видео неоднозначен. Можно, например, выделить и отдельно анализировать и компенсировать четные и нечетные поля, но при этом увеличится временной интервал, то есть, уменьшится схожесть изображений. Пожалуй, наиболее правильным является использования разумного Боб-деинтерлейса, создающего полноформатный выход с соудвоением частоты и, хотя при этом уменьшится скорость обработки. Кстати, функции DePanEstimate и DepanInterleve имеют ряд параметров для тонкой настройки, в частности, скорость оценки движения можно повысить установкой параметра fftw (с использованием и внешней библиотеки FFTW3.DLL).
#Пример скрипта 16.3
# Шумоподавление с компенсацией глобального движения
# и Bob-деинтерлейсом
LoadPlugin("Depan.dll")
LoadPlugin("LeakKernelDeint.dll")
LoadPlugin("DeGrainMedian.dll")
AviSource("test.avi") # пусть аналоговое чересстрочное
LeakKernelBob(order=1) # для TFF
AssumeTFF() # LeakKernelBob не сохраняет доминантность полей
M=DepanEstimate(trust=3, fftw=true)
# спецклип M с данными по движению
DepanInterleave(data=M,prev=1,next=1)#утроенное число кадров
DeGrainMedian() # некоторый шумопонижающий фильтр
Selectevery(3,1) # выделим из каждых трех один кадр
SeparateFields()
selectevery(4,0,3)#выделяем исходные не интерполированные поля
weave()
В приведенном скрипте при отсутствии шумоподавителя исходный клип передается на выход неизменным, а два уровня "скобок" (внешний Bob и внутренний Depan) стремятся сделать соседей фильтруемого кадра (поля) как можно более на него похожими.
Еще одним использованием глобального движения является такая его частичная компенсация, при которой происходит снижение тряски кадра, как в аппаратных стабилизаторах видеокамер. Один из простых алгоритмов стабилизации реализован в функции DepanStabilize.
#Пример скрипта 16.4
# Стабилизация тряски
LoadPlugin("Depan.dll")
LoadPlugin("DeGrainMedian.dll")
AviSource("test.avi")
AssumeTFF() # для аналогового чересстрочного видео
SeparateFields()
M=DepanEstimate(trust=3) # спецклип M с данными по движению
DepanStabilize(data=M, cutoff=1, mirror=15) # cтабилизация
Weave()
DeGrainMedian(interlaced=true) # фильтрация после стабилизации
Некоторую стабилизацию можно реализовать также с помощью плагина Motion (разработчик "mg262"), возможно также использования известного плагина DeShaker (разработчик Gunnar Thalin) для VirtualDub, с которым DePan имеет общий формат лог-файлов.
При помощи частичной компенсации глобального движения также можно построить кадры, соответствующие промежуточным моментам времени, что можно использовать, например, для повышения частоты кадров старых любительских узкопленочных фильмов, съемки панорам становятся более плавными.
Однако компенсация глобального движения эффективна не всегда, а только если движение действительно в основном глобальное. Если движение объектов существенно разнится, то необходим анализ и компенсация локального движения, что реализовано в плагинах MVTools (разработчики "Manao", "Fizick") и Motion (разработчик "mg262"), которые ведут анализ поблочно. Плагин Motion высоко оптимизирован по скорости, но оценка движения более точна у плагина MVTools, который и будет описан в данной статье.
Использование компенсации локального движения для целей понижения шума аналогично рассмотренному использованию глобального движения. Для каждого блока в текущем кадре находится похожий на него блок в предыдущем, компенсацией пиксели ставятся на соответствующие места, и производится фильтрация. Впервые для AviSynth это было реализовано в известном плагине Dust (разработчик "Steady"), который был в свое время самым лучшим и медленным шумоподавителем. В плагине MVTools имеется встроенная функция понижения шума MVDenoise а также новая усовершенствованная MVDegrain2. Более универсальным (это не означает оптимальным) решением является независимая компенсация движения и использование с ним произвольного временного или пространственно-временного шумоподавителя.
#Пример скрипта 16.5
# Шумоподавление с компенсацией локального движения
LoadPlugin("MVTools.dll")
LoadPlugin("LeakKernelDeint.dll")
LoadPlugin("DeGrainMedian.dll")
AviSource("test.avi") # пусть аналоговое чересстрочное
LeakKernelBob(order=1) # Bob-деинтерлейс для TFF
AssumeTFF() # LeakKernelBob не сохраняет доминантность полей
Vf=MVAnalyse(isb=false, truemotion=true)
# спецклип Vf с векторами движения вперед
Vb=MVAnalyse(isb=true, truemotion=true)
# спецклип Vb с векторами движения назад
f=MVFlow(vectors=vf)
b= MVFlow(vectors=vb)
Interleave(f, last, b)
DeGrainMedian() # некоторый временной шумопонижающий фильтр
Selectevery(3,1) # выделим из каждых трех один кадр
SeparateFields()
selectevery(4,0,3) # выделяем исходные не интерполированные поля
weave()
Плагин MVTools имеет в составе ряд функций, в частности для создания маски движения MVMask, для изменения частоты кадров MVFlowFps и др. Описание и простые базовые примеры их использования хорошо описаны в документации. Рядом пользователей составлены и более сложные скрипты с использованием MVTools, в частности с большим числом компенсированных кадров для сильного понижения шума.
Стоит обратить внимание и на попытки реализовать компенсированный по движению деинтерлейс, из которых одной из наиболее удачных признана скриптовая функция MVBob (составитель "scharfis_brain"), приведенная в файле mvbob.avs (вместе со вспомогательными функциями) в прилагаемом архиве avs.zip.
Она использует упоминавшиеся выше плагины MVTools, MaskTools, TomsMoComp, LeakKernelDeint, Eedi2, Undot и RemoveGrain, и имеет следующие именованные параметры:
"blksize" — размер блоков (по умолчанию = 8)
"pel" — точность (по умолчанию =2, субпиксельная)
"th" — порог для коррекции ошибочной компенсации (по умолчанию = 8)
"ths" — порог для коррекции статичных областей (по умолчанию = 3)
"bobth" — порог деинтерлейса для клипа анализа движения (по умолчанию = 6)
"quick" — предварительный боб — быстрый (по умолчанию = false, то есть медленный Eedi2, иначе – Tomsbob)
MVBob по назначению реализует Боб-деинтерлейс, и может быть использована для организации "обычного" деинтерлейса просто выбором, например, только четных кадров (или только нечетных, или попеременно) из результата.
#Пример скрипта 16.6
# Качественный деинтерлейс с компенсацией движения
LoadPlugin("MVTools.dll")
LoadPlugin("MaskTools.dll")
LoadPlugin("TomsMoComp.dll")
LoadPlugin("LeakKernelDeint.dll")
LoadPlugin("EEDI2.dll")
LoadPlugin("Undot.dll")
LoadPlugin("RemoveGrainS.dll")
# В оригинальном файла mvbob.avs был вызов всех плагинов,
# мы их там закомментировали
Import("mvbob.avs")
AviSource("test.avi") # пусть аналоговое чересстрочное
AssumeTFF() # Измените для DV на AssumeBFF
ConvertToYV12(interlaced=true) # пока поддерживается YV12
MVBob() # Боб-деинтерлейс с параметрам по-умолчанию
SelectEven() # выбрали четные кадры (ведущее поле четное)
Другой известной аналогичной функцией является скрипт MCBob (составитель — "Didee"), использующий поблочную компенсацию MVCompensate и поэтому несколько менее медленный.
Отметим, что алгоритмы анализа и компенсация движения не совершенны (плагины и скрипты находятся в процессе разработки), и возможны некоторые артефакты. Ряд защитных мер их по предотвращению уменьшает и без того невысокую скорость обработки.
Самой сложной проблемой является не компенсация, а интерполяция движения, то есть восстановление (реконструкция) местоположения и формы движущихся объектов изображения в промежуточные времена между кадрами, например, для изменения частоты кадров, преобразования PAL-NTSC и т.п. (темы заслуживают особого рассмотрения и обсуждаются). Преобразование частоты проводится с прогрессивным видео, а для чересстрочного предварительно применяется деинтерлейс (типа Боб для видеокамеры или подбор полей и прореживания для фильмов), затем преобразование частоты с последующим выделением нужных полей и преобразованием видео в чересстрочное (при необходимости). Используемые в функции MVFlowFps (и в функциях-скриптах плагина Motion типа MotionProtectedFps) методы могут дать для многих видео-отрезков достаточно неплохие результаты, на уровне лучших коммерческих пакетов.
#Пример скрипта 16.7
# Удвоение частоты видео с компенсацией движения
LoadPlugin("MVTools.dll")
# предполагаем прогрессивный источник
source = AviSource("film.avi")
# обратные вектора движения
backward_vec = source.MVAnalyse(overlap=4, isb = true, idx=1)
# используем перекрытие блоков overlap для качества
# прямые вектора движения
forward_vec = source.MVAnalyse(overlap=4, isb = false, idx=1)
# удвоим частоту, удваивая ее числитель и не меняя знаменатель
source.MVFlowFps(backward_vec, forward_vec,
num=2*FramerateNumerator(source),
den=FramerateDenominator(source), idx=1)
Но в ряде случаев потребуется кропотливая работа по подбору параметров и составлению скрипта для борьбы с артефактами, с медленной обработкой и без гарантии получения приемлемых результатов для всех кадров ввиду ряда причин (заслонения объектов, наличия повторяющихся схожих элементов, вспышек, очень быстрых движений, изменения формы, ограничений и недостатков используемого метода). В таком случае можно использовать и более простые методы изменения частоты, аналогичные используемым подавляющим большинством монтажных программ и кодировщиков (или просто положиться на них). В частности, встроенная в AviSynth функция ConvertFps работает быстро и использует смешение (blend) соседних кадров с весом, пропорциональным близости кадра к рассчитываемому моменту времени. Рекомендуется, если это, возможно, не терять оригинальных кадров (полей) при преобразовании, то есть увеличивать частоту кратно, и, например, попробовать преобразовать фотоаппаратное 15 Гц видео в стандартный формат NTSC 30 Гц (точнее 29,97), а не в PAL 25 Гц. Есть и функция ChangeFps, реализующая метод дублирования кадров, что позволяет избежать их изменения, но за счет введения прерывистости движения. Стоит отметить и наличие функции AssumeFps, которая не меняет последовательность и число кадров, а просто заставляет AviSynth полагать, что частота равна новому заданному значению (удобно для малых изменений частоты захваченного видео типа 24,995, но может потребоваться подгонка звука). Может быть организовано и изменение частоты путем преобразования из прогрессивного в чересстрочное видео с повтором некоторых полей по определенному шаблону с использованием DoubleWeave, SelectEvery и Weave (фактически это промышленный стандартный метод Pulldown, используемый при записи фильмов в формате NTSC, и, кстати, может быть реализован прямой модификацией готового MPEG2 файла программой DGPullown без участия AviSynth).
Вы можете сами выбрать свой "яд" (плавность с возможными артефактами, смешение кадров или прерывистость).