如何在不分配内存的情况下将openv映射到具有对齐支持的特征

How to map opencv to eigen with alignment support without allocate the memory?

本文关键字:映射 特征 支持 对齐 openv 分配 情况下 内存      更新时间:2023-10-16

我使用opencv从一些数据集(28*28行,200000 cols)读取大数据,并希望将其映射到具有对齐支持的特征矩阵,而无需分配另一个大缓冲区。

cv::Mat big_data(28*28, 200000, CV_64F);
//...read data and preprocess
EMatrix map_big_data;
//cv2Eigen will allocate a new, big buffer
cv::cv2Eigen(big_data, map_big_data);

是否有可能映射矩阵而不分配另一个大内存?这是可以调整cv::Mat的大小,我想避免两个大的缓冲区同时存在(可能抛出bad_alloc)

cv::Mat big_data(28*28, 200000, CV_64F);
//read data and preprocess....
using EMatrix = Eigen::Matrix<double, Eigen::Dynamic,
            Eigen::Dynamic, Eigen::RowMajor>;
using EMap = Eigen::Map<EMatrix, Eigen::Aligned>;        
//resize the cv::Mat to meet the alignment requirement(16bytes aligned),is this possible?How could I get the align_cols?
big_data.resize(big_data.rows, align_cols);
//this may or may not crash
EMap map_big_data(reinterpret_cast<double*>(big_data.data),
big_data.rows,
big_data.cols);

编辑:使用Eigen::aligned_allocator来分配对齐内存

Eigen::aligned_allocator<double> alloc;
int const Rows = 28*28;
int const Cols = 200000;
auto buffer = alloc.allocate(Rows*Cols);
cv::Mat big_data(Rows, Cols, CV_64F, buffer, Cols * sizeof(double));
//read data set and do some preprocess....
using EMatrix = Eigen::Matrix<double, Eigen::Dynamic,
                Eigen::Dynamic, Eigen::RowMajor>;
using EMap = Eigen::Map<EMatrix, Eigen::Aligned>; 
EMap map_big_data(reinterpret_cast<double*>(big_data.data),
    big_data.rows,
    big_data.cols);
//some jobs.....
alloc.deallocate(buffer, 0);

这样可以吗?

为什么要直接使用特征分配器呢?使用Eigen::MatrixXd(或类似的),并将指向数据的指针传递给cvMat构造函数。使用这种方式,cvMat"包装"数据而不复制它(与Eigen::Map相同)。

int Rows = 28*28;
int Cols = 200000;
Eigen::Matrix<double, Eigen::Dynamic,
            Eigen::Dynamic, Eigen::RowMajor> eigenMat(Rows, Cols);
cv::Mat big_data(Rows, Cols, CV_64F, eigenMat.data(), Cols * sizeof(double));
//read data set and do some preprocess....

你唯一不应该做的是尝试调整big_data的大小,但eigenMat如果必要的话。

来自OpenCV文档:


指向用户数据的指针。接受数据和步进参数的矩阵构造函数不分配矩阵数据。相反,它们只是初始化指向指定数据的矩阵头,这意味着不会复制任何数据。这个操作非常高效,可以使用OpenCV函数来处理外部数据。外部数据不会自动释放,所以您应该注意它。

这样就没有映射,不需要尝试确定是否有额外的填充,也不需要记住解除分配。同时还获得了特征矩阵的所有优点