3

Numpy ndarrayを使用して、OpenCV にリンクされ、OpenCV のMatデータ型を使用する動的 C++ ライブラリ関数を Python 2.7に公開しようとすると、問題が発生しました。

ここで lightalchemist のソリューションに似たソリューションを思いつきました。また、この SO の質問で説明されているboost::python と boost::numpy (Python 2.7 にもリンクされています) を使用してみました。

今は前者を貫いています。iPython でモジュールをロードできるようになりました。また、inspectモジュールを使用して移植しようとしている関数が表示されます。それを呼び出して実行することもできます。ただし、NumpyAllocator ( lightalchemist のソリューションを参照) クラスを使用してMatオブジェクトを ndarray に変換しようとすると、特に問題が発生します。まず、外部の C++ 実行可能ファイルからpyopencv_from関数を呼び出そうとすると、NumpyAllocator がコード化されたとおりに使用され、セグメンテーション違反が発生します。

PyEnsureGIL gil;

、毎回メッセージなし。Lightalchemist のソリューションはpyopencv_to (編集: 渡された ndarray が既に割り当てられている場合) でそれを使用しておらず、機能しているようです。ただし、公式の OpenCV cv2.cpp はその中でもアロケーターを使用するため、その関数を使用しようとすると、入力 ndarray を Mat に変換することさえできません。

iPython からモジュールを使用しようとすると、関数が表示されます。繰り返しますが、正しく実行されます (進行状況がコンソールに出力されます) が、pyopencv_fromに到達すると、セグメンテーション違反が発生し、iPython シェルが強制終了されます。

編集:公式の OpenCV ポートと同じように、単一の関数を公開していることを除いて、lightalchemist とまったく同じソースを使用しています。

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);
}

この変換の問題を解決する方法について手がかりを持っている人はいますか?

4

1 に答える 1

2

問題は

PyEnsureGIL gil;

声明。外部 C++ 関数を使用しようとした場合にのみ機能しませんでした。ここで2つの出力値を1つにパックしようとしたときに、実際に問題が発生しました。

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

一時的な回避策は、次のステートメントを使用することだけでした。

return pyopencv_from(edgeGrad);

編集:すみません、また台無しにしました。Py_BuildValue は問題なく動作します。私の機能をもう一度テストしたところ、完全に機能しました。前回テストしたときに return キーワードを入力するのを忘れたに違いないため、「例外が設定されていないエラー戻り」が発生しました。

これが完全な機能コードです(OpenCVのものを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;
}

アップデート:

これは、OpenCV の Mat クラスを使用してコードをできるだけ簡単に公開するために作成したオープン C++ コードを含むgithub リポジトリです。これはOpenCV 3.X用です。

OpenCV 2.X の場合、Yati Sagade によるこのコード/例を使用できます。明示的な変換を気にせずに opencv Mat クラスを使用して関数を公開したい場合は、Yati のコードの変換関数を使用して、コードの Boost コンバーターを簡単に適合させることができます。

于 2012-12-06T18:16:43.953 に答える