【python的numpy数组(c++接口PyArrayObject*) 和c++的Mat的相互转换】

python的numpy数组(c++接口PyArrayObject*) 和c++的Mat的相互转换

背景

想要尝试qt+onnx跑个双目的模型,结果在onnx的c++版本上跑出现了谜之内存泄漏,为了先达成目标,先用c++调用python的函数来实现功能。
这时候出现一个需要考虑的问题:c++的Mat和python的numpy数组如何相互转换

需求定义

将保存在Mat内的图像传递到PyArrayObject内,将保存在PyArrayObject内的图像传递到Mat内

前人工作

参考这篇文章,实现了将mat内容传递到PyArrayObject*的功能,代码片段如下:

        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];//连续空间
            }
        }
 
        npy_intp Dims[3] = { y, x, z}; //注意这个维度数据!
        PyObject *PyArray = PyArray_SimpleNewFromData(3, Dims, NPY_UBYTE, CArrays);
		/*   些许操作之后,最后释放内存 */
        delete []CArrays ;
        CArrays =nullptr;

探索尝试过程

在网上冲浪好半天,可能是眼残啊,没找到啥将保存在PyArrayObject*内的图像传递到Mat内的实现,于是自己尝试了一下:

void np2mat(PyObject* np, Mat& img)
{
    PyArrayObject *arr = (PyArrayObject *)np;
    
    auto sz = img.size();
    int x = sz.width;
    int y = sz.height;
    int z = img.channels();
    int size = x*y*z;
    
    memcpy((uchar*)img.data,arr->data,size);
}

在维度一致的情况下,可以实现功能。那看来要实现会比想象中简单,PyArrayObject和mat里的data都指向数组的首地址,反过来看将mat内容传递到PyArrayObject*也可以简化为:

void np2mat(PyObject* np, Mat& img)
{
    if(img.empty())
        return NULL;

    auto sz = img.size();
    int x = sz.width;
    int y = sz.height;
    int z = img.channels();
    npy_intp Dims[3] = { y, x, z}; //注意这个维度数据!

    PyArrayObject *PyArray = (PyArrayObject *)PyArray_SimpleNewFromData(3, Dims, NPY_UBYTE,(uchar*)img.data);
    return (PyObject*) PyArray;
}

可能需要这么些个头文件,具体在电脑啥位置可以百度,和各人python环境位置相关:

#include <Python.h>
#include <object.h>
#include <numpy/arrayobject.h>

结果双目跑onnx(python)

在使用GPU的情况下,速度不算很快,还需要进一步优化

猜你喜欢

转载自blog.csdn.net/weixin_42492254/article/details/123126441