在python中从BackgroundSubtractorMOG2获取背景模型

在python中从BackgroundSubtractorMOG2获取背景模型,python,opencv,mog,Python,Opencv,Mog,我需要得到高斯和opencv混合的背景模型。我知道如果有可能在Python接口中找到它,在C++中有一个方法叫做GETBACKGRUMEDIMAGE,但我没有得到好的结果。我尝试了opencv 3.0.0-dev,因为它有BackgroundSubtractorMOG2实现,但help()函数并没有记录后台模型的方法实现。您知道是否存在未记录的实现吗?我搜索了如何编辑opencv源代码来实现python实现,但还没有找到相关文档。我更喜欢避免使用ScPi.Weave编译C++代码,而且我不知道S

我需要得到高斯和opencv混合的背景模型。我知道如果有可能在Python接口中找到它,在C++中有一个方法叫做GETBACKGRUMEDIMAGE,但我没有得到好的结果。我尝试了opencv 3.0.0-dev,因为它有BackgroundSubtractorMOG2实现,但help()函数并没有记录后台模型的方法实现。您知道是否存在未记录的实现吗?我搜索了如何编辑opencv源代码来实现python实现,但还没有找到相关文档。我更喜欢避免使用ScPi.Weave编译C++代码,而且我不知道SyPy.WaveWin对于情况下是有用的。

< P>这是一个使用CyType的简单包装器,我只在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)    

改编了Zaw Lin的解决方案

  • Ubuntu 18.04
  • OpenCV 3.2通过
    apt安装libopencv dev安装
<>主要区别在于,在Python中创建/分配了结果(<代码> FG< /Cult>/Cuth> BG<代码>代码),然后传递给C++ LIB。 Zaw Lin的解决方案给了我错误(errno 139-SIG_SEGV),因为该应用程序正在访问无效的内存区域。希望它能为某人节省几个小时:)

mog2.cpp:

#包括
cv::BackgroundSubtractorMOG2*mog=cv::createBackgroundSubtractorMOG2(500,16,false);
外部“C”void getfg(int行、int列、无符号字符*imgData、,
无符号字符*fgD){
cv::Mat img(行、列、cv_8UC3,(空*)imgData);
cv::材料fg(行、列、cv_8UC1、fgD);
mog->应用(img、fg);
}
外部“C”void getbg(整数行、整数列、无符号字符*bgD){
cv::Mat bg=cv::Mat(行、列、cv_8UC3、bgD);
mog->getBackgroundImage(背景图像);
}
将其编译为:

gcc\
-共享\
-o libmog2.so\
-fPIC./mog2.cpp\
-lopencv_核心-lopencv_highgui-lopencv_对象检测-lopencv_imgproc-lopencv_功能2D-lopencv_ml-lopencv_calib3d-lopencv_视频
然后是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)
opencv 3.0

bgd=dict(history=20,nmixtures=20,backgroundRatio=0.5,noiseSigma=0)
fgbg=cv2.bgsegm.createBackgroundSubtractorMOG(**bgd)

试试这个:我正在使用opencv 3.0.0-dev,因为我已经阅读了您建议的链接……现在我正在尝试理解opencv python解析器是如何工作的……否则,如果没有其他解决方案,我认为我应该用python APIC编写MOG2的包装器——也许类似这样的东西就足够了<代码>背景=0.99*bg+0.01*(边框和~cv2.cvtColor(fg,cv2.COLOR_GRAY2BGR));cv2.imshow('bg',bg/255)
MOG2绑定在opencv 3-dev中已经可用。那你为什么要编写自己的呢?@AbidRahmanK MOG2绑定在opencv 3-dev中还没有我需要的背景图片。我在Mac OS X上,我删除了u declspec(ddlexport)并创建了一个动态库。ctypes可以工作,但我在getfg(f)的imshow上遇到了分段错误。我需要一段时间才能接触到mac,我不熟悉mac编程,但我在ubuntu上试用过,效果很好。你能在ubuntu上试试吗?如果你还有问题,我可以更新更多细节。我已经用Python C API编写了一个包装器,但是你的是最好的解决方案。我将尝试强制它在我的系统上工作:)删除
\uu declspec(dllexport)
使它可以在Ubuntu上编译(作为共享库,所有opencv库都添加了-l)。尽管我的问题是无法从返回的地址加载映像。行
np.ndarray(buffer=buf[…])
因SIG_SEGV(分段故障)而失败.有什么想法吗?@ZawLin,我现在很长时间都在尝试在windows上构建wrapper.dll文件。它只是不起作用。我安装了opencv,并尝试使用以下命令编译:
gcc-o fgbg.dll mog2.cpp-ic:/opencv3.4.10/opencv/build/include-ic:/opencv3.4.10/opencv/build/include/opencv2-lc:/opencv3.4.10/opencv/x64/vc14/lib
它给我的错误如下`对
cv::String::allocate的未定义引用(unsigned int)'c:/mingw/bin/./lib/gcc/mingw32/9.2.0/../../../../../../../../mingw32/bin/ld.exe:
请您解释一下如何构建wrapper.dll好吗?谢谢,我用一个静态编译的opencv版本对它进行了测试。所以我们花了一段时间用共享库对它进行了测试。re Emanuel:更正的错误:
shape=(行,列,列,1)
getfg
中的
应仅为
shape=(行,列)
。如果将
res
包装(转换)为SimpleCV
Image
(使用
Image(res)
),则会导致错误.更新answer@Matyas我不能编译C++代码到LIMOG2.2文件。我一直在获得错误“opencv2/opencv.Hpp:HungEng/Directory”。我使用Windows 10。我尝试添加<代码>包含“C:/OpenCV2/OpenCV.HPP”。但是没有运气。你能分享一下你是如何解决这个问题的吗?嘿,文德塔,我重新检查了UBUTU18.04的编译;OpenCV3.2更新了C++编译的工作。你有一个更一般的问题,你的安装头文件没有被发现/检测,所以你应该看看如何在Windows中配置它。自从linux/ubuntu开箱即用以来,我就没有经历过这些步骤。