Search code examples
c++opencv

Opencv - How to differentiate jitter from panning?


I'm working on a video stabilizer using Opencv in C++.
At this time of the project I'm correctly able to find the translation between two consecutive frames with 3 different technique (Optical Flow, Phase Correlation, BFMatcher on points of interests).
To obtain a stabilized image I add up all the translation vector (from consecutive frame) to one, which is used in warpAffine function to correct the output image.

I'm having good result on fixed camera but result on camera in translation are really bad : the image disappear from the screen.

I think I have to distinguish jitter movement that I want to remove from panning movement that I want to keep. But I'm open to others solutions.


Solution

  • I would suggest you the possible approaches (in complexity order):

    • apply some easy-to-implement IIR low pass filter on the translation vectors before applying the stabilization. This will separate the high frequency (jitter) from the low frequency (panning)
    • same idea, a bit more complex, use Kalman filtering to track a motion with constant velocity or acceleration. You can use OpenCV's Kalman filter for that.
    • A bit more tricky, put a threshold on the motion amplitude to decide between two states (moving vs static camera) and filter the translation or not.
    • Finaly, you can use some elaborate technique from machine Learning to try to identify the user's desired motion (static, panning, etc.) and filter or not the motion vectors used for the stabilization.

    Just a threshold is not a low pass filter. Possible low pass filters (that are easy to implement):

    • there is the well known averaging, that is already a low-pass filter whose cutoff frequency depends on the number of samples that go into the averaging equation (the more samples the lower the cutoff frequency).
    • One frequently used filter is the exponential filter (because it forgets the past with an exponential rate decay). It is simply computed as x_filt(k) = a*x_nofilt(k) + (1-a)x_filt(k-1) with 0 <= a <= 1.
    • Another popular filter (and that can be computed beyond order 1) is the Butterworth filter.
    • Etc Low pass filters on Wikipedia, IIR filters...