-
-
Save Xonxt/26d2a9ac6c56505d0896822ede99a646 to your computer and use it in GitHub Desktop.
/* | |
This requires adding the "include" directory of your Python installation to the include diretories | |
of your project, e.g., in Visual Studio you'd add `C:\Program Files\Python36\include`. | |
You also need to add the 'include' directory of your NumPy package, e.g. | |
`C:\Program Files\PythonXX\Lib\site-packages\numpy\core\include`. | |
Additionally, you need to link your "python3#.lib" library, e.g. `C:\Program Files\Python3X\libs\python3X.lib`. | |
*/ | |
// python bindings | |
#include "Python.h" | |
#include "numpy/arrayobject.h" | |
#include <iostream> | |
#include "opencv2/opencv.hpp" | |
// references to all the functions | |
PyObject *m_PyDict, *m_PyFooBar; | |
// reference to the Pyhton module | |
PyObject* m_PyModule; | |
int main(int argc, char** argv) { | |
// initialize Python embedding | |
Py_Initialize(); | |
// set the command line arguments (can be crucial for some python-packages, like tensorflow) | |
PySys_SetArgv(argc, (wchar_t**) argv); | |
// add the current folder to the Python's PATH | |
PyObject *sys_path = PySys_GetObject("path"); | |
PyList_Append(sys_path, PyUnicode_FromString(".")); | |
// this macro is defined by NumPy and must be included | |
import_array1(-1); | |
// load our python script (see the gist at the bottom) | |
// use the script's filename, sans the extension | |
m_PyModule = PyImport_ImportModule("pythonScript"); | |
if (m_PyModule != NULL) | |
{ | |
// get dictionary of all available entities in the module | |
m_PyDict = PyModule_GetDict(m_PyModule); | |
// grab the functions we are interested in (using its name) | |
m_PyFooBar = PyDict_GetItemString(m_PyDict, "foo_bar"); | |
// execute the function | |
if (m_PyFooBar != NULL) | |
{ | |
// take a cv::Mat object from somewhere (we'll just create an empty one) | |
cv::Mat img = cv::Mat::zeros(480, 640, CV_8U); | |
// total number of elements (here it's a greyscale 640x480) | |
const unsigned int nElem = 640 * 480; | |
// create an array of apropriate datatype | |
uchar* m = new uchar[nElem]; | |
// copy the data from the cv::Mat object into the array | |
std::memcpy(m, img.data, nElem * sizeof(uchar)); | |
// the dimensions of the matrix | |
npy_intp mdim[] = { 480, 640 }; | |
// convert the cv::Mat to numpy.array | |
PyObject* mat = PyArray_SimpleNewFromData(2, mdim, NPY_UINT8, (void*) m); | |
// create a Python-tuple of arguments for the function call | |
// "()" means "tuple". "O" means "object" | |
PyObject* args = Py_BuildValue("(O)", mat); | |
// if we want several arguments, we can write ("i" means "integer"): | |
// PyObject* args = Py_BuildValue("(OOi)", mat, mat, 123); | |
// to send two images and an integer, equivalent to Python's (mat, mat, 123) tuple | |
// see detailed explanation here: https://docs.python.org/2.0/ext/buildValue.html | |
// execute the function | |
PyObject* result = PyEval_CallObject(m_PyFooBar, args); | |
// process the result | |
// ... | |
// decrement the object references | |
Py_XDECREF(mat); | |
Py_XDECREF(result); | |
Py_XDECREF(args); | |
delete[] m; | |
} | |
} | |
else | |
{ | |
std::cerr << "Failed to load the Python module!" << std::endl; | |
PyErr_Print(); | |
} | |
return 0; | |
} |
// same example, but for a 3-channel RGB image. | |
// python bindings | |
#include "Python.h" | |
#include "numpy/arrayobject.h" | |
#include <iostream> | |
#include "opencv2/opencv.hpp" | |
// for the references to all the functions | |
PyObject *m_PyDict, *m_PyFooBar; | |
// for the reference to the Pyhton module | |
PyObject* m_PyModule; | |
int main(int argc, char** argv) { | |
// initialize everything (see gist above for details) | |
Py_Initialize(); | |
PySys_SetArgv(argc, (wchar_t**)argv); | |
PyObject *sys_path = PySys_GetObject("path"); | |
PyList_Append(sys_path, PyUnicode_FromString(".")); | |
import_array1(-1); | |
m_PyModule = PyImport_ImportModule("pythonScript"); | |
if (m_PyModule != NULL) | |
{ | |
// get dictionary of available items in the module | |
m_PyDict = PyModule_GetDict(m_PyModule); | |
// grab the functions we are interested in | |
m_PyFooBar = PyDict_GetItemString(m_PyDict, "foo_bar"); | |
// execute the function | |
if (m_PyFooBar != NULL) | |
{ | |
// take a cv::Mat object from somewhere (we'll just create one) | |
cv::Mat img = cv::Mat::zeros(480, 640, CV_8UC3); | |
// total number of elements (here it's an RGB image of size 640x480) | |
const unsigned int nElem = 640 * 480 * 3; | |
// create an array of apropriate datatype | |
uchar* m = new uchar[nElem]; | |
// copy the data from the cv::Mat object into the array | |
std::memcpy(m, img.data, nElem * sizeof(uchar)); | |
// the dimensions of the matrix | |
npy_intp mdim[] = { 480, 640, 3 }; | |
// convert the cv::Mat to numpy.array | |
PyObject* mat = PyArray_SimpleNewFromData(3, mdim, NPY_UINT8, (void*) m); | |
// create a Python-tuple of arguments for the function call | |
// "()" means "tuple". "O" means "object" | |
PyObject* args = Py_BuildValue("(O)", mat); | |
// execute the function | |
PyObject* result = PyEval_CallObject(m_PyFooBar, args); | |
// process the result | |
// ... | |
// decrement the object references | |
Py_XDECREF(mat); | |
Py_XDECREF(result); | |
Py_XDECREF(args); | |
delete[] m; | |
} | |
} | |
else | |
{ | |
std::cerr << "Failed to load the Python module!" << std::endl; | |
PyErr_Print(); | |
} | |
return 0; | |
} |
import cv2 | |
import numpy as np | |
# define the function that we will call from the C++ code | |
def foo_bar(img=None): | |
if img is not None: | |
cv2.imshow("image in python", img) |
Yes. I already installed numpy package in python. That why i can run your code in VS 2017. Now i want run your code in VS 2019 but i have the problem. Thanks you response for me.
I have more information, now i return VS 2017 and this code have the same problem :)) . I install two Visual Studio together 2017 and 2019. First 2017 and second 2019.
https://gist.github.com/Xonxt/26d2a9ac6c56505d0896822ede99a646#gistcomment-3723333
I tested it again and I think it didn't have any overhead anymore. thanks for the reply.
@Xonxt
Hi guys, long time no reply :)
I have a new question for you. How i can choose enviromnent for python? It's mean when i call python from c++ script? How to choose env to run python script.
Example: I using ubuntu 18.04 OS . I have 2 virtual environment ( anaconda and venv) and 1 real environment python3.6.9 default of ubuntu (python default). How to i know what env i run python code when call from c++ and how to change it? is it based on python.h (python.a in linux). I think this is similar on window with venv and anaconda and python when install from offcial web site of python.
Yes. I already installed numpy package in python. That why i can run your code in VS 2017. Now i want run your code in VS 2019 but i have the problem.
Thanks you response for me.