3

По сути, я хочу ускорить видео (обычно некоторые математические вещи, такие как пример "Прыгающих шаров" при обработке с исходным кодом - 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 (или другие инструменты с открытым исходным кодом) сделать это в "одну строку"?

1 ответ1

0

Хотя ссылка с @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 -{encoding parameters} output

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

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

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

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

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

... а затем я использую этот скрипт на 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

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .