Je vais envoyer un tableau c++
À un python comme numpy array
Et récupérer un autre numpy array
. Après avoir consulté numpy
documentation et quelques autres threads et peaufinage du code, enfin le code fonctionne mais je voudrais savoir si ce code est écrit de manière optimale compte tenu de:
c++
Et numpy (python)
.Code C++:
// python_embed.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
#include "Python.h"
#include "numpy/arrayobject.h"
#include<iostream>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
Py_SetProgramName(argv[0]);
Py_Initialize();
import_array()
// Build the 2D array
PyObject *pArgs, *pReturn, *pModule, *pFunc;
PyArrayObject *np_ret, *np_arg;
const int SIZE{ 10 };
npy_intp dims[2]{SIZE, SIZE};
const int ND{ 2 };
long double(*c_arr)[SIZE]{ new long double[SIZE][SIZE] };
long double* c_out;
for (int i{}; i < SIZE; i++)
for (int j{}; j < SIZE; j++)
c_arr[i][j] = i * SIZE + j;
np_arg = reinterpret_cast<PyArrayObject*>(PyArray_SimpleNewFromData(ND, dims, NPY_LONGDOUBLE,
reinterpret_cast<void*>(c_arr)));
// Calling array_tutorial from mymodule
PyObject *pName = PyUnicode_FromString("mymodule");
pModule = PyImport_Import(pName);
Py_DECREF(pName);
if (!pModule){
cout << "mymodule can not be imported" << endl;
Py_DECREF(np_arg);
delete[] c_arr;
return 1;
}
pFunc = PyObject_GetAttrString(pModule, "array_tutorial");
if (!pFunc || !PyCallable_Check(pFunc)){
Py_DECREF(pModule);
Py_XDECREF(pFunc);
Py_DECREF(np_arg);
delete[] c_arr;
cout << "array_tutorial is null or not callable" << endl;
return 1;
}
pArgs = PyTuple_New(1);
PyTuple_SetItem(pArgs, 0, reinterpret_cast<PyObject*>(np_arg));
pReturn = PyObject_CallObject(pFunc, pArgs);
np_ret = reinterpret_cast<PyArrayObject*>(pReturn);
if (PyArray_NDIM(np_ret) != ND - 1){ // row[0] is returned
cout << "Function returned with wrong dimension" << endl;
Py_DECREF(pFunc);
Py_DECREF(pModule);
Py_DECREF(np_arg);
Py_DECREF(np_ret);
delete[] c_arr;
return 1;
}
int len{ PyArray_SHAPE(np_ret)[0] };
c_out = reinterpret_cast<long double*>(PyArray_DATA(np_ret));
cout << "Printing output array" << endl;
for (int i{}; i < len; i++)
cout << c_out[i] << ' ';
cout << endl;
// Finalizing
Py_DECREF(pFunc);
Py_DECREF(pModule);
Py_DECREF(np_arg);
Py_DECREF(np_ret);
delete[] c_arr;
Py_Finalize();
return 0;
}
Dans CodeReview, il y a une réponse fantastique: Link ...
xtensor est une bibliothèque C++ destinée à l'analyse numérique avec des expressions de tableau multidimensionnelles.
xtensor fournit
Initialisez un tableau 2D et calculez la somme de l'une de ses lignes et d'un tableau 1D.
#include <iostream>
#include "xtensor/xarray.hpp"
#include "xtensor/xio.hpp"
xt::xarray<double> arr1
{{1.0, 2.0, 3.0},
{2.0, 5.0, 7.0},
{2.0, 5.0, 7.0}};
xt::xarray<double> arr2
{5.0, 6.0, 7.0};
xt::xarray<double> res = xt::view(arr1, 1) + arr2;
std::cout << res;
Les sorties
{7, 11, 14}
#include "pybind11/pybind11.h"
#include "xtensor-python/pyvectorize.hpp"
#include <numeric>
#include <cmath>
namespace py = pybind11;
double scalar_func(double i, double j)
{
return std::sin(i) - std::cos(j);
}
PYBIND11_PLUGIN(xtensor_python_test)
{
py::module m("xtensor_python_test", "Test module for xtensor python bindings");
m.def("vectorized_func", xt::pyvectorize(scalar_func), "");
return m.ptr();
}
Code Python:
import numpy as np
import xtensor_python_test as xt
x = np.arange(15).reshape(3, 5)
y = [1, 2, 3, 4, 5]
z = xt.vectorized_func(x, y)
z
Les sorties
[[-0.540302, 1.257618, 1.89929 , 0.794764, -1.040465],
[-1.499227, 0.136731, 1.646979, 1.643002, 0.128456],
[-1.084323, -0.583843, 0.45342 , 1.073811, 0.706945]]
D'après mon expérience, cela semble être assez efficace. Pour obtenir encore plus d'efficacité, essayez ceci: http://ubuntuforums.org/showthread.php?t=1266059
En utilisant weave, vous pouvez incorporer du code C/C++ dans Python afin que cela puisse être utile.
http://docs.scipy.org/doc/scipy-0.15.1/reference/generated/scipy.weave.inline.html
Voici un lien sur la façon dont Python peut être utilisé pour interfacer entre de nombreux langages différents avec des exemples.
http://docs.scipy.org/doc/numpy/user/c-info.python-as-glue.html
Voici un exemple rapide et simple de comment passer des tableaux numpy à c ++ en utilisant Cython:
http://www.birving.com/blog/2014/05/13/passing-numpy-arrays-between-python-and/
Comme moyen supplémentaire, sans toucher directement à l'API Python C, il est possible d'utiliser pybind11 (bibliothèque d'en-tête uniquement):
CPP:
#include <pybind11/embed.h> // everything needed for embedding
#include <iostream>
#include <Eigen/Dense>
#include<pybind11/eigen.h>
using Eigen::MatrixXd;
namespace py = pybind11;
int main()
{
try
{
Py_SetProgramName("PYTHON");
py::scoped_interpreter guard{};
py::module py_test = py::module::import("py_test");
MatrixXd m(2,2);
m(0,0) = 1;
m(1,0) = 2;
m(0,1) = 3;
m(1,1) = 4;
py::object result = py_test.attr("test_mat")(m);
MatrixXd res = result.cast<MatrixXd>();
std::cout << "In c++ \n" << res << std::endl;
}
catch (std::exception ex)
{
std::cout << "ERROR : " << ex.what() << std::endl;
}
return 1;
}
Dans py_test.py
:
def test_mat(m):
print ("Inside python m = \n ",m )
m[0,0] = 10
m[1,1] = 99
return m
Sortie:
Inside python m =
[[ 1. 3.]
[ 2. 4.]]
In c++
10 3
2 99
Voir documentation officielle .
ps: j'utilise Eigen pour la matrice C++.
Nous passerons un tableau 2D à python écrite dans le fichier pyCode.py
:
def pyArray (a):
print ("Contents of a :")
print (a)
c = 0
return c
c_code.cpp
#include <Python.h>
#include <stdio.h>
#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
#include <numpy/arrayobject.h>
float Array [] = {1.2, 3.4, 5.6, 7.8};
int main (int argc, char *argv[])
{
float *ptr = Array;
PyObject *pName, *pModule, *pDict, *pFunc, *pArgs, *pValue;
npy_intp dims[1] = { 4 };
PyObject *py_array;
setenv("PYTHONPATH",".",1);
Py_Initialize ();
pName = PyUnicode_FromString ("pyCode");
pModule = PyImport_Import(pName);
pDict = PyModule_GetDict(pModule);
import_array ();
py_array = PyArray_SimpleNewFromData(1, dims, NPY_FLOAT, ptr);
pArgs = PyTuple_New (1);
PyTuple_SetItem (pArgs, 0, py_array);
pFunc = PyDict_GetItemString (pDict, (char*)"pyArray");
if (PyCallable_Check (pFunc))
{
PyObject_CallObject(pFunc, pArgs);
} else
{
cout << "Function is not callable !" << endl;
}
Py_DECREF(pName);
Py_DECREF (py_array);
Py_DECREF (pModule);
Py_DECREF (pDict);
Py_DECREF (pFunc);
Py_Finalize ();
return 0;
}
compiler le code: g++ -g -fPIC c_code.cpp -o runMe -lpython3.5m -I/usr/include/python3.5m/
fichier: cv_mat_code.cpp
#include <iostream>
#include <Python.h>
#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
#include <numpy/arrayobject.h>
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;
int main (int argc, char *argv[])
{
float data[42] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42 };
Mat mat1 (cv::Size (5, 2), CV_32F, data, Mat::AUTO_STEP);
int row = 0;
float *p = mat1.ptr<float>(row);
cout << "Mat" << mat1 <<endl;
PyObject *pName, *pModule, *pDict, *pFunc, *pArgs, *pValue;
npy_intp dims[2] = { 2, 5 };
PyObject *py_array;
setenv("PYTHONPATH",".",1);
Py_Initialize ();
pName = PyUnicode_FromString ("pyCode");
pModule = PyImport_Import(pName);
pDict = PyModule_GetDict(pModule);
// Required for the C-API : http://docs.scipy.org/doc/numpy/reference/c-api.array.html#importing-the-api
import_array ();
py_array = PyArray_SimpleNewFromData(2, dims, NPY_FLOAT, p);
pArgs = PyTuple_New (1);
PyTuple_SetItem (pArgs, 0, py_array);
pFunc = PyDict_GetItemString (pDict, (char*)"pyArray");
if (PyCallable_Check (pFunc))
{
PyObject_CallObject(pFunc, pArgs);
} else
{
cout << "Function is not callable !" << endl;
}
Py_DECREF(pName);
Py_DECREF (py_array);
Py_DECREF (pModule);
Py_DECREF (pDict);
Py_DECREF (pFunc);
Py_Finalize ();
return 0;
}
Compilez le code: g++ -g -fPIC cv_mat_code.cpp -o runMe -lpython3.5m -I/usr/include/python3.5m/ -I/usr/include/ -lopencv_core -lopencv_imgproc -lopencv_highgui