Python保存numpy数组供C++加载为OpenCV Mat/Eigen矩阵方法
NPY文件跨语言加载方案
针对你用numpy.save生成的float32类型、形状为[10000,18,5]的npy文件,不需要修改Python侧的保存逻辑,C++侧可以非常简便地加载到OpenCV Mat、Eigen矩阵结构中,没有额外重型依赖。
核心原理
npy是numpy的原生存储格式,结构非常简单,除了很短的文件头存储数据类型、维度、存储顺序信息外,后续就是和numpy内存布局完全一致的连续二进制块,你存储的float32类型和C++的float类型位宽完全匹配,不需要做数值转换,加载开销和读裸二进制文件几乎一致。
npy文件结构如下:
- 前6字节为固定魔数:
\x93NUMPY- 接下来2字节为格式版本号
- 接下来2或4字节为文件头长度
- 接下来是ASCII编码的字典字符串,记录数据类型
descr、存储顺序fortran_order、维度shape- 文件头之后是连续的原始数组数据
你可以自己写100行以内的代码完成解析,不需要依赖第三方库。
加载到目标结构的方法
解析拿到原始数据的指针、维度、存储顺序后,直接映射到对应矩阵结构即可,注意numpy默认是C序(行优先)存储,和OpenCV默认布局一致,和Eigen默认的列优先布局不同,映射时需要指定行优先参数。
- 加载到OpenCV Mat
// 假设解析后得到:float* data_ptr 指向原始数据起始位置,shape为维度数组 std::vector<int> shape = {10000, 18, 5}; // 直接构造Mat,默认共享解析得到的内存 cv::Mat mat(shape.size(), shape.data(), CV_32F, (void*)data_ptr); // 需要Mat持有独立内存时调用clone,即可释放原始加载的缓冲区 cv::Mat mat_owned = mat.clone();
- 加载到Eigen结构
如果是二维矩阵场景,可以把三维数组reshape为二维使用;如果需要保留三维结构,可以用Eigen的Tensor模块:
// 二维映射:将数据reshape为10000行、18*5=90列的行优先矩阵 Eigen::Map<Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>> mat2d_map((float*)data_ptr, 10000, 90); // 拷贝得到独立持有的Eigen矩阵 Eigen::MatrixXf eigen_mat = mat2d_map; // 三维映射:使用Eigen::Tensor保留原始维度 Eigen::TensorMap<Eigen::Tensor<float, 3, Eigen::RowMajor>> tensor3d_map((float*)data_ptr, 10000, 18, 5); // 拷贝得到独立持有的Eigen Tensor Eigen::Tensor<float, 3, Eigen::RowMajor> eigen_tensor = tensor3d_map;
注意事项
- 不要忽略存储顺序参数:如果Eigen映射时不指定
Eigen::RowMajor,读出来的数据会完全错位。 - 严格匹配数据类型:numpy的float32对应C++的
float,不要误用double,否则会出现数值错乱。 - 不需要转存CSV、JSON等文本格式,这类格式加载速度比二进制慢10~100倍,还会存在浮点数精度损失。
- 如果不需要压缩,直接用
numpy.save存npy即可,比numpy.savez压缩包少了解压步骤,加载速度更快。
内容的提问来源于stack exchange,提问作者mcExchange
相关产品推荐
相关产品推荐

