当前位置: 首页 > 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…...

华为云AI开发平台ModelArts

华为云ModelArts&#xff1a;重塑AI开发流程的“智能引擎”与“创新加速器”&#xff01; 在人工智能浪潮席卷全球的2025年&#xff0c;企业拥抱AI的意愿空前高涨&#xff0c;但技术门槛高、流程复杂、资源投入巨大的现实&#xff0c;却让许多创新构想止步于实验室。数据科学家…...

HTML 语义化

目录 HTML 语义化HTML5 新特性HTML 语义化的好处语义化标签的使用场景最佳实践 HTML 语义化 HTML5 新特性 标准答案&#xff1a; 语义化标签&#xff1a; <header>&#xff1a;页头<nav>&#xff1a;导航<main>&#xff1a;主要内容<article>&#x…...

iOS 26 携众系统重磅更新,但“苹果智能”仍与国行无缘

美国西海岸的夏天&#xff0c;再次被苹果点燃。一年一度的全球开发者大会 WWDC25 如期而至&#xff0c;这不仅是开发者的盛宴&#xff0c;更是全球数亿苹果用户翘首以盼的科技春晚。今年&#xff0c;苹果依旧为我们带来了全家桶式的系统更新&#xff0c;包括 iOS 26、iPadOS 26…...

多场景 OkHttpClient 管理器 - Android 网络通信解决方案

下面是一个完整的 Android 实现&#xff0c;展示如何创建和管理多个 OkHttpClient 实例&#xff0c;分别用于长连接、普通 HTTP 请求和文件下载场景。 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas…...

Java如何权衡是使用无序的数组还是有序的数组

在 Java 中,选择有序数组还是无序数组取决于具体场景的性能需求与操作特点。以下是关键权衡因素及决策指南: ⚖️ 核心权衡维度 维度有序数组无序数组查询性能二分查找 O(log n) ✅线性扫描 O(n) ❌插入/删除需移位维护顺序 O(n) ❌直接操作尾部 O(1) ✅内存开销与无序数组相…...

376. Wiggle Subsequence

376. Wiggle Subsequence 代码 class Solution { public:int wiggleMaxLength(vector<int>& nums) {int n nums.size();int res 1;int prediff 0;int curdiff 0;for(int i 0;i < n-1;i){curdiff nums[i1] - nums[i];if( (prediff > 0 && curdif…...

相机Camera日志分析之三十一:高通Camx HAL十种流程基础分析关键字汇总(后续持续更新中)

【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了:有对最普通的场景进行各个日志注释讲解,但相机场景太多,日志差异也巨大。后面将展示各种场景下的日志。 通过notepad++打开场景下的日志,通过下列分类关键字搜索,即可清晰的分析不同场景的相机运行流程差异…...

聊一聊接口测试的意义有哪些?

目录 一、隔离性 & 早期测试 二、保障系统集成质量 三、验证业务逻辑的核心层 四、提升测试效率与覆盖度 五、系统稳定性的守护者 六、驱动团队协作与契约管理 七、性能与扩展性的前置评估 八、持续交付的核心支撑 接口测试的意义可以从四个维度展开&#xff0c;首…...

Maven 概述、安装、配置、仓库、私服详解

目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

Python Ovito统计金刚石结构数量

大家好,我是小马老师。 本文介绍python ovito方法统计金刚石结构的方法。 Ovito Identify diamond structure命令可以识别和统计金刚石结构,但是无法直接输出结构的变化情况。 本文使用python调用ovito包的方法,可以持续统计各步的金刚石结构,具体代码如下: from ovito…...