当前位置: 首页 > news >正文

OpenCV cv::Mat到 Eigen 的正确转换——cv2eigen

在进行计算机视觉项目时,我们经常需要处理相机位姿的变换。最近,我在项目中遇到了一个看似简单但实际上颇具挑战性的问题:从 OpenCV 的 cv::Mat 格式转换到 Eigen 库的格式。这个过程中遇到了一些问题,但最终找到了一个稳健的解决方案。

问题描述: 我们有两个表示相机位姿的 4x4 变换矩阵,格式为 cv::Mat。目标是计算这两个位姿之间的变换,并提取出平移向量。

初始尝试: 最初,我们尝试直接从 cv::Mat 中提取平移向量:

Eigen::Vector3d transLast(mLastFrameTcw.at<double>(0, 3),mLastFrameTcw.at<double>(1, 3),mLastFrameTcw.at<double>(2, 3)
);
Eigen::Vector3d transCurrent(mCurrentFrameTcw.at<double>(0, 3),mCurrentFrameTcw.at<double>(1, 3),mCurrentFrameTcw.at<double>(2, 3)
);
TRANS_PRED = transCurrent - transLast;

遇到的问题: 针对简单的工程,代码运行完全没有问题,但是放到复杂工程里面,代码就会输出莫名其妙的结果!!!!!这种方法可能会导致错误,原因如下:

  1. 直接访问 cv::Mat 的元素可能不安全,特别是当矩阵的存储格式不确定时。
  2. 这种方法忽略了旋转部分的影响,可能导致计算结果不准确。
  3. 在某些情况下,可能会出现索引错误或类型不匹配的问题。

改进的解决方案: 经过多次尝试和改进,我们最终采用了以下方法:

// 直接相减 cv::Mat
cv::Mat diff = mCurrentFrameTcw - mLastFrameTcw;// 将 cv::Mat 转换为 Eigen 矩阵
Eigen::MatrixXd eigenDiff;
cv::cv2eigen(diff, eigenDiff);// 从 eigenDiff 的最后一列提取前三个元素赋值给 TRANS_PRED
TRANS_PRED = eigenDiff.block<3,1>(0, eigenDiff.cols()-1);

这个解决方案的优点:

  1. 使用 cv::Mat 的矩阵减法,保持了原始数据的完整性。
  2. 利用 OpenCV 提供的 cv2eigen 函数,安全地将 cv::Mat 转换为 Eigen 矩阵。
  3. 使用 Eigen 的 block 操作,精确地提取所需的平移向量。

结论: 在处理计算机视觉中的坐标变换问题时,正确地在不同库(如 OpenCV 和 Eigen)之间转换数据格式是至关重要的。通过采用矩阵减法和适当的类型转换,我们可以准确地计算相机位姿之间的变换。这个经验教训提醒我们,在处理不同库之间的数据转换时,要特别注意数据类型的一致性和操作的正确性。在future类似的问题中,我们可以借鉴这种方法,确保在不同数学库之间进行安全和准确的数据转换。

下面给出完整的代码(注意:下面的两个版本都可以用,只是区分两个中哪个更鲁棒!!!)

#include <iostream>
#include <iomanip>
#include <opencv2/core.hpp>
#include <Eigen/Dense>
#include <opencv2/core/eigen.hpp>void CalculateTransPred_Method1(const cv::Mat& mLastFrameTcw, const cv::Mat& mCurrentFrameTcw, Eigen::Vector3d& TRANS_PRED) {std::cout << "Method 1: Direct extraction from cv::Mat" << std::endl;Eigen::Vector3d transLast(mLastFrameTcw.at<double>(0, 3),mLastFrameTcw.at<double>(1, 3),mLastFrameTcw.at<double>(2, 3));Eigen::Vector3d transCurrent(mCurrentFrameTcw.at<double>(0, 3),mCurrentFrameTcw.at<double>(1, 3),mCurrentFrameTcw.at<double>(2, 3));std::cout << "transLast: " << transLast.transpose() << std::endl;std::cout << "transCurrent: " << transCurrent.transpose() << std::endl;TRANS_PRED = transCurrent - transLast;std::cout << "TRANS_PRED: " << TRANS_PRED.transpose() << std::endl;
}void CalculateTransPred_Method2(const cv::Mat& mLastFrameTcw, const cv::Mat& mCurrentFrameTcw, Eigen::Vector3d& TRANS_PRED) {std::cout << "\nMethod 2: Using cv::Mat subtraction and Eigen conversion" << std::endl;cv::Mat diff = mCurrentFrameTcw - mLastFrameTcw;Eigen::MatrixXd eigenDiff;cv::cv2eigen(diff, eigenDiff);std::cout << "Difference (diff) in Eigen::MatrixXd format:" << std::endl;std::cout << eigenDiff << std::endl;TRANS_PRED = eigenDiff.block<3,1>(0, eigenDiff.cols()-1);std::cout << "TRANS_PRED: " << TRANS_PRED.transpose() << std::endl;
}int main() {cv::Mat mLastFrameTcw = (cv::Mat_<double>(4, 4) -0.1642483, 0.094168551, -0.98191381, 0.90703607,0.0095526827, 0.99553794, 0.093877248, -0.038507219,0.98637277, 0.0060392693, -0.164415, -3.4207926,0, 0, 0, 1);cv::Mat mCurrentFrameTcw = (cv::Mat_<double>(4, 4) -0.16892175, 0.093616515, -0.98117346, 0.92409742,0.009967736, 0.99559039, 0.093275994, -0.039425559,0.98557907, 0.0059762667, -0.16911002, -3.4853551,0, 0, 0, 1);Eigen::Vector3d TRANS_PRED;std::cout << std::fixed << std::setprecision(6);std::cout << "mLastFrame.mTcw:" << std::endl;std::cout << mLastFrameTcw << std::endl;std::cout << "\nmCurrentFrame.mTcw:" << std::endl;std::cout << mCurrentFrameTcw << std::endl;CalculateTransPred_Method1(mLastFrameTcw, mCurrentFrameTcw, TRANS_PRED);CalculateTransPred_Method2(mLastFrameTcw, mCurrentFrameTcw, TRANS_PRED);return 0;
}

相关文章:

OpenCV cv::Mat到 Eigen 的正确转换——cv2eigen

在进行计算机视觉项目时&#xff0c;我们经常需要处理相机位姿的变换。最近&#xff0c;我在项目中遇到了一个看似简单但实际上颇具挑战性的问题&#xff1a;从 OpenCV 的 cv::Mat 格式转换到 Eigen 库的格式。这个过程中遇到了一些问题&#xff0c;但最终找到了一个稳健的解决…...

PostgreSQL的扩展(extensions)-常用的扩展-pg_pathman

PostgreSQL的扩展&#xff08;extensions&#xff09;-常用的扩展-pg_pathman pg_pathman 是一个用于 PostgreSQL 的分区管理扩展。它提供了一种高效的方式来管理和使用数据库分区&#xff0c;可以显著提升查询性能&#xff0c;特别是在处理大规模数据集时。 安装 pg_pathman…...

数据结构之树

基础知识&#xff1a; 树是一种非线性结构&#xff0c;其严格的数学定义是&#xff1a;如果一组数据中除了第一个节点&#xff08;第一个节点称为根节点&#xff0c;没有直接前驱节点&#xff09;之外&#xff0c;其余任意节点有且仅有一个直接前驱&#xff0c;有零个或多个直接…...

6毛钱SOT-23封装28V、400mA 开关升压转换器,LCD偏置电源和白光LED应用芯片TPS61040

SOT-23-5 封装 TPS61040 丝印PHOI 1 特性 • 1.8V 至 6V 输入电压范围 • 可调节输出电压范围高达 28V • 400mA (TPS61040) 和 250mA (TPS61041) 内部开关电流 • 高达 1MHz 的开关频率 • 28μA 典型空载静态电流 • 1A 典型关断电流 • 内部软启动 • 采用 SOT23-5、TSOT23…...

saga模型

​ Saga源于Hector Garcaa-Molrna和Kenneth Salem发表的论文Sagas。一个LLT事务&#xff08;Long Lived Transaction&#xff09;可以分成若干个小的事务执行单元&#xff0c;这些小执行单元就是saga事务。Saga方案更适合用于长事务场景。Saga模型将一个分布式事务拆分为多个本…...

深度神经网络:解锁智能的密钥

深度神经网络&#xff1a;解锁智能的密钥 在人工智能的浩瀚星空中&#xff0c;深度神经网络&#xff08;Deep Neural Networks, DNNs&#xff09;无疑是最耀眼的那颗星。它以其强大的学习能力、高度的适应性和广泛的应用场景&#xff0c;成为了我们解锁智能世界的一把密钥。本…...

国际现货黄金最新价格如何分析?结合较高的时间周期

国际现货黄金投资是一种24小时交易的品种&#xff0c;这意味着&#xff0c;在交易日我们打开电脑图表&#xff0c;分析完走势之后就有机会做交易了。但问题也出在这里&#xff0c;如果对国际现货黄金最新价格把握不住&#xff0c;分析和交易就无从谈起了&#xff0c;下面我们就…...

微服务和kafka

一、微服务简介 1.单体架构 分布式--微服务--云原生 传统架构&#xff08;单机系统&#xff09;&#xff0c;一个项目一个工程&#xff1a;比如商品、订单、支付、库存、登录、注册等等&#xff0c;统一部署&#xff0c;一个进程 all in one的架构方式&#xff0c;把所有的…...

Jetpack架构组件_Navigaiton组件_1.Navigaiton切换Fragment

1.Navigation主要作用 方便管理Fragment &#xff08;1&#xff09;方便我们管理Fragment页面的切换 &#xff08;2&#xff09;可视化的页面导航图&#xff0c;便于理清页面间的关系。 &#xff08;3&#xff09;通过destination和action完成页面间的导航 &#xff08;4&a…...

[计算机网络] 虚拟局域网

虚拟局域网 VLAN&#xff08;Virtual Local Area Network&#xff0c;虚拟局域网&#xff09;是将一个物理的局域网在逻辑上划分成多个广播域的技术。 通过在交换机上配置VLAN&#xff0c;可以实现在同一个VLAN 内的用户可以进行二层互访&#xff0c;而不同VLAN 间的用户被二…...

LabVIEW遇到无法控制国外设备时怎么办

当使用LabVIEW遇到无法控制国外产品的问题时&#xff0c;解决此类问题需要系统化的分析和处理方法。以下是详细的解决思路和具体办法&#xff0c;以及不同方法的分析和比较&#xff0c;包括寻求代理、国外技术支持、国内用过的人请教等内容。 1. 了解产品的通信接口和协议 思路…...

.hmallox勒索病毒解密方法|勒索病毒解决|勒索病毒恢复|数据库修复

导言&#xff1a; 在当今数字化时代&#xff0c;勒索病毒已经成为网络安全的一大威胁&#xff0c;其中包括了最近出现的.hmallox勒索病毒。这类恶意软件不仅能够对计算机系统进行加密&#xff0c;还会要求用户支付赎金以换取解密密钥&#xff0c;给个人用户和企业带来了严重的…...

Redis发布、订阅模式(Pub/Sub)详解

Redis发布、订阅模式&#xff08;PUB-SUB&#xff09;详解 Redis的发布订阅&#xff08;Pub/Sub&#xff09;机制是一种消息通信模式&#xff0c;用于消息的广播。它允许多个客户端订阅&#xff08;Subscribe&#xff09;特定的频道&#xff08;Channel&#xff09;&#xff0c…...

Django-开发一个列表页面

需求 基于ListView,创建一个列表视图,用于展示"BookInfo"表的信息要求提供分页提供对书名,作者,描述的查询功能 示例展示: 1. 数据模型 models.py class BookInfo(models.Model):titlemodels.CharField(verbose_name"书名",max_length100)authormode…...

flink 处理函数和流转换

目录 处理函数分类 概览介绍 KeydProcessFunction和ProcessFunction 定时器TimeService 窗口处理函数 多流转换 分流-侧输出流 合流 联合&#xff08;Uniion&#xff09; 连接&#xff08;connect&#xff09; 广播连接流&#xff08;BroadcatConnectedStream&#xf…...

详细分析Springmvc中的@ModelAttribute基本知识(附Demo)

目录 前言1. 注解用法1.1 方法参数1.2 方法1.3 类 2. 注解场景2.1 表单参数2.2 AJAX请求2.3 文件上传 3. 实战4. 总结 前言 将请求参数绑定到模型对象上&#xff0c;或者在请求处理之前添加模型属性 可以在方法参数、方法或者类上使用 一般适用这几种场景&#xff1a; 表单…...

和利时SIS安全系统模块SGM210 SGM210-A02

和利时SIS安全系统模块SGM210 SGM210-A02 阀门定位器&#xff1a;&#xff08;福克斯波罗, YTC&#xff0c;山武&#xff09; PLC&#xff1a;&#xff08;西门子&#xff0c;施耐德&#xff0c;ABB,AB,三菱&#xff0c;欧姆龙&#xff09; 泵阀&#xff1a;&#xff08;力士…...

浔川3样AI产品即将上线!——浔川总社部

浔川3样AI产品即将上线&#xff01; 浔川AI翻译v3.0 即将上线&#xff01; 浔川画板v5.1 即将上线&#xff01; 浔川AI五子棋v1.4 即将上线&#xff01; 整体通告详见&#xff1a;浔川AI五子棋&#xff08;改进&#xff08;完整&#xff09;版1.3&#xff09;——浔川python社…...

小阿轩yx-MySQL索引、事务

小阿轩yx-MySQL索引、事务 MySQL 索引介绍 是一个排序的列表&#xff0c;存储着索引的值和包含这个值的数据所在行的物理地址数据很多时&#xff0c;索引可以大大加快查询的速度使用索引后可以不用扫描全表来定位某行的数据而是先通过索引表找到该行数据对应的物理地址然后访…...

搞定求职难题:工作岗位列表+简历制作工具 | 开源专题 No.75

SimplifyJobs/New-Grad-Positions Stars: 8.5k License: NOASSERTION 这个项目是一个用于分享和跟踪美国、加拿大或远程职位的软件工作机会列表。该项目的核心优势和关键特点如下&#xff1a; 自动更新新岗位信息便捷地提交问题进行贡献提供一键申请选项 BartoszJarocki/cv…...

RestClient

什么是RestClient RestClient 是 Elasticsearch 官方提供的 Java 低级 REST 客户端&#xff0c;它允许HTTP与Elasticsearch 集群通信&#xff0c;而无需处理 JSON 序列化/反序列化等底层细节。它是 Elasticsearch Java API 客户端的基础。 RestClient 主要特点 轻量级&#xff…...

Flask RESTful 示例

目录 1. 环境准备2. 安装依赖3. 修改main.py4. 运行应用5. API使用示例获取所有任务获取单个任务创建新任务更新任务删除任务 中文乱码问题&#xff1a; 下面创建一个简单的Flask RESTful API示例。首先&#xff0c;我们需要创建环境&#xff0c;安装必要的依赖&#xff0c;然后…...

树莓派超全系列教程文档--(61)树莓派摄像头高级使用方法

树莓派摄像头高级使用方法 配置通过调谐文件来调整相机行为 使用多个摄像头安装 libcam 和 rpicam-apps依赖关系开发包 文章来源&#xff1a; http://raspberry.dns8844.cn/documentation 原文网址 配置 大多数用例自动工作&#xff0c;无需更改相机配置。但是&#xff0c;一…...

Cesium1.95中高性能加载1500个点

一、基本方式&#xff1a; 图标使用.png比.svg性能要好 <template><div id"cesiumContainer"></div><div class"toolbar"><button id"resetButton">重新生成点</button><span id"countDisplay&qu…...

项目部署到Linux上时遇到的错误(Redis,MySQL,无法正确连接,地址占用问题)

Redis无法正确连接 在运行jar包时出现了这样的错误 查询得知问题核心在于Redis连接失败&#xff0c;具体原因是客户端发送了密码认证请求&#xff0c;但Redis服务器未设置密码 1.为Redis设置密码&#xff08;匹配客户端配置&#xff09; 步骤&#xff1a; 1&#xff09;.修…...

让回归模型不再被异常值“带跑偏“,MSE和Cauchy损失函数在噪声数据环境下的实战对比

在机器学习的回归分析中&#xff0c;损失函数的选择对模型性能具有决定性影响。均方误差&#xff08;MSE&#xff09;作为经典的损失函数&#xff0c;在处理干净数据时表现优异&#xff0c;但在面对包含异常值的噪声数据时&#xff0c;其对大误差的二次惩罚机制往往导致模型参数…...

Python基于历史模拟方法实现投资组合风险管理的VaR与ES模型项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档&#xff09;&#xff0c;如需数据代码文档可以直接到文章最后关注获取。 1.项目背景 在金融市场日益复杂和波动加剧的背景下&#xff0c;风险管理成为金融机构和个人投资者关注的核心议题之一。VaR&…...

Razor编程中@Html的方法使用大全

文章目录 1. 基础HTML辅助方法1.1 Html.ActionLink()1.2 Html.RouteLink()1.3 Html.Display() / Html.DisplayFor()1.4 Html.Editor() / Html.EditorFor()1.5 Html.Label() / Html.LabelFor()1.6 Html.TextBox() / Html.TextBoxFor() 2. 表单相关辅助方法2.1 Html.BeginForm() …...

MeshGPT 笔记

[2311.15475] MeshGPT: Generating Triangle Meshes with Decoder-Only Transformers https://library.scholarcy.com/try 真正意义上的AI生成三维模型MESHGPT来袭&#xff01;_哔哩哔哩_bilibili GitHub - lucidrains/meshgpt-pytorch: Implementation of MeshGPT, SOTA Me…...

理想汽车5月交付40856辆,同比增长16.7%

6月1日&#xff0c;理想汽车官方宣布&#xff0c;5月交付新车40856辆&#xff0c;同比增长16.7%。截至2025年5月31日&#xff0c;理想汽车历史累计交付量为1301531辆。 官方表示&#xff0c;理想L系列智能焕新版在5月正式发布&#xff0c;全系产品力有显著的提升&#xff0c;每…...