Get background model from BackgroundSubtractorMOG2 in python

EmanuelOverflow picture EmanuelOverflow · Sep 26, 2013 · Viewed 9.2k times · Source

I need to get the background model of a Mixture of Gaussian with opencv. I know that there is a method called getBackgroundImage in C++ I searched if it is possible to get it in python interface but I haven't get good result. I Tried opencv 3.0.0-dev because it has BackgroundSubtractorMOG2 implementation, but help() function don't document method implementation for background model. Do you know if there is undocumented implementation? I searched how to edit opencv source to implement a python implementation but i haven't found documentation about it. I prefer avoid to use scipy.weave to compile c++ code, furthermore i don't know if scipy.weave is useful in thi situation

Answer

Matyas picture Matyas · Oct 8, 2013

Adapted Zaw Lin's solution on

  • Ubuntu 18.04
  • OpenCV 3.2 installed via apt install libopencv-dev

The main difference is that the result (fg / bg) images are created/allocated in python and then passed down to the c++ lib. Zaw Lin's solution was giving me errors (errno 139 - SIG_SEGV), because of the app was accessing invalid memory zones. Hope it saves someone a couple of hours :)

mog2.cpp:

#include <opencv2/opencv.hpp>

cv::BackgroundSubtractorMOG2 *mog = cv::createBackgroundSubtractorMOG2 (500, 16, false);

extern "C" void getfg(int rows, int cols, unsigned char* imgData,
        unsigned char *fgD) {
    cv::Mat img(rows, cols, CV_8UC3, (void *) imgData);
    cv::Mat fg(rows, cols, CV_8UC1, fgD);
    mog->apply(img, fg);
}

extern "C" void getbg(int rows, int cols, unsigned char *bgD) {
    cv::Mat bg = cv::Mat(rows, cols, CV_8UC3, bgD);
    mog->getBackgroundImage(bg);
}

Compile it like:

gcc  \
    -shared \
    -o libmog2.so  \
    -fPIC ./mog2.cpp  \
    -lopencv_core -lopencv_highgui -lopencv_objdetect -lopencv_imgproc -lopencv_features2d -lopencv_ml -lopencv_calib3d -lopencv_video

And then python:

mog2.py

import numpy as np
import ctypes as C
import cv2

libmog = C.cdll.LoadLibrary('path/to/libmog2.so')

def getfg(img):
    (rows, cols) = (img.shape[0], img.shape[1])
    res = np.zeros(dtype=np.uint8, shape=(rows, cols))
    libmog.getfg(img.shape[0], img.shape[1],
                       img.ctypes.data_as(C.POINTER(C.c_ubyte)),
                       res.ctypes.data_as(C.POINTER(C.c_ubyte)))
    return res


def getbg(img):
    (rows, cols) = (img.shape[0], img.shape[1])
    res = np.zeros(dtype=np.uint8, shape=(rows, cols, 3))

    libmog.getbg(rows, cols, res.ctypes.data_as(C.POINTER(C.c_ubyte)))
    return res


if __name__ == '__main__':
    c = cv2.VideoCapture(0)
    while 1:
        _, f = c.read()
        cv2.imshow('f', f)
        cv2.imshow('fg', getfg(f))
        cv2.imshow('bg', getbg(f))
        if cv2.waitKey(1) == 27:
            exit(0)