gmd_web_logo

Gmd C++ library

v5.5.3

Table of contents

Overview

Gmd C++ library is designed for automatic detection of moving objects on videos. The library is implemented in C++ (C++17 standard) and utilizes the OpenMP library (2.0 standard and newer) to facilitate parallel computation. The library depends on the ObjectDetector, Frame and ConfigReader libraries (their source code is not included in the repository, see Build and connect to your project) and uses no other third-party code. The library is compatible with any processors and operating systems that support the C++ compiler (C++17 standard), provided the compiler has built-in support for the OpenMP (2.0 standard and newer) parallel computing language. The library processes video of different camera types (daylight, SWIR, MWIR and LWIR) and detects small-size and low-contrast moving objects against complex backgrounds. Each instance of the Gmd C++ class performs frame-by-frame processing of one video data stream: the result of a frame also depends on the previous frames of the stream. The library inherits its interface from the ObjectDetector (provides interface for object detector) class, offering flexible and customizable parameters. The library is designed mainly for fixed cameras and for PTZ cameras while pan, tilt and zoom do not change. The library can also be used for object detection after the camera has been moved by an external command. The library compatible with low-power CPU and uses C++17 standard.

Gmd is general-purpose software: it is not tied to any sector or application, and the developer of a program decides what the program does with it.

Versions

Table 1 - Library versions.

Version Release date What’s new
4.0.0 12.06.2020 First version.
5.0.0 11.09.2023 - Interface changed to ObjectDetector.
- Motion mask calculation algorithm optimized.
- Added frame buffer to provide detection on noisy video.
5.1.0 25.09.2023 - ObjectDetector interface updated.
- Added decodeAndExecuteCommand(…) method.
5.1.1 30.10.2023 - getParams method updated.
5.1.2 06.11.2023 - Fixed processing time parameter calculation.
5.1.3 13.11.2023 - ObjectDetector class updated.
5.1.4 02.01.2024 - ObjectDetector class updated.
- Demo application updated.
- Documentation updated.
5.2.0 10.01.2024 - Updated with new interface of ObjectDetector with class names in parameters structure.
5.3.0 18.04.2024 - Frame buffer size runtime changing issue fixed.
- Code optimized.
- Demo application updated.
- Documentation updated.
5.3.1 20.05.2024 - Submodules updated.
- Documentation updated.
5.3.2 10.07.2024 - CMake structure updated.
5.3.3 19.07.2024 - CMake structure updated for compiled version file collection.
5.3.4 13.08.2025 - Fix bug with build on Windows.
5.4.0 17.06.2026 - Search of the objects on the motion mask reworked (less sensitive to noise).
- Reported object rectangle smoothed from frame to frame.
- Memory of the motion mask calculation reduced, motion mask calculation optimized.
- MAX_X_SPEED / MAX_Y_SPEED made SCALE_FACTOR-independent (specified in source-frame pixels).
- Code review fixes (parameter handling, documentation).
5.5.0 23.09.2026 - SIMD acceleration (x86 AVX2, SSE2, and ARM NEON) for frame preprocessing and color format conversion.
- Motion mask calculation accelerated (fast path for the most frequent case, checks without division).
- Compile-time instruction set detection (AVX2 / AVX / SSE2 on x86, ARM NEON on ARM with scalar fallback).
5.5.1 12.10.2026 - Submodules updated.
- Fixed build on x86 without AVX2: the SSE2 path uses only SSE2 intrinsics.
- Added missing standard library includes.
5.5.2 20.10.2026 - Sub-repositories excluded: the dependencies (Frame, ConfigReader, ObjectDetector and SimpleFileDialog for the demo application) are added from the neighbour folders or by the top-level project.
- Input checks: frame data, frame size (32 - 8192 pixels) and data size, mask data and size, NaN, infinity and out of range param values; initObjectDetector(…) changes the params only if all values are valid.
- Fixed crashes on frames without data or with negative size, on decodeAndExecuteCommand(…) without data and with MAX_X_SPEED / MAX_Y_SPEED equal to 0.
- Memory allocation errors are reported by detect(…), setMask(…) and getMotionMask(…).
- Same results with all compilers and processors (no fused multiply-add), CMake option GMD_ENABLE_SIMD.
- Compiler warnings fixed, hardening compiler and linker flags, OpenMP flags given to the programs that link the library.
- Example, benchmark and demo application: input checks and fixes.
- Example: the video file is read and decoded with the VSourceFile library (no OpenCV), the detected objects are printed.
- Demo application: the video file is read and decoded with the VSourceFile library; cameras and video streams are not supported.
- Demo application: the user interface uses the SimpleUI library instead of OpenCV (sliders for the params, video and motion mask side by side); video recording into MP4 files with the VideoRecorderMp4 library.
- Documentation updated.
5.5.3 25.10.2026 - Benchmark application: the frames are drawn with the SimpleUI library, OpenCV is not used any more.
- Stand alone build: the combined dynamic library is linked for the target of the compiler (cross build with Clang).

Library files

The library is supplied as source code or compiled version. The user is provided with a set of files in the form of a CMake project (repository). The repository structure is shown below:

CMakeLists.txt ------------ Main CMake file of the library.
src ----------------------- Folder with library source code.
    CMakeLists.txt -------- CMake file of the library.
    Gmd.h ----------------- Main library header file.
    GmdVersion.h ---------- Header file with library version.
    GmdVersion.h.in ------- Service CMake file to generate version header.
    Gmd.cpp --------------- C++ implementation file.
demo ---------------------- Folder for demo application.
    CMakeLists.txt -------- CMake file for demo application.
    main.cpp -------------- Source C++ file of demo application.
example ------------------- Folder for example application.
    CMakeLists.txt -------- CMake file of example application.
    main.cpp -------------- Source C++ file of example application.
benchmark ----------------- Folder with benchmark application.
    CMakeLists.txt -------- CMake file of benchmark application.
    main.cpp -------------- Source C++ file of benchmark application.
static -------------------- Folder with images of the documentation.
video --------------------- Folder with test video.
    test.mp4 -------------- Test video file.

The library depends on the ObjectDetector library (interface of object detectors) which depends on the Frame (video frame) and ConfigReader (JSON configuration) libraries. The source code of these libraries is not included in the repository (see Build and connect to your project). The example and the demo application depend on the VSourceFile library (reading and decoding of video files) and on the libraries VSourceFile depends on (VSource, VCodec, VDecoderH264, VDecoderH265, VDecoderJPEG, FormatConverter). Additionally demo application depends on the SimpleFileDialog library which provide file dialog function, on the SimpleUI library which provides the user interface (window, sliders and drawing) and on the VideoRecorderMp4 library which records video into MP4 files (it depends on the VEncoderJPEG, FormatConverter and VCodec libraries). The benchmark application depends on the SimpleUI library, which draws the moving objects on the frames.

Key features and capabilities

Table 2 - Key features and capabilities.

Parameter and feature Description
Programming language C++ (standard C++17) using the OpenMP library (version 2.0 and higher).
Supported OS Compatible with any operating system that supports the C++ compiler (C++17 standard) and the OpenMP library (version 2.0 and higher).
Shape of detected objects The library is able to detect moving objects of any shape. The minimum and maximum height and width of the objects to be detected are set by the user in the library parameters.
Supported pixel formats RGB24, BGR24, GRAY, YUV24, YUYV, UYVY, NV12, NV21, YV12, YU12. The library uses the GRAY format for video processing. If the pixel format of the image is different from GRAY, the library pre-converts the pixel formats to GRAY.
Maximum and minimum video frame size The minimum size of video frames to be processed is 32x32 pixels, and the maximum size is 8192x8192 pixels (frames of other sizes are rejected). The size of the video frames to be processed has a significant impact on the computation speed.
Coordinate system The algorithm uses a window coordinate system with the zero point in the upper left corner of the video frame.
Calculation speed The processing time per video frame depends on the computing platform used. The processing time per video frame can be estimated with the demo application. It is possible to scale video frames to provide higher calculation speed.
Discreteness of computation of coordinates The algorithm calculates the object bounding box for each detected object. The increment for calculation of position and parameters of the bounding box is 1 pixel.
Detection of moving objects An object is reported after it has moved in one horizontal or vertical direction during X_DETECTION_CRITERIA or Y_DETECTION_CRITERIA frames. After that it is reported with the same ID on every frame on which it is found (see Library principles).
Working conditions Algorithms implemented in the library are designed to work on fixed cameras mainly. It is possible to work with slight camera movement depending on the background. It is also possible to operate with a moving camera when the background is uniform. It is recommended to use a demo application to evaluate the quality of the algorithms in specific situations.

Supported pixel formats

Frame library (dependency of the Gmd library) contains Fourcc enum which defines supported pixel formats (Frame.h file). Gmd library supports RAW pixel formats only. The library uses the GRAY format for video processing. If the pixel format of the image is different from GRAY, the library pre-converts the pixel formats to GRAY. 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'),
    /// JPEG compressed format.
    JPEG  = MAKE_FOURCC_CODE('J', 'P', 'E', 'G'),
    /// H264 compressed format.
    H264  = MAKE_FOURCC_CODE('H', '2', '6', '4'),
    /// HEVC compressed format.
    HEVC  = MAKE_FOURCC_CODE('H', 'E', 'V', 'C')
};

Table 3 - Bytes layout of supported RAW pixel formats. Example of 4x4 pixels image.

rgbRGB24 bgrBGR24
yuvYUV24 grayGRAY
yuyvYUYV uyvyUYVY
nv12NV12 nv21NV21
yu12YU12 yv12YV12

Library principles

The library processes each video frame in the following steps:

  1. The frame is converted to GRAY format (grayscale) and reduced SCALE_FACTOR times horizontally and vertically (processing size). If FRAME_BUFFER_SIZE is greater than 1, the mean of the last FRAME_BUFFER_SIZE frames is processed.
  2. The binary motion mask of the frame is calculated at the processing size (0 - no motion, 255 - motion). SENSITIVITY sets the brightness threshold, pixels where the detection mask is 0 have no motion. This is the most time-consuming step, it can be calculated in several threads (NUM_THREADS). The motion mask of the last frame is given by the getMotionMask(…) method.
  3. The objects of the frame are found on the motion mask and filtered by size (MIN_OBJECT_WIDTH, MAX_OBJECT_WIDTH, MIN_OBJECT_HEIGHT and MAX_OBJECT_HEIGHT).
  4. The objects are matched with the objects of the previous frames, so an object keeps its ID from frame to frame. MAX_X_SPEED and MAX_Y_SPEED set the largest expected movement of an object between two frames.
  5. An object is reported after it has moved in one horizontal or vertical direction during X_DETECTION_CRITERIA or Y_DETECTION_CRITERIA frames. After that it is reported with the same ID on every frame on which it is found. An object that is not found during RESET_CRITERIA frames in a row is dropped (it is kept while it overlaps another object which is already reported): when it is found again, it is reported after the same number of frames and with a new ID.
  6. The objects of the last frame can be retrieved using the getObjects() method.

The library is available as either source code or a compiled application. To utilize the library as source code, developers must incorporate the library files into their project. The usage sequence for the library is as follows:

  1. Include the library files in the project.
  2. Create an instance of the Gmd C++ class. If you need multiple parallel cameras processing you have to create multiple Gmd C++ class instances.
  3. If necessary, modify the default library parameters using the setParam(…) method.
  4. Create Frame class object for input frame and a vector of Objects.
  5. Call the detect(…) method to identify objects.
  6. Fill the created vector of Objects using the getObjects() method.

Motion detection principles:

gmd_principle

Gmd class description

Gmd class declaration

Gmd.h file contains Gmd class declaration. Gmd class inherits interface from ObjectDetector interface class. The methods detect(…) and getMotionMask(…) must be called from one thread; all other methods are thread-safe and can be called from any thread, also while a frame is processed (a change of params is applied from the next frame). Class declaration:

class Gmd : public ObjectDetector
{
public:
    /// Get string of current library version.
    static std::string getVersion();

    /// Class constructor.
    Gmd();

    /// Class destructor.
    ~Gmd() override;

    /// The detector can not be copied or moved (it owns mutexes).
    Gmd(const Gmd&) = delete;
    Gmd(Gmd&&) = delete;
    Gmd& operator= (const Gmd&) = delete;
    Gmd& operator= (Gmd&&) = delete;

    /// Init object detector.
    bool initObjectDetector(ObjectDetectorParams& params) override;
    
    /// Set object detector param.
    bool setParam(ObjectDetectorParam id, float value) override;
    
    /// Get object detector param value.
    float getParam(ObjectDetectorParam id) override;
    
    /// Get object detector params structure.
    void getParams(ObjectDetectorParams& params) override;
    
    /// Get list of objects.
    std::vector<Object> getObjects() override;
    
    /// Execute command.
    bool executeCommand(ObjectDetectorCommand id) override;
    
    /// Perform detection.
    bool detect(rapidpixel::Frame& frame) override;
    
    /// Set detection mask.
    bool setMask(rapidpixel::Frame mask) override;
    
    /// Decode command.
    bool decodeAndExecuteCommand(uint8_t* data, int size) override;
    
    /// Get the binary motion mask of the last processed frame.
    bool getMotionMask(rapidpixel::Frame& mask);
};

getVersion method

The getVersion() method returns string of current version of Gmd class. Method declaration:

static std::string getVersion();

Method can be used without Gmd class instance. Example:

std::cout << "Gmd version: " << rapidpixel::Gmd::getVersion() << std::endl;

Console output:

Gmd version: 5.5.3

initObjectDetector method

The initObjectDetector(…) method initializes motion detector. Method declaration:

bool initObjectDetector(ObjectDetectorParams& params) override;
Parameter Value
params Object detector parameters class. Object detector should initialize all parameters listed in ObjectDetectorParams. The library takes into account only following parameters from ObjectDetectorParams class:
frameBufferSize (Default value 1)
minObjectWidth (Default value 4)
maxObjectWidth (Default value 128)
minObjectHeight (Default value 4)
maxObjectHeight (Default value 128)
sensitivity (Default value 10)
scaleFactor (Default value 1)
numThreads (Default value 1)
minXSpeed (Default value 0.1)
maxXSpeed (Default value 15)
minYSpeed (Default value 0.1)
maxYSpeed (Default value 15)
xDetectionCriteria (Default value 15)
yDetectionCriteria (Default value 15)
resetCriteria (Default value 5)
enable (Default value true)
The values are checked with the rules of setParam(…) (see ObjectDetectorParam enum description). The params are changed only if all values are valid. The list of detected objects is cleared. initObjectDetector(…) is thread-safe.

Returns: TRUE if all values are valid and the params are set or FALSE if a value is not valid (no param is changed then).

setParam method

The setParam(…) method designed to set new object detector parameter value. setParam(…) is thread-safe method. This means that the setParam(…) method can be safely called from any thread. Method declaration:

bool setParam(ObjectDetectorParam id, float value) override;
Parameter Description
id Parameter ID according to ObjectDetectorParam enum. The library supports not all parameters from ObjectDetectorParam enum.
value Parameter value. Value depends on parameter ID. Integer parameters take the value truncated toward zero (for example 2.9 sets 2). NaN, infinity and values outside of the valid range of the parameter (see ObjectDetectorParam enum description) are rejected.

Returns: TRUE if the parameter was set or FALSE if not (not supported or not valid value, the parameter is not changed then).

getParam method

The getParam(…) method designed to obtain object detector parameter value. getParam(…) is thread-safe method. This means that the getParam(…) method can be safely called from any thread. Method declaration:

float getParam(ObjectDetectorParam id) override;
Parameter Description
id Parameter ID according to ObjectDetectorParam enum. The library supports not all parameters from ObjectDetectorParam enum. If the library doesn’t support particular parameter the method will return -1.

Returns: parameter value or -1 if the parameter is not supported by the library.

getParams method

The getParams(…) method designed to obtain object detector params structures as well a list of detected objects (included in ObjectDetectorParams class). getParams(…) is thread-safe method. This means that the getParams(…) method can be safely called from any thread. Method declaration:

void getParams(ObjectDetectorParams& params) override;
Parameter Description
params Object detector params ObjectDetectorParams. If the library doesn’t support particular parameter it will be not changeable and will have default value.

getObjects method

The getObjects() method returns list of detected objects. User can obtain object list of detected objects via getParams(…) method as well. Method declaration:

std::vector<Object> getObjects() override;

Returns: list of objects detected on the last processed frame (see Object class description). If no detected object or the detector is disabled the list will be empty. getObjects() is thread-safe.

executeCommand method

The executeCommand(…) method designed to execute object detector command. executeCommand(…) is thread-safe method. This means that the executeCommand(…) method can be safely called from any thread. Method declaration:

bool executeCommand(ObjectDetectorCommand id) override;
Parameter Description
id Command ID according to ObjectDetectorCommand enum.

Returns: TRUE is the command was executed or FALSE if not (only if command ID not valid).

detect method

The detect(…) performs detection algorithm. Method declaration:

bool detect(rapidpixel::Frame& frame) override;
Parameter Description
frame Video frame for processing. Object detector processes only RAW pixel formats (BGR24, RGB24, GRAY, YUV24, YUYV, UYVY, NV12, NV21, YV12, YU12, see Frame class description). The library uses the GRAY format for video processing. If the pixel format of the image is different from GRAY, the library pre-converts the pixel formats to GRAY. The frame must have data (not nullptr), width and height from 32 to 8192 pixels and a data size (size field, bytes) not smaller than the size the library reads: width x height for GRAY, NV12, NV21, YV12 and YU12 (only the luma plane is used), width x height x 2 for YUYV and UYVY, width x height x 3 for BGR24, RGB24 and YUV24. The library can not check that the data pointer is valid for the data size: this is the responsibility of the caller.

Returns: TRUE if the video frame was processed or the detector is disabled. FALSE if the frame is not valid (the state of the detector is not changed), if the memory for the frame size can not be allocated (the detector is reset) or if the frame has more objects than the detector can associate with its tracks (scene with too much motion: the tracks are aged and no objects are reported). The list of detected objects is empty after FALSE. detect(…) must not be called from several threads at the same time.

setMask method

The setMask(…) method designed to set detection mask. The user can disable detection in any areas of the video frame. For this purpose the user can create an image of any size and configuration with GRAY pixel format. Mask image pixel values equal to 0 prohibit detection of objects in the corresponding place of video frames. Any other mask pixel value other than 0 allows detection of objects at the corresponding location of video frames. The mask is used for detection algorithms to compute a binary motion mask. The method can be called either before video frame processing or during video frame processing. Method declaration:

bool setMask(rapidpixel::Frame mask) override;
Parameter Description
mask Detection mask is a Frame object with GRAY pixel format (NV12, NV21, YV12 and YU12 are also accepted - their luma plane is used). Detector omits image segments where detection mask pixel values equal 0. Mask can have any resolution from 1x1 to 8192x8192 pixels; it must have data (not nullptr) and a data size not smaller than width x height. If the mask resolution (width and height) is not equal to the processing resolution, the library resamples the mask (nearest-neighbour, up or down as needed) to the internal processing matrix resolution (frame width/height divided by SCALE_FACTOR) used to compute the binary motion mask. The mask is applied when the next frame is processed. setMask(…) is thread-safe.

Returns: TRUE if the mask is accepted or FALSE if not (not valid pixel format, size or data, or the memory can not be allocated; the mask is not changed then).

getMotionMask method

The getMotionMask(…) method retrieves the motion detection binary mask (0 - no motion, 255 - motion) of the last processed frame, that is utilized by the detector to identify objects in the video stream. Method not included in ObjectDetector interface. The method is not thread-safe: it must be called from the same thread as detect(…). Method declaration:

bool getMotionMask(rapidpixel::Frame& mask);
Parameter Description
mask Image of the motion mask. The mask is always produced in GRAY pixel format at the internal (scaled) matrix resolution. If the passed Frame does not already match that format and resolution (or has no data), the library reallocates it as GRAY at the matrix resolution before filling it.

Returns: TRUE if the motion mask was copied or FALSE if not (the detector has no buffers after a failed memory allocation or the memory of the mask can not be allocated).

decodeAndExecuteCommand method

The decodeAndExecuteCommand(…) method decodes and executes command which encoded by encodeSetParamCommand(…) or encodeCommand(…) method of ObjectDetector class. decodeAndExecuteCommand(…) is thread-safe method. This means that 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. nullptr is rejected (the method returns FALSE).
size Size of command. Must be 11 bytes for SET_PARAM or 7 bytes for COMMAND.

Returns: TRUE if command decoded (SET_PARAM or COMMAND) and executed (action command or set param command) or FALSE if not. The decoded parameter ID, value and command ID are checked by setParam(…) and executeCommand(…).

encodeSetParamCommand method of ObjectDetector class

The encodeSetParamCommand(…) static method of the ObjectDetector interface designed to encode command to change any parameter for remote object detector (including motion detectors). To control object detector remotely, the developer has to design his own protocol and according to it encode the command and deliver it over the communication channel. To simplify this, the ObjectDetector class contains static methods for encoding the control command. The ObjectDetector 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, ObjectDetectorParam 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 ObjectDetectorParam enum.
value Parameter value. Value depends on parameter ID.

encodeSetParamCommand(…) is static and used without ObjectDetector class instance. This method used on client side (control system). Command encoding example:

// Buffer for encoded data.
uint8_t data[11];
// Size of encoded data.
int size = 0;
// Parameter value.
float outValue = 10.0f;
// Encode command.
rapidpixel::ObjectDetector::encodeSetParamCommand(
    data, size, rapidpixel::ObjectDetectorParam::MIN_OBJECT_WIDTH, outValue);

encodeCommand method of ObjectDetector class

The encodeCommand(…) static method of the ObjectDetector interface designed to encode command for remote object detector (including motion detectors). To control object detector remotely, the developer has to design his own protocol and according to it encode the command and deliver it over the communication channel. To simplify this, the ObjectDetector class contains static methods for encoding the control command. The ObjectDetector class provides two types of commands: a parameter change command (SET_PARAM) and an action command (COMMAND). encodeCommand(…) designed to encode COMMAND (action command). Method declaration:

static void encodeCommand(uint8_t* data, int& size, ObjectDetectorCommand id);
Parameter Description
data Pointer to data buffer for encoded command. Must have size >= 7.
size Size of encoded data. Will be 7 bytes.
id Command ID according to ObjectDetectorCommand enum.

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

// Buffer for encoded data.
uint8_t data[11];
// Size of encoded data.
int size = 0;
// Encode command.
rapidpixel::ObjectDetector::encodeCommand(
    data, size, rapidpixel::ObjectDetectorCommand::RESET);

decodeCommand method of ObjectDetector class

The decodeCommand(…) static method of the ObjectDetector interface designed to decode command on object detector side (edge device) encoded by encodeSetParamCommand(…) or encodeCommand(…) method of ObjectDetector class. Method declaration:

static int decodeCommand(uint8_t* data, int size, ObjectDetectorParam& paramId, ObjectDetectorCommand& commandId, float& value);
Parameter Description
data Pointer to input command. Must not be nullptr (the method returns -1). The pointer must be valid for size bytes.
size Size of command. Must be exactly 7 bytes for COMMAND or exactly 11 bytes for SET_PARAM.
paramId Parameter ID according to ObjectDetectorParam enum. After decoding SET_PARAM command the method will return parameter ID.
commandId Command ID according to ObjectDetectorCommand enum. After decoding COMMAND the method will return command ID.
value Parameter value (after decoding SET_PARAM command).

Returns: 0 - in case decoding COMMAND, 1 - in case decoding SET_PARAM command or -1 in case errors (data is nullptr, wrong size, wrong version, wrong command type or ID which is not a member of the enum). The method checks the version (MAJOR.MINOR) of the ObjectDetector library which encoded the command. The output arguments are not changed if the method returns -1.

Data structures

ObjectDetectorCommand enum

Enum declaration:

enum class ObjectDetectorCommand
{
    /// Reset.
    RESET = 1,
    /// Enable.
    ON,
    /// Disable.
    OFF
};

Table 4 - Object detector commands description. Some commands maybe unsupported by particular object detector class.

Command Description
RESET Reset algorithm. Clears the list of detected objects and resets all internal filters. Reset command will be applied only after processing new video frame.
ON Enable object detector. If the detector is not activated, frame processing is not performed - the list of detected objects will always be empty.
OFF Disable object detector. If the detector is not activated, frame processing is not performed - the list of detected objects will always be empty.

ObjectDetectorParam enum

Enum declaration:

enum class ObjectDetectorParam
{
    /// Logging mode. Values:
    /// 0 - Disable,
    /// 1 - Only file,
    /// 2 - Only terminal (console),
    /// 3 - File and terminal (console).
    LOG_MODE = 1,
    /// Frame buffer size. Depends on implementation.
    FRAME_BUFFER_SIZE,
    /// Minimum object width to be detected, pixels. To be detected object's
    /// width must be >= MIN_OBJECT_WIDTH.
    MIN_OBJECT_WIDTH,
    /// Maximum object width to be detected, pixels. To be detected object's
    /// width must be <= MAX_OBJECT_WIDTH.
    MAX_OBJECT_WIDTH,
    /// Minimum object height to be detected, pixels. To be detected object's
    /// height must be >= MIN_OBJECT_HEIGHT.
    MIN_OBJECT_HEIGHT,
    /// Maximum object height to be detected, pixels. To be detected object's
    /// height must be <= MAX_OBJECT_HEIGHT.
    MAX_OBJECT_HEIGHT,
    /// Minimum object's horizontal speed to be detected, pixels/frame. To be
    /// detected object's horizontal speed must be >= MIN_X_SPEED.
    MIN_X_SPEED,
    /// Maximum object's horizontal speed to be detected, pixels/frame. To be
    /// detected object's horizontal speed must be <= MAX_X_SPEED.
    MAX_X_SPEED,
    /// Minimum object's vertical speed to be detected, pixels/frame. To be
    /// detected object's vertical speed must be >= MIN_Y_SPEED.
    MIN_Y_SPEED,
    /// Maximum object's vertical speed to be detected, pixels/frame. To be
    /// detected object's vertical speed must be <= MAX_Y_SPEED.
    MAX_Y_SPEED,
    /// Probability threshold from 0 to 1. To be detected object detection
    /// probability must be >= MIN_DETECTION_PROBABILITY.
    MIN_DETECTION_PROBABILITY,
    /// Horizontal track detection criteria, frames. By default shows how many
    /// frames the objects must move in any(+/-) horizontal direction to be
    /// detected.
    X_DETECTION_CRITERIA,
    /// Vertical track detection criteria, frames. By default shows how many
    /// frames the objects must move in any(+/-) vertical direction to be
    /// detected.
    Y_DETECTION_CRITERIA,
    /// Track reset criteria, frames. By default shows how many
    /// frames the objects should be not detected to be excluded from results.
    RESET_CRITERIA,
    /// Detection sensitivity. Depends on implementation. Default from 0 to 1.
    SENSITIVITY,
    /// Frame scaling factor for processing purposes. Reduce the image size by
    /// scaleFactor times horizontally and vertically for faster processing.
    SCALE_FACTOR,
    /// Num threads. Number of threads for parallel computing.
    NUM_THREADS,
    /// Processing time of last frame in microseconds.
    PROCESSING_TIME_MCS,
    /// Algorithm / backend type. Depends on implementation.
    TYPE,
    /// Mode. Default: 0 - Off, 1 - On.
    MODE,
    /// Custom parameter. Depends on implementation.
    CUSTOM_1,
    /// Custom parameter. Depends on implementation.
    CUSTOM_2,
    /// Custom parameter. Depends on implementation.
    CUSTOM_3
};

Table 5 - Gmd class params description (from ObjectDetector interface class). Some params may be unsupported by Gmd class.

Parameter Access Description
LOG_MODE – Not supported by Gmd. setParam() returns FALSE and getParam() returns -1.
FRAME_BUFFER_SIZE read / write Frame buffer size (temporal smoothing), frames. Valid values from 1 to 128. Default value is 1. The detector averages each pixel over the last FRAME_BUFFER_SIZE frames and looks for motion on this averaged image. 1 - no averaging, maximum responsiveness: best for fast and/or small targets (a larger value smears their motion and can average a small target away). Greater than 1 - time smoothing that averages out a fast-changing background (water ripples and glints, sensor noise, heat shimmer, foliage): suitable for slow objects - the target barely moves between the averaged frames and survives, while the background clutter is smoothed away. Higher values suppress more clutter but add latency and blur fast motion, so use the smallest value that cleans up the background.
MIN_OBJECT_WIDTH read / write Minimum object width to be detected, pixels. Valid values from 1 to 8192. Should be <= MAX_OBJECT_WIDTH (the values are not checked against each other: if MIN_OBJECT_WIDTH > MAX_OBJECT_WIDTH no object is detected). To be detected object’s width must be >= MIN_OBJECT_WIDTH (compared at the processing size: values divided by SCALE_FACTOR). Default value is 4.
MAX_OBJECT_WIDTH read / write Maximum object width to be detected, pixels. Valid values from 1 to 8192. Should be >= MIN_OBJECT_WIDTH. To be detected object’s width must be <= MAX_OBJECT_WIDTH (compared at the processing size). Default value is 128.
MIN_OBJECT_HEIGHT read / write Minimum object height to be detected, pixels. Valid values from 1 to 8192. Should be <= MAX_OBJECT_HEIGHT (the values are not checked against each other: if MIN_OBJECT_HEIGHT > MAX_OBJECT_HEIGHT no object is detected). To be detected object’s height must be >= MIN_OBJECT_HEIGHT (compared at the processing size). Default value is 4.
MAX_OBJECT_HEIGHT read / write Maximum object height to be detected, pixels. Valid values from 1 to 8192. Should be >= MIN_OBJECT_HEIGHT. To be detected object’s height must be <= MAX_OBJECT_HEIGHT (compared at the processing size). Default value is 128.
MIN_X_SPEED read / write Minimum horizontal movement threshold, pixels/frame. Fixed at 0.1 in Gmd (not configurable): setParam(…) accepts any value and keeps 0.1.
MAX_X_SPEED read / write Maximum EXPECTED horizontal displacement of an object between two frames, in source-frame pixels/frame (independent of SCALE_FACTOR). This is not a hard speed filter: an object whose per-frame motion exceeds this value cannot be linked to its track and is effectively dropped, while slower objects are NOT rejected. Set it to ~the fastest expected object motion. Valid values from 0 to 256. Recommended value is 15.
MIN_Y_SPEED read / write Minimum vertical movement threshold, pixels/frame. Fixed at 0.1 in Gmd (not configurable): setParam(…) accepts any value and keeps 0.1.
MAX_Y_SPEED read / write Maximum EXPECTED vertical displacement of an object between two frames, in source-frame pixels/frame (independent of SCALE_FACTOR). Not a hard speed filter — see MAX_X_SPEED. Valid values from 0 to 256. Recommended value is 15.
MIN_DETECTION_PROBABILITY read / write Not used. Can have any values (stored without check). Default value is -1.
X_DETECTION_CRITERIA read / write Horizontal track detection criteria, frames. Shows how many frames the objects must move in any(+/-) horizontal direction to be detected. Valid values from 1 to 256. Default value is 15.
Y_DETECTION_CRITERIA read / write Vertical track detection criteria, frames. Shows how many frames the objects must move in any(+/-) vertical direction to be detected. Valid values from 1 to 256. Default value is 15.
RESET_CRITERIA read / write Track reset criteria, frames. Shows how many frames the objects should be not detected to be excluded from results. Valid values from 1 to 256. Default value is 5.
SENSITIVITY read / write Detection sensitivity. For Gmd library this parameters means pixel brightness deviation threshold from 0.001 to 255 for calculation motion mask. The first processing step is the computation of the binary motion mask. The algorithm makes a decision about the presence of motion in a particular pixel also on the basis of changes in pixel brightness. The brightness threshold is determined by the SENSITIVITY parameter. The lower this parameter is, the less contrasty objects will be detected, but there will be more influence of video noise. The larger this parameter is, the more contrast objects must have in order to be detected. The normal value for thermal cameras is 15. The normal value for daylight cameras is 10. Default value is 10.
SCALE_FACTOR read / write Frame scaling factor for processing purposes. Reduce the image size by scaleFactor times horizontally and vertically for faster processing. Allows to increase calculation speed but slightly reduces sensitivity. Valid values from 1 to 10 (an out-of-range value is rejected and the previous value is kept). Default value is 1.
NUM_THREADS read / write Num threads. Number of threads used to compute the binary motion mask. Valid values from 0 to 64. A value of 0 or 1 means single-threaded processing; values greater than 1 split the motion-mask computation into that many horizontal row bands (capped at the processing height divided by 8, rounded up).
PROCESSING_TIME_MCS read only Processing time of last frame in microseconds. setParam(…) returns FALSE.
TYPE – Not supported by Gmd. setParam() returns FALSE and getParam() returns -1.
MODE read / write Mode. Default: 0 - Off, 1 - On (any other value is On, NaN and infinity are rejected). If the detector is not activated, frame processing is not performed - the list of detected objects will always be empty. Default value is 1.
CUSTOM_1 – Not supported by Gmd. setParam() returns FALSE and getParam() returns -1.
CUSTOM_2 – Not supported by Gmd. setParam() returns FALSE and getParam() returns -1.
CUSTOM_3 – Not supported by Gmd. setParam() returns FALSE and getParam() returns -1.

Object structure

Object structure used to describe detected object. Object structure declared in ObjectDetector.h file and also included in ObjectDetectorParams structure. Structure declaration:

struct Object
{
    /// Object ID. Must be unique for particular object.
    int id{ 0 };
    /// Frame ID. Must be the same as frame ID of processed video frame.
    int frameId{ 0 };
    /// Object type. Depends on implementation.
    int type{ 0 };
    /// Object rectangle width, pixels.
    int width{ 0 };
    /// Object rectangle height, pixels.
    int height{ 0 };
    /// Object rectangle top-left horizontal coordinate, pixels.
    int x{ 0 };
    /// Object rectangle top-left vertical coordinate, pixels.
    int y{ 0 };
    /// Horizontal component of object velocity, +-pixels/frame.
    float vX{ 0.0f };
    /// Vertical component of object velocity, +-pixels/frame.
    float vY{ 0.0f };
    /// Detection probability from 0 (minimum) to 1 (maximum).
    float p{ 0.0f };
};

Table 6 - Object structure fields description.

Field Type Description
id int Object ID (from 1). The library will try keep the same object ID for particular object from frame to frame.
frameId int Frame ID. Will be the same as frame ID of processed video frame.
type int Object type. Gmd always reports 0 (no object classes).
width int Object rectangle width, pixels (at least 1). The size filter (MIN_OBJECT_WIDTH and MAX_OBJECT_WIDTH, see ObjectDetectorParam enum description) is applied to the objects found on the motion mask; the reported rectangle of an object is smoothed from frame to frame.
height int Object rectangle height, pixels (at least 1). The size filter (MIN_OBJECT_HEIGHT and MAX_OBJECT_HEIGHT) is applied to the objects found on the motion mask; the reported rectangle of an object is smoothed from frame to frame.
x int Object rectangle top-left horizontal coordinate, pixels. Near the borders of the frame the rectangle can be partly outside of the frame.
y int Object rectangle top-left vertical coordinate, pixels.
vX float Horizontal component of the estimated object velocity, pixels/frame (in source-frame pixels).
vY float Vertical component of the estimated object velocity, pixels/frame (in source-frame pixels).
p float Detection probability. Gmd always reports 1.0f for detected (confirmed-track) objects.

ObjectDetectorParams class description

ObjectDetectorParams class declaration

ObjectDetectorParams class used for object detector initialization (initObjectDetector(…) method) or to get all actual params (getParams() method) including list of detected objects. Also ObjectDetectorParams provides structure to write/read params from JSON files (JSON_READABLE macro, see ConfigReader class description) and provide methods to encode and decode params. Class declaration:

class ObjectDetectorParams
{
public:
    /// Init string. Depends on implementation.
    std::string initString{ "" };
    /// Logging mode. Values:
    /// 0 - Disable,
    /// 1 - Only file,
    /// 2 - Only terminal (console),
    /// 3 - File and terminal (console).
    int logMode{ 0 };
    /// Frame buffer size. Depends on implementation.
    int frameBufferSize{ 1 };
    /// Minimum object width to be detected, pixels. To be detected object's
    /// width must be >= minObjectWidth.
    int minObjectWidth{ 4 };
    /// Maximum object width to be detected, pixels. To be detected object's
    /// width must be <= maxObjectWidth.
    int maxObjectWidth{ 128 };
    /// Minimum object height to be detected, pixels. To be detected object's
    /// height must be >= minObjectHeight.
    int minObjectHeight{ 4 };
    /// Maximum object height to be detected, pixels. To be detected object's
    /// height must be <= maxObjectHeight.
    int maxObjectHeight{ 128 };
    /// Minimum object's horizontal speed to be detected, pixels/frame. To be
    /// detected object's horizontal speed must be >= minXSpeed.
    float minXSpeed{ 0.0f };
    /// Maximum object's horizontal speed to be detected, pixels/frame. To be
    /// detected object's horizontal speed must be <= maxXSpeed.
    float maxXSpeed{ 30.0f };
    /// Minimum object's vertical speed to be detected, pixels/frame. To be
    /// detected object's vertical speed must be >= minYSpeed.
    float minYSpeed{ 0.0f };
    /// Maximum object's vertical speed to be detected, pixels/frame. To be
    /// detected object's vertical speed must be <= maxYSpeed.
    float maxYSpeed{ 30.0f };
    /// Probability threshold from 0 to 1. To be detected object detection
    /// probability must be >= minDetectionProbability.
    float minDetectionProbability{ 0.5f };
    /// Horizontal track detection criteria, frames. By default shows how many
    /// frames the objects must move in any(+/-) horizontal direction to be
    /// detected.
    int xDetectionCriteria{1};
    /// Vertical track detection criteria, frames. By default shows how many
    /// frames the objects must move in any(+/-) vertical direction to be
    /// detected.
    int yDetectionCriteria{ 1 };
    /// Track reset criteria, frames. By default shows how many
    /// frames the objects should be not detected to be excluded from results.
    int resetCriteria{ 1 };
    /// Detection sensitivity. Depends on implementation. Default from 0 to 1.
    float sensitivity{ 0.04f };
    /// Frame scaling factor for processing purposes. Reduce the image size by
    /// scaleFactor times horizontally and vertically for faster processing.
    int scaleFactor{ 1 };
    /// Num threads. Number of threads for parallel computing.
    int numThreads{ 1 };
    /// Processing time of last frame in microseconds.
    int processingTimeMcs{ 0 };
    /// Algorithm / backend type. Depends on implementation.
    int type{ 0 };
    /// Mode. Default: false - Off, on - On.
    bool enable{ true };
    /// Custom parameter. Depends on implementation.
    float custom1{ 0.0f };
    /// Custom parameter. Depends on implementation.
    float custom2{ 0.0f };
    /// Custom parameter. Depends on implementation.
    float custom3{ 0.0f };
    /// List of detected objects.
    std::vector<Object> objects;
    // A list of object class names used in detectors that recognize different
    // object classes. Detected objects have an attribute called 'type.'
    // If a detector doesn't support object class recognition or can't determine
    // the object type, the 'type' field must be set to 0. Otherwise, the 'type'
    // should correspond to the ordinal number of the class name from the
    // 'classNames' list (if the list was set in params), starting from 1
    // (where the first element in the list has 'type == 1').
    std::vector<std::string> classNames{ "" };

    JSON_READABLE(ObjectDetectorParams, initString, logMode, frameBufferSize,
                  minObjectWidth, maxObjectWidth, minObjectHeight,
                  maxObjectHeight, minXSpeed, maxXSpeed, minYSpeed, maxYSpeed,
                  minDetectionProbability, xDetectionCriteria,
                  yDetectionCriteria, resetCriteria, sensitivity, scaleFactor,
                  numThreads, type, enable, custom1, custom2, custom3,
                  classNames);

    /**
     * @brief Default constructor.
     */
    ObjectDetectorParams() = default;

    /**
     * @brief Copy constructor.
     * @param src Source object.
     */
    ObjectDetectorParams(const ObjectDetectorParams& src) = default;

    /**
     * @brief Copy operator.
     * @param src Source object.
     * @return ObjectDetectorParams object.
     */
    ObjectDetectorParams& operator= (const ObjectDetectorParams& src) = default;

    /**
     * @brief Encode (serialize) params.
     * @param data Pointer to data buffer.
     * @param bufferSize Size of data buffer.
     * @param size Size of data.
     * @param mask Pointer to parameters mask.
     * @return TRUE if params encoded or FALSE if not.
     */
    bool encode(uint8_t* data, int bufferSize, int& size,
                ObjectDetectorParamsMask* mask = nullptr);

    /**
     * @brief Decode (deserialize) params.
     * @param data Pointer to data (serialized params).
     * @param dataSize Size of data.
     * @return TRUE is params decoded or FALSE if not.
     */
    bool decode(uint8_t* data, int dataSize);
};

Table 7 - ObjectDetectorParams class fields description.

Field Type Description
initString string Not used. Can have any values.
logMode int Not used. Can have any values.
frameBufferSize int Frame buffer size (temporal smoothing), frames. Valid values from 1 to 128. Default value is 1. The detector averages each pixel over the last FRAME_BUFFER_SIZE frames and looks for motion on this averaged image. 1 - no averaging, maximum responsiveness: best for fast and/or small targets (a larger value smears their motion and can average a small target away). Greater than 1 - time smoothing that averages out a fast-changing background (water ripples and glints, sensor noise, heat shimmer, foliage): suitable for slow objects - the target barely moves between the averaged frames and survives, while the background clutter is smoothed away. Higher values suppress more clutter but add latency and blur fast motion, so use the smallest value that cleans up the background.
minObjectWidth int Minimum object width to be detected, pixels. Valid values from 1 to 8192. Should be <= maxObjectWidth (see MIN_OBJECT_WIDTH in Table 5). Default value is 4.
maxObjectWidth int Maximum object width to be detected, pixels. Valid values from 1 to 8192. Should be >= minObjectWidth. Default value is 128.
minObjectHeight int Minimum object height to be detected, pixels. Valid values from 1 to 8192. Should be <= maxObjectHeight (see MIN_OBJECT_HEIGHT in Table 5). Default value is 4.
maxObjectHeight int Maximum object height to be detected, pixels. Valid values from 1 to 8192. Should be >= minObjectHeight. Default value is 128.
minXSpeed float Minimum horizontal movement threshold, pixels/frame. Fixed at 0.1 in Gmd (not configurable, any value is accepted).
maxXSpeed float Maximum EXPECTED horizontal displacement of an object between two frames, in source-frame pixels/frame (independent of scaleFactor). Not a hard speed filter: objects moving faster cannot be linked to their track (dropped), slower objects are not rejected. Valid values from 0 to 256. Recommended value is 15.
minYSpeed float Minimum vertical movement threshold, pixels/frame. Fixed at 0.1 in Gmd (not configurable, any value is accepted).
maxYSpeed float Maximum EXPECTED vertical displacement of an object between two frames, in source-frame pixels/frame (independent of scaleFactor). Not a hard speed filter — see maxXSpeed. Valid values from 0 to 256. Recommended value is 15.
minDetectionProbability float Not used. Can have any values.
xDetectionCriteria int Horizontal track detection criteria, frames. Shows how many frames the objects must move in any(+/-) horizontal direction to be detected. Valid values from 1 to 256. Default value is 15.
yDetectionCriteria int Vertical track detection criteria, frames. Shows how many frames the objects must move in any(+/-) vertical direction to be detected. Valid values from 1 to 256. Default value is 15.
resetCriteria int Track reset criteria, frames. Shows how many frames the objects should be not detected to be excluded from results. Valid values from 1 to 256. Default value is 5.
sensitivity float Detection sensitivity. For Gmd library this parameters means pixel brightness deviation threshold from 0.001 to 255 for calculation motion mask. The first processing step is the computation of the binary motion mask. The algorithm makes a decision about the presence of motion in a particular pixel also on the basis of changes in pixel brightness. The brightness threshold is determined by the SENSITIVITY parameter. The lower this parameter is, the less contrasty objects will be detected, but there will be more influence of video noise. The larger this parameter is, the more contrast objects must have in order to be detected. The normal value for thermal cameras is 15. The normal value for daylight cameras is 10.
scaleFactor int Frame scaling factor for processing purposes. Reduce the image size by scaleFactor times horizontally and vertically for faster processing. Allows to increase calculation speed but slightly reduces sensitivity. Valid values from 1 to 10. Default value is 1.
numThreads int Num threads. Number of threads used to compute the binary motion mask. Valid values from 0 to 64. A value of 0 or 1 means single-threaded processing; values greater than 1 split the motion-mask computation into that many horizontal row bands (capped at the processing height divided by 8, rounded up).
processingTimeMcs int Processing time of last frame in microseconds.
type int Not used. Can have any values.
enable bool Mode: false - Off, true - On. If the detector is not activated, frame processing is not performed - the list of detected objects will always be empty.
custom1 float Not used. Can have any values.
custom2 float Not used. Can have any values.
custom3 float Not used. Can have any values.
objects std::vector List of detected objects.
classNames std::vector Not used. Can have any values.

Note: ObjectDetectorParams class fields listed in Table 7 must reflect params set/get by methods setParam(…) and getParam(…).

Serialize object detector params

ObjectDetectorParams class provides method encode(…) to serialize object detector params (fields of ObjectDetectorParams class, see Table 5). Serialization of object detector params necessary in case when you need to send params via communication channels. Method provides options to exclude particular parameters from serialization. To do this method inserts binary mask (4 bytes) where each bit represents particular parameter and decode(…) method recognizes it. Method declaration:

bool encode(uint8_t* data, int bufferSize, int& size, ObjectDetectorParamsMask* mask = nullptr);
Parameter Value
data Pointer to data buffer. Buffer size should be at least 102 bytes.
bufferSize Size of data buffer. If the data buffer size is not large enough to serialize all detected objects (40 bytes per object), not all objects will be included in the data.
size Size of encoded data. For default-constructed params (empty object list, empty initString, single empty class name) it is 102 bytes; it grows by 40 bytes per encoded object plus the lengths of initString and class-name strings.
mask Parameters mask - pointer to ObjectDetectorParamsMask structure. ObjectDetectorParamsMask (declared in ObjectDetector.h file) determines flags for each field (parameter) declared in ObjectDetectorParams class. If the user wants to exclude any parameters from serialization, he can put a pointer to the mask. If the user wants to exclude a particular parameter from serialization, he should set the corresponding flag in the ObjectDetectorParamsMask structure to false.

ObjectDetectorParamsMask structure declaration:

struct ObjectDetectorParamsMask
{
    bool initString{ true };
    bool logMode{ true };
    bool frameBufferSize{ true };
    bool minObjectWidth{ true };
    bool maxObjectWidth{ true };
    bool minObjectHeight{ true };
    bool maxObjectHeight{ true };
    bool minXSpeed{ true };
    bool maxXSpeed{ true };
    bool minYSpeed{ true };
    bool maxYSpeed{ true };
    bool minDetectionProbability{ true };
    bool xDetectionCriteria{ true };
    bool yDetectionCriteria{ true };
    bool resetCriteria{ true };
    bool sensitivity{ true };
    bool scaleFactor{ true };
    bool numThreads{ true };
    bool processingTimeMcs{ true };
    bool type{ true };
    bool enable{ true };
    bool custom1{ true };
    bool custom2{ true };
    bool custom3{ true };
    bool objects{ true };
    bool classNames{ true };
};

Example without parameters mask:

// Prepare params.
rapidpixel::ObjectDetectorParams in;
in.logMode = 1;
in.classNames = { "apple", "banana", "orange", "pineapple", "strawberry",
                  "watermelon", "lemon", "peach", "pear", "plum" };
for (int i = 0; i < 5; ++i)
{
    rapidpixel::Object obj;
    obj.id = i + 1;
    obj.type = i % 3;
    obj.width = 10 + i;
    obj.height = 20 + i;
    obj.x = 100 + 10 * i;
    obj.y = 200 + 10 * i;
    obj.vX = 1.5f;
    obj.vY = -0.5f;
    obj.p = 0.9f;
    in.objects.push_back(obj);
}

// Encode data.
uint8_t data[1024];
int size = 0;
if (!in.encode(data, 1024, size))
{
    std::cout << "Can't encode params" << std::endl;
    return false;
}
std::cout << "Encoded data size: " << size << " bytes" << std::endl;

Example with parameters mask:

// Prepare params.
rapidpixel::ObjectDetectorParams in;
in.logMode = 1;
in.classNames = { "apple", "banana", "orange", "pineapple", "strawberry",
                  "watermelon", "lemon", "peach", "pear", "plum" };
for (int i = 0; i < 5; ++i)
{
    rapidpixel::Object obj;
    obj.id = i + 1;
    obj.type = i % 3;
    obj.width = 10 + i;
    obj.height = 20 + i;
    obj.x = 100 + 10 * i;
    obj.y = 200 + 10 * i;
    obj.vX = 1.5f;
    obj.vY = -0.5f;
    obj.p = 0.9f;
    in.objects.push_back(obj);
}

// Prepare mask.
rapidpixel::ObjectDetectorParamsMask mask;
mask.logMode = false;

// Encode data.
uint8_t data[1024];
int size = 0;
if (!in.encode(data, 1024, size, &mask))
{
    std::cout << "Can't encode params" << std::endl;
    return false;
}
std::cout << "Encoded data size: " << size << " bytes" << std::endl;

Deserialize object detector params

ObjectDetectorParams class provides method decode(…) to deserialize params (fields of ObjectDetectorParams class, see Table 5). Deserialization of params necessary in case when you need to receive params via communication channels. Method automatically recognizes which parameters were serialized by encode(…) method. Method declaration:

bool decode(uint8_t* data, int dataSize);
Parameter Value
data Pointer to encode data buffer.
dataSize Size of encoded data.

Returns: TRUE if data decoded (deserialized) or FALSE if not.

Example:

// Prepare params.
rapidpixel::ObjectDetectorParams in;
in.logMode = 1;
in.classNames = { "apple", "banana", "orange", "pineapple", "strawberry",
                  "watermelon", "lemon", "peach", "pear", "plum" };
for (int i = 0; i < 5; ++i)
{
    rapidpixel::Object obj;
    obj.id = i + 1;
    obj.type = i % 3;
    obj.width = 10 + i;
    obj.height = 20 + i;
    obj.x = 100 + 10 * i;
    obj.y = 200 + 10 * i;
    obj.vX = 1.5f;
    obj.vY = -0.5f;
    obj.p = 0.9f;
    in.objects.push_back(obj);
}

// Encode data.
uint8_t data[1024];
int size = 0;
if (!in.encode(data, 1024, size))
{
    std::cout << "Can't encode params" << std::endl;
    return false;
}
std::cout << "Encoded data size: " << size << " bytes" << std::endl;

// Decode data.
rapidpixel::ObjectDetectorParams out;
if (!out.decode(data, size))
{
    std::cout << "Can't decode data" << std::endl;
    return false;
}

Read params from JSON file and write to JSON file

ObjectDetector library depends on ConfigReader library which provides method to read params from JSON file and to write params to JSON file. Example of writing and reading params to JSON file:

// Prepare params.
rapidpixel::ObjectDetectorParams in;
in.logMode = 1;
in.classNames = { "apple", "banana", "orange", "pineapple", "strawberry",
                  "watermelon", "lemon", "peach", "pear", "plum" };
for (int i = 0; i < 5; ++i)
{
    rapidpixel::Object obj;
    obj.id = i + 1;
    obj.type = i % 3;
    obj.width = 10 + i;
    obj.height = 20 + i;
    obj.x = 100 + 10 * i;
    obj.y = 200 + 10 * i;
    obj.vX = 1.5f;
    obj.vY = -0.5f;
    obj.p = 0.9f;
    in.objects.push_back(obj);
}

// Write params to file.
rapidpixel::ConfigReader inConfig;
if (!inConfig.set(in, "ObjectDetectorParams") ||
    !inConfig.writeToFile("ObjectDetectorParams.json"))
{
    std::cout << "Can't write config file" << std::endl;
    return false;
}

// Read params from file.
rapidpixel::ConfigReader outConfig;
if (!outConfig.readFromFile("ObjectDetectorParams.json"))
{
    std::cout << "Can't open config file" << std::endl;
    return false;
}

rapidpixel::ObjectDetectorParams out;
if (!outConfig.get(out, "ObjectDetectorParams"))
{
    std::cout << "Can't read params from file" << std::endl;
    return false;
}

ObjectDetectorParams.json will look like (the list of objects is not written to the file):

{
    "ObjectDetectorParams": {
        "initString": "",
        "logMode": 1,
        "frameBufferSize": 1,
        "minObjectWidth": 4,
        "maxObjectWidth": 128,
        "minObjectHeight": 4,
        "maxObjectHeight": 128,
        "minXSpeed": 0.0,
        "maxXSpeed": 30.0,
        "minYSpeed": 0.0,
        "maxYSpeed": 30.0,
        "minDetectionProbability": 0.5,
        "xDetectionCriteria": 1,
        "yDetectionCriteria": 1,
        "resetCriteria": 1,
        "sensitivity": 0.039999999105930328,
        "scaleFactor": 1,
        "numThreads": 1,
        "type": 0,
        "enable": true,
        "custom1": 0.0,
        "custom2": 0.0,
        "custom3": 0.0,
        "classNames": [
            "apple",
            "banana",
            "orange",
            "pineapple",
            "strawberry",
            "watermelon",
            "lemon",
            "peach",
            "pear",
            "plum"
        ]
    }
}

Build and connect to your project

Build stand alone

The repository does not contain sub-repositories. The libraries Gmd depends on (Frame, ConfigReader, ObjectDetector), the libraries the example and the demo application depend on (VSource, VCodec, VDecoderH264, VDecoderH265, VDecoderJPEG, FormatConverter, VSourceFile), the library the benchmark and the demo application depend on (SimpleUI) and the libraries only the demo application depends on (SimpleFileDialog, VEncoderJPEG, VideoRecorderMp4) must be cloned into the same folder as Gmd. The folder structure must be:

<work folder>
    Gmd
    Frame
    ConfigReader
    ObjectDetector
    VSource
    VCodec
    VDecoderH264
    VDecoderH265
    VDecoderJPEG
    FormatConverter
    VSourceFile
    SimpleFileDialog
    SimpleUI
    VEncoderJPEG
    VideoRecorderMp4

Typical commands to build the library, the example, the benchmark and the demo application (use the URLs of the repositories provided to you):

git clone <Gmd repository URL>
git clone <Frame repository URL>
git clone <ConfigReader repository URL>
git clone <ObjectDetector repository URL>
git clone <VSource repository URL>
git clone <VCodec repository URL>
git clone <VDecoderH264 repository URL>
git clone <VDecoderH265 repository URL>
git clone <VDecoderJPEG repository URL>
git clone <FormatConverter repository URL>
git clone <VSourceFile repository URL>
git clone <SimpleFileDialog repository URL>
git clone <SimpleUI repository URL>
git clone <VEncoderJPEG repository URL>
git clone <VideoRecorderMp4 repository URL>
cd Gmd
mkdir build
cd build
cmake ..
make

On Windows use cmake --build . --config Release instead of make. If Gmd is the top-level CMake project, the main CMakeLists.txt file adds the folders ../Frame, ../ConfigReader and ../ObjectDetector (in this order) before the library itself, the folder ../SimpleUI (once) before the benchmark and the demo application, the folders ../VSource, ../VCodec, ../VDecoderH264, ../VDecoderH265, ../VDecoderJPEG, ../FormatConverter and ../VSourceFile (in this order, once) before the demo application and the example and the folders ../SimpleFileDialog, ../VEncoderJPEG and ../VideoRecorderMp4 (in this order) before the demo application. If a folder does not exist CMake stops with an error. The folders of a program are not needed if the program is not built, for example cmake .. -D_SUBMODULE_CACHE_OVERWRITE=OFF -D_GMD_EXAMPLE=OFF -D_GMD_DEMO=OFF builds without the example and the demo application (see CMake options). The library needs OpenMP. On Linux the window of the demo application needs the X11 development libraries (libx11-dev and libxext-dev): without them the SimpleUI library builds a window that shows nothing and gets no keys (the demo application can be stopped only with Ctrl+C then). The build also copies the headers of the library and of its dependencies to the folder build/output/include and combines the libraries into one library in the folder build/output/lib (libGmd.a and libGmd.so on Linux, Gmd.lib with MSVC; a program that links the combined library must also link the OpenMP runtime).

CMake options

Table 8 - CMake options of the repository. In the options below ${PARENT} is the prefix defined by the top-level project (empty if Gmd is the top-level project).

Option Default Description
${PARENT}_GMD ON Build the library.
${PARENT}_GMD_BENCHMARK ON (stand alone), OFF (included in other project) Build the benchmark application (needs SimpleUI).
${PARENT}_GMD_DEMO ON (stand alone), OFF (included in other project) Build the demo application (needs SimpleFileDialog, SimpleUI, VideoRecorderMp4, VEncoderJPEG, VSourceFile and the libraries VSourceFile depends on).
${PARENT}_GMD_EXAMPLE ON (stand alone), OFF (included in other project) Build the example application (needs VSourceFile and the libraries it depends on).
${PARENT}_SUBMODULE_CACHE_OVERWRITE ON Forced rewriting of the options above in the CMake cache. The top-level project sets it to OFF when it includes Gmd as a sub-repository. In the stand alone build the options above can be set only together with this option OFF, for example cmake .. -D_SUBMODULE_CACHE_OVERWRITE=OFF -D_GMD_DEMO=OFF.
CMAKE_BUILD_TYPE Release (if not specified) Build type.
GMD_ENABLE_SIMD ON Use the SIMD code of the library (see Portability). OFF defines the macro GMD_NO_SIMD: the portable code is used (the results are the same).

Connect to your project

If you want to connect Gmd library to your CMake project as source code, you can do the following. For example, if your repository has structure:

CMakeLists.txt
src
    CMakeLists.txt
    yourLib.h
    yourLib.cpp

Create 3rdparty folder in your repository and add the repositories of Gmd and of its dependencies (Frame, ConfigReader, ObjectDetector) to this folder (as sub-repositories or as copies). The new structure of your repository will be as follows:

CMakeLists.txt
src
    CMakeLists.txt
    yourLib.h
    yourLib.cpp
3rdparty
    Frame
    ConfigReader
    ObjectDetector
    Gmd

Create CMakeLists.txt file in 3rdparty folder. CMakeLists.txt should be containing:

cmake_minimum_required(VERSION 3.13)

################################################################################
## 3RD-PARTY
## dependencies for the project
################################################################################
project(3rdparty LANGUAGES CXX)

################################################################################
## SETTINGS
## basic 3rd-party settings before use
################################################################################
# To inherit the top-level architecture when the project is used as a submodule.
SET(PARENT ${PARENT}_YOUR_PROJECT_3RDPARTY)
# Disable self-overwriting of parameters inside included subdirectories.
SET(${PARENT}_SUBMODULE_CACHE_OVERWRITE OFF CACHE BOOL "" FORCE)

################################################################################
## CONFIGURATION
## 3rd-party submodules configuration
################################################################################
SET(${PARENT}_SUBMODULE_FRAME                           ON  CACHE BOOL "" FORCE)
if (${PARENT}_SUBMODULE_FRAME)
    SET(${PARENT}_FRAME                                 ON  CACHE BOOL "" FORCE)
    SET(${PARENT}_FRAME_TEST                            OFF CACHE BOOL "" FORCE)
endif()

SET(${PARENT}_SUBMODULE_CONFIG_READER                   ON  CACHE BOOL "" FORCE)
if (${PARENT}_SUBMODULE_CONFIG_READER)
    SET(${PARENT}_CONFIG_READER                         ON  CACHE BOOL "" FORCE)
    SET(${PARENT}_CONFIG_READER_EXAMPLES                OFF CACHE BOOL "" FORCE)
    SET(${PARENT}_CONFIG_READER_TESTS                   OFF CACHE BOOL "" FORCE)
endif()

SET(${PARENT}_SUBMODULE_OBJECT_DETECTOR                 ON  CACHE BOOL "" FORCE)
if (${PARENT}_SUBMODULE_OBJECT_DETECTOR)
    SET(${PARENT}_OBJECT_DETECTOR                       ON  CACHE BOOL "" FORCE)
    SET(${PARENT}_OBJECT_DETECTOR_TEST                  OFF CACHE BOOL "" FORCE)
    SET(${PARENT}_OBJECT_DETECTOR_EXAMPLE               OFF CACHE BOOL "" FORCE)
endif()

SET(${PARENT}_SUBMODULE_GMD                             ON  CACHE BOOL "" FORCE)
if (${PARENT}_SUBMODULE_GMD)
    SET(${PARENT}_GMD                                   ON  CACHE BOOL "" FORCE)
    SET(${PARENT}_GMD_BENCHMARK                         OFF CACHE BOOL "" FORCE)
    SET(${PARENT}_GMD_DEMO                              OFF CACHE BOOL "" FORCE)
    SET(${PARENT}_GMD_EXAMPLE                           OFF CACHE BOOL "" FORCE)
endif()

################################################################################
## INCLUDING SUBDIRECTORIES
## Adding subdirectories according to the 3rd-party configuration
################################################################################
if (${PARENT}_SUBMODULE_FRAME)
    add_subdirectory(Frame)
endif()

if (${PARENT}_SUBMODULE_CONFIG_READER)
    add_subdirectory(ConfigReader)
endif()

if (${PARENT}_SUBMODULE_OBJECT_DETECTOR)
    add_subdirectory(ObjectDetector)
endif()

if (${PARENT}_SUBMODULE_GMD)
    add_subdirectory(Gmd)
endif()

File 3rdparty/CMakeLists.txt adds the dependencies in the order of their mutual dependencies and then Gmd to your project and excludes test applications, examples, the benchmark and the demo application from compiling (by default they are excluded from compiling if Gmd is included as sub-repository). Gmd does not add its dependencies when it is included in another project: they must be added by your project (a missing dependency stops the build with a compile error such as ObjectDetector.h: No such file or directory). The new structure of your repository:

CMakeLists.txt
src
    CMakeLists.txt
    yourLib.h
    yourLib.cpp
3rdparty
    CMakeLists.txt
    Frame
    ConfigReader
    ObjectDetector
    Gmd

Next, you need to include the ‘3rdparty’ folder in the main CMakeLists.txt file of your repository. Add the following string at the end of your main CMakeLists.txt:

add_subdirectory(3rdparty)

Next, you have to include Gmd library in your src/CMakeLists.txt file (the library also gives the OpenMP compiler and linker flags to your target):

target_link_libraries(${PROJECT_NAME} Gmd)

Done!

Portability

The library is written in standard C++17 and uses OpenMP for the calculation of the motion mask: the results do not depend on the number of threads (NUM_THREADS). SIMD code is used for the conversion of the frames to gray. It is chosen at compile time by the instruction set of the compiler target (the CMake files add no instruction set flags): SSE2 on x86-64 and on x86 with SSE2 code generation, AVX2 if the whole project is compiled for AVX2 (for example with -mavx2 or /arch:AVX2), NEON on ARM processors with NEON. The portable C++ code is used on other processors and if the CMake option GMD_ENABLE_SIMD is OFF (macro GMD_NO_SIMD). The library is compiled without fused multiply-add contraction (-ffp-contract=off for GCC and Clang), so all SIMD variants, compilers and processors give the same results. The library is built and checked with GCC 12 and 13 and Clang 15 and 18 on Linux x86-64 and aarch64 and with Visual Studio 2026 (MSVC 14.51) on Windows x86-64 and x86.

Example

A simple application shows how to use the Gmd library. The application opens a video file (the first command line argument, test.mp4 in the working directory if the argument is not given; the file video/test.mp4 of the repository can be used) with the VSourceFile library. VSourceFile reads H264, HEVC and JPEG video from MP4, MOV, M4V and AVI files and from elementary streams, decodes the frames to NV12 and delivers them at the frame rate of the file; at the end of the file it plays the file again from the beginning. The application processes 1000 frames and prints the objects detected on each frame. The detector uses the luma plane of the NV12 frames.

#include <iostream>
#include <string>
#include <vector>
#include "Gmd.h"
#include "VSourceFile.h"



namespace
{
/// Number of frames the example processes. The video source plays the file
/// again from the beginning at its end.
constexpr int FRAMES_NUMBER{1000};
/// Timeout of waiting for a frame from the video source, milliseconds.
constexpr int FRAME_TIMEOUT_MS{1000};
/// Number of failed attempts to get a frame in a row after which the example
/// stops (the file can not be read or decoded).
constexpr int MAX_READ_FAILURES{10};
}



int main(int argc, char* argv[])
{
    std::cout << "Gmd v" << rapidpixel::Gmd::getVersion()
              << ", VSourceFile v" << rapidpixel::VSourceFile::getVersion()
              << std::endl;

    // Open video file: the first command line argument, "test.mp4" if the
    // argument is not given.
    std::string fileName{argc > 1 ? argv[1] : "test.mp4"};
    rapidpixel::VSourceFile videoSource;
    if (!videoSource.openVSource(fileName))
    {
        std::cout << "Can't open video file " << fileName << std::endl;
        return -1;
    }

    // Create detector and set params.
    rapidpixel::Gmd detector;
    if (!detector.setParam(
            rapidpixel::ObjectDetectorParam::MIN_OBJECT_WIDTH, 4.0f) ||
        !detector.setParam(
            rapidpixel::ObjectDetectorParam::MAX_OBJECT_WIDTH, 96.0f) ||
        !detector.setParam(
            rapidpixel::ObjectDetectorParam::MIN_OBJECT_HEIGHT, 4.0f) ||
        !detector.setParam(
            rapidpixel::ObjectDetectorParam::MAX_OBJECT_HEIGHT, 96.0f) ||
        !detector.setParam(
            rapidpixel::ObjectDetectorParam::SENSITIVITY, 10.0f))
    {
        std::cout << "Can't set detector params" << std::endl;
        return -1;
    }

    // The video source decodes the frames to NV12: the detector uses the luma
    // plane. The same frame object is used for every frame.
    rapidpixel::Frame frame;
    int processedFrames{0};
    int readFailures{0};

    // Main loop.
    while (processedFrames < FRAMES_NUMBER)
    {
        // Get next video frame.
        frame.fourcc = rapidpixel::Fourcc::NV12;
        if (!videoSource.getFrame(frame, FRAME_TIMEOUT_MS))
        {
            ++readFailures;
            if (readFailures >= MAX_READ_FAILURES)
            {
                std::cout << "Can't read video frames" << std::endl;
                return -1;
            }
            continue;
        }
        readFailures = 0;
        ++processedFrames;

        // Detect objects.
        if (!detector.detect(frame))
        {
            std::cout << "Frame " << frame.frameId << " not processed"
                      << std::endl;
            continue;
        }

        // Print detected objects.
        const std::vector<rapidpixel::Object> objects = detector.getObjects();
        if (!objects.empty())
        {
            std::cout << "Frame " << frame.frameId << ":";
            for (const rapidpixel::Object& object : objects)
            {
                std::cout << " [id " << object.id << ": x " << object.x
                          << ", y " << object.y << ", width " << object.width
                          << ", height " << object.height << "]";
            }
            std::cout << std::endl;
        }
    }

    videoSource.closeVSource();
    return 0;
}

Console output (beginning) for the file video/test.mp4:

Gmd v5.5.3, VSourceFile v2.0.2
Frame 37: [id 1: x 171, y 255, width 16, height 33]
Frame 38: [id 1: x 171, y 255, width 17, height 32]

Benchmark

Benchmark application located in /benchmark folder and is intended to check performance (processing time per frame) on particular platform. After start user should enter the size of the frames, the size and the number of moving objects and detector params (a value out of the valid range stops the application with a message). The benchmark generates the frames itself: squares of random colors (drawn with the SimpleUI library) move over a black or a noise background and bounce at the frame borders. The benchmark application will show processing time per frame (milliseconds) until it is stopped (Ctrl+C) or 100 frames in a row are not processed. Benchmark output example:

=================================================
Gmd v5.5.3 benchmark
=================================================

Image size - 1280
Object size - 720
Number of objects - 4
Random background (y/n) - y
Default detector parameters:
FRAME_BUFFER_SIZE = 1
SENSITIVITY = 10
X_DETECTION_CRITERIA = 15
Y_DETECTION_CRITERIA = 15
RESET_CRITERIA = 5
SCALE_FACTOR = 1
NUM_THREADS = 1
---------------------------
Default params (y/n) - n
FRAME_BUFFER_SIZE - 5
SENSITIVITY - 10
X_DETECTION_CRITERIA - 15
Y_DETECTION_CRITERIA - 15
RESET_CRITERIA - 15
SCALE_FACTOR - 1
NUM_THREADS - 4
Time Gmd 53.375 msec
Time Gmd 30.684 msec
Time Gmd 23.086 msec
Time Gmd 26.592 msec
Time Gmd 34.032 msec
Time Gmd 23.89 msec
Time Gmd 24.416 msec

Demo application

Demo application overview

The demo application is intended to evaluate the performance of the Gmd C++ library. User can check performance of Gmd library on any video file. It is console application and serves as an example of using the Gmd library. The application uses the VSourceFile library to read and decode video files (H264, HEVC and JPEG video in MP4, MOV, M4V and AVI files and in elementary streams *.h264, *.hevc and *.mjpeg) the SimpleUI library for the user interface (window, sliders and drawing) and the VideoRecorderMp4 library for video recording (MP4 files). Cameras and video streams are not supported.

Launch and user interface

The demo application does not require installation. The demo application compiled for Windows OS x64 (Windows 10 and newer). The demo application for Linux OS can be provided upon request. Table 9 shows list of files of demo application.

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

File Description
GmdDemo.exe Demo application executable file for windows OS.
GmdDemo.json Demo application config file.
VC_redist.x64 Installer of necessary system libraries for Windows x64.
src/main.cpp Source code.
test.mp4 Test video file.

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

sudo chmod +x GmdDemo
./GmdDemo

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. Config file GmdDemo.json included video capture params (videoSource field) and object detector parameters (all others). If the demo application does not find the file after startup (or can not read the params from it), it will create it with default parameters. Config file content with default parameters:

{
    "Params": {
        "videoSource": "file dialog",
        "objectDetector": {
            "initString": "",
            "logMode": 0,
            "frameBufferSize": 1,
            "minObjectWidth": 4,
            "maxObjectWidth": 128,
            "minObjectHeight": 4,
            "maxObjectHeight": 128,
            "minXSpeed": 0.10000000149011612,
            "maxXSpeed": 15.0,
            "minYSpeed": 0.10000000149011612,
            "maxYSpeed": 15.0,
            "minDetectionProbability": -1.0,
            "xDetectionCriteria": 15,
            "yDetectionCriteria": 15,
            "resetCriteria": 5,
            "sensitivity": 10.0,
            "scaleFactor": 1,
            "numThreads": 1,
            "type": -1,
            "enable": true,
            "custom1": -1.0,
            "custom2": -1.0,
            "custom3": -1.0,
            "classNames": []
        }
    }
}

Table 10 - Parameters description.

Field Type Description
videoSource string Video file. If the parameter is set to “file dialog”, then after start the program will offer to select video file via file selection dialog. Otherwise the parameter is a file name (e.g. “test.mp4”). The video is decoded with the VSourceFile library (H264, HEVC and JPEG video in MP4, MOV, M4V and AVI files and in elementary streams *.h264, *.hevc and *.mjpeg) and is played at the frame rate of the file. The software plays the video with repetition i.e. when the end of the video file is reached, playback starts again.
classNames string Not used. Can have any value (Gmd does not recognize object classes).
custom1 float Not used. Can have any value.
custom2 float Not used. Can have any value.
custom3 float Not used. Can have any value.
enable bool enable / disable detector. Default value true.
frameBufferSize int Frame buffer size (temporal smoothing), frames. Valid values from 1 to 128. Default value is 1. The detector averages each pixel over the last FRAME_BUFFER_SIZE frames and looks for motion on this averaged image. 1 - no averaging, maximum responsiveness: best for fast and/or small targets (a larger value smears their motion and can average a small target away). Greater than 1 - time smoothing that averages out a fast-changing background (water ripples and glints, sensor noise, heat shimmer, foliage): suitable for slow objects - the target barely moves between the averaged frames and survives, while the background clutter is smoothed away. Higher values suppress more clutter but add latency and blur fast motion, so use the smallest value that cleans up the background.
initString string Not used. Can have any value.
logMode int Not used. Can have any value.
maxObjectHeight int Maximum object height to be detected, pixels. To be detected object’s height must be <= maxObjectHeight. Default value 128.
maxObjectWidth int Maximum object width to be detected, pixels. To be detected object’s width must be <= maxObjectWidth. Default value 128.
minXSpeed float Minimum horizontal movement threshold, pixels/frame. Fixed at 0.1 in Gmd (not configurable).
maxXSpeed float Maximum EXPECTED horizontal displacement of an object between two frames, in source-frame pixels/frame (independent of scaleFactor). Not a hard speed filter: objects moving faster cannot be linked to their track (dropped), slower objects are not rejected. Valid values from 0 to 256. Recommended value is 15.
minYSpeed float Minimum vertical movement threshold, pixels/frame. Fixed at 0.1 in Gmd (not configurable).
maxYSpeed float Maximum EXPECTED vertical displacement of an object between two frames, in source-frame pixels/frame (independent of scaleFactor). Not a hard speed filter — see maxXSpeed. Valid values from 0 to 256. Recommended value is 15.
minDetectionProbability float Not used. Can have any value.
minObjectHeight int Minimum object height to be detected, pixels. To be detected object’s height must be >= minObjectHeight. Default value 4.
minObjectWidth int Minimum object width to be detected, pixels. To be detected object’s width must be >= minObjectWidth. Default value 4.
numThreads int Num threads. Number of threads used to compute the binary motion mask. Valid values from 0 to 64. A value of 0 or 1 means single-threaded processing; values greater than 1 split the motion-mask computation into that many horizontal row bands (capped at the processing height divided by 8, rounded up).
resetCriteria int The number of consecutive video frames in which the object was not detected, so it will be excluded from the internal object list. The internal object list is used to associate newly detected objects with objects detected in the previous video frame. Internal objects list allow to library keep static object ID from frame to frame. If object not detected during number of frames < resetCriteria next time of detection will not change of object ID.
scaleFactor int Frame scaling factor for processing purposes. Reduce the image size by scaleFactor times horizontally and vertically for faster processing. Allows to increase calculation speed but slightly reduces sensitivity.
sensitivity float Detection sensitivity. For Gmd library this parameters means pixel brightness deviation threshold from 0.001 to 255 for calculation motion mask. The first processing step is the computation of the binary motion mask. The algorithm makes a decision about the presence of motion in a particular pixel also on the basis of changes in pixel brightness. The brightness threshold is determined by the SENSITIVITY parameter. The lower this parameter is, the less contrasty objects will be detected, but there will be more influence of video noise. The larger this parameter is, the more contrast objects must have in order to be detected. The normal value for thermal cameras is 15. The normal value for daylight cameras is 10.
type int Not used. Can have any value.
xDetectionCriteria int Horizontal track detection criteria, frames. Shows how many frames the objects must move in any(+/-) horizontal direction to be detected. Valid values from 1 to 256. Default value 15.
yDetectionCriteria int Vertical track detection criteria, frames. Shows how many frames the objects must move in any(+/-) vertical direction to be detected. Valid values from 1 to 256. Default value 15.

After starting the application (running the executable file) the user should select the video file in the dialog box (if parameter “videoSource” in config file is set to “file dialog”). After that the user will see the user interface as shown bellow. The window shows the sliders of the detector params (top), the original video with detection results (left) and the binary motion mask (right). The picture is fitted to the size of the window, the window can be resized. Each detected object is represented by red rectangle with the object ID above it. The application stops if the video file gives no frame for 10 consecutive attempts (1 second each) or if its frames can not be converted to BGR24 (odd frame size). A frame the detector can not process (for example a scene with too much motion) is shown without objects, the window shows “frame not processed” then. If the params of the config file are not valid the application stops with the message “Can’t init detector”.

gmd_demo_application_interface

Control

To control the application, it is necessary that the main video display window was active (in focus). The keys work in any keyboard layout and with CapsLock. The program is controlled by the keyboard, the sliders and the mouse (detection ROI control): a rectangle drawn with the left mouse button on the video (left part of the picture) sets the detection mask, the detector omits the area outside of the rectangle. The sliders set the params of the detector (see Table 10): frame buffer size (1 - 128), sensitivity (1 - 255), X detection criteria, Y detection criteria and reset criteria (1 - 256), min and max object width (1 - frame width), min and max object height (1 - frame height) and scale factor (1 - 10). A moved slider sets the param at once; the params set by the sliders are not saved to the config file. A slider shows the param of the config file limited to its range, the detector uses the param of the config file until the slider is moved.

Table 11 - Control buttons.

Button Description
ESC Exit the application. If video recording is active, it will be stopped (the files are completed).
SPACE Reset motion detector.
R Start/stop video recording. When video recording is started, three files are created in the working directory: dst_[date and time].mp4 (video with detection results), mask_[date and time].mp4 (motion mask) and mix_[date and time].mp4 (video and motion mask side by side) in the original resolution of the video, without the texts of the window. The date and time have the format DD_MM_YYYY_HH_MM_SS; if a file with this name exists, _1, _2, … is added to the name. The frames are compressed to JPEG (quality 80 %) and recorded with the frame rate of the video file. To stop the recording, press the R key again. During video recording, the application shows the message “RECORDING: R to stop”.

The user can set the detection mask (mark a rectangular area where objects are to be detected). In order to set a rectangular detection area it is necessary to draw a line with the mouse with the left button pressed from the left-top corner of the required detection area to the right-bottom corner. The detection area will be marked in cyan color as shown in the image.


Table of contents