Algomorph/pyboostcvconverter

empty cv::Mat objects

Closed this issue · 6 comments

I have tried to use your fromNDArrayToMat function but a Mat object with no data is returned (if I try an imshow i indeed get a segmentation fault).
I have read that this could depend on errors during the conversion, but what these errors could be ? I am pretty sure I am passing a legit numpy array ... How can I debug this issue ?

Thank you for your project

Hi, Dario, please tell me your operating system & version, the python version that you're using, and how exactly you're trying to use the code.
It's intended to be used as sample code, not as a separate dynamic library linked by another binary. Does the example I give in the README work for you in the python shell after you make/build the install target?

Hello, I'm using Ubuntu 16.04, Python 3.5.2, OpenCV 3.4.2.17 (installed by Pip).

I have tried to follow the example you presented in the README, which works on my setup (dot and dot2 functions both print 14.0)
Basically, I have a c++ class MyClass implementing the method void myMethod(cv::Mat), which I would expose to python (together with the class constructor ). For doing so, I've defined the following extension module based on your example, implementing implict conversion:

#include <boost/python.hpp>
#include "MyClass.h"
#include "pyboostcvconverter.hpp"

#if (PY_VERSION_HEX >= 0x03000000)

    static void *init_ar() {
#else
        static void init_ar(){
#endif
        Py_Initialize();

        import_array();
        return NUMPY_IMPORT_ARRAY_RETVAL;
    }

BOOST_PYTHON_MODULE(my_class_ext)
{
	init_ar();

    boost::python::to_python_converter<cv::Mat,
            pbcvt::matToNDArrayBoostConverter>();
    pbcvt::matFromNDArrayBoostConverter();

	using namespace boost::python;
    class_<MyClass,boost::noncopyable>("MyClass", init<int, int>())
		.def("myMethod", &MyClass::myMethod)
    ;
}

in python:

import my_class_ext
from my_class_ext import Myclass

mc = MyClass(640,480)
...
mc.myMethod(nd_array)

This give me a segmentation fault.

For better investigating what is going on, I defined a dummy function within the extension module that I am now executing instead of myMethod:

#include <boost/python.hpp>
#include "MyClass.h"
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include "pyboostcvconverter.hpp"

void dummy(PyObject *obj, PyObject *rgb){

	cv::Mat cv_rgb;

	std::cout<< "conversion" << std::endl; 
	cv_rgb = pbcvt::fromNDArrayToMat(rgb);
	std::cout<< "end conversion" << std::endl; 

	cv::imshow("temp", cv_rgb);
	cv::waitKey(0);
}


#if (PY_VERSION_HEX >= 0x03000000)

    static void *init_ar() {
#else
        static void init_ar(){
#endif
        Py_Initialize();

        import_array();
        return NUMPY_IMPORT_ARRAY_RETVAL;
    }

BOOST_PYTHON_MODULE(my_class_ext)
{
	init_ar();

    boost::python::to_python_converter<cv::Mat,
            pbcvt::matToNDArrayBoostConverter>();
    pbcvt::matFromNDArrayBoostConverter();

	using namespace boost::python;
    class_<MyClass,boost::noncopyable>("MyClass", init<int, int>())
		.def("myMethod", dummy)
    ;
}

and in python:

import my_class_ext
from my_class_ext import Myclass

mc = MyClass(640,480)
...
mc.dummy(nd_array)

I don't really know what I changed from yesterday but now i get a segmentation fault on the pbcvt::fromNDArrayToMat(rgb); call, while yesterday (as I wrote in my previous message), I was getting to the imshow function, which was failing (segmentation fault)

Many thanks for your support

I tried:

	void dummy(PyObject *rgb){
		cv::Mat cv_rgb;

		std::cout<< "conversion" << std::endl;
		cv_rgb = pbcvt::fromNDArrayToMat(rgb);
		std::cout<< "end conversion" << std::endl;

		cv::imshow("temp", cv_rgb);
		cv::waitKey(0);
	}

And def("dummy", dummy); within the module definition, it seems to work just fine.
The way you defined an external dummy method to act as a class method seems sensible, but I'm not sure it is supposed to work this way. I'll try to come up with a small class example right now and see if it works, and then give you an update. NB: I'm on the same system and Python version, and using the vanilla OpenCV 3.4.2 compiled from release code.

@DarioTurchi , now I tried this:

class Dummy {
public:
	void dummy(PyObject* rgb) {
		cv::Mat cv_rgb;

		std::cout << "conversion" << std::endl;
		cv_rgb = pbcvt::fromNDArrayToMat(rgb);
		std::cout << "end conversion" << std::endl;

		cv::imshow("temp", cv_rgb);
		cv::waitKey(0);
	}
};

And this in the module:

class_<Dummy>("Dummy").def("dummy", &Dummy::dummy);

It seems to work fine:
image

I also went back to an older project of mine that did something like what you're doing:
https://github.com/Algomorph/cve/blob/master/src/python_module.cpp

Syntax seems to be correct...
Are you certain that you're linking the correct OpenCV component libraries?
Since you installed OpenCV via pip, that seems to be the only difference. I don't think pip would install all the component libraries, like libopencv_highgui.so.3.4.2 (I think it just puts cv2.so / equivalent somewhere in PYTHONPATH), so your code might be trying to link against an OpenCV 2.4 equivalent, which could cause a segfault when used in conjunction with OpenCV 3.4 that is using Qt.

First of all, I would ensure that your CMake is linking the proper modules, i.e., for highgui:

find_package(OpenCV COMPONENTS core highgui REQUIRED) #add other modules as you see fit
#and then, somewhere below
target_link_libraries( your_target_name
        ${Boost_LIBRARIES}
        ${OpenCV_LIBRARIES}
        ${PYTHON_LIBRARIES}
        )

Secondly, please ensure that it's linking the right version of OpenCV! You can use that either by running something like 'ldd pbcvt.cpython-35m-x86_64-linux-gnu.so | grep opencv' in the terminal, within the build output folder, or by inspecting the libraries that CMake detects in cmake-gui.

@DarioTurchi , I haven't heard from you in awhile, I hope that you found a fix. I'll close this for now, please feel free to reopen if necessary.

Hello,
Unfortunately I had to get my code working quickly so I've found a different solution for converting ndarray to cv::Mat and couldn't properly investigate the issue following your suggestions. I'd like, however, to adopt your library in the future, so I'll probably be back at you.
Thank you very much anyway.