4

I have written a C++ method from which I need to return a structure to Python. I'm already able to send an OpenCV mat from Python to C++ using BOOST following the method described in this link.

Now I need to go the other way; return from C++ to Python, and then access that structure in Python. Can it be done?

Any samples or reference links would be good. I have tried googling before posting this question and I couldn't get any samples or explanation links.

2 Answers 2

5

You can use another function from 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);
}

Then the Boost Python wrapper will look like:

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

    return boostPyObjFrame;
}

Please have a look at this link: https://wiki.python.org/moin/boost.python/handle to make sure that you use the appropriate boost::python::handle<> function for your case.

If you need don't need to return a cv::Mat but different data you might consider to use boost::python::list or boost::python::dict. For example if you want to return a vectors of 2D points to Python you can do something like:

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
}

Finally the Boost Python wrapper:

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

I haven't tested this specific solution but it should work in principle.

Sign up to request clarification or add additional context in comments.

7 Comments

Thanks for the answer. I need to return a C++ structure. I think I can derive from the "Mat" example you have given? I will give a try and get back to you, If I am returning a struture say Struct samp { int a; char b; }; how can I access this in Python?
I am getting this error,<error: could not convert ‘boostPyObjFrame’ from ‘boost::python::api::object (*)(boost::python::handle<>)’ to ‘boost::python::api::object’> What would be the reason.
My intention is to send some variables of different datatypes from C++ as return value. I thought of sending it as structure but I am ok even if it is of class object.
Try to change the line where boostPyObjFrame is defined to: boost::python::object booostPyObjFrame(boost::python::handle<>(boost::python::borrowed((PyObject*)pyObjFrame))) or just: boost::python::object booostPyObjFrame(boost::python::handle<>((PyObject*)pyObjFrame)))
If you don't need to return a Mat converted to Python numpy array you can more easily use in the C++ code boost::python::dict or boost::python::list to wrap your data to be returned.
|
-1

This might be a little too late, but take a look at https://github.com/spillai/numpy-opencv-converter

1 Comment

In addition to linking the GitHub repo, also mind explaining how this helps with the question.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.