通过Mat/Numpy转换向Python公开基于OpenCV的C ++函数 [英] Exposing OpenCV-based C++ function with Mat/Numpy conversion to Python

查看:261
本文介绍了通过Mat/Numpy转换向Python公开基于OpenCV的C ++函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到了一个问题,试图通过使用Numpy ndarray 向Python 2.7公开与OpenCV链接的动态C ++库函数,并使用OpenCV的 Mat 数据类型.

I've ran into a problem trying to expose dynamic C++ library functions, linked to OpenCV and using OpenCV's Mat datatype, to Python 2.7 with the use of Numpy ndarray.

我想出了一个类似于 lightalchemist的解决方案解决方案,我也尝试使用boost :: python和boost :: numpy(也链接到Python 2.7)

I've come up with a solution similar to lightalchemist's solution here and I've also tried using boost::python and boost::numpy (also linked to Python 2.7) described in this SO question.

现在,我坚持使用前者.我已经到了可以在iPython中加载模块的地步,并且看到了我正在尝试使用 inspect 模块移植的函数,我什至可以调用它甚至执行它.但是,当我尝试使用 NumpyAllocator (

Right now I'm sticking with the former. I've got to a point where I can load the module in iPython, and I see a function I'm trying to port using the inspect module, I can even call it and it even executes. However, the problem occurs specifically when I try to use the NumpyAllocator (see lightalchemist's solution) class to convert the Mat object back to ndarray. Firstly, when I try to call pyopencv_from function from an outside C++ executable, and it uses the NumpyAllocator as it's coded, it segfaults at

PyEnsureGIL gil;

,每次无消息. Lightalchemist的解决方案未在 pyopencv_to 中使用它(如果已分配传入的ndarray),它似乎可以工作.但是,官方的OpenCV cv2.cpp也确实使用了分配器,因此,如果我尝试使用该函数,甚至无法将输入ndarray转换为Mat.

, with no message, every time. Lightalchemist's solution doesn't use it in pyopencv_to ( if the ndarray passed-in is already allocated), and it seems to work. However, the official OpenCV cv2.cpp does use the allocator in that as well, so if I try to use that the function can't even convert the input ndarray to Mat.

当我尝试使用iPython中的模块时,它会看到该功能.再次,它正确执行了(将进度打印到控制台),但是当它到达 pyopencv_from 时,它会隔离并杀死iPython shell.

When I try to use the module from iPython, it sees the function. Again, it executes it correctly (prints progress to the console), but when it reaches the pyopencv_from, it segfaults and kills the iPython shell.

我使用的光源与lightalchemist相同,除了我要公开一个功能,与官方OpenCV端口相同:

I'm using exaclty the same source as lightalchemist, except I'm exposing a single function, the same way as the official OpenCV port does:

static PyMethodDef methods[] = {
{"findEdgesCGTG", (PyCFunction)pycvex_findEdgesCGTG, METH_KEYWORDS, "findEdgesCGTG(source) -> edgeGradient, edgeOrientations"},
    {NULL, NULL}
};
extern "C"
#if defined WIN32 || defined _WIN32
__declspec(dllexport)
#endif
void initcvex()
{
  import_array();
  PyObject* m = Py_InitModule(MODULESTR, methods);
  PyObject* d = PyModule_GetDict(m);
  opencv_error = PyErr_NewException((char*)MODULESTR".error", NULL, NULL);
  PyDict_SetItemString(d, "error", opencv_error);
}

有人知道如何解决此转换问题吗?

Does anyone have any clue on how to resolve this conversion problem?

推荐答案

问题不是

PyEnsureGIL gil;

声明.只有当我尝试使用外部C ++函数时,这才行不通.当我尝试将两个输出值打包为一个时,实际上发生了问题:

statement. That only didn't work if I tried to use an external C++ function. The problem actually happened when I tried to pack two output values into one here:

return Py_BuildValue("(NN)", pyopencv_from(edgeGrad), pyopencv_from(edgeOri));

临时解决方法只是使用以下语句:

The temporary work-around was just to use the following statement:

return pyopencv_from(edgeGrad);

抱歉,我又搞砸了. Py_BuildValue可以正常工作.刚刚再次测试了我的功能,它就完美地运行了.我一定忘了上次测试它时使用return关键字,所以它给了我没有设置异常的错误返回".

Sorry, I messed up again. The Py_BuildValue works just fine. Just tested my function again, it works perfectly. I must have forgotten to put the return keyword last time I tested it, so it gave me "error return without exception set."

这是完整的功能代码(我希望对将OpenCV内容移植到python的人有用)

Here's the full function code (I hope it's useful for anyone porting OpenCV stuff to python)

static PyObject* pycvex_findEdgesCGTG(PyObject* , PyObject* args, PyObject* kw)
{
    PyObject* pyobj_source = NULL;
    Mat source;
    Mat edgeGrad;
    Mat edgeOri;
    const char* keywords[] = { "src", NULL };
    if( PyArg_ParseTupleAndKeywords(args, kw, "O:findEdgesCGTG", (char**)keywords, &pyobj_source) &&
        pyopencv_to(pyobj_source, source));
    {
        ERRWRAP2(findEdgesCGTG(source,edgeGrad,edgeOri));
        return Py_BuildValue("(NN)", pyopencv_from(edgeGrad), pyopencv_from(edgeOri));
    }
    return NULL;
}

更新:

这是 github存储库,其中包含我为使用OpenCV的Mat类公开代码而编写的开放C ++代码尽可能少的痛苦.这用于 OpenCV 3.X .

Here is the github repo with the open C++ code I wrote for exposing code using OpenCV's Mat class with as little pain as possible. This is for OpenCV 3.X.

对于OpenCV 2.X ,您可以使用

For OpenCV 2.X you can use this code / example by Yati Sagade. If you'd like to expose functions using the opencv Mat class without worrying about explicit conversions, it's easy to adapt the Booost converters from my code with the conversion functions in Yati's code.

这篇关于通过Mat/Numpy转换向Python公开基于OpenCV的C ++函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆