Beschleunigen Sie das Video mit zusammengesetzten zusammengesetzten Bildern (Mittelwert // "Bewegungsunschärfe")?

844
sdaau

Grundsätzlich möchte ich ein Video beschleunigen (in der Regel einige mathematische Dinge wie Bouncing Balls, beispielsweise bei der Verarbeitung mit Quellcode - YouTube ). Ich möchte jedoch nicht nur Frames löschen, sondern stattdessen Frames "zusammenführen" (wie in der Abbildung gezeigt):

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

Mit anderen Worten: Wenn ich das Video fünfmal beschleunigen möchte, anstatt nur jeden fünften Frame zu "dezimieren" (also das ursprüngliche Frame 01 folgt dann Frame 06 im neuen Ausgabestrom), möchte ich das neue Frame ( im neuen Ausgabestrom) eine "Summe" der Frames von 01 bis 05 sein:

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

Da der Farbbereich begrenzt ist, würde ich eine konstante k benötigen, um die Farbwerte zu steuern: Wir arbeiten beispielsweise mit RGBA-Pixeln mit Bereichen von 0,0 bis 1,0; Wenn dann an Position x, y jedes Original-Frame01-Frame05 voll rot (1,0,0,1) ist, müsste ich das Alpha jedes Eingangspixels mit 1/5 = 0,2 multiplizieren, um das Ausgangspixel sicherzustellen (die Summe) ist auch voll rot (1,0,0,1), ohne den Farbbereich zu überschreiten; grob gesagt:

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

(Wenn Sie jedoch RGB-Pixel ohne Alpha annehmen, müssen Sie jeden RGB-Kanal mit 0,2 multiplizieren.)

Wenn wir ein mathematisches Video wie das springende Ball-Beispiel haben, in dem es keine natürliche Bewegungsunschärfe gibt, würde dies zu einer Art "Bewegungsunschärfe" führen (dh anstatt einer Kugel pro Frame hätte ich fünf Kugeln auf einer Rahmen, die Bewegung nachzeichnen).

Ich schätze, ich könnte dies durch Extrahieren der Frames als Bilder machen, und meinen eigenen benutzerdefinierten Code zum Erzeugen neuer Frames und schließlich zum Erstellen eines neuen Ausgabevideos aus den neuen Frames verwenden. Da dies mich jedoch "für immer" in Anspruch nehmen kann, habe ich mich gefragt: können dies ffmpeg(oder andere Open-Source-Tools) dies in einem "Einzeiler" tun?

2
Siehe https://video.stackexchange.com/q/16552/1871 Gyan vor 7 Jahren 1

1 Antwort auf die Frage

0
sdaau

Der Link von @Mulvya https://video.stackexchange.com/q/16552/1871 beantwortet zwar die Frage mit ffmpeg:

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

... beachten Sie, dass ( https://ffmpeg.org/ffmpeg-filters.html ):

Das Tblend-Filter (Zeitmischfilter) entnimmt zwei aufeinanderfolgende Frames aus einem einzigen Stream und gibt das Ergebnis aus, das durch Mischen des neuen Frames über dem alten Frame erhalten wird.

Es werden also nur zwei Frames miteinander gemischt, was bedeutet, dass Sie zum Mischen von vier Frames tblend=average,framestep=2wie im obigen Beispiel zweimal wiederholen müssen .

Aber ich möchte 700 Bilder pro Bild pro Frame tblend=average,framestep=2kombinieren (und ich bezweifle, dass mehr als 350 Mal ein korrektes Parsing durchgeführt wird ffmpeg). Also entschloss ich mich, zuerst die Frames zu entpacken und dann meine eigene Verarbeitung mit Python durchzuführen. Auspacken:

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

... und dann benutze ich dieses Python-Skript mit python blendManyImages.py; Da jedes Bild mit gleichem Gewicht in der Überblendung nicht zu den gewünschten Bildmerkmalen führt, verwenden diese Skripts eine Formel, die Bildern früher im Stream mehr Gewicht verleiht:

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 

Sobald diese Ausgangsbildsequenz berechnet ist, können Sie daraus ein Video erstellen, das wiederum Folgendes verwendet ffmpeg:

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