背景:在算法测试阶段想在C++算法中直接获取基于python的目标检测结果。如果你想把python检测结果保存在本地再用C++读取可以忽略此博客。
python脚本接口中的主要函数 def image_infer(img_path) ''' 省略。。。。。 ''' print(result) return result // 返回值是所有目标检测框的位置,是一个二维数组。
接下来如何在C++里面得到python返回值呢,主要代码具体如下
cmakeList.txt里需要加的部分
...
## python 版本根据自己的相应修改
find_package(Boost COMPonENTS thread serialization python REQUIRED)
include_directories(${Boost_INCLUDE_DIR}
/usr/include/python3.8)
...
ADD_EXECUTABLE(target *.cpp)
TARGET_link_LIBRARIES(target
...
${Boost_LIBRARIES}
/usr/lib/x86_64-linux-gnu/libboost_python38.so
/usr/lib/x86_64-linux-gnu/libstdc++.so.6
/usr/lib/x86_64-linux-gnu/libpython3.8.so
)
#includeusing namespace boost::python; int main() { ... Py_Initialize(); if(!Py_IsInitialized()){ cout << "[Error] Python init error" << endl; return -1; } string py_dir = "sys.path.append('xxx')"; //存放python脚本的路径 PyRun_SimpleString("import sys"); PyRun_SimpleString(py_dir.c_str()); PyObject *pModule = Pyimport_importModule("infer"); //这里的infer即为python脚本名 if (pModule == nullptr){ cout <<"[Error] import module error" << endl; return -1; } cout << "[INFO] Get Module" << endl; PyObject *pFunction = PyObject_GetAttrString(pModule, "image_infer"); if (pFunction == nullptr){ cout << "[Error] import function error" << endl; return -1; } cout << "[INFO] Get Function" << endl; PyObject *args = PyTuple_New(1); PyObject *args1 = PyUnicode_FromString("xxx/.jpg"); //图片路径 PyTuple_SetItem(args, 0, args1); PyObject *pRet = PyObject_CallObject(pFunction, args); PyObject *iter = PyObject_GetIter(pRet); while(true) { PyObject *next = PyIter_Next(iter); if (!next) { // nothing left in the iterator break; } if(!PyList_Check(next)) { // error, we were expecting a list value } // PyObject *res = PyList_AsTuple(next); PyObject *iter2 = PyObject_GetIter(next); while(true) { PyObject *next2 = PyIter_Next(iter2); if(!next2) break; if (!PyFloat_Check(next2)) { // error, we were expecting a floating point value } double foo = PyFloat_AsDouble(next2); cout << foo << " "; } cout << endl; } ... }
例子运行结果
python脚本里的打印结果: [[837.7739868164062, 82.12419128417969, 1023.6489868164062, 316.09344482421875, 0.0], [0.856614351272583, 85.63136291503906, 320.9000244140625, 317.7690734863281, 0.0], [168.07826232910156, 113.46662902832031, 321.42633056640625, 293.0325012207031, 0.0], [1.623028039932251, 85.82231903076172, 172.3456268310547, 316.8103942871094, 0.0], [275.1335144042969, 120.93679809570312, 320.4854736328125, 279.6253662109375, 0.0], [835.6593017578125, 107.04777526855469, 886.0287475585938, 296.23529052734375, 0.0], [310.59307861328125, 120.15199279785156, 330.61077880859375, 286.6786804199219, 0.0], [169.95175170898438, 119.09870910644531, 241.6178436279297, 294.2791748046875, 0.0]] C++里得到的返回值 837.774 82.1242 1023.65 316.093 0 0.856614 85.6314 320.9 317.769 0 168.078 113.467 321.426 293.033 0 1.62303 85.8223 172.346 316.81 0 275.134 120.937 320.485 279.625 0 835.659 107.048 886.029 296.235 0 310.593 120.152 330.611 286.679 0 169.952 119.099 241.618 294.279 0
参考链接:
链接一:C++调用Python3接口
链接二:ubuntu 16.04 C++ 调用python脚本实现方式
链接三:使用C扩展python:将列表传递给PyArg_ParseTuple
链接四:PyArg_ParseTuple函数文档



