C++里面调用Python函数得到目标检测的返回结果(可实现二维数组的传输)

背景:在算法测试阶段想在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

帅小枫

我还没有学会写个人说明!

暂无评论

发表评论

相关推荐

YOLOX笔记

目录 1. 样本匹配 正负样本划分过程 2. yoloxwarmcos 学习率 3. 无法开启多gpu训练, 或者多gpu训练卡住? 1. 样本匹配 正负样本划分过程 说明: gt_centerbbox是在gt_bbox中心点向四周