Pass Mat to Python Script ?

asked 2018-05-18 06:55:50 -0600

RPH gravatar image

updated 2018-05-18 07:14:12 -0600

Hi, I am using OpenCV v2.4.13.6 with C++ in QT Creator. I am trying to pass an OpenCV Mat object to a Python script using Python interpreter. I need to convert the OpenCV Mat to a PyObject so that I can pass it to the Python script.

Something like this:

PyObject *pName, *pModule, *pFunc, *pValue, *pMat;
Mat img;
Py_Initialize();
pName = PyUnicode_FromString("load-mat"); //python script is named load-mat
pModule = PyImport_Import(pName);
pFunc = PyObject_GetAttrString(pModule, "load_mat") //python function is named load_mat()
############################################
//Need to convert Mat img to PyObject *pMat
############################################
pValue = PyObject_CallFunctionObjArgs(pFunc, pMat, NULL);
Py_Finalize();

I read somewhere:

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

pMat = pyopencv_from(img);

But placing that into my C++ code straight I get the following 2 errors:

error: 'g_numpyAllocator' was not declared in this scope
error: 'pyObjectFromRefcount' was not declared in this scope

What is the easiest method of getting this to work ? Thanks

edit retag flag offensive close merge delete

Comments

oh, noes, don't try to write your own wrapper.

WHY do you (think, you) need to do this ?

v2.4.13.6 -- outdated. (frozen in the state of ~5 years ago) why do you use that ?

berak gravatar imageberak ( 2018-05-18 07:05:17 -0600 )edit

Hi, I'm not trying to write my own wrapper. I was just following the guide here: Embedding Python in Another Application. I had trouble building OpenCV v3 from source for MinGW x64 compiler. What's wrong with using OpenCV v2 ?

RPH gravatar imageRPH ( 2018-05-18 07:18:28 -0600 )edit

I'm not trying to write my own wrapper.

if you start like this, sure you do !

again, why do you need it ?

(there's also a problem: if you use cv2 AND your own wrappers, you have 2 (different) opencv versions in your program)

maybe you're better off, adding another module (with your c++ code & headers) to the opencv codebase, and let the python generator do it's job. then, also, cv::Mat is already correctly wrapped there. (no need to do that again)

have a look here and try to explain better, where you start from, and what you're trying to achieve, please.

berak gravatar imageberak ( 2018-05-18 07:47:35 -0600 )edit

Ok, maybe it's better for me to explain at a high level what I'm trying to achieve, then you can let me know if it's possible.

1) I have a script in Python that trains a classifier on pre-loaded images. I have another Python script that should take as input an OpenCV image and pass it through the classifier (which I load from file) to produce a prediction. This Python script/function is the one I am referring to in my code.

2) I have a C++ program that gets the OpenCV image that I wish to pass through the classifier.

Basically the classification is in Python but the image that I wish to classify is in my C++ program. So somehow I need to pass the Mat image that I have in C++ to the Python script for classification and have it return the prediction result ...(more)

RPH gravatar imageRPH ( 2018-05-18 08:37:04 -0600 )edit

ah, i missed the "embedding" part. that's the other side of the table.

i still think, it's a bad idea. why are there even 3 seperate programs ? can't you replace the c++ image acquisition with something in python ?

berak gravatar imageberak ( 2018-05-18 09:59:37 -0600 )edit

No, I need to use C++ because it's a GUI program. I cannot convert the python code to C++ either.

There are 3 programs because 1. is for the main GUI program that captures images, 2. is a python script for training a classifier (as I said already, this cannot be re-written in C++ with ease - it's a complex CNN), and 3. is for loading the trained classifier and performing forward-pass prediction on a given image.

If I can just convert my Mat object to a PyObject in the C++ program then I can pass it to the python script for prediction. Surely this is possible ? Yes, it may not be the best idea, but I think it should be possible. Maybe with something like the "pyopencv_from()" function ?

RPH gravatar imageRPH ( 2018-05-18 11:05:57 -0600 )edit

@berak Anymore info on this ?

RPH gravatar imageRPH ( 2018-05-21 03:20:28 -0600 )edit

no, sorry.

berak gravatar imageberak ( 2018-05-21 03:30:49 -0600 )edit

@berak I'm using the built in OpenCV wrapper pyopencv_from() included in "modules\python\src2\cv2" to wrap the Mat as a Numpy Array but my program crashes on the line PyObject* o = PyArray_SimpleNew(dims, _sizes, typenum); Any idea why ?

RPH gravatar imageRPH ( 2018-05-21 07:52:29 -0600 )edit

Nevermind, I solved it by adding the line: import_array(); to my main function.

RPH gravatar imageRPH ( 2018-05-21 08:19:11 -0600 )edit