参考网站:
1、配置项目属性表
将Python目录下的include和libs文件夹路径配置到属性表中,如果需要用到虚拟环境,就把envs虚拟环境下的相关文件路径配置到属性表
如果 需要用到一些其他的第三方库 就要再次进行关联。例如用numpy 就需要去Lib/site-packages 下 关联需要用到的包
2、C++代码编辑
导入头文件 Python.h:#include <Python.h>
// 架构 #include <iostream> #include "Python.h" using namespace std; int main() { //初始化Python环境 Py_SetPythonHome(L"D:\\anaconda");//路径为python.exe所在路径,注意使用双斜杠或反斜杠 Py_Initialize(); // 添加项目所属 目录 PyRun_SimpleString("import sys"); PyRun_SimpleString("sys.path.append('.')"); //路径问py文件所在目录,如果在当前目录下则使用 '.' PyObject * pFunc = NULL; //导入模块 PyObject* pModule = PyImport_ImportModule("test");//py文件名 if (!pModule) { cout << "Python get module failed." << endl; return 0; } cout << "Python get module succeed." << endl; // PyObject_GetAttrString pFunc = PyObject_GetAttrString(pModule, "func"); //函数名为 func PyEval_CallObject(pFunc, NULL); //调用 无返回类型 Py_Finalize(); return 0; }
报错1:
3、传参类型表
1.调用无参 无返回值
PyEval_CallObject(pFunc, NULL); //直接调用
2.调用无参 但有返回值
//调用无参 但有返回值 PyObject * pp = PyEval_CallObject(pFunc, NULL); //返回值给pp Object对象 int res = 0; //接收数据 int类型 PyArg_Parse(pp, "i", &res); //类型转换 i就是整形 cout << "res:" << res << endl;//输出结果
3.调用有参 无返回值
PyObject* pArgs = PyTuple_New(2); //初始化俩个参数 PyTuple_SetItem(pArgs, 0, Py_BuildValue("i", 2)); //0:表示序号。第一个参数。 PyTuple_SetItem(pArgs, 1, Py_BuildValue("i", 4)); //1:也表示序号。第二个参数。i:表示传入的参数类型是int类型。 PyEval_CallObject(pFunc, pArgs); //无返回类型
4.调用有参 有返回值
PyObject* pArgs = PyTuple_New(2); //初始化两个参数 PyTuple_SetItem(pArgs, 0, Py_BuildValue("i", 2)); //0:表示序号。第一个参数。 PyTuple_SetItem(pArgs, 1, Py_BuildValue("i", 4)); //1:也表示序号。第二个参数。i:表示传入的参数类型是int类型。 PyObject * pp = PyEval_CallObject(pFunc, pArgs); //无返回类型 int res = 0; PyArg_Parse(pp, "i", &res);//转换返回类型 cout << "res:" << res << endl;//输出结果
5.c++ Mat 转 python Numpy
Mat转Numpy需要配置numpy库,见上面
#include <numpy/arrayobject.h> //导入numpy头文件 Mat img = imread("./frame.png"); // 读取图片 if (img.empty()) { cout << "img read wrong" << endl; Py_Finalize(); return -1; } cout << img.size() << endl; // CV::Mat 转 python numpy------------------------------------ auto sz = img.size(); // 获取图像的尺寸 int x = sz.width; int y = sz.height; int z = img.channels(); uchar *CArrays = new uchar[x*y*z];//这一行申请的内存需要释放指针,否则存在内存泄漏的问题 int iChannels = img.channels(); int iRows = img.rows; int iCols = img.cols * iChannels; 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] = { y, x, z }; //注意这个维度数据! PyObject *PyArray = PyArray_SimpleNewFromData(3, Dims, NPY_UBYTE, CArrays);
报错:
解决办法:在Py_Initialize()后加入“import_array()”语句即可。 在有返回值的函数里,括号里需要有对应类型的返回值
注意:当编译"import_array()"时,可能会出现以下错误:
解决方法:在自己安装的python目录中搜索"object.h"文件,将其56行"#define Py_REF_DEBUG"语句注释掉即可。
6、 c++ PyArrayObject 转 Mat
//将PyObject *pReturn 转换为Mat类型 PyArrayObject *Py_array1; //读取从python脚本返回的numpy值 //查看是否是元组数据 if (PyTuple_Check(pReturn)) { //当返回值不止一个,pReturn是一个元组 PyArg_UnpackTuple(pReturn, "ref", 2, 2, &Py_array1, &a); //解析元组的内容 //获取矩阵维度 npy_intp *Py_array1_shape = PyArray_DIMS(Py_array1); //获取元组第一个元素(矩阵)的大小 npy_intp array1row = Py_array1_shape[0]; npy_intp array1col = Py_array1_shape[1]; npy_intp array1high = Py_array1_shape[2]; Mat mask(array1row, array1col, CV_8UC3, PyArray_DATA(Py_array1)); imwrite("./cut.png", mask); imshow("su", mask); waitKey(0); // Py_XDECREF(PyArray); /*这里Py_XDECREF(ArgList); 和 Py_XDECREF(PyArray);不能同时使用,否则会引起内存访问冲突 * 我的理解是:PyTuple_SetItem并不复制数据,只是引用的复制。因此对这两个对象中的任意一个使用 * Py_XDECREF都可以回收对象。使用两次的话反而会导致冲突。 */ Py_XDECREF(ArgList); delete[] CArrays; // 释放数组内存,最好在PyArray被使用完以后释放 CArrays = nullptr; Py_XDECREF(pReturn); }
VS Qt中C++调用Python 报错
问题出在python.h这个头文件中存在一个变量名叫“slots”,然而slots又是qt的关键字,所以qt的moc会把它当成宏先处理掉。
找到python/include下object.h文件 将第448行改为
#undef slots PyType_Slot *slots; /* terminated by slot==0. */ #define slots Q_SLOTS
c++ 调用Python接口 Mat传参与接收 完整代码
c++端代码
#include "Python.h" #include <numpy/ndarrayobject.h> #include <opencv2/opencv.hpp> #include <iostream> using namespace cv; using namespace std; int main() { // 初始化----------------------------------------------- Py_SetPythonHome(L"D:/anaconda"); Py_Initialize(); cout << "Python start --------------------" << endl; if (!Py_IsInitialized()) { cout << "Python start defeat--------------------" << endl; return -1; } // 加载python文件---------------------------------------------- PyRun_SimpleString("import sys"); PyRun_SimpleString("sys.path.append('.')"); // demo_test.py的路径 PyObject *moduleName = PyUnicode_FromString("demo_test"); //载入名为demo_test.py的文件 PyObject *pModule = PyImport_Import(moduleName); if (!pModule) { //如果不存在改文件,则结束 printf("can't find python file"); Py_Finalize(); //关闭python解释器 return -1; } PyObject *pFunc = PyObject_GetAttrString(pModule, "run"); //获取函数 if (!pFunc) { printf("can't find function [run]"); Py_Finalize(); return -1; } int *a; // 读取图片--------------------------------------------------- Mat img = imread("frame.png"); // 读取图片 if (img.empty()) { cout << "img read wrong" << endl; Py_Finalize(); return -1; } cout << img.size() << endl; // CV::Mat 转 python numpy------------------------------------ auto sz = img.size(); // 获取图像的尺寸 int x = sz.width; int y = sz.height; int z = img.channels(); uchar *CArrays = new uchar[x*y*z];//这一行申请的内存需要释放指针,否则存在内存泄漏的问题 int iChannels = img.channels(); int iRows = img.rows; int iCols = img.cols * iChannels; 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] = { y, x, z }; //注意这个维度数据! PyObject *PyArray = PyArray_SimpleNewFromData(3, Dims, NPY_UBYTE, CArrays); // 准备其他python函数需要的参数 //... // 将图片以及其他参数进行封装 PyObject *ArgList = PyTuple_New(1); //参数列表:创建一个长度为1的元组 PyTuple_SetItem(ArgList, 0, PyArray); //将PyArray的引用指向元组ArgList的第0个元素 PyObject *pReturn = PyObject_CallObject(pFunc, ArgList); if (pReturn == NULL) { printf("Return value is NULL."); Py_Finalize(); return -1; } PyArrayObject *Py_array1; //读取从python脚本返回的numpy值 //查看是否是元组数据 if (PyTuple_Check(pReturn)) { //当返回值不止一个,pReturn是一个元组 PyArg_UnpackTuple(pReturn, "ref", 2, 2, &Py_array1, &a); //解析元组的内容 //获取矩阵维度 npy_intp *Py_array1_shape = PyArray_DIMS(Py_array1); //获取元组第一个元素(矩阵)的大小 npy_intp array1row = Py_array1_shape[0]; npy_intp array1col = Py_array1_shape[1]; npy_intp array1high = Py_array1_shape[2]; Mat mask(array1row, array1col, CV_8UC3, PyArray_DATA(Py_array1)); imwrite("test.png", mask); imshow("out", mask); waitKey(0); // Py_XDECREF(PyArray); /*这里Py_XDECREF(ArgList); 和 Py_XDECREF(PyArray);不能同时使用,否则会引起内存访问冲突 * 我的理解是:PyTuple_SetItem并不复制数据,只是引用的复制。因此对这两个对象中的任意一个使用 * Py_XDECREF都可以回收对象。使用两次的话反而会导致冲突。 */ Py_XDECREF(ArgList); delete[] CArrays; // 释放数组内存,最好在PyArray被使用完以后释放 CArrays = nullptr; Py_XDECREF(pReturn); } //Py_CLEAR(moduleName); //Py_CLEAR(pModule); Py_XDECREF(moduleName); Py_XDECREF(pModule); Py_XDECREF(pFunc); //Py_XDECREF是很有必要的,为了避免内存泄漏 Py_Finalize(); // 关闭Python return 0; }
python端代码
注意这里的返回值是元祖形式
#coding:utf-8 import cv2 import numpy as np def run(imgdata): return imgdata, 0
完结
标签:Mat,PyArray,Python,array1,Py,C++,PyObject,PyTuple,XDECREF From: https://www.cnblogs.com/lidabo/p/17630785.html