[C++详细]CV::Mat和Eigen矩阵之间的相互转换
2.Eigen默认按列优先存储,cv::Mat按照行优先存储,为了保证数据访问的一致性,需要对Eigen二次转化,Eigen。3.同理,在Eigen转回cv::Mat时,如果是列存储,转换行存储到cv::Mat。如上所有对应索引项的数据和原图片zimg的索引项数据值一致,则转换成功。4.Eigen转cv::Mat,这里需要额外输入转换的行列和通道类型。1.cv::Mat到 Eigen::Matri
·
1.cv::Mat到 Eigen::MatrixXf,使用深拷贝
// 将 cv::Mat 转换为 Eigen::MatrixXf,支持多通道图像
Eigen::MatrixXf cvMatToEigen(const cv::Mat& cvMat) {
// 获取通道数
int channels = cvMat.channels();
int rows = cvMat.rows;
int cols = cvMat.cols * channels; // 展开列数以包含所有通道数据
// 将数据转换为浮点型并按通道展开
cv::Mat cvMatFloat;
if (cvMat.type() != CV_32F) {
cvMat.convertTo(cvMatFloat, CV_32F);
}
else {
cvMatFloat = cvMat.clone();
}
// 创建 Eigen::MatrixXf,并进行深拷贝
Eigen::MatrixXf eigenMat(rows, cols);
for (int i = 0; i < rows; ++i) {
const float* rowPtr = cvMatFloat.ptr<float>(i);
for (int j = 0; j < cols; ++j) {
eigenMat(i, j) = rowPtr[j];
}
}
return eigenMat;
}
2.Eigen默认按列优先存储,cv::Mat按照行优先存储,为了保证数据访问的一致性,需要对Eigen二次转化,Eigen列存储转行存储。
// 从列优先的 Eigen::MatrixXf 转换为行优先的 Eigen::Matrix
Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> toRowMajor(const Eigen::MatrixXf& mat) {
// 创建行优先的矩阵,并逐元素复制
Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> rowMajorMat(mat.rows(), mat.cols());
rowMajorMat = mat; // 自动完成逐元素复制,确保正确布局
return rowMajorMat;
}
3.同理,在Eigen转回cv::Mat时,如果是列存储,转换行存储到cv::Mat。
//从行优先的 Eigen::Matrix 转换为列优先的 Eigen::MatrixXf
Eigen::MatrixXf toColumnMajor(const Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>&rowMajorMat) {
// 创建列优先的 Eigen::MatrixXf,并逐元素复制
Eigen::MatrixXf colMajorMat(rowMajorMat.rows(), rowMajorMat.cols());
colMajorMat = rowMajorMat; // 自动完成逐元素复制,确保正确布局
return colMajorMat;
}
4.Eigen转cv::Mat,这里需要额外输入转换的行列和通道类型
// 将 Eigen::MatrixXf 转换为 cv::Mat,支持多通道图像
cv::Mat eigenToCvMat(const Eigen::MatrixXf& eigenMat, int rows, int cols, int type) {
// 获取通道数
int channels = (type == CV_8UC3) ? 3 : (type == CV_8UC4) ? 4 : 1;
// 确保 Eigen::MatrixXf 的列数和 cv::Mat 的列数(含通道)一致
if (eigenMat.cols() != cols * channels || eigenMat.rows() != rows) {
throw std::runtime_error("Matrix dimensions do not match the expected rows, columns, and channels.");
}
// 创建 cv::Mat,并根据类型分配内存
cv::Mat cvMat(rows, cols, type);
// 将数据转换到相应类型并逐元素拷贝
if (type == CV_32F || type == CV_32FC3 || type == CV_32FC4) {
// 直接拷贝浮点数据
for (int i = 0; i < rows; ++i) {
float* rowPtr = cvMat.ptr<float>(i);
for (int j = 0; j < cols * channels; ++j) {
rowPtr[j] = eigenMat(i, j);
}
}
}
else if (type == CV_8UC3 || type == CV_8UC4 || type == CV_8UC1) {
// 转换为8位无符号整数(假设Eigen中的值在[0, 255]范围内)
for (int i = 0; i < rows; ++i) {
uchar* rowPtr = cvMat.ptr<uchar>(i);
for (int j = 0; j < cols * channels; ++j) {
rowPtr[j] = static_cast<uchar>(eigenMat(i, j));
}
}
}
else {
throw std::runtime_error("Unsupported cv::Mat type.");
}
return cvMat;
}
使用案例:
cv::Mat zimg = cv::imread("temp.jpg", cv::IMREAD_UNCHANGED);
float z11 = zimg.data[0];
float z12 = zimg.data[1];
float z13 = zimg.data[2];
float z14 = zimg.data[3];
auto zimg2 = toRowMajor(cvMatToEigen(zimg));
float z121 = zimg2.data()[0];
float z122 = zimg2.data()[1];
float z123 = zimg2.data()[2];
float z124 = zimg2.data()[3];
auto zimg3 = eigenToCvMat(cvMatToEigen(zimg), zimg.rows, zimg.cols, zimg.type());
float z131 = zimg3.data[0];
float z132 = zimg3.data[1];
float z133 = zimg3.data[2];
float z134 = zimg3.data[3];
auto zimg4 = eigenToCvMat(toColumnMajor(toRowMajor(cvMatToEigen(zimg))), zimg.rows, zimg.cols, zimg.type());
float z141 = zimg4.data[0];
float z142 = zimg4.data[1];
float z143 = zimg4.data[2];
float z144 = zimg4.data[3];
如上所有对应索引项的数据和原图片zimg的索引项数据值一致,则转换成功。
更多推荐
所有评论(0)