Get background model from BackgroundSubtractorMOG2 in python

旧城冷巷雨未停 提交于 2019-11-30 10:13:51

Zaw Lin's solution in Ubuntu 12.04:

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(100, 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(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_contrib -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)

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)    

opencv 3.0

bgd=dict(history=20,nmixtures=20,backgroundRatio=0.5,noiseSigma=0)
fgbg=cv2.bgsegm.createBackgroundSubtractorMOG(**bgd)
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!