Wrap my method which returns a cv::Mat

149 views
Skip to first unread message

Dat Chu

unread,
May 14, 2010, 11:04:58 AM5/14/10
to ctypes...@googlegroups.com
Hello,

I have a method which does some extension to OpenCV that returns a cv::Mat

class MyClass {
public:
    cv::Mat MyAwesomeMethod() const;
}

How do I wrap this method using Boost.Python or Py++ so that I can call it from Python?

I know how to wrap simple classes using Boost.Python but I need help with handling cv::Mat return type.

With warm regards,

Dat Chu

--
You received this message because you are subscribed to the Google Groups "ctypes-opencv" group.
To post to this group, send email to ctypes...@googlegroups.com.
To unsubscribe from this group, send email to ctypes-openc...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/ctypes-opencv?hl=en.

Minh-Tri Pham

unread,
May 15, 2010, 3:08:38 AM5/15/10
to ctypes...@googlegroups.com
Hi Dat,

You need to wrap both two classes cv::Mat and MyClass. But the most important
part is that you have to register class cv::Mat before registering class
MyClass. Once class cv::Mat is registered, it can be used freely just like
other primitive data types.

If you don't want to wrap class cv::Mat then you have to write
from_python/to_python conversion code. But you still need to register the
conversion code before wrapping functions/classes using cv::Mat. However,
writing conversion code is a lot more technically difficult than wrapping a
class.

Another issue is that if your function returns cv::Mat then it should be no
problem. However, if your function returns a reference to cv::Mat (i.e.
cv::Mat &) or a pointer to cv::Mat (i.e. cv::Mat *) then you need to include
a call policy.

Why don't you take a look at the following source files in PyOpenCV and see
how it was done in PyOpenCV:

Mat.pypp.cpp
Mat.pypp.hpp
HOGDescriptor.pypp.cpp (check the getDefaultPeopleDetector() function)
HOGDescriptor.pypp.hpp

Cheers,
Minh-Tri

On 5/14/2010 4:04 PM, Dat Chu wrote:
> Hello,
>
> I have a method which does some extension to OpenCV that returns a cv::Mat
>
> class MyClass {
> public:
> cv::Mat MyAwesomeMethod() const;
> }
>
> How do I wrap this method using Boost.Python or Py++ so that I can call it
> from Python?
>
> I know how to wrap simple classes using Boost.Python but I need help with
> handling cv::Mat return type.
>
> With warm regards,
>
> Dat Chu
>

--
Dr. Minh-Tri Pham
Research Fellow
Surrey Space Centre, University of Surrey, Guildford, GU2 7XH, UK
Mob: +44 (0) 778 774 1089 | Tel: +44 (0) 148 368 2224

Dat Chu

unread,
May 17, 2010, 10:19:20 AM5/17/10
to ctypes...@googlegroups.com
I think I didn't ask the correct question.

Since I am a user of pyopencv. I assume that PyOpenCV has already wrapped cv::Mat. How should I go about wrapping my class so that it can use the cv::Mat wrapped by PyOpenCV.

If this cannot be done with Boost.Python, I can try to switch to Py++.


With warm regards,

Dat Chu

Minh-Tri Pham

unread,
May 17, 2010, 11:28:15 AM5/17/10
to ctypes...@googlegroups.com
Hi Dat,

I see what you mean. What you are asking is doable but it is rather
technically challenging. In order to expose a function returning cv::Mat in
your Boost.Python module, you need to register *in your module* some code to
convert from a C++'s cv::Mat object to a Python object and vice versa. If you
don't register any conversion code in your module, the default conversion
code that Boost.Python provides is to generate a TypeError exception. Since
you would like to use PyOpenCV for the purpose of wrapping cv::Mat, I think
your two best choices are:

1) rip apart Mat.pypp.cpp and any source files you need from PyOpenCV's
source archive and compile/link them together with your code wrapping MyClass.

2) write C++ to_python/from_python conversion code that, when called, imports
pyopencv, gets the Python type of its Mat object, and does the conversion
between a C++ object and a Python object properly. More specifically, the
to_python code must take a pointer to your cv::Mat and create a Python object
of type PyOpenCV's Mat that wraps around your cv::Mat object. The from_python
code must take a Python object, verify that it is of type PyOpenCV's Mat, and
return a pointer to the wrapped cv::Mat object. You will also have to worry
about reference counting. Take a look at the following files for examples:

ndarray.hpp
ndarray.cpp
sequence.hpp
sequence.cpp

in which I have written some conversion code to interface with numpy's
ndarray. The code is based on an example in Py++, which is based on
Boost.Python's _undocumented_ API. :)

Cheers,
Minh-Tri
>> ctypes-openc...@googlegroups.com<ctypes-opencv%2Bunsu...@googlegroups.com>
>> .

Dat Chu

unread,
May 18, 2010, 11:13:23 PM5/18/10
to ctypes...@googlegroups.com
Hi Tri,

I have found the solution to my problem. If I want to use cv::Mat in my Boost.Python code.

All I need to do is to import the pyopencvext.so which I built using the CMakeLists.txt file that I posted in bug number #2.

Once this file is imported, cv::Mat object in C++ is translated into pyopencvext.Mat in Python. Now the problem is:

import pyopencvext
import curxd

a = curxd.Object3D('94002d35.wrl')
b = a.geometry_image()
b.ndarray

ValueError: dimensions too large

What gives? b is a 512x512x3 cv::Mat in C++.

Dat Chu

Minh-Tri Pham

unread,
May 19, 2010, 2:56:25 AM5/19/10
to ctypes...@googlegroups.com
That's awesome, Dat. I'm surprised when hearing this as I haven't tried it
myself before. I didn't know it was that easy. :)

I guess the "ValueError: dimensions too large" issue involves building
pyopencv using CMake and is not related to this issue at all (i.e. see my
comment in issue 2).

Cheers,
Minh-Tri
>> <ctypes-opencv%2Bunsu...@googlegroups.com<ctypes-opencv%252Buns...@googlegroups.com>
Reply all
Reply to author
Forward
0 new messages