需求
项目需要在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