现在用c++重构了python工程,有一部分后处理不想再花时间重构了,所以直接拿过来调用。边搜资料边做的,做这个demo花了些时间,所以记下来以防忘记。
找了很多的c++调用python的方法,首先可以肯定的有不止一种方式,直接使用python库、numpy arrayobject库来做;另外一种是使用boost/python boost/numpy的方式。后一种没有调通,是链接库的问题,也记录下来放在后面了。
-
调包的基本结构
C/C++调用Python(OpenCV与Numpy)
作者收集了很多的信息,帮助蛮大的。
-
编译,收集自stackoverflow:
how to build this project
g++ -o cc cc.cpp `pkg-config --cflags --libs opencv` -I/usr/include/python3.5 -lpython3.5m
值得说明一下的是,python3.5m是在路径
/usr/lib/x86_64-linux-gnu/libpython3.5m.so
下,可以自行搜素。另外,代码中有个warning,使用宏定义就可以去掉了,在代码中也有说明
-
代码块
-
import_array()有奇怪的返回值,这篇博客也提到了解决方法
import_array()报错,返回值类型与函数类型不匹配
。但是要删东西,还有不报错误的风险。这儿我忘记了在哪看到的代码了,也没能在历史记录里找到,先把代码贴过来。其实就是将这个函数加一个壳。然后用init替换import_array。
size_t init() {
import_array();
- 调包的基本结构 C++调用python并传递数组
- debug出现的错误,主要是boost/numpy问题,安装之后还是出现找不到库的情况,stackoverflow上有个对话,是统一的问题,需要修改环境变量后解决了,先在这儿记下来吧
- boost库的安装
cc.cpp
// c++: cc.cpp
#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION //需要放在numpy/arrayobject.h之前
#include<opencv/cv.hpp>
#include <Python.h>
#include <iostream>
#include <numpy/arrayobject.h>
using namespace cv;
using namespace std;
int main(int argc, char *argv[]) {
wchar_t *program = Py_DecodeLocale(argv[0], NULL);
cout << argv[0] << endl;
if (program == NULL) {
fprintf(stderr, "Fatal error: cannot decode argv[0]\n");
exit(1);
Py_SetProgramName(program); /* 不见得是必须的 */
/* 非常重要,折腾的时间主要是因为这儿引起的【1】 */
Py_Initialize();
PyRun_SimpleString("import sys");
PyRun_SimpleString("sys.path.append(\"/home/user/project/run_retina/build\")");
import_array();
/* 非常重要 */
/* 读图 */
Mat sml_img = imread("lena.jpg");
/* 导入模块和函数,貌似两种方式都可以,不需要加.py,后面回再提到 */
// PyObject *pName = PyUnicode_DecodeFSDefault("simple_module");
PyObject *pName = PyUnicode_FromString("simple_module");
/*这些检查也非常有帮助*/
if (pName == NULL) {
PyErr_Print();
throw std::invalid_argument("Error: PyUnicode_FromString");
PyObject *pModule = PyImport_Import(pName);
if (pModule == NULL) {
PyErr_Print();
throw std::invalid_argument("fails to import the module");
PyObject *pFunc = PyObject_GetAttrString(pModule, "super_resolution");
if (pFunc == NULL) {
PyErr_Print();
throw std::invalid_argument("fails to PyObject_GetAttrString");
/* 准备输入参数 */
PyObject *pArgs = PyTuple_New(2);
if (!sml_img.isContinuous()) { sml_img = sml_img.clone(); }
npy_intp dims[] = {sml_img.rows, sml_img.cols, 3};
PyObject *pValue = PyArray_SimpleNewFromData(3, dims, NPY_UINT8, sml_img.data);
PyTuple_SetItem(pArgs, 0, pValue); /* pValue的引用计数被偷偷减一,无需手动再减 */
PyTuple_SetItem(pArgs, 1, Py_BuildValue("i", 2)); /* 图像放大2倍 */
/* 调用函数 */
PyObject *pRetValue = PyObject_CallObject(pFunc, pArgs);
/* 解析返回结果 */
PyArrayObject *ret_array;
PyArray_OutputConverter(pRetValue, &ret_array);
npy_intp *shape = PyArray_SHAPE(ret_array);
Mat big_img(shape[0], shape[1], CV_8UC3, PyArray_DATA(ret_array));
imwrite("aa.jpg", big_img);
/* 释放所有 */
//Py_DECREF(...);
return 0;
simple_module.py
# simple_module.py
import cv2 as cv
def simple_func(a,b):return a+b
def super_resolution(img, scale=4):
height, width = img.shape[:2]
dsize = (width*scale, height*scale)
big_img = cv.resize(img, dsize)
print(img.shape, big_img.shape)
cv.imwrite('aaa.jpg',big_img)
return big_img
多个numpy返回值
PyArrayObject *r1, *r2, *r3, *r4, *r5, *r6;
PyArg_UnpackTuple(pRetValue, "ref", 6, 6, &r1, &r2, &r3, &r4, &r5, &r6);
npy_intp *shape1 = PyArray_SHAPE(r1);
npy_intp *shape2 = PyArray_SHAPE(r2);
npy_intp *shape3 = PyArray_SHAPE(r3);
npy_intp *shape4 = PyArray_SHAPE(r4);
npy_intp *shape5 = PyArray_SHAPE(r5);
npy_intp *shape6 = PyArray_SHAPE(r6);
std::cout << "shape[1]:" << shape1[0] <<
" shape2:" << shape2[0] << "," << shape2[1] <<
" shape3:" << shape3[0] <<
" shape4:" << shape4[0] << "," << shape4[1] <<
" shape5:" << shape5[0] <<
" shape6:" << shape6[0] << "," << shape6[1] <<
std::endl;
list_id float32 (11,)
list_track float32 float32 (20, 2) (11,)
list_box float32 (11, 4)
entran;pass_by;ratio float32 (3,)
entrance_line;rec float32 (4, 2)
shape[1]:11 shape2:20,2 shape3:11 shape4:11,4 shape5:3 shape6:4,2
背景现在用c++重构了python工程,有一部分后处理不想再花时间重构了,所以直接拿过来调用。边搜资料边做的,做这个demo花了些时间,所以记下来以防忘记。资料找了很多的c++调用python的方法,首先可以肯定的有不止一种方式,直接使用python库、numpy arrayobject库来做;另外一种是使用boost/python boost/numpy的方式。后一种没有调通,是链接库的问...
格拉布拉斯
围绕GraphBLAS的Python包装器
要安装, conda install -c conda-forge grblas 。这还将安装SuiteSparse graphblas编译的C库。
当前与,但目标是使其与GraphBLAS规范的所有实现一起使用。
该库采用的方法是尽可能地遵循C-API规范,同时进行Python语法允许的改进。因为规范总是传递要写入的输出对象,所以我们遵循相同的规范,这与Python正常运行的方式有很大不同。实际上,许多熟悉其他Python数据库(numpy,pandas等)的人会发现,不为每个调用创建新对象都是很奇怪的。
在最高级别上,目标是在赋值运算符=的左侧分离输出,掩码和累加器,并将计算放在右侧。不幸的是,这种方法在Python处理分配的方法上并不总是很好,因此我们(ab)使用左移<<符号来赋予相同的分配风格。这开辟了各种美好的可能性。
1. Python是解释语言,程序写起来非常方便
写程序方便对做机器学习的人很重要。
因为经常需要对模型进行各种各样的修改,这在编译语言里很可能是牵一发而动全身的事情,Python里通常可以用很少的时间实现。
举例来说,在C等编译语言里写一个矩阵乘法,需要自己分配操作数(矩阵)的内存、分配结果的内存、手动对BLAS接口调用gemm、最后如果没用smart pointer还得手动回收内存空间。Python几乎就是import numpy; numpy.dot两句话的事。
当然现在很多面向C/C++
pip install numpy
由于pycharm是jetBrains 针对python的一款IDE,因为我之前一直写C++用的就是CLION,非常喜欢jetBrains家简便清洁的风格,所以面对市面上五花八门的python IDE的时候很决绝的选择了pycharm ,不过就是因为轻便名,所以其默认的编译器不包括一般的python 库(比如 numpy),因为我还会用到很多的python的第三方库,所以直接选择安装anaconda (如何安装见前一blog),会出现这样的错误
/home/shenying/dl/untitled/venv/bi
支持几乎所有流行的平台和语言,让您快速构建您的应用程序。
无论您是开发移动应用程序(Android、iOS、Java、Objective-C、C++)、Web
应用程序(Javascript)、与后端集成(Linux、MacOS、Windows、Python、C++)还是使用
Raspberry
创建很酷的设备,mesibo
都有为您提供
Mesibo
Python
库使您能够将聊天客户端与后端的各种科学计算和机器学习系统(如
TensorFlow、Matlab、Octave、NumPy
等)连接起来,以创建强大的聊天体验。
Mesibo
Python
模块需要安装以下软件:
1.美思博C/C++库
安装共享库(在基于
Linux
NumCpp:Python NumPy库的一个Templatized Header Only C ++实现
NumCpp 是一个高性能的数学计算 C++ 库,它提供了一个简单的 Numpy/Matlab 类似的接口。
地址 https://github.com/dpilger26/NumCpp
文档地址 https://dpilger26.github.io/NumCpp/doxygen...
1. 使用PyPy:PyPy是一个用于Python解释器的即时编译器,可以显著提高Python程序的速度。
2. 使用Cython:Cython是一种将Python代码编译为C语言的扩展,可以提高Python程序的速度。
3. 使用NumPy:NumPy是一个用于数值计算的Python库,它使用C语言编写的底层代码,可以显著提高Python程序的速度。
4. 使用并行编程:使用多线程或多进程可以加速Python程序的执行,特别是在处理大量数据时。
5. 减少函数调用:Python的函数调用开销相对较大,因此减少函数调用可以提高程序的速度。
6. 使用生成器和迭代器:使用生成器和迭代器可以减少内存使用量,并且可以更快地处理数据。
7. 使用缓存:使用缓存可以避免重复计算,提高程序的速度。
8. 尽量使用内置函数和模块:Python的内置函数和模块通常比自己编写的代码更快,因此尽量使用它们可以提高程序的速度。
lifeplayer_:
undefined reference to `nppiWarpAffine_8u_C1R'
m0_60587665: