vstabiliser2dlite_web_logo

VStabiliser2dLite C++ library

v1.0.0

Table of contents

Overview

VStabiliser2dLite is a C++ library for fast 2D digital video stabilization (horizontal offset and vertical offset). The library is designed for camera systems requiring video vibration compensation without any external dependencies — it requires only a C++17 compiler and the CMake build system. The library is written in standard C++17. The motion-estimation FFT is provided by the bundled, header-only PocketFFT (BSD-3-Clause; see src/impl/fft.h) — no third-party libraries need to be installed or linked. The stabilization algorithm estimates inter-frame motion by phase correlation in the frequency domain (FFT) and applies a Kalman motion filter to separate vibration from intentional camera movement. It inherits the interface from VStabiliser (source code included, Apache 2.0 license), providing a standardized and interchangeable contract compatible with other VStabiliser-based implementations. The library supports various pixel formats (RGB24, BGR24, GRAY, YUV24, YUYV, UYVY, NV12, NV21, YV12, YU12, listed in the Frame class) and performs calculations in a single computational thread.

Versions

Table 1 - Library versions.

Version Release date What’s new
1.0.0 05.06.2026 First version.

Library files

The library is supplied only as source code. The repository structure is shown below:

CMakeLists.txt --------------------- Main CMake file of the library.
3rdparty --------------------------- Folder with third-party libraries.
    CMakeLists.txt ----------------- CMake file to include third-party libraries.
    VStabiliser -------------------- Folder with VStabiliser interface library source code.
src -------------------------------- Folder with library source code.
    CMakeLists.txt ----------------- CMake file of the library.
    VStabiliser2dLite.h ------------ Main library header file.
    VStabiliser2dLiteVersion.h ----- Header file with library version.
    VStabiliser2dLiteVersion.h.in -- Service CMake file to generate version file.
    VStabiliser2dLite.cpp ---------- C++ class definitions file.
    impl --------------------------- Folder with algorithm implementation files.
        VStabiliser2dLiteImpl.h ---- Library implementation header file.
        VStabiliser2dLiteImpl.cpp -- C++ implementation file.
        ImageMotionFilter2d.h ------ Kalman motion filter header file.
        ImageMotionFilter2d.cpp ---- Kalman motion filter implementation.
        fft.h ---------------------- Bundled PocketFFT (header-only, BSD-3-Clause).
demo ------------------------------- Folder for demo application.
    CMakeLists.txt ----------------- CMake file for demo application.
    3rdparty ----------------------- Folder with third-party libraries.
        CMakeLists.txt ------------- CMake file to include third-party libraries.
        SimpleFileDialog ----------- Folder with SimpleFileDialog library source code.
    main.cpp ----------------------- Source C++ file of demo application.
benchmark -------------------------- Folder for benchmark application.
    CMakeLists.txt ----------------- CMake file for benchmark application.
    main.cpp ----------------------- Source C++ file of benchmark application.
static ----------------------------- Folder with static assets.
    test.mp4 ----------------------- Test video used as the default input
examples --------------------------- Folder with examples.
    CMakeLists.txt ----------------- CMake file to include examples.
    BgrExample --------------------- Example for BGR24 pixel format.
    BgrWithoutCopyingExample ------- Example for BGR24 pixel format.
    GrayExample -------------------- Example for GRAY pixel format.
    Nv12Example -------------------- Example for NV12 pixel format.
    Nv21Example -------------------- Example for NV21 pixel format.
    RgbExample --------------------- Example for RGB24 pixel format.
    UyvyExample -------------------- Example for UYVY pixel format.
    Yu12Example -------------------- Example for YU12 pixel format.
    YuvExample --------------------- Example for YUV24 pixel format.
    YuyvExample -------------------- Example for YUYV pixel format.
    Yv12Example -------------------- Example for YV12 pixel format.

Key features and capabilities

Table 2 - Key features and capabilities.

Parameter and feature Description
Programming language C++ (standard C++17). No external dependencies.
Supported OS Any operating system with a C++17 compiler and CMake 3.13 or higher.
Number of stabilization axes 2D stabilization: horizontal and vertical offset only. Rotation compensation is not supported in VStabiliser2dLite.
Supported pixel formats RGB24, BGR24, GRAY, YUV24, YUYV, UYVY, NV12, NV21, YV12, YU12.
Allocated memory Not mode than 330 KB without input and output image data size. Doesn’t depends on video frames size.
Maximum compensated frame shift The library detects inter-frame motion up to 20% of frame size.
Boresight correction The library provides a method to add constant offsets for the result image: horizontal offset (pixels) and vertical offset (pixels).

Supported pixel formats

The Frame library bundled in VStabiliser2dLite defines the Fourcc enum for supported pixel formats. VStabiliser2dLite supports RAW pixel formats and converts the input to GRAY internally for motion estimation. Fourcc enum declaration:

enum class Fourcc
{
    /// RGB 24bit pixel format.
    RGB24 = MAKE_FOURCC_CODE('R', 'G', 'B', '3'),
    /// BGR 24bit pixel format.
    BGR24 = MAKE_FOURCC_CODE('B', 'G', 'R', '3'),
    /// YUYV 16bits per pixel format.
    YUYV  = MAKE_FOURCC_CODE('Y', 'U', 'Y', 'V'),
    /// UYVY 16bits per pixel format.
    UYVY  = MAKE_FOURCC_CODE('U', 'Y', 'V', 'Y'),
    /// Grayscale 8bit.
    GRAY  = MAKE_FOURCC_CODE('G', 'R', 'A', 'Y'),
    /// YUV 24bit per pixel format.
    YUV24 = MAKE_FOURCC_CODE('Y', 'U', 'V', '3'),
    /// NV12 pixel format.
    NV12  = MAKE_FOURCC_CODE('N', 'V', '1', '2'),
    /// NV21 pixel format.
    NV21  = MAKE_FOURCC_CODE('N', 'V', '2', '1'),
    /// YU12 (YUV420) - Planar pixel format.
    YU12  = MAKE_FOURCC_CODE('Y', 'U', '1', '2'),
    /// YV12 (YVU420) - Planar pixel format.
    YV12  = MAKE_FOURCC_CODE('Y', 'V', '1', '2'),
};

VStabiliser2dLite class description

VStabiliser2dLite class declaration

VStabiliser2dLite.h contains the VStabiliser2dLite class declaration. VStabiliser2dLite inherits the interface from VStabiliser. Class declaration:

namespace cr
{
namespace vstab
{
class VStabiliser2dLite: public VStabiliser
{
public:

    /// Class constructor.
    VStabiliser2dLite();

    /// Class destructor.
    ~VStabiliser2dLite();

    /// Get string of current VStabiliser2dLite class version.
    static std::string getVersion();

    /// Init all video stabiliser parameters by params structure.
    bool initVStabiliser(const cr::vstab::VStabiliserParams& params) override;

    /// Set value to parameter with given id.
    bool setParam(cr::vstab::VStabiliserParam id, float value) override;

    /// Get parameter with given id.
    float getParam(cr::vstab::VStabiliserParam id) override;

    /// Get params.
    void getParams(VStabiliserParams& params) override;

    /// Execute command.
    bool executeCommand(VStabiliserCommand id, float value = 0.0f) override;

    /// Stabilise video frame.
    bool stabilise(cr::video::Frame& src, cr::video::Frame& dst) override;

    /// Get offsets: horizontal, vertical and rotation.
    void getOffsets(float& dX, float& dY, float& dA) override;

    /// Decode and execute command.
    bool decodeAndExecuteCommand(uint8_t* data, int size) override;
};
}
}

getVersion method

The getVersion() method returns the current VStabiliser2dLite class version as a string. Method declaration:

static std::string getVersion();

Method can be used without a VStabiliser2dLite class instance. Example:

std::cout << "VStabiliser2dLite version: " << VStabiliser2dLite::getVersion();

Console output:

VStabiliser2dLite version: 1.0.0

initVStabiliser method

The initVStabiliser(…) method initializes the video stabilizer from a set of parameters. Method declaration:

bool initVStabiliser(const cr::vstab::VStabiliserParams& params) override;
Parameter Description
params VStabiliserParams class object.

Returns: TRUE if parameters were accepted or FALSE if not.

setParam method

The setParam(…) method changes a single video stabilizer parameter. NOTE: the new value is applied only on the next processed video frame. Thread-safe — backed by std::atomic<T> per field; safe to invoke from any thread, including concurrently with stabilise(...). Method declaration:

bool setParam(cr::vstab::VStabiliserParam id, float value) override;
Parameter Description
id Parameter ID according to VStabiliserParam enum.
value Parameter value. Depends on parameter ID.

Returns: TRUE if param was accepted or FALSE if not.

getParam method

The getParam(…) method returns the current value of a single video stabilizer parameter. Thread-safe — lock-free atomic load; safe to invoke from any thread, including concurrently with stabilise(...). Method declaration:

float getParam(cr::vstab::VStabiliserParam id) override;
Parameter Description
id Parameter ID according to VStabiliserParam enum.

Returns: Parameter value, or 0 if the parameter is not supported / not used by VStabiliser2dLite. This deliberately deviates from the base VStabiliser interface (which documents -1) — see Table 3 below for the per-parameter behaviour.

getParams method

The getParams(…) method returns all video stabilizer parameters. Thread-safe — may be invoked from any thread. Method declaration:

void getParams(VStabiliserParams& params) override;
Parameter Description
params VStabiliserParams class object to be filled.

executeCommand method

The executeCommand(…) method executes a video stabilizer action command. Thread-safe — atomic field updates for RESET / ON / OFF; HOLD_MSEC publishes the deadline through a single atomic store. Safe to invoke from any thread, including concurrently with stabilise(...). Method declaration:

bool executeCommand(VStabiliserCommand id, float value = 0.0f) override;
Parameter Description
id Command ID according to VStabiliserCommand enum.
value Command argument. Depends on command ID.

Returns: TRUE if the command was executed or FALSE if not.

stabilise method

The stabilise(…) method performs video stabilization. Concurrent calls from multiple threads are serialised internally by a std::mutex (the FFT scratch buffers, the ping-pong spectrum index and the Kalman filter state are non-atomic and not re-entrant); for best throughput call from a single processing thread per VStabiliser2dLite instance. Method declaration:

bool stabilise(cr::video::Frame& src, cr::video::Frame& dst) override;
Parameter Description
src Source frame. Only RAW pixel formats are supported (compressed formats such as JPEG, H264, HEVC are not). Supported formats: RGB24, BGR24, GRAY, YUV24, YUYV, UYVY, NV12, NV21, YV12, YU12. All formats use 2D stabilization only.
dst Result frame. Pixel format matches the source frame. If stabilization is disabled (MODE = 0) the library copies the source frame to the result frame. If the destination frame is not initialized the library initializes it.

Returns: TRUE if the video frame was processed or FALSE in case of any errors.

getOffsets method

The getOffsets(…) method returns the offsets applied to the last processed video frame. For VStabiliser2dLite, the rotation angle dA is always 0 (rotation is not estimated). Method declaration:

void getOffsets(float& dX, float& dY, float& dA) override;
Parameter Description
dX Horizontal offset in pixels applied to the last processed frame.
dY Vertical offset in pixels applied to the last processed frame.
dA Rotational angle in radians. Always 0 in VStabiliser2dLite.

encodeSetParamCommand method of VStabiliser interface class

The encodeSetParamCommand(…) static method encodes command to change any parameters of remote video stabiliser. To control a stabiliser remotely, the developer has to develop his own protocol and according to it encode the command and deliver it over the communication channel. To simplify this, the VStabiliser class contains static methods for encoding the control commands. The VStabiliser class provides two types of commands: a parameter change command (SET_PARAM) and an action command (COMMAND). encodeSetParamCommand(…) designed to encode SET_PARAM command. Method declaration:

static void encodeSetParamCommand(uint8_t* data, int& size, VStabiliserParam id, float value);
Parameter Description
data Pointer to data buffer for encoded command. Must have size >= 11.
size Size of encoded data. Will be 11 bytes.
id Parameter ID according to VStabiliserParam enum.
value Parameter value.

encodeSetParamCommand(…) is static and used without VStabiliser class instance. This method used on client side (control system). Example:

// Buffer for encoded data.
uint8_t data[11];
// Size of encoded data.
int size = 0;
// Encode command.
VStabiliser::encodeSetParamCommand(data, size, VStabiliserParam::X_FILTER_COEFF, 0.8f);

encodeCommand method of VStabiliser interface class

The encodeCommand(…) static method encodes video stabiliser action command. To control a stabiliser remotely, the developer has to develop his own protocol and according to it encode the command and deliver it over the communication channel. To simplify this, the VStabiliser class contains static methods for encoding the control commands. The VStabiliser class provides two types of commands: a parameter change command (SET_PARAM) and an action command (COMMAND). encodeCommand(…) designed to encode COMMAND command (action command). Method declaration:

static void encodeCommand(uint8_t* data, int& size, VStabiliserCommand id, float value = 0.0f);
Parameter Description
data Pointer to data buffer for encoded command. Must have size >= 11.
size Size of encoded data. Will be 11 bytes.
id Command ID according to VStabiliserCommand enum.
value Command argument. Depends on command ID.

encodeCommand(…) is static and used without VStabiliser class instance. This method used on client side (control system). Encoding example:

// Buffer for encoded data.
uint8_t data[11];
// Size of encoded data.
int size = 0;
// Encode command.
VStabiliser::encodeCommand(data, size, VStabiliserCommand::HOLD_MSEC, 1200);

decodeCommand method of VStabiliser interface class

The decodeCommand(…) static method designed to decode command on video stabiliser side. To control a stabiliser remotely, the developer has to develop his own protocol and according to it encode the command and deliver it over the communication channel. To simplify this, the VStabiliser interface class contains static method to decode input command (commands should be encoded by methods encodeSetParamCommand(…) or encodeCommand(…)). The VStabiliser class provides two types of commands: a parameter change command (SET_PARAM) and an action command (COMMAND). Method declaration:

static int decodeCommand(uint8_t* data, int size, VStabiliserParam& paramId, VStabiliserCommand& commandId, float& value);
Parameter Description
data Pointer to input command.
size Size of command. Must be 11 bytes (both COMMAND and SET_PARAM are encoded as 11 bytes).
paramId Video stabiliser parameter ID according to VStabiliserParam enum. After decoding SET_PARAM command the method will return parameter ID.
commandId Video stabiliser command ID according toVStabiliserCommand enum. After decoding COMMAND the method will return command ID.
value Video stabiliser parameter value after decoding SET_PARAM command or command argument after decoding COMMAND.

Returns: 0 - in case decoding COMMAND, 1 - in case decoding SET_PARAM command or -1 in case errors.

decodeCommand(…) is static and used without VStabiliser class instance. Command decoding example:

// Buffer for encoded data.
uint8_t data[11];
int size = 0;
VStabiliser::encodeCommand(data, size, VStabiliserCommand::ON);

// Decode command.
VStabiliserCommand commandId;
VStabiliserParam paramId;
float value = (float)(rand() % 20);
if (VStabiliser::decodeCommand(data, size, paramId, commandId, value) != 0)
{
    cout << "Command not decoded" << endl;
    return false;
}

decodeAndExecuteCommand method

The decodeAndExecuteCommand(…) method decodes and executes command on video stabiliser side. The decodeAndExecuteCommand(…) method can be safely called from any thread. Method declaration:

bool decodeAndExecuteCommand(uint8_t* data, int size) override;
Parameter Description
data Pointer to input command.
size Size of command. Must be 11 bytes (both SET_PARAM and COMMAND are encoded as 11 bytes).

Returns: TRUE if command decoded (SET_PARAM or COMMAND) and executed (action command or set param command).

Data structures

VStabiliserParam enum

VStabiliserParam enum lists video stabilizer parameters. Declared in VStabiliser.h of the VStabiliser library. Enum declaration:

namespace cr
{
namespace vstab
{
enum class VStabiliserParam
{
    /// Not used by VStabiliser2dLite (kept for VStabiliser-interface
    /// compatibility — always operates on the full source frame).
    SCALE_FACTOR = 1,
    /// Not used by VStabiliser2dLite. The per-frame shift limit is
    /// hard-wired in code (37.5 % of the source width). setParam(...)
    /// returns false, getParam(...) returns 0.
    X_OFFSET_LIMIT,
    /// Not used by VStabiliser2dLite. Same rules as X_OFFSET_LIMIT.
    Y_OFFSET_LIMIT,
    /// Not supported by VStabiliser2dLite (rotation is not estimated).
    A_OFFSET_LIMIT,
    /// Horizontal stabilization strength. Range [0, 1]: 0 - near pass-through
    /// (almost no stabilization), 1 - strongest stabilization.
    X_FILTER_COEFF,
    /// Vertical stabilization strength. Range [0, 1]: 0 - near pass-through
    /// (almost no stabilization), 1 - strongest stabilization.
    Y_FILTER_COEFF,
    /// Not supported by VStabiliser2dLite (rotation is not estimated).
    A_FILTER_COEFF,
    /// Stabilisation mode: 0 - off (the library copies the input image),
    /// 1 - stabilisation on.
    MODE,
    /// Transparent border mode: 0 - black borders, 1 - borders filled from
    /// previous frames.
    TRANSPARENT_BORDER,
    /// Constant horizontal image offset in pixels added to each processed
    /// frame (boresight correction).
    CONST_X_OFFSET,
    /// Constant vertical image offset in pixels added to each processed
    /// frame (boresight correction).
    CONST_Y_OFFSET,
    /// Not supported by VStabiliser2dLite (rotation is not applied).
    CONST_A_OFFSET,
    /// Read only. Horizontal offset (pixels) applied to the last frame.
    INSTANT_X_OFFSET,
    /// Read only. Vertical offset (pixels) applied to the last frame.
    INSTANT_Y_OFFSET,
    /// Not supported by VStabiliser2dLite (rotation is not estimated).
    INSTANT_A_OFFSET,
    /// Not used by VStabiliser2dLite (single algorithm).
    TYPE,
    /// Not used by VStabiliser2dLite.
    CUT_FREQUENCY_HZ,
    /// Not used by VStabiliser2dLite. The motion filter runs on a fixed
    /// 30 FPS nominal time step regardless of the actual input frame rate;
    /// tune X/Y_FILTER_COEFF empirically for the host pipeline instead.
    FPS,
    /// Read only. Processing time of the last video frame, in microseconds.
    PROCESSING_TIME_MKS,
    /// Not used by VStabiliser2dLite.
    LOG_MODE,
    /// Not used by VStabiliser2dLite (single plain-C++ backend).
    BACKEND,
    /// Not used by VStabiliser2dLite.
    CUSTOM_1,
    /// Not used by VStabiliser2dLite.
    CUSTOM_2,
    /// Not used by VStabiliser2dLite.
    CUSTOM_3
};
}
}

Table 3 - Video stabilizer parameters supported by VStabiliser2dLite.

Unused parameters (rows marked not used below) are kept in the enum only for VStabiliser interface compatibility. For every such parameter setParam(...) returns false and getParam(...) returns 0 — the library does not store the value.

Parameter Description
SCALE_FACTOR Not used — VStabiliser2dLite always operates on the full source frame; the FFT scale is fixed internally.
X_OFFSET_LIMIT Not used. The per-frame shift limit is hard-wired in code (37.5 % of the source width — see Table 2). setParam(...) returns false, getParam(...) returns 0.
Y_OFFSET_LIMIT Not used. Same rules as X_OFFSET_LIMIT.
A_OFFSET_LIMIT Not used — rotation is not estimated.
X_FILTER_COEFF Horizontal stabilization strength. Range [0, 1]: 0 — near pass-through (almost no stabilization), 1 — strongest stabilization. Default: 0.8.
Y_FILTER_COEFF Vertical stabilization strength. Range [0, 1]: 0 — near pass-through (almost no stabilization), 1 — strongest stabilization. Default: 0.8.
A_FILTER_COEFF Not used — rotation is not estimated.
MODE Stabilization mode: 0 — off (library copies input frame), 1 — on. Default: 1.
TRANSPARENT_BORDER 0 — black fill at shifted borders, 1 — fill from previous frame. Default: 1.
CONST_X_OFFSET Constant horizontal offset in pixels added to every processed frame (boresight correction). Accepted range: 0..8192; setParam(...) returns false for values outside this range or non-finite. Default: 0.
CONST_Y_OFFSET Constant vertical offset in pixels added to every processed frame (boresight correction). Accepted range: 0..8192; setParam(...) returns false for values outside this range or non-finite. Default: 0.
CONST_A_OFFSET Not used — rotation is not applied.
INSTANT_X_OFFSET Read only. Horizontal offset (pixels) applied to the last processed frame.
INSTANT_Y_OFFSET Read only. Vertical offset (pixels) applied to the last processed frame.
INSTANT_A_OFFSET Not usedgetOffsets(...) always sets dA to 0.
TYPE Not used — VStabiliser2dLite implements a single algorithm.
CUT_FREQUENCY_HZ Not used.
FPS Not used. The internal motion filter runs on a fixed 30 FPS nominal time step regardless of the actual input frame rate. Estimating the real FPS reliably is a host-side concern; the recommended practice is to tune X_FILTER_COEFF / Y_FILTER_COEFF empirically for the deployed pipeline (typically a fixed frame rate per system).
PROCESSING_TIME_MKS Read only. Processing time of the last frame in microseconds.
LOG_MODE Not used — the library produces no log output.
BACKEND Not used — single plain-C++ backend.
CUSTOM_1 Not used.
CUSTOM_2 Not used.
CUSTOM_3 Not used.

VStabiliserCommand enum

VStabiliserCommand enum lists video stabilizer commands. Declared in VStabiliser.h. Enum declaration:

namespace cr
{
namespace vstab
{
enum class VStabiliserCommand
{
    /// Reset stabilisation algorithm. No params.
    RESET = 1,
    /// Enable stabilisation. After execution parameter MODE must be set to 1. No params.
    ON,
    /// Disable stabilisation. After execution parameter MODE must be set to 0. No params.
    OFF,
    /// Hold processing for some time. Parameter - time in milliseconds.
    HOLD_MSEC
};
}
}

Table 4 - Video stabilizer commands.

Command Description
RESET Reset the stabilization algorithm state (clears frame buffers, zeroes offsets).
ON Enable stabilization. After execution parameter MODE is set to 1.
OFF Disable stabilization. After execution parameter MODE is set to 0.
HOLD_MSEC Suspend stabilization for the given number of milliseconds. During the timeout the library copies input frames without applying any correction. Used to pause stabilization while a pan-tilt unit is moving.

VStabiliserParams class description

VStabiliserParams class is used for video stabilizer initialization (initVStabiliser(…)) or to retrieve all current parameters (getParams(…)). It also provides methods to serialize/deserialize parameters and to read/write JSON configuration files. VStabiliserParams is declared in VStabiliser.h of the VStabiliser library.

VStabiliserParams class declaration

namespace cr
{
namespace vstab
{
class VStabiliserParams
{
public:
    /// Scale factor. 1 - original frame size, 2 - scaled down by 2, etc.
    int   scaleFactor{1};
    /// READ ONLY / library-managed. Maximum detectable horizontal shift in
    /// source pixels per frame. The base struct default (150) is ignored by
    /// VStabiliser2dLite: initVStabiliser(...) does NOT copy this field, and
    /// the library writes its own value (default 100) when the first frame
    /// is processed.
    int   xOffsetLimit{150};
    /// READ ONLY / library-managed. Same rules as xOffsetLimit.
    int   yOffsetLimit{150};
    /// Not used by VStabiliser2dLite (rotation is not estimated).
    float aOffsetLimit{10.0f};
    /// Horizontal stabilization strength. Range [0, 1]: 0 - near pass-through,
    /// 1 - strongest stabilization.
    float xFilterCoeff{0.9f};
    /// Vertical stabilization strength. Range [0, 1]: 0 - near pass-through,
    /// 1 - strongest stabilization.
    float yFilterCoeff{0.9f};
    /// Not used by VStabiliser2dLite (rotation is not estimated).
    float aFilterCoeff{0.9f};
    /// Enable/disable stabilisation.
    bool  enable{true};
    /// Enable/disable transparent borders.
    bool  transparentBorder{true};
    /// Constant horizontal image offset in pixels (boresight correction).
    int   constXOffset{0};
    /// Constant vertical image offset in pixels (boresight correction).
    int   constYOffset{0};
    /// Not used by VStabiliser2dLite (rotation is not applied).
    float constAOffset{0.0f};
    /// Read only. Horizontal offset (pixels) applied to the last frame.
    int   instantXOffset{0};
    /// Read only. Vertical offset (pixels) applied to the last frame.
    int   instantYOffset{0};
    /// Not used by VStabiliser2dLite (rotation is not estimated).
    float instantAOffset{0.0f};
    /// Not used by VStabiliser2dLite (single algorithm).
    int   type{2};
    /// Not used by VStabiliser2dLite.
    float cutFrequencyHz{2.0f};
    /// Not used by VStabiliser2dLite — the internal motion filter runs on a
    /// fixed 30 FPS nominal time step regardless of the actual input frame
    /// rate. Tune xFilterCoeff/yFilterCoeff empirically for the deployed
    /// pipeline instead.
    float fps{30.0f};
    /// Read only. Processing time of the last video frame, in microseconds.
    int   processingTimeMks{0};
    /// Not used by VStabiliser2dLite.
    int   logMod{0};
    /// Not used by VStabiliser2dLite (single plain-C++ backend).
    int   backend{0};
    /// Not used by VStabiliser2dLite.
    float custom1{0};
    /// Not used by VStabiliser2dLite.
    float custom2{0};
    /// Not used by VStabiliser2dLite.
    float custom3{0};

    JSON_READABLE(VStabiliserParams, scaleFactor, xOffsetLimit, yOffsetLimit,
                  aOffsetLimit, xFilterCoeff, yFilterCoeff, aFilterCoeff,
                  enable, transparentBorder, constXOffset, constYOffset,
                  constAOffset, type, cutFrequencyHz, fps, logMod, backend,
                  custom1, custom2, custom3);

    bool encode(uint8_t* data, int bufferSize, int& size,
                VStabiliserParamsMask* mask = nullptr);
    bool decode(uint8_t* data, int dataSize);
};
}
}

Table 6 - VStabiliserParams class field descriptions.

Field Type Description
scaleFactor int Not used — VStabiliser2dLite always operates on the full source frame; initVStabiliser does not forward this field.
xOffsetLimit int Not used. setParam(X_OFFSET_LIMIT, ...) returns false, getParam returns 0; the per-frame shift limit is hard-wired (37.5 % of source width).
yOffsetLimit int Not used. Same rules as xOffsetLimit.
aOffsetLimit float Not used — rotation is not supported.
xFilterCoeff float Horizontal stabilization strength. Range [0, 1]: 0 — near pass-through, 1 — strongest stabilization. Default 0.8.
yFilterCoeff float Vertical stabilization strength. Range [0, 1]: 0 — near pass-through, 1 — strongest stabilization. Default 0.8.
aFilterCoeff float Not used — rotation is not supported.
enable bool Enable/disable stabilization. Default true.
transparentBorder bool Enable/disable transparent borders. Default true.
constXOffset int Constant horizontal offset in pixels (boresight correction). Accepted range 0..8192. Default 0.
constYOffset int Constant vertical offset in pixels (boresight correction). Accepted range 0..8192. Default 0.
constAOffset float Not used — rotation is not supported.
instantXOffset int Read only. Horizontal offset applied to the last frame.
instantYOffset int Read only. Vertical offset applied to the last frame.
instantAOffset float Not usedgetOffsets(...) always sets dA to 0.
type int Not used — VStabiliser2dLite implements a single algorithm.
cutFrequencyHz float Not used.
fps float Not used. The internal motion filter runs on a fixed 30 FPS nominal time step. Tune xFilterCoeff / yFilterCoeff empirically for the deployed pipeline instead.
processingTimeMks (read only) int Processing time of the last frame in microseconds.
logMod int Not used.
backend int Not used — single plain-C++ backend.
custom1 float Not used.
custom2 float Not used.
custom3 float Not used.

Serialize video stabiliser params

The encode(…) method serializes the video stabilizer parameters for transmission over a communication channel. Method declaration:

bool encode(uint8_t* data, int bufferSize, int& size,
            VStabiliserParamsMask* mask = nullptr);
Parameter Description
data Pointer to the output data buffer.
bufferSize Capacity of the output buffer in bytes.
size Output: size in bytes of the encoded payload written to data.
mask Optional pointer to VStabiliserParamsMask to select which fields to include. Pass nullptr to serialize all fields.

Returns: TRUE if the parameters were encoded successfully or FALSE if the buffer was too small.

Example:

VStabiliserParams in;
uint8_t data[1024];
int size = 0;
in.encode(data, 1024, size);
std::cout << "Encoded data size: " << size << " bytes" << std::endl;

Deserialize video stabiliser params

The decode(…) method deserializes the video stabilizer parameters. Method declaration:

bool decode(uint8_t* data, int dataSize);
Parameter Description
data Pointer to the input data buffer (produced by encode(...)).
dataSize Size of the input data buffer in bytes.

Returns: TRUE if decoded successfully or FALSE otherwise.

Example:

VStabiliserParams in;
uint8_t data[1024];
int size = 0;
in.encode(data, 1024, size);

VStabiliserParams out;
if (!out.decode(data, size))
    std::cout << "Can't decode data" << std::endl;

Read params from JSON file and write to JSON file

The bundled ConfigReader library provides methods to read and write parameters from/to a JSON file:

VStabiliserParams in;
in.scaleFactor = 2;
in.fps = 25.0f;
// Note: xOffsetLimit / yOffsetLimit are library-managed and ignored by
// initVStabiliser(...) — assigning them in the user struct has no effect.

// Write params to file.
cr::utils::ConfigReader inConfig;
inConfig.set(in, "VStabiliserParams");
inConfig.writeToFile("VStabiliser2dLiteParams.json");

// Read params from file.
cr::utils::ConfigReader outConfig;
outConfig.readFromFile("VStabiliser2dLiteParams.json");
VStabiliserParams out;
outConfig.get(out, "VStabiliserParams");

VStabiliser2dLiteParams.json will look like:

{
    "VStabiliserParams": {
        "aFilterCoeff": 0.9,
        "aOffsetLimit": 10.0,
        "backend": 0,
        "constAOffset": 0.0,
        "constXOffset": 0,
        "constYOffset": 0,
        "custom1": 0.0,
        "custom2": 0.0,
        "custom3": 0.0,
        "cutFrequencyHz": 2.0,
        "enable": true,
        "fps": 25.0,
        "logMod": 0,
        "scaleFactor": 2,
        "transparentBorder": true,
        "type": 2,
        "xFilterCoeff": 0.9,
        "xOffsetLimit": 150,
        "yFilterCoeff": 0.9,
        "yOffsetLimit": 150
    }
}

Note: Many fields above (scaleFactor, xOffsetLimit, yOffsetLimit, aOffsetLimit, aFilterCoeff, constAOffset, type, cutFrequencyHz, fps, logMod, backend, custom1..3) are part of the shared VStabiliserParams serialization format defined by the VStabiliser interface but are not used by VStabiliser2dLitesetParam(...) for any of them returns false, getParam(...) returns 0, and initVStabiliser(...) does not copy them from the input struct. The numbers in the JSON snippet above are the parent-struct defaults; getParams(...) on a freshly-constructed VStabiliser2dLite instance reports the actual runtime defaults instead — most notably xFilterCoeff / yFilterCoeff = 0.8, all “not used” fields = 0.

Build and connect to your project

The library itself and the benchmark have no external dependencies — only a C++17 compiler and CMake 3.13+. The demo and the per-format examples additionally require OpenCV (used only for video capture and display); when building the project standalone they are enabled by default, so OpenCV must be available, or disable them via the *_DEMO / *_EXAMPLES CMake options.

Build commands:

cd VStabiliser2dLite
mkdir build
cd build
cmake -DCMAKE_BUILD_TYPE=Release ..
cmake --build . --config Release

The demo and all OpenCV-based examples default to static/test.mp4 (relative to the working directory). Run them from the project root so the path resolves correctly:

# From the project root:
./build/bin/VStabiliser2dLiteDemo
./build/bin/VStabiliser2dLiteBenchmark
./build/bin/VStabiliser2dLiteRgbExample

To connect VStabiliser2dLite as a submodule to your CMake project, copy or add the repository to your 3rdparty/ folder and add the following to your 3rdparty/CMakeLists.txt:

cmake_minimum_required(VERSION 3.13)
project(3rdparty LANGUAGES CXX)

SET(PARENT ${PARENT}_YOUR_PROJECT_3RDPARTY)
SET(${PARENT}_SUBMODULE_CACHE_OVERWRITE OFF CACHE BOOL "" FORCE)

add_subdirectory(VStabiliser2dLite)

Then in your target’s CMakeLists.txt:

target_link_libraries(${PROJECT_NAME} VStabiliser2dLite)

Example

Below is a minimal example (identical to examples/BgrExample). It uses OpenCV to read frames from the bundled static/test.mp4, stabilises each BGR24 frame and displays the source and stabilised video in two windows. Press ESC to exit or SPACE to reset the stabiliser. For a build with no external dependencies (no OpenCV), see the benchmark application, which generates two synthetic YUV24 frames containing a single bright rectangle shifted by a fixed offset and measures the per-frame stabilisation cost in pure C++.

#include <iostream>
#include <opencv2/opencv.hpp>
#include <VStabiliser2dLite.h>

// Entry point.
int main(void)
{
    // Init video source.
    cv::VideoCapture cap;
    if (!cap.open("static/test.mp4"))
        return -1;

    // Get video frame size.
    int width = (int)cap.get(cv::CAP_PROP_FRAME_WIDTH);
    int height = (int)cap.get(cv::CAP_PROP_FRAME_HEIGHT);

    // Init images.
    cv::Mat opencvSrcFrame(cv::Size(width, height), CV_8UC3);
    cv::Mat opencvDstFrame(cv::Size(width, height), CV_8UC3);
    cr::video::Frame srcFrame(width, height, cr::video::Fourcc::BGR24);
    cr::video::Frame dstFrame(width, height, cr::video::Fourcc::BGR24);

    // Create video stabilizer object.
    cr::vstab::VStabiliser2dLite videoStabilizer;

    // Main loop.
    while (true)
    {
        // Capture next video frame.
        cap >> opencvSrcFrame;
        if (opencvSrcFrame.empty())
        {
            // If we have video we can set initial video position.
            cap.set(cv::CAP_PROP_POS_FRAMES, 1);
            videoStabilizer.executeCommand(cr::vstab::VStabiliserCommand::RESET);
            continue;
        }

        // Copy video frame data from OpenCV image to Frame object.
        memcpy(srcFrame.data, opencvSrcFrame.data, srcFrame.size);

        // Stabilise frame.
        if (!videoStabilizer.stabilise(srcFrame, dstFrame))
            std::cout << "Stabilisation not calculated" << std::endl;

        // Copy image to OpenCV image.
        memcpy(opencvDstFrame.data, dstFrame.data, dstFrame.size);

        // Show video.
        cv::imshow("SOURCE VIDEO", opencvSrcFrame);
        cv::imshow("RESULT VIDEO", opencvDstFrame);

        // Process keyboard events.
        switch (cv::waitKey(1))
        {
        case 27: // ESC - exit.
            exit(0);
        case 32: // SPACE - reset video stabilizer.
            videoStabilizer.executeCommand(cr::vstab::VStabiliserCommand::RESET);
            break;
        }
    }

    return 1;
}

Demo application

Demo application overview

The demo application is intended to evaluate the performance of the VStabiliser2dLite C++ library. The application allows you to evaluate the operation of the algorithm. It is a small OpenCV-based application and serves as an example of using the VStabiliser2dLite library. The application uses the OpenCV library for capturing video, recording video, displaying video, and forming a simple user interface, and the bundled SimpleFileDialog library (source code included, Apache 2.0 license) to open a video file through a native file dialog.

Launch and user interface

The demo application does not require installation. It is compiled for Windows x64 (Windows 10 and newer) as well as for Linux (several distros; to get the demo application for a specific Linux distro, send us a request). Table 7 shows the files that make up the demo application.

Table 7 - List of files of demo application (example for Windows OS).

File Description
VStabiliser2dLiteDemo.exe Demo application executable file for windows OS.
opencv_world480.dll OpenCV library file version 4.8.0 for Windows x64.
opencv_videoio_msmf480_64.dll OpenCV library file version 4.8.0 for Windows x64.
opencv_videoio_ffmpeg480_64.dll OpenCV library file version 4.8.0 for Windows x64.
VC_redist.x64 Installer of necessary system libraries for Windows x64.
src Folder with application source code.
static/test.mp4 Test video file (loaded when the user selects it through the file-open dialog at startup; not auto-loaded).

To launch demo application run VStabiliser2dLiteDemo.exe executable file on Windows x64 OS or run commands on Linux:

sudo chmod +x VStabiliser2dLiteDemo
./VStabiliser2dLiteDemo

If a message about missing system libraries appears (on Windows OS) when launching the application, you must install the VC_redist.x64.exe program, which will install the system libraries required for operation.

The demo application sets the video stabiliser parameters in code (enable = true, xFilterCoeff = 0.8, yFilterCoeff = 0.8, transparentBorder = true), so no configuration file is required. The per-frame shift limit is hard-wired (37.5 % of the source width / height — see Table 2) and not user-tunable. Command-line arguments are not parsed. At startup the application prompts on stdin:

Open file dialog? (y/n)
  • Answering y/Y/yes/Yes opens a native file-open dialog via SimpleFileDialog. Cancelling the dialog produces an empty string and the demo exits with ERROR: No video source selected.
  • Any other answer reads the video source string from stdin — a short numeric value (e.g. “0”) opens that camera index, anything else is treated as a file path / RTSP URL.

When capturing video from a video file, the software plays the video with repetition i.e. when the end of the video file is reached, playback starts again — executeCommand(VStabiliserCommand::RESET) is called on the wrap so the Kalman state does not bleed across the loop boundary.

After the source is opened the user will see the user interface. The window shows the original video (top) and the video processed by the stabilisation algorithm (bottom). The upper part of the window shows the processing time of the current video frame.

vstabiliser2dlite_demo_app

Control

To control the application, it is necessary that the main video display window was active (in focus), and also it is necessary that the English keyboard layout was activated without CapsLock mode. The program is controlled by the keyboard and by two on-screen sliders.

Table 8 - Control buttons.

Button Description
ESC Exit the application. If video recording is active, it will be stopped.
SPACE Reset stabilization algorithm.
H Hold (pause) stabilisation for 1 second. Invokes the HOLD_MSEC command with a 1000 ms argument: input frames are passed through unchanged for one second, after which stabilisation resumes automatically.
R Start/stop video recording. When video recording is enabled, a files dst_[date and time].avi (result video) and mix_[date and time].avi (combined source and result video) are created in the directory with the application executable file. Recording is performed of what is displayed to the user. To stop the recording, press the R key again. During video recording, the application shows a warning message.

In addition to the keyboard, the application provides two on-screen sliders (Table 9), attached below the video window.

Table 9 - On-screen sliders.

Control Description
X Coeff % Slider for the horizontal smoothing coefficient (X_FILTER_COEFF). Integer range 0–100 is scaled to [0..1] and applied to every frame. 0 disables horizontal compensation, 1 is maximum horizontal stabilization.
Y Coeff % Slider for the vertical smoothing coefficient (Y_FILTER_COEFF). Integer range 0–100 is scaled to [0..1] and applied to every frame. 0 disables vertical compensation, 1 is maximum vertical stabilization.

Table of contents