Ускорение видео с помощью составных кадров слияния (усреднение // «размытие в движении»)?

806
sdaau

По сути, я хочу ускорить видео (обычно некоторые математические вещи, такие как пример «Прыгающих шаров» при обработке с исходным кодом - YouTube ); однако я не хочу просто отбрасывать кадры, а вместо этого хочу «объединить» (из-за отсутствия лучшего термина) кадры, как показано на диаграмме:

+----------+----------+----------+----------+----------+----------+ | Frame 01 | Frame 02 | Frame 03 | Frame 04 | Frame 05 | Frame 06 | +---+------+-----+----+----+-----+-----+----+-----+----+----------+ | | | | | | +---+ | | | | | | +<--+ | | | +--->+ + +<------------+ | | | +<------------------------+ | ++--+<-----------------------------------+ | +-----v-----+ | NFrame 01 | +-----------+ 

Другими словами: если я хочу ускорить видео в 5 раз, вместо того, чтобы просто «прореживать», беря каждый 5-й кадр (так, чтобы за первым кадром 01 следовал кадр 06 в новом выходном потоке), я бы хотел новый кадр ( в новом выходном потоке) быть «суммой» кадров от 01 до 05:

NFrame01 = k*(Frame01 + Frame02 + Frame03 + Frame04 + Frame05) 

Поскольку цветовой диапазон ограничен, мне понадобится постоянная k для управления значениями цвета: скажем, мы работаем с пикселями RGBA, с диапазонами от 0,0 до 1,0; затем, если в позиции x, y каждого оригинального Frame01-Frame05 полностью красного цвета (1,0,0,1), мне пришлось бы умножить альфа каждого входного пикселя на 1/5 = 0,2, чтобы обеспечить выходной пиксель (сумма) также полностью красный (1,0,0,1), не переходя цветовой диапазон; грубо говоря:

NFrame01(x,y) = [1.0, 1.0, 1.0, 0.2]*(Frame01(x,y) + Frame02(x,y) + Frame03(x,y) + Frame04(x,y) + Frame05(x,y)) 

(С другой стороны, предполагая, что пиксели RGB не имеют альфа-канала, нам нужно умножить каждый из каналов RGB на 0,2)

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

Я думаю, что я мог бы сделать это, извлекая кадры в виде изображений, и иметь свой собственный код, генерировать новые кадры и, наконец, создавать новое выходное видео из новых кадров - но так как это может занять у меня «навсегда», мне было интересно: Может быть ffmpeg(или другие инструменты с открытым исходным кодом) сделать это в "одну строку"?

2
См. Https://video.stackexchange.com/q/16552/1871. Gyan 7 лет назад 1

1 ответ на вопрос

0
sdaau

Хотя ссылка на @Mulvya https://video.stackexchange.com/q/16552/1871 действительно отвечает на вопрос ffmpeg:

ffmpeg -i input \ -vf "tblend=average,framestep=2,tblend=average,framestep=2,setpts=0.25*PTS" \ -r srcfps - output 

... обратите внимание, что ( https://ffmpeg.org/ffmpeg-filters.html ):

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

Таким образом, он смешивает только два кадра, что означает, что для смешивания четырех кадров вы должны повторить tblend=average,framestep=2дважды, как в примере выше.

Но я хочу смешать 700 изображений входного кадра на каждое изображение выходного кадра (и я сомневаюсь, что tblend=average,framestep=2повторные 350+ раз будут правильно проанализированы ffmpeg). Поэтому я решил сначала распаковать кадры, а затем выполнить собственную обработку с использованием Python. Распаковать:

mkdir ofrs # original frames mkdir outfrs # out frames ffmpeg -i myvideo.mp4 ofrs/img-%05d.png 

... а потом я использую этот скрипт Python с python blendManyImages.py ; поскольку наличие в изображении каждого изображения с равным весом не дает нужных мне функций изображения, в этих сценариях используется формула, которая придает больший вес изображениям, находящимся ранее в потоке:

python blendManyImages.py:

# http://stackoverflow.com/questions/25102461/python-rgb-matrix-of-an-image # http://stackoverflow.com/questions/40810716/how-to-get-a-list-of-float-rgba-pixels-values-using-pillow   from PIL import Image import numpy import math  # open an image, to get the data size: im = Image.open('ofrs/img-00001.png') #~ data = numpy.asarray(im) data = numpy.array(im) # same as .asarray print("Array dimensions: %s"%(repr(data.shape))) data = data.astype(float) print("[20, 30]=%s"%(repr(data[20, 30]))) #~ print(data) #[[[240. 240. 240.] # [240. 240. 240.] ... #~ data = numpy.divide(data, 255.0) #[[[ 0.94117647 0.94117647 0.94117647] # [ 0.94117647 0.94117647 0.94117647] ... # erase data: data.fill(0) #~ print(data)  inputframes = 44100 outptframes = 60 decimate = inputframes/outptframes # 735 k = 1.0/decimate # 0.001360 print(decimate, k) i = 1 # input frame counter o = 1 # output frame counter while i <= 44100: data.fill(0) for dcnt in xrange(0, decimate): ifname = "ofrs/img-%05d.png"%(i) #print(ifname) tdata = numpy.divide(numpy.array(Image.open(ifname)).astype(float), 255.0) # manually tuned formula: give more weight to earlier frames data += numpy.multiply(tdata, k*70*pow(math.e,-0.05*dcnt)) i = i+1 # data should be done here; save ofname = "outfrs/img-%02d.png"%(o) print(ofname) oim = Image.fromarray(numpy.multiply(data, 255).astype('uint8')).convert('RGB') oim.save(ofname) o = o+1 

И как только эта последовательность изображений выходного кадра будет вычислена, можно сделать из нее видео, снова используя ffmpeg:

ffmpeg -framerate 60 -i outfrs/img-%02d.png output.mp4 

Похожие вопросы