Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python script stuck when reaching CV2 functions

I am trying to call a python script from C++ using boost:python.

the module and class are being called and everything works fine until the script reaches a function that uses opencv

the c++ code to call python is a part of a class that is started via a thread. the code part to call python is:

#include <boost/python.hpp>
#include "boost/python/stl_iterator.hpp"

#include <opencv2/opencv.hpp>

...

imencode(".jpg", image, imageBuffer);

namespace python = boost::python;

vector<unsigned char>::iterator iter;
python::list list;
for (iter = imageBuffer.begin(); iter != imageBuffer.end(); ++iter) {
    list.append(*iter);
}


python::object python_module = python::import("file");
python::object klass = python_module.attr("klass")(this->modelPath.c_str());
python::object res =  klass.attr("fun")(list);

file.py looks like:

import numpy as np
import cv2
class klass:

    def __init__(self, model_path):

        self.model = model_path

    def fun(self, image):

        image = np.asarray(image, dtype=np.uint8)
        print("b4")
        image = cv2.imdecode(image, 1)
        print("after")
        return 1

The "print("b4")" line is printed but once imdecode is reached the code is stuck and nothing happens

opencv-python is installed using

sudo pip3 install opencv-python

the opencv-python version is 4.1.0 the numpy version is 1.16.3

I am using python 3.5

why the code is coming to a pause and how to solve that

EDIT

I just need to mention the call is done from a thread. If the call is done from Main the code works. This Code is called via pthread_create()

Apparently i am missing something in the threading

EDIT 2

So it was really a threading issue and I figured out "a solution" I will post as an answer. I don't know if this is the correct way to address it but it works

like image 930
EYakoumi Avatar asked Oct 17 '25 02:10

EYakoumi


1 Answers

To solve this issue i added the following after py_initialize

Py_Initialize();
PyEval_InitThreads();
PyEval_ReleaseLock();

then when the thread starts I did:

PyGILState_STATE gstate;
gstate = PyGILState_Ensure();

then do all the python calls ....

at the end call

PyGILState_Release(gstate);

Note that any python calls (even the DECREF calls) after PyGILState_Release() will not work and cause a code crash that's why i put that call in my threaded class destructor as the last thing to call.

like image 192
EYakoumi Avatar answered Oct 18 '25 15:10

EYakoumi



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!