Получить фоновую модель из BackgroundSubtractorMOG2 в Python
Мне нужно получить фоновую модель смеси Гаусса с opencv. Я знаю, что в C++ есть метод getBackgroundImage. Я искал, возможно ли получить его в интерфейсе Python, но я не получил хорошего результата. Я попробовал opencv 3.0.0-dev, потому что он имеет реализацию BackgroundSubtractorMOG2, но функция help() не документирует реализацию метода для фоновой модели. Знаете ли вы, есть ли недокументированная реализация? Я искал, как отредактировать исходный код opencv для реализации Python, но я не нашел документации об этом. Я предпочитаю избегать использования scipy.weave для компиляции кода на C++, более того, я не знаю, полезен ли scipy.weave в этой ситуации
3 ответа
РешениеZaw Lin в Ubuntu 12.04:
Основное отличие состоит в том, что результат (fg
/ bg
) изображения создаются / размещаются в python, а затем передаются в библиотеку C++. Решение Zaw Lin дало мне ошибки (errno 139 - SIG_SEGV), потому что приложение обращалось к недопустимым зонам памяти. Надеюсь, это сэкономит кому-то пару часов:)
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);
}
Скомпилируйте это так:
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
А потом питон:
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)
Вот простая оболочка с использованием ctypes, я тестировал только на Windows
CPP, построить как 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;
}
питон
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)