Eigen入门系列 —— Eigen::Matrix矩阵点乘、叉乘、转置、求逆、求和、行列式、迹、数乘

Eigen入门系列 —— Eigen::Matrix矩阵点乘、叉乘、转置、求逆、求和、行列式、迹、数乘


前言

随着工业自动化、智能化的不断推进,机器视觉(2D/3D)在工业领域的应用和重要程度也同步激增(识别、定位、抓取、测量,缺陷检测等),而针对不同作业场景进行解决方案设计时,通常会借助PCL、OpenCV、Eigen等简单方便的开源算法库进行方案的快速验证和迭代以满足作业场景下的目标需求。

为了让对工业机器视觉方向感兴趣的同学能够少走一些弯路,故推出了此一系列简易入门教程示例,让初次使用者能够最简单直观地感受到当前所用算法模块的执行效果。

后续会逐步扩增与工业机器视觉相关的一些其它内容,如:

项目案例剖析场景数据分析基础算法模块相机评测 等;

如有兴趣可加入群聊(若入群二维码被屏蔽,则可以通过Q群(1032861997)或评论、私信博主“群聊”,邀请入群),与同道同学及圈内同行一起交流讨论。

在这里插入图片描述


程序说明

展示Eigen::Matrix矩阵运算,点乘、叉乘、转置、求逆、求和、行列式、迹、数乘等;

输出结果

在这里插入图片描述

代码示例

/*
 * @File: matrix_arithmetic.cpp
 * @Brief: eigen course
 * @Description: 展示Eigen::Matrix矩阵运算
 * @Version: 0.0.1
 * @Author: MuYv
 */
#include <iostream>
#include <Eigen/Dense>



int main(int argc, char** argv){
    // Eigen::Matrix为模板类,可自由定义不同维度的矩阵,
    // 此处仅展示较为常用的几种数据类型,其它定制化需求类型的使用,可以此类推;

    // 自定义创建4x4的矩阵,模板参数依次为:数据类型,行数,列数;
    Eigen::Matrix<float, 4, 4> matrix_4f;
    // 使用常数值进行初始化填充;
    matrix_4f = Eigen::Matrix<float,4,4>::Random();
    std::cout<<"matrix_4f random init:\n"<<matrix_4f<<std::endl<<std::endl;
    std::cout << "transpose:\n" << matrix_4f.transpose()<<std::endl<<std::endl;     // 转置
    std::cout << "sum: " << matrix_4f.sum()<<std::endl;                             // 各元素和
    std::cout << "det: " << matrix_4f.determinant()<<std::endl;                     // 行列式
    std::cout << "trace: " << matrix_4f.trace()<<std::endl<<std::endl;              // 迹
    std::cout << "times 10:\n" << 10 * matrix_4f<<std::endl<<std::endl;             // 数乘
    std::cout << "inverse:\n" << matrix_4f.inverse()<<std::endl<<std::endl;         // 逆
    
    
    // 3x1 列向量
    Eigen::Vector3f vector_3f(1.0f, 2.0f, 3.0f);
    std::cout<<"vector_3f:\n"<<vector_3f<<std::endl;

    Eigen::Vector3f vector_3f_tmp = Eigen::Vector3f::Constant(4.0f);
    std::cout<<"vector_3f_tmp:\n"<<vector_3f_tmp<<std::endl<<std::endl;

    // 点乘
    std::cout<<"vector_3f.dot(vector_3f_tmp): "<<(vector_3f.dot(vector_3f_tmp))<<std::endl<<std::endl;
    // 叉乘
    std::cout<<"vector_3f.cross(vector_3f_tmp):\n"<<(vector_3f.cross(vector_3f_tmp))<<std::endl<<std::endl;
    // 与矩阵变换
    Eigen::Matrix3f rotation = Eigen::Matrix3f::Random();
    std::cout<<"matrix transform:\n"<<(rotation*vector_3f)<<std::endl<<std::endl;
    

    return 0;
}

<think>我们正在使用Eigen库,并且需要对一个Matrix4d类型的矩阵进行操作。Matrix4d是一个4x4的双精度浮矩阵。 在Eigen中,有多种方法,最直接的是使用`.inverse()`成员函。但是,对于固定大小的矩阵(如4x4),Eigen会使用优化过的算法,通常是通过LU分解或者直接使用伴随矩阵的方法(对于小矩阵)来。 另外,我们也可以显式地使用分解方法(如PartialPivLU)来矩阵,这样可能在某些情况下更高效或更稳定。 根据引用[4],我们看到一个例子,其中使用了`.inverse()`成员函,然后还使用了一个迭代步骤来增加精度(通过残差修正)。但是,对于4x4矩阵,通常直接已经足够高效和精确。 因此,我们可以这样操作: 1. 直接使用`.inverse()`方法。 2. 或者使用分解方法(如PartialPivLU)来。 下面分别展示两种方法: 方法1:直接使用inverse() ```cpp #include <Eigen/Dense> using namespace Eigen; Matrix4d A; // 假设我们有一个矩阵A // 填充A的据... Matrix4d invA = A.inverse(); // 直接 ``` 方法2:使用PartialPivLU分解 ```cpp #include <Eigen/Dense> using namespace Eigen; Matrix4d A; // 填充A... // 创建PartialPivLU分解对象,然后调用inverse()方法 Matrix4d invA = A.partialPivLu().inverse(); ``` 注意:对于4x4这样的小矩阵,两种方法在性能上差异不大,但使用分解方法可能提供更好的值稳定性(特别是当矩阵接近奇异时,虽然本身在矩阵奇异时会失败)。另外,如果矩阵是正定的,也可以考虑使用LLT或LDLT分解(但Matrix4d不一定正定)。 引用[4]中还提到了一种迭代修正的方法,用于提高解的精度。如果你对精度有更高要,可以像引用[4]中那样进行残差修正。但是,对于大多应用,直接已经足够。 因此,对于一般情况,我们推荐直接使用`.inverse()`方法,因为它简单直接。 示例代码: ```cpp #include <iostream> #include <Eigen/Dense> int main() { Eigen::Matrix4d A; A << 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16; // 检查矩阵是否可(可选,因为时如果不可会抛出异常或得到错误结果) double det = A.determinant(); if (det == 0) { std::cout << "Matrix is singular and cannot be inverted." << std::endl; return 0; } // 直接 Eigen::Matrix4d invA = A.inverse(); std::cout << "Original matrix A:\n" << A << std::endl; std::cout << "Inverse of A:\n" << invA << std::endl; // 验证:A * invA 应该近似于单位矩阵 std::cout << "A * invA:\n" << A * invA << std::endl; return 0; } ``` 注意:上面的矩阵A实际上是一个奇异矩阵行列式为0),所以不可。在实际应用中,我们需要确保矩阵。 另外,Eigen时如果矩阵是奇异的,可能会产生NaN或无穷大,或者抛出异常(取决于设置)。因此,在实际应用中,最好检查矩阵是否可(例如通过行列式或者使用分解时的info标志)。 引用[4]中提到了使用残差修正的方法,这里也给出一个类似的例子(虽然通常用于解线性方程组,但也可以用于后的修正): 但注意:后,我们得到的是矩阵,而残差修正通常用于解线性方程组。如果我们要解方程组Ax=b,那么我们可以先,然后x = A^{-1}b,然后进行修正。但直接矩阵本身并不需要修正步骤。 因此,对于单纯矩阵,我们只需要使用上述方法之一即可。 总结:在Eigen中对Matrix4d,推荐使用`A.inverse()`。 相关问题: 1. Eigen库中有几种方法?各自适用于什么情况? 2. 如何判断一个矩阵是否可? 3. 在Eigen中如何处理奇异矩阵(不可矩阵)的操作? 4. Eigen库中除了,还有哪些矩阵分解方法? 5. 如何提高值精度?</think>在Eigen库中对`Matrix4d`(4×4双精度浮矩阵)进行操作,推荐使用以下两种高效且稳定的方法: --- ### 方法1:直接使用`.inverse()`成员函(推荐) ```cpp #include <Eigen/Dense> Eigen::Matrix4d A; // 填充矩阵据(示例) A << 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16; // 操作 Eigen::Matrix4d invA = A.inverse(); ``` - **原理**:Eigen对固定大小的小矩阵(如4×4)会自动优化,默认使用**LU分解**[^4]。 - **优**:代码简洁,性能高效。 - **注意**:若矩阵奇异(不可),会触发值不稳定或NaN结果。建议先检查行列式: ```cpp if (A.determinant() != 0) { // 行列式非零才 invA = A.inverse(); } ``` --- ### 方法2:显式使用LU分解(更稳定) ```cpp #include <Eigen/Dense> Eigen::Matrix4d A; // 填充矩阵据... // 使用PartialPivLU分解 Eigen::PartialPivLU<Eigen::Matrix4d> lu(A); if (lu.isInvertible()) { // 检查是否可 Eigen::Matrix4d invA = lu.inverse(); } ``` - **原理**:显式调用LU分解并利用分解结果值稳定性更高[^4]。 - **优**:可显式检查可性(`isInvertible()`),避免值错误。 --- ### 关键注意事项 1. **矩阵性**: - 前需确保矩阵**满秩**(行列式非零)。 - 可通过`A.determinant() != 0`或`lu.isInvertible()`验证。 2. **性能优化**: - 对于4×4固定大小矩阵Eigen会展开循环优化,无需手动优化[^2]。 3. **精度提升**(可选): - 若需更高精度,可迭代修正残差(参考Eigen文档)[^4]: ```cpp Eigen::Vector4d b; // 假设有向量b Eigen::Vector4d x = invA * b; // 初始解 x += invA * (b - A * x); // 残差修正 ``` --- ### 示例代码 ```cpp #include <iostream> #include <Eigen/Dense> int main() { Eigen::Matrix4d A; A << 2, 0, 0, 0, 0, 3, 0, 0, 0, 0, 4, 0, 0, 0, 0, 5; // 对角矩阵(可) if (A.determinant() != 0) { Eigen::Matrix4d invA = A.inverse(); std::cout << "Inverse matrix:\n" << invA << std::endl; // 验证: A * invA 应接近单位矩阵 std::cout << "A * invA:\n" << A * invA << std::endl; } else { std::cerr << "Matrix is singular!" << std::endl; } return 0; } ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值