任务描述:C++ 调用Python训练的TensorFlow模型(多个深度学习算法模型),封装为dll或者封装为exe文件。
调用形式:C++直接调用Python运行脚本,没有涉及各个算法间数据流的传递,保存为中间文件(.png,.txt等);
主要步骤如下:
1、获取tensorflow可以运行的python环境;2、将环境添加到VS2015工程中(当然其它版本的VS也是可以的);3、写测试主程序,然后封装为DLL、Lib;4、调用接口;
1、获取Python环境
一般用的都是虚拟环境,比如用Anaconda创建虚拟环境,然后打包整个虚拟环境,打包的方式就是复制整个文件夹。下图是我用的虚拟环境(TF35,都是用Anaconda 创建的,位置:~/Anaconda3/envs/)
2、将环境添加到VS2015
当然VS其它版本也是可以的, 创建好一个空的项目后,将TF35文件夹放到新建工程的根目录(位置可以自己确定),具体添加步骤如下图所示:(1)C/C++:附加包含目录,"TF35\include";(2)链接器:附加依赖项, "TF35\libs\python35.lib";(3)调试/环境:PATH=TF35. 必须添加,否则无法成功导入环境。
3、写主测试程序,封装接口
完成步骤2后,基本上已经配置好Python的虚拟环境了,主程序如下:
#include <Python.h>
#include <iostream>
#include <string>
#include <windows.h>
#include <stdlib.h>
//extern "C" _declspec(dllexport)int DLPose()
int main()
{
Py_SetPythonHome(L"TF35"); // 添加Python环境路径
Py_Initialize();
if (Py_IsInitialized())
std::cout << "Init Success 1" << std::endl;
PyRun_SimpleString("import sys");
PyRun_SimpleString("sys.path.append('./')");
PyRun_SimpleString("print(sys.version)\n");
system("python ./merge/deal_img.py");
system("python ./merge/KerasYolo3/yolo_video.py");
system("python ./merge/deeplabv3/deeplabv3_demo_v3.py");
system("python ./merge/Spine/test_v3.py");
}
注意:通常按照上面的代码,可以运行相应的深度学习算法模型,完成测试,一般运行的时候会报错:找不到python35.dll,可以按照下图设置,或者将python35.dll放到VS工程的根目录,具体可以自己尝试:
封装为DLL,LIB:程序如下,只需更改函数名字:int main --> extern "C" _ declspec(dllexport) int DLPose(),后面的名字是标准的DLL接口,int DLPose()是自己命的函数名;
#include <Python.h>
#include <iostream>
#include <string>
#include <windows.h>
#include <stdlib.h>
extern "C" _declspec(dllexport)int DLPose()
// int main()
{
Py_SetPythonHome(L"TF35"); // 添加Python环境路径
Py_Initialize();
if (Py_IsInitialized())
std::cout << "Init Success 1" << std::endl;
PyRun_SimpleString("import sys");
PyRun_SimpleString("sys.path.append('./')");
PyRun_SimpleString("print(sys.version)\n");
system("python ./merge/deal_img.py");
system("python ./merge/KerasYolo3/yolo_video.py");
system("python ./merge/deeplabv3/deeplabv3_demo_v3.py");
system("python ./merge/Spine/test_v3.py");
return 0;
}
当然还需要一个头文件(DLPose.h):为了方便让他人知道接口的函数名字;
#pragma once
extern "C" _declspec(dllexport)int DLPose();
还需要设置:将配置类型改为动态库(.dll)
完成上面的准备后,可以编译工程,运行结果如下,SpinEstimate.dll,SpinEstimate.lib是需要的文件,Lib文件的名字和工程的名字一致;
4、调用封装的DLL
新建一个新的工程,调用上述封装好的接口,DLL和LIB,测试工程无需再添加Python环境,编译运行即可;
#include<iostream>
// #include<Python.h>
#include<windows.h>
#include"DLPose.h"
#include<stdlib.h>
int main()
{
DLPose(); // 接口的名字,也即是要调用的函数名,没有输入参数
return 0;
}
注意:需作如下设置,添加PATH=TF35,否则无法使用虚拟环境,当然可以还有其它的处理方式,比如像步骤2一样给测试工程添加Python环境(具体情况,具体测试!);
5、调用exe文件
如果不想调用DLL,可以将原工程直接打包成Exe文件,这样使用更加方便。只需使用默认的配置类型即可。生成后的exe文件位于~x64\Release目录下,此时可以用cmd直接运行,或者其它程序直接调用该exe文件。
注意:不管是调用DLL,或者是Exe,只要直接运行Exe文件,都会存在无法成功启动Python环境的问题,此时需要将虚拟环境添加到系统环境变量即可。具体如下图所示: