Loading

np.ndarray与Eigen::Matrix之间的互相转换

需求

项目需要在C++中调用一些numpy矩阵数据,希望可以实现相互转化。

实现

C++读取

有关npy读取可以使用库llohse/libnpy
局限是一次只能读取单个npy数组,多个不同纬度的矩阵拼接比较麻烦
多个数组保存的npz文件则需要用rogersce/cnpy读取

Python保存

使用numpy保存的数组默认是行顺序而Eigen::MatrixXf默认按列读取
故最好在保存npz时序列化为fortan顺序方便Eigen导入(注意dtype)

# must save in fortan order for egien to parse as dynamic size
w = [np.asfortranarray(x) for x in arrays]
np.savez('~/save_weights.npz',*w)

转化为Eigen::Matrix

以cnpy为例,调用cnpy::npz_load()将返回std::map<string, NpyArray>可根据key进行索引。
转化主要用到Eigen::Map需要注意入参non-const类型可能需要转换

Eigen::MatrixXf npy2mat(const cnpy::NpyArray& npy)
{
    const size_t& row = npy.shape.front();
    const size_t& col = npy.shape.back();
    float* dat = const_cast<float*>(npy.data<float>());
    // read in column major, ndarray must in fortan order
    return Eigen::Map<Eigen::MatrixXf>(dat, row, col);
}

输出为std::vector

对于Eigen::Matrix可以采用遍历的方式取值,这里介绍一种转为std::vector的通用方式。

std::vector<float> output
static Eigen::Matrix<float,1,4> out_mat;
out_mat << 1.0f, 2.0f, 3.0f, 4.0f;
output.assign(out_mat.data(), out_mat.data() + out_mat.size());

参考

rogersce/cnpy: library to read/write .npy and .npz files in C/C++
llohse/libnpy: C++ library for reading and writing of numpy's .npy files
Eigen: Advanced initialization
c++ - Initialise Eigen::vector with std::vector - Stack Overflow

posted @ 2022-01-11 21:33  azureology  阅读(929)  评论(0编辑  收藏  举报