背景:在算法测试阶段想在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
)
#include <boost/python.hpp>
using 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函数文档
以上方式比较简单,不需要安装额外的库即可在C++中调用python脚本函数,跑pytorch训练的模型。而实际想工程化应用的话还是要安装ncnn模块来在C++中直接调用训练模型,这种方式可以输出神经网络任意一层的输出。
版权声明:本文为CSDN博主「帅小枫」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_43421058/article/details/121331891
暂无评论