IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Python知识库 -> vs2010c++调用python,并打包移植到其他电脑 -> 正文阅读

[Python知识库]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上运行的。

  Python知识库 最新文章
Python中String模块
【Python】 14-CVS文件操作
python的panda库读写文件
使用Nordic的nrf52840实现蓝牙DFU过程
【Python学习记录】numpy数组用法整理
Python学习笔记
python字符串和列表
python如何从txt文件中解析出有效的数据
Python编程从入门到实践自学/3.1-3.2
python变量
上一篇文章      下一篇文章      查看所有文章
加:2022-07-17 16:19:02  更:2022-07-17 16:20:41 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/15 12:02:08-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码