Acelerar o vídeo com quadros de mesclagem compostos (com média de // "motion blur")?

2

Basicamente, quero acelerar um vídeo (normalmente algumas coisas baseadas em matemática, como Exemplo de bolas saltantes no processamento com código-fonte - YouTube ); no entanto, eu não quero apenas descartar quadros, mas ao invés disso eu quero "mesclar" (por falta de termo melhor) quadros, como mostrado no diagrama:

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

Em outras palavras: se eu quiser acelerar o vídeo 5 vezes, em vez de apenas "dizimar" tirando cada 5º frame (então o Frame original 01 é então seguido pelo Frame 06 no novo fluxo de saída), eu gostaria novo quadro (no novo fluxo de saída) para ser uma "soma" dos quadros de 01 a 05:

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

Como o intervalo de cores é limitado, eu precisaria de uma constante k para controlar valores de cores: digamos que trabalhamos com pixels RGBA, com intervalos de 0,0 a 1,0; então, se na posição x, y de cada Quadro01-Quadro05 original estiver totalmente vermelho (1,0,0,1), eu teria que multiplicar o alfa de cada pixel de entrada por 1/5 = 0,2, para garantir o pixel de saída (a soma) também está totalmente vermelha (1,0,0,1) sem ultrapassar a faixa de cores; grosso modo:

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))

(Alternativamente, assumindo pixels RGB sem alfa, teríamos que multiplicar cada um dos canais RGB por 0,2)

Se tivermos um vídeo matemático como o exemplo da bola quicando, onde não há nenhum borrão de movimento natural, eu acho que isso resultaria em um "borrão de movimento" (ou seja, em vez de uma bola por quadro, eu teria cinco bolas em um quadro, traçando o movimento).

Eu acho que eu poderia fazer isso extraindo os quadros como imagens, e ter meu próprio código personalizado gerando novos quadros, e finalmente fazer um novo vídeo de saída dos novos quadros - mas como isso pode me levar "para sempre", queria saber: talvez ffmpeg (ou outras ferramentas de código aberto) façam isso em um "one-liner"?

    
por sdaau 17.04.2017 / 09:14

1 resposta

0

Enquanto o link do link @Mulvya realmente responde à pergunta com ffmpeg :

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

... observe que ( link ):

The tblend (time blend) filter takes two consecutive frames from one single stream, and outputs the result obtained by blending the new frame on top of the old frame.

Então, apenas combina dois quadros, o que significa que para mesclar quatro quadros, você precisa repetir tblend=average,framestep=2 duas vezes, como no exemplo acima.

Mas, quero misturar 700 imagens de quadro de entrada por imagem de quadro de saída (e duvido que tblend=average,framestep=2 repetido 350+ vezes seja analisado corretamente por ffmpeg ). Então, decidi primeiro descompactar os quadros e depois fazer meu próprio processamento usando Python. Para desempacotar:

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

... e então eu uso este script python com python blendManyImages.py ; já que ter cada imagem com o mesmo peso na mesclagem não resultou nos recursos de imagem necessários, esse script usa uma fórmula que dá maior peso às imagens anteriores no fluxo:

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

E, assim que a sequência de imagens do quadro de saída é calculada, pode-se fazer um vídeo, usando novamente ffmpeg :

ffmpeg -framerate 60 -i outfrs/img-%02d.png output.mp4
    
por 17.04.2017 / 13:05