vs2010c++调用python,并打包移植到其他电脑

前言

想要在c++中部署训练好的深度学习模型方法可能有很多种,但是在低版本c++中部署深度学习模型似乎方法比较单一。由于进入项目时,大部分代码都是在vs2010上编译的,需要在程序中调用深度学习模型进行图片识别,采用调用python接口的方式进行部署及封装。vs2010版本为32位,python版本为python3.7.5 32位。除此以外需要安装cython,pyinstaller和vs2017,这三个工具是为了将python程序直接转译为可执行代码,加快运行速度用的。

过程

1.vs2010导入python库

这部分我就不写了,网上太多的例子。不过需要注意一点的是,如果vs2010是debug模式就要导入对应的dll,如python37_d.dll等,这个在单独安装python的时候会有一个选项,默认是不安装,这个需要自己选上才会在安装文件夹中出现。如果是安装anaconda的,这个可能没有。

要注意在编译的时候,会提示出现缺少inttypes.h头文件的错误,网上会有大量资源提供inttypes.h下载,但是要下载对应自己vs2010版本的文件,同时对于vs2010版,还需要安装对应版本的boost库,这时候才能正常调用python接口,我的boost库的版本是1.55版。这里我提供一个下载资源,有需要的自己下:

https://gitee.com/liuzhic_enfi/cxx_call_python.git

2.代码实践

这一块其实写的人不少,但有些方法不同意,而且很容易给后期打包的时候出现bug。
首先是启动阶段,如果是需要用到循环识别多图,这部分代码要写到循环外,如果要封装为函数,记得要返回里面模型的指针变量。

Py_SetPythonHome(L"./");//这里是python的安装目录
Py_Initialize();
if (Py_IsInitialized()==0)
{
	printf("init python failed");
}
PyEval_InitThreads(); 
PyRun_SimpleString("import sys");
PyRun_SimpleString("sys.path.append('./')");//这里需要调用python文件的地址
model = load_model();

其中load_model()函数里面的内容是

PyObject* load_model()
{
	PyObject* pModule = PyImport_ImportModule("testpython1");//python文件名
	PyObject *pDict = NULL;
    pDict = PyModule_GetDict(pModule);
	PyObject* pFunc = NULL;
	pFunc = PyDict_GetItemString(pDict, "build"); //def func函数名
	PyObject* model =PyObject_CallObject(pFunc, NULL);
	return model;
}

循环读图中最重要的内容是将图片所在地址copy到numpy所在地址
这里附上for循环里面cv::Mat格式转为adarray格式的代码:

cv::Mat img = color_list[0].clone();
//cv::imshow("img",img);
//cv::waitKey(0);
cv::cvtColor(img,img,cv::COLOR_BGR2RGB);
int iChannels = img.channels();
int iRows = img.rows;
int iCols = img.cols * 3;

uchar* CArrays = new uchar[img.rows * img.cols * 3];

if (img.isContinuous())
{
	iCols *= iRows;
	iRows = 1;
}
uchar* p;
int id = -1;
for (int i = 0; i < iRows; i++)
{
	// get the pointer to the ith row
	p = img.ptr<uchar>(i);
	// operates on each pixel
	for (int j = 0; j < iCols; j++)
	{
		CArrays[++id] = p[j];//
	}
}
import_array1(-1);
npy_intp Dims[3] = { img.rows, img.cols, 3 }; //
PyObject *PyArray = PyArray_SimpleNewFromData(3, Dims, NPY_UBYTE, CArrays);
//delete []CArrays ;
//CArrays =nullptr;
PyObject *ArgList = PyTuple_New(2);//传入python的type必须为tuple
PyTuple_SetItem(ArgList, 0, PyArray);//将图片导入tuple第0项
PyTuple_SetItem(ArgList, 1, model);//将模型导入tuple第1项

这一部分我一直心里感觉不舒服,是因为我只能用逐个遍历像素的方式传递地址,真正大佬都用std::memcpy()函数,不知后期有没有大佬能够用这个函数提升一下这段代码整体效率。
附:今天我把这段遍历像素的for循环改了,可以提升一部分代码效率:
原:

uchar* p;
int id = -1;
for (int i = 0; i < iRows; i++)
{
	// get the pointer to the ith row
	p = img.ptr<uchar>(i);
	// operates on each pixel
	for (int j = 0; j < iCols; j++)
	{
		CArrays[++id] = p[j];//
	}
}

替换为:

std::memcpy(CArrays,img.ptr<uchar>(0),int(img.rows * img.cols * 3));

然后是向python函数导入变量和导出结果部分的代码:

PyObject* pModule = PyImport_ImportModule("testpython1");//文件名
PyObject *pDict = NULL;
pDict = PyModule_GetDict(pModule);
PyObject* pFunc2 = NULL;
pFunc2 = PyDict_GetItemString(pDict, "run"); //def func函数名
PyObject* pp2 = PyObject_CallObject(pFunc2, ArgList);  //传递参数,并得到结果
int res = 0;
PyArg_Parse(pp2, "i", &res);//结果转为int型
delete []CArrays ;
CArrays =nullptr;

现在循环内部就完成了,跳出循环后注意添加:

Py_Finalize();

3.打包

c++的打包让我一直很难受,因为不像python中的pyinstaller工具,可以自动找到并复制库文件(不过也是,python库文件放置那么统一,找不到也难)。这个打包时需要将python安装文件里面的大部分内容(主要是安装文件夹中的那些文件以及所用库的文件),boost库放置在工程文件夹中的bin文件夹中,这里我先提前声明,因为这里面我只知道一部分有用,剩下的文件我也不清楚,所以我就把所有文件考到bin文件夹下了。python自身代码可以利用pyinstaller打包为文件夹形式,并将文件夹内所有文件考到bin文件夹下。
如果移植到其他电脑上发现没有调用python接口,注意代码中这句:

Py_SetPythonHome(L"./");//这里是python的安装目录

设置python环境在本文件夹就可以了,基本上这句没问题都能启动,后期找不到的文件也会报错提示。这里用pyinstaller打包python的原因不仅仅是它会将程序编译为可执行文件,同时还会自动配置环境,像onnxruntime本来不支持win7环境,但是用pyinstaller打包封装后的程序是可以在win7上运行的。

VS2010C++ 项目移植到更高版本的 Visual Studio 时,需要注意以下几点: 1. 解决方案和项目文件的兼容性:在使用更高版本的 Visual Studio 打开 VS2010 的解决方案时,可能会自动进行解决方案和项目文件的升级。确保备份原始项目文件,以防升级过程中出现问题。 2. 平台工具集的更改:不同版本的 Visual Studio 可能使用不同的平台工具集。在迁移项目时,需要确保选择正确的平台工具集,以保持与原始项目的兼容性。可以在项目属性中调整平台工具集的设置。 3. 代码兼容性:在较新版本的 Visual Studio 中,可能会引入一些新的 C++ 特性和语法改变。您需要仔细检查和修改代码,以确保它们与新版本的编译器和标准库兼容。特别是一些过时或不推荐使用的功能,可能需要进行相应的更新。 4. 第三方库和依赖项:如果您的项目依赖于第三方库或其他外部组件,确保这些库在新版本的 Visual Studio 中仍然可用,并进行必要的更新。可能需要重新配置和重新编译这些库,以适应新环境。 5. 编译和链接选项:在新版本的 Visual Studio 中,编译和链接选项可能会有所变化。检查并更新项目属性中的编译器和链接器设置,以确保其与新环境相匹配。 6. 平台和配置:如果您的项目涉及多个平台或配置(例如 x86 和 x64,Debug 和 Release),请确保在新版本的 Visual Studio 中正确配置和设置它们。 7. 测试和调试:在迁移项目后,进行全面的测试和调试,以确保项目在新版本的 Visual Studio 中正常工作,并检查是否存在任何问题或错误。 在进行迁移之前,建议先阅读新版本 Visual Studio 的文档和迁移指南,了解与您的项目相关的特定更改和注意事项。此外,及时备份项目文件和相关资源,以防在迁移过程中出现问题。 请注意,这些是一般性的建议,具体迁移过程可能因项目的复杂性和特定要求而有所不同。对于更复杂的项目,可能需要更深入的了解和调整。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值