Each example video is a concatenation of 2 copies of certain frame sequence, so that the «seam», or «rapture», is exactly at the middle of the time scale. Original videos were taken from videos.pexels.com.

Before

After

Now, let's try it on video with almost no initial periodicity and with high range of colours.

Before

After

Approach

Given a channel (R, G, B) of a pixel, its values at consequent frames of the sequence make the function, also called a signal, f(t), which is approximated by the partial sum of its Fourier series

f(t) = a0/2 + ∑k=1n [ akcos(kt) + bksin(kt) ]

where the time t = tj = 2πj/SignalLength belongs to the [0; 2π) interval and, as well as the signal f(t), is discrete. As usual, n = SignalLength/2 and SignalLength = 2r. Using the well-known Direct/Inverse Fast Fourier Transform, we switch between the signal and its spectrum, consisting of ak and bk coefficients. Then we nullify or reduce some of them, in particular those corresponding to the high frequencies, to decrease the «leap» of f(t) at 0, which causes the «seam» of the looped video.

Filtering the spectrum of the time series of pixel values is a well-known approach to video processing and transformation, see e.g. [Fuchs2010]. It is also used to amplify subtle motions, which are hard to perceive by the naked eye, see [Wu2012], [Wadhwa2013].

Speaking of looping, we consider this approach to be «intermediate» in quality and simplicity between the classic «cut video in 2 halves and append the 1st one to the 2nd one with small crossfaded overlap» and more sophisticated methods like [Liao2013], [Liao2015], [Tralie2018].

The advantage of this approach becomes its disadvantage from the other point of view. The classic method produces the video where the time interval with overlap may be distinguishable from the rest of the video, because visual perception tends to separate two «layers» being crossfaded. In constrast, the spectrum cut transformation affects the whole video, and makes it harder to recognize the moment when the period ends. However, as you can see in the examples above, this transformation introduces blurring, echo of some moving objects, and loss of «high frequency» details, making the video more static in comparison to the original one.

Usage

Run FVL binary without any options to get the most essential parts of what is given below.

FVL works with the frame images in lossless .png format, not with the video files (.mp4, .avi etc.) Therefore you need first to extract the frames from the video, and then make the video from the transformed frames. For this purpose use e.g. ffmpeg. From ffmpeg's manual:

/path/to/in dir contains input images: 000001.png, 000002.png, etc. Their number must be a power of 2.

/path/to/out dir will contain output images with the same enumeration.

--tile (or -t) option specifies tile size: the frame rectangle in processed tile by tile of no bigger than this size, to reduce memory consumption.

--cut (or -c) is followed by cutting method and its parameter. Possible arguments are described further.

--[no]delin (or -[n]dl) switches delinearization (see further).

Input and output paths are mandatory, the rest of the options may be omitted, in which case they are set to defaults: --tile 256 --cut acmax 1.5 --delin.

Spectrum cut methods

All methods can be preceded by delinearization, which is subtracting the linear component K × t from the signal. K is estimated as in linear regression. This should improve the result e.g. when the pixels are becoming increasingly brighter/darker throughout the sequence. To [not] delinearize, provide --[no]delin option.

• dzhigh: start from HighestFrequency and nullify until |Derivative at 0| < p

• dzacmax: use minimal power s such that |Derivative at 0| < p after acmax-transform with p ← s

Don't hesitate, grab the source from Download and add more efficient cut methods you are presumably aware of (see spectrumcut.go). For instance, make the cutting more synchronous for 3 pixel channels.

Examples

$ ./fvl ~/test/in ~/test/out -t 408 -c acmax 1.5 -dl

$ ./fvl ~/test/in ~/test/out -t 408 -c dzhigh 20 -dl

$ ./fvl ~/test/in ~/test/out -t 320 -c up 0.6 -ndl

Limitations

Probably the most annoying limitation of the current implementation is that the number of frames must be an exact power of 2, e.g. 128, 256, 512.

Commonly for the «periodicity amplification» algorithms aimed at structure preservation, it is not enough to have just something to amplify in the first place. The input frame sequence should be periodic enough, on its own, where the periodicity needs to be; otherwise, as the 2nd example above implies, the structure may be lost. Typical examples are water streams/waves/ripples, swaying of leaves and branches of trees, and other kinds of small oscillations.

See Videos for more examples, revealing other limitations. In general, you have to find the equilibrium between retaining too noticeable seam and losing too many motion details.

The amount of memory consumed by the running instance of FVL in bytes should be approximately

Memory = TileWidth × TileHeight × Channels × NumberOfFrames

but it can occupy 2–3 times more than that due to the supplemental data structures and the behaviour of garbage collector.

All stages of the process are parallelized, thus the more CPU cores you have, the faster it comes to an end. Just beware of overheat to make sure that «it» in the previous sentence means the process, not the CPU...