OpenCV矩阵与Eigen矩阵相互转换

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OpenCV矩阵与Eigen矩阵相互转换相关的知识,希望对你有一定的参考价值。

参考技术A OpenCV 矩阵结构为: cv::Mat ,或者 cv::Mat_ 等,当需要与 Eigen 的矩阵结构相互转换时主要使用函数:

cv::eigen2cv 和 cv::cv2eigen ,需要头文件:
#include<opencv2/core/eigen.hpp>

包含头文件(顺序不能错!!!先包含eigen相关库,再包含opencv库!)

备注:经笔者实验,该转换存在矩阵精度损失的问题,具体是由于什么原因造成的,待查更新。

更详细的相关内容参看这篇博客: eigen与opencv矩阵转换,eigen与matlab函数比照

将特征矩阵转换为无符号字符 *

【中文标题】将特征矩阵转换为无符号字符 *【英文标题】:Converting Eigen matrix to unsigned char * 【发布时间】:2019-06-20 17:13:43 【问题描述】:

我正在尝试使用 Eigen 与 unsigned char * 类型进行交互。我可以转换为 Eigen,然后再转换为浮点数,但是当我转换回 unsigned char 时,结果是错误的。 我需要 Eigen 矩阵为浮点类型,以便可以对其执行算术运算。然后我需要把它带回 unsigned char 以便我可以保存它。

#include <Eigen/Dense>
#include <iostream>
int main()
unsigned char* data;
for (int i=0;i<9;++i) 
    data[i]= i;

//Map data to Eigen
Map<Matrix<unsigned char,3,3> ,RowMajor> img(data,3,3);
//Convert to float
MatrixXf gray = img.cast<float>();
//Convert back to unsigned char*
float *gray_array = gray.data();
unsigned char *gray_UC = (unsigned char*)gray_array;

std::cout<<"Eigen matrix converted to unsigned char:"<<(float)*(gray_UC+1)<<std::endl;
std::cout<<"Eigen matrix as float: "<<*(gray_array+i)<<std::endl;
std::cout<<"Original data converted to float: "<<(float)*(data+1)<<std::endl;

数据是 unsigned char* 类型。

我希望 gray_UC 和 data 相同,但事实并非如此。更重要的是,gray_array 打印了正确的浮点值,所以可能是转换为 unsigned char 是错误的。

【问题讨论】:

我无法复制并粘贴提供的代码并对其进行编译。它不是独立的。 minimal reproducible example 在这里会很有帮助。问题可能是指针别名。提供的演员阵容相当可疑。 强制转换数组不会强制转换条目。见this question。或者干脆使用 Eigen 的 cast 方法返回。但您可能希望自定义转换包含舍入。 【参考方案1】:

当你这样做时:

(float)*(gray_UC+1)

您正在获取指针gray_UC 并根据pointer arithmetic 向其添加一个。如果unsigned char 是一个字节,则意味着在gray_UC 之后只有一个字节。然后你取消引用它,将下一个字节作为unsigned char,然后将该值转换为float。我认为结果应该是 0 到 255 之间的浮点数。

这里:

(float)*(data+1)

您将指针data 加1,但在本例中是指向float 的指针,它是4 个字节,会将指针向前4 个字节。接下来,您取消引用并将其强制转换为浮点数(无论如何都不应该有任何影响),因此您将获得 data 指向的浮点缓冲区中的第二个浮点值。

为了从gray_UC 获得相同的结果,您可以执行以下操作:

*(((float*) gray_UC) + 1)

【讨论】:

我不明白为什么(float)*(gray_UC+1) 会给出错误的结果。 gray_UC+1 是下一个字节的地址,然后转换为浮点数。它应该给出正确的结果,除非gray_UC 从一开始就错了 @Bubble float 值占用四个字节。如果您将gray_UC+1 解释为float 指针,您将获得一个float 值的三个字节和下一个值的一个字节,这不会产生任何有意义的结果。【参考方案2】:

这是一个适合我的解决方案,灵感来自@Nico Schertler 的评论。我在 for 循环中进行强制转换。但是我必须先使用一个数组,然后将第一个元素的地址提供给我的unsigned char *

将来我应该考虑尝试std::transform@Nico Schertler 的链接中的建议。

请注意,我没有将 Eigen 数组直接转换为 unsigned char,因为我的实际应用程序正在使用一个大数组。当我尝试它时,我得到了一个与内存问题有关的错误。

这是我的解决方案:

unsigned char gray_UC_tmp[size];
for (int i=0; i<9;++i)
      gray_UC_tmp[i] = static_cast<unsigned char> (gray_array[i]);

gray_UC = gray_UC_tmp;

【讨论】:

以上是关于OpenCV矩阵与Eigen矩阵相互转换的主要内容,如果未能解决你的问题,请参考以下文章

Python旋转矩阵与旋转向量的相互转换(OpenCV)

Python旋转矩阵与旋转向量的相互转换(OpenCV)

四元素与矩阵之间相互转换

位姿转换

将动态矩阵转换为 Eigen 中的固定矩阵

将特征矩阵转换为无符号字符 *