【问题标题】:Return a structure to Python from C++ using BOOST.python使用 BOOST.python 将结构从 C++ 返回到 Python
【发布时间】:2013-10-04 15:53:42
【问题描述】:

我编写了一个 C++ 方法,我需要从中将结构返回给 Python。 我已经能够按照link 中描述的方法使用 BOOST 将 OpenCV mat 从 Python 发送到 C++。

现在我需要走另一条路;从 C++ 返回到 Python,然后在 Python 中访问该结构。能做到吗?

任何示例或参考链接都会很好。在发布此问题之前,我曾尝试使用谷歌搜索,但找不到任何示例或解释链接。

【问题讨论】:

    标签: c++ python boost wrapper boost-python


    【解决方案1】:

    您可以使用 modules/python/src2/cv2.cpp 中的另一个函数:

    PyObject* pyopencv_from(const cv::Mat& m)
    {
      if( !m.data )
          Py_RETURN_NONE;
      cv::Mat temp, *p = (cv::Mat*)&m;
      if(!p->refcount || p->allocator != &g_numpyAllocator)
      {
          temp.allocator = &g_numpyAllocator;
          m.copyTo(temp);
          p = &temp;
      }
      p->addref();
      return pyObjectFromRefcount(p->refcount);
    }
    

    那么 Boost Python 包装器将如下所示:

    boost::python::object toPython( const cv::Mat &frame )
    {
        PyObject* pyObjFrame = pyopencv_from( frame );
        boost::python::object boostPyObjFrame(boost::python::handle<>((PyObject*)pyObjFrame));
    
        return boostPyObjFrame;
    }
    

    请查看此链接:https://wiki.python.org/moin/boost.python/handle 以确保您使用适合您的案例的 boost::python::handle 函数。

    如果您需要不需要返回 cv::Mat 但不同的数据,您可以考虑使用 boost::python::list 或 boost::python::dict。例如,如果您想将 2D 点的向量返回给 Python,您可以执行以下操作:

    boost::python::dict toPython( std::vector<cv::Point> newPoints, std::vector<cv::Point> oldPoints )
    {
        boost::python::dict pointsDict;
        boost::python::list oldPointsList;
        boost::python::list newPointsList;
    
        for( size_t ii = 0; ii < oldPoints.size( ); ++ii )
        {
            oldPointsList.append( boost::python::make_tuple( oldPoints[ii].x, oldPoints[ii].y ) );
        }
    
        for( size_t ii = 0; ii < newPoints.size( ); ++ii )
        {
            newPointsList.append( boost::python::make_tuple( newPoints[ii].x, newPoints[ii].y ) );
        }
    
        pointsDict["oldPoints"] = oldPointsList;
        pointsDict["newPoints"] = newPointsList;
        return pointsDict
    }
    

    最后是 Boost Python 包装器:

    BOOST_PYTHON_MODULE( myWrapper )
    {
        // necessary only if array (cv::Mat) is returned
        import_array();
        boost::python::converter::registry::insert( &extract_pyarray, type_id<PyArrayObject>());
    
        def toPython("toPython", &toPython);
    }
    

    我还没有测试过这个特定的解决方案,但原则上它应该可以工作。

    【讨论】:

    • 感谢您的回答。我需要返回一个 C++ 结构。我想我可以从您给出的“Mat”示例中得出?我会尝试并回复你,如果我要返回一个结构说 Struct samp { int a;字符 b; };如何在 Python 中访问它?
    • 我收到这个错误,)' to 'boost::python::api::object'> 是什么原因。
    • 我的意图是从 C++ 发送一些不同数据类型的变量作为返回值。我想把它作为结构发送,但即使它是类对象我也可以。
    • 尝试将 boostPyObjFrame 定义的行更改为: boost::python::object booostPyObjFrame(boost::python::handle(boost::python::borrowed((PyObject*) pyObjFrame))) 或只是: boost::python::object booostPyObjFrame(boost::python::handle((PyObject*)pyObjFrame))))
    • 如果您不需要返回转换为 Python numpy 数组的 Mat,您可以更轻松地在 C++ 代码中使用 boost::python::dict 或 boost::python::list 来包装您的要返回的数据。
    【解决方案2】:

    这可能有点太晚了,但是看看https://github.com/spillai/numpy-opencv-converter

    【讨论】:

    • 除了链接 GitHub 存储库之外,还请注意解释这对解决问题有何帮助。
    猜你喜欢
    • 2018-08-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-07
    • 1970-01-01
    相关资源
    最近更新 更多