#define PY_SSIZE_T_CLEAN
#include
#include
#include
#include
#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
#include "numpy/arrayobject.h"
#include
extern "C" {
// Simple addition test function (return = in1 + in2)
static PyObject* test_func(PyObject* self, PyObject* args) {
int input1, input2;
if (!PyArg_ParseTuple(args, "ii", &input1, &input2)) { // Arguments are 2 integer values ("ii")
return nullptr;
}
PyObject *return_value = PyLong_FromLong(input1 + input2); // Create object to return
return return_value;
}
// Simple image processing function (Inverse image color)
static PyObject* test_image_processing(PyObject* self, PyObject* args) {
PyArrayObject* input_image;
PyObject* output_image;
if(!PyArg_ParseTuple(args, "O!", &PyArray_Type, &input_image)) { // Argument is an Numpy array object
return nullptr;
}
output_image = PyArray_NewLikeArray(input_image, NPY_ANYORDER, NULL, 0); // Create object to return
int ndim = PyArray_NDIM(input_image); // Number of dimensions of the input Numpy array
npy_intp *shape;
shape = PyArray_SHAPE(input_image); // Shape of the input Numpy array (npy_intp[])
// Obtain data buffer pointers
char* in_buf = static_cast(PyArray_DATA(input_image)); // PyArray_DATA() will return void*
char* out_buf = static_cast(PyArray_DATA(reinterpret_cast(output_image)));
// Image processing
size_t C = shape[2];
size_t W = shape[1];
size_t H = shape[0];
for(size_t y=0; y(PyArray_DATA(input_image)); // PyArray_DATA() will return void*
// Image processing with OpenCV
cv::Mat in_mat(shape[0] /*Width(rows)*/, shape[1] /*Height(cols)*/, CV_8UC3, in_buf); // Input cv::Mat generated from input Numpy object
cv::Mat out_mat; // Mat object to store final image
cv::Mat channels[3]; // Mat object for channel extraction
cv::cvtColor(in_mat, in_mat, cv::COLOR_BGR2GRAY); // Color -> Gray scale
cv::split(in_mat, channels); // Channel extraction. packed BGR -> [B, G, R]
cv::Canny(channels[0], out_mat, th1, th2); // Canny edge detection
npy_intp out_shape[] = { out_mat.rows, out_mat.cols, out_mat.channels() };
PyObject* result = PyArray_SimpleNew(3, out_shape, NPY_UINT8); // Create a Numpy object to return
char* out_buf = static_cast(PyArray_DATA(reinterpret_cast(result))); // Obtain data buffer pointer of the final image
memcpy(out_buf, out_mat.data, out_shape[0] * out_shape[1] * out_shape[2]); // Copy data buffer
return result; // Return created Numpy object
}
// Numpy array attribute extraction test function
static PyObject* npy_array_test(PyObject* self, PyObject* args) {
PyArrayObject* input_image;
if(!PyArg_ParseTuple(args, "O!", &PyArray_Type, &input_image)) { // Argument is a Numpy object
return nullptr;
}
size_t ndims = PyArray_NDIM(input_image); // Number of dimensions
std::cout << "#Dims: " << PyArray_NDIM(input_image) << std::endl;
npy_intp* shape = PyArray_SHAPE(input_image); // Shape
for(size_t i=0; i(PyArray_DATA(input_image)); // PyArray_DATA() will return void*
// Show first 10 items of the Numpy array
int bytes = PyArray_NBYTES(input_image);
int disp_size = bytes<10 ? bytes : 10;
for(size_t i=0; i(test_func), METH_VARARGS, "test method function of test module"},
{"test_image_processing", static_cast(test_image_processing), METH_VARARGS, "test image processing function"},
{"test_image_processing_OCV", static_cast(test_image_processing_OCV), METH_VARARGS, "test image processing function"},
{"npy_array_test", static_cast(npy_array_test), METH_VARARGS, "test numpy array handling test"},
{NULL, NULL, 0, NULL}
};
// Module definition table
PyModuleDef test_module = {
PyModuleDef_HEAD_INIT,
"python_cpp_module",
"test module",
-1,
method_table
};
// Initialize and register module function
// Function name must be 'PyInit_'+module name
// This function must be the only *non-static* function in the source code
PyMODINIT_FUNC PyInit_python_cpp_module(void) {
import_array(); // Required to receive Numpy object as arguments
if (PyErr_Occurred()) {
return nullptr;
}
return PyModule_Create(&test_module);
}
} // extern "C"