Get background model from BackgroundSubtractorMOG2 in python

前端 未结 3 1195
猫巷女王i
猫巷女王i 2020-12-29 16:58

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 i

相关标签:
3条回答
  • 2020-12-29 17:22

    here's a simple wrapper using ctypes, i have only tested on windows

    cpp, build as dll

    #include "opencv2/opencv.hpp"
    cv::BackgroundSubtractorMOG2 mog(100, 16, false);
    
    cv::Mat bg;
    cv::Mat fg;
    extern "C" __declspec(dllexport)  unsigned char*  getfg(int rows,int cols, unsigned char* fdata)
    {
        cv::Mat frame= cv::Mat(rows, cols, CV_8UC3,fdata);
        mog(frame,fg);
        //check fg.iscont(), copy as needed
        return fg.data;
    }
    
    
    extern "C" __declspec(dllexport)   unsigned char*  getbg()
    {
        mog.getBackgroundImage(bg);
        return bg.data;
    }
    

    python

    import cv2
    import numpy as np
    import ctypes as C
    lib = C.cdll.LoadLibrary('wrapper.dll')
    
    def getfg(img):
        ptr = lib.getfg(img.shape[0],img.shape[1],img.ctypes.data_as(C.POINTER(C.c_ubyte)))
    
        buf = (C.c_ubyte * img.shape[0] * img.shape[1]  * 1).from_address(ptr)
        res = np.ndarray(buffer=buf, dtype=np.uint8,
                           shape=(img.shape[0], img.shape[1], 1))
        return res
    
    def getbg(img):
        ptr = lib.getbg()
        buf = (C.c_ubyte * img.shape[0] * img.shape[1]  * 3).from_address(ptr)
        res = np.ndarray(buffer=buf, dtype=np.uint8,
                           shape=(img.shape[0], img.shape[1], 3))
        return res
    
    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)    
    
    0 讨论(0)
  • 2020-12-29 17:23

    opencv 3.0

    bgd=dict(history=20,nmixtures=20,backgroundRatio=0.5,noiseSigma=0)
    fgbg=cv2.bgsegm.createBackgroundSubtractorMOG(**bgd)
    
    0 讨论(0)
  • 2020-12-29 17:27

    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)
    
    0 讨论(0)
提交回复
热议问题