Eigen库从入门到放弃(3. The Matrix class)

在eigen中,所有的矩阵和向量都是Matrix的模板类对象,Matrix类接收6个模板参数,有三个是有默认值的,另外三个需要强制我们手动设置,我们先研究一下它的这三个参数,三个强制设置的参数分别是:

Matrix<typename Scalar, int RowsAtCompileTime, int ColsAtCompileTime>

其中Scalar是变量类型,比如可以float,Scalar types列出了所有支持的数据类型;RowsAtCompileTime和ColsAtCompileTime是在编译期间就已经确定好的行和列,我们后面讨论如何来设置一些动态shape的矩阵(动态的意思就是编译期间不能确定)
eigen对于一些常见的shape和类型进行了typedef,比如Matrix4f就是4x4 float矩阵的简写,具体定义如下:

typedef Matrix<float, 4, 4> Matrix4f;

对于vector,也是一样,也就是一行或一列的矩阵,我们也进行了简化的定义,列向量和行向量分别定义如下:

typedef Matrix<float, 3, 1> Vector3f;  // 列向量
typedef Matrix<int, 1, 2> RowVector2i;  // 行向量

还有一个问题没有解决就是,我们的shape是动态的,比如我的矩阵的行数是根据一个vector.size()来确定的,这种在编译的时候,编译器无法知道具体的形状,所以eigen还支持你将行列设置为Dynamic,这种我们称为dynamic size,而对于那种你设置为(3, 3)(4, 4)形状的我们称之为fixed size,比如我们之前遇到过的MatrixXd就是dynamic size,定义如下:

typedef Matrix<double, Dynamic, Dynamic> MatrixXd;
// 下面是定义成int动态vector
typedef Matrix<int, Dynamic, 1> VectorXi;
// 同理,你可以像下面这样,定义一个只有列是动态的类型
Matrix<float, 3, Dynamic>

有一些需要注意的点,对于我们的动态形状的矩阵,它的size是0*0的,且没有分配任何空间,但是如果你使用fixed size,size是有的,空间也是被分配好的。

Matrix3f a;  // 3*3矩阵,有9个float的空间被申请,但是里面的coefficients没有被初始化
MatrixXf b;  //  动态矩阵,size目前是0*0,里面没有申请内存,也没有被初始化

构造函数,对于矩阵先传行,而且他们的coefficients也就是每个位置的值,都没有被初始化:

MatrixXf a(10,15);
VectorXf b(30);

还有如下的初始化方法也支持:

Vector2d a(5.0, 6.0);
Vector3d b(5.0, 6.0, 7.0);
Vector4d c(5.0, 6.0, 7.0, 8.0);   // 最多到4个Vector2i a(1, 2);                      // A column vector containing the elements {1, 2}
Matrix<int, 5, 1> b {1, 2, 3, 4, 5};   // A row-vector containing the elements {1, 2, 3, 4, 5}
Matrix<int, 1, 5> c = {1, 2, 3, 4, 5}; // A column vector containing the elements {1, 2, 3, 4, 5}// 在具有固定大小或运行时大小的矩阵和向量的一般情况下,系数必须按行分组,并作为初始化列表的初始化列表传递,初始化的时候,一定要一行一行来
MatrixXi a {      // construct a 2x2 matrix{1, 2},     // first row{3, 4}      // second row
};
Matrix<double, 2, 3> b {{2, 3, 4},{5, 6, 7},
};// 对于列向量或行向量,允许隐式转置。这意味着可以从单行初始化列向量
VectorXd a {{1.5, 2.5, 3.5}};             // A column-vector with 3 coefficients
RowVectorXd b {{1.0, 2.0, 3.0, 4.0}};     // A row-vector with 4 coefficients

对于元素的获取,可以使用()来获取值,所有的Eigen矩阵都是列优先,但是也可以设置成行优先,具体可以参考Storage orders.
对于vector中的基于索引的访问,也可以使用操作符[],但请记住,c++不允许操作符[]接受多个参数。我们将运算符[]限制为向量,因为c++语言中可能会把matrix[i,j]编译成与matrix[j]相同的东西!
还有一种叫做逗号初始化语法,可以方便地设置矩阵和向量系数。

Matrix3f m;
m << 1, 2, 3,4, 5, 6,7, 8, 9;
std::cout << m;

矩阵的当前大小可以通过rows()、cols()和size()来获取。这些方法分别返回行数、列数和系数数。通过resize()方法调整动态大小矩阵的大小。注意,resize()是改变大小的,不是shape

#include <iostream>
#include <Eigen/Dense>int main()
{Eigen::MatrixXd m(2,5);m.resize(4,3);std::cout << "The matrix m is of size "<< m.rows() << "x" << m.cols() << std::endl;std::cout << "It has " << m.size() << " coefficients" << std::endl;Eigen::VectorXd v(2);std::cout << "The vector v is of size before " << v.size() << std::endl;std::cout << "The vector v is of size before " << v.size() << std::endl;std::cout << "As a matrix, v is of size "<< v.rows() << "x" << v.cols() << std::endl;v.resize(5);std::cout << "The vector v is of size " << v.size() << std::endl;std::cout << "As a matrix, v is of size "<< v.rows() << "x" << v.cols() << std::endl;
}

在这里插入图片描述
如果resize()后的大小没变化,那数据也不会变化,但是如果大小变化,那resize()操作会破坏原始数据,如果不想破坏原始数据,使用conservativeResize()。
但是对于固定尺寸的矩阵,其实相当于没啥用,因为尺寸一致啥都没干,尺寸不一致会报错,所以对于fixed size的矩阵或者向量就不要用了。
另外,对于=,其实也有一个resize()的效果在里面,=是将一个矩阵拷贝给另一个矩阵,这样就会把被赋值那个矩阵的形状也改变了,但是也是仅限于dynamic size的,对于fixed size,不可以将矩阵赋值给shape不一样的对象。

MatrixXf a(2,2);
std::cout << "a is of size " << a.rows() << "x" << a.cols() << std::endl;
MatrixXf b(3,3);
a = b;
std::cout << "a is now of size " << a.rows() << "x" << a.cols() << std::endl;//  输出
// 	a is of size 2x2
//    a is now of size 3x3

但是什么时候应该使用固定大小(例如Matrix4f),什么时候又应该使用动态大小(例如MatrixXf)?答案是:对于非常小的尺寸尽可能使用固定大小,对于较大的尺寸或必须使用动态大小。对于较小的大小,特别是小于(大约)16的大小,使用固定大小对性能非常有益,因为它允许Eigen避免动态内存分配并展开循环。在内部,固定大小的特征矩阵只是一个普通数组,比如:Matrix4f mymatrix;就相当于float mymatrix[16];,几乎是不花费任何时间,但是对于dynamic size矩阵,需要在堆上申请空间,比如你做MatrixXf mymatrix(rows,columns);相当于在底层float *mymatrix = new float[rows*columns];,除此之外,MatrixXf对象将其行数和列数存储为成员变量。

当然,使用固定大小的限制是,只有在编译时知道大小时才行。此外,对于足够大的大小,例如大于(大约)32的大小,使用固定大小的性能优势变得可以忽略不计。更糟糕的是,尝试在函数内部使用固定大小创建一个非常大的矩阵可能会导致堆栈溢出,因为Eigen会尝试将数组自动分配为局部变量,而这通常是在堆栈上完成的。最后,根据具体情况,当使用动态大小时,Eigen也可以更积极地尝试向量化(使用SIMD指令),请参阅向量化。

开头我们说过,Matrix类一共有6个模板参数,但是我们只讨论了3个,剩下的3个是可选的,下面是完整的参数:

Matrix<typename Scalar,int RowsAtCompileTime,int ColsAtCompileTime,int Options = 0,int MaxRowsAtCompileTime = RowsAtCompileTime,int MaxColsAtCompileTime = ColsAtCompileTime>
  • Options是位字段。在这里,我们只讨论一个:RowMajor。它指定这种类型的矩阵使用行为主存储顺序;默认情况下,存储顺序是以列为主的。请参阅存储顺序页面。例如,此类型表示行为主的3x3矩阵:Matrix<float, 3, 3, RowMajor>

  • MaxRowsAtCompileTime和MaxColsAtCompileTime在需要指定时非常有用,即使在编译时不知道矩阵的确切大小,但在编译时知道一个固定的上限。这样做的最大原因可能是为了避免动态内存分配。例如,下面的矩阵类型使用12个浮点数的普通数组,没有动态内存分配:Matrix<float, Dynamic, Dynamic, 0, 3, 4>,也就是说最开始的时候就申请好了,后面不会动态的申请了,又支持了动态,有限制了内存分配。
    还有一些typedefs,具体如下:

    MatrixNt : Matrix<type, N, N>. 如 Matrix<int, Dynamic, Dynamic>,MatrixXi
    MatrixXNt: Matrix<type, Dynamic, N>. 如 Matrix<int, Dynamic, 3>,MatrixX3i
    MatrixNXt: Matrix<type, N, Dynamic>. 如 Matrix<d, 4, Dynamic>,Matrix4Xd
    VectorNt:Matrix<type, N, 1>. 如 Matrix<float, 2, 1>,Vector2f
    RowVectorNt: Matrix<type, 1, N>. 如  Matrix<double, 1, 3>,RowVector3d
    

上面的N可以是2,3,4或者X(对应其中的dynamic 那个维度)
t可以是i,f,d,cf,cd,分别是int、float、double、complex<float>、complex<double>,其实不仅是这五种,还有很多,参考Scalar types。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/619244.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MATLAB GUI图形化界面设计计算器

MATLAB GUI界面设计教程可以帮助用户创建交互式的图形用户界面&#xff0c;以简化与MATLAB程序的交互过程。以下是一个简化的教程&#xff0c;指导你如何进行MATLAB GUI界面设计&#xff1a; 1. 启动GUIDE或App Designer GUIDE&#xff1a;在MATLAB命令窗口中输入guide命令&a…

基于java的社区生活超市管理系统

开发语言&#xff1a;Java 框架&#xff1a;ssm 技术&#xff1a;JSP JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09; 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;eclipse/myeclip…

STM32之DHT11温湿度传感器

目录 一 DHT11温湿度传感器简介 1.1 传感器特点 1.2 传感器特性 1.3 传感器引脚说明 二 测量原理及方法 2.1 典型应用电路 2.2 单线制串行简介 2.2.1 串行接口 (单线双向) 2.2.2 数据示例 2.3 通信时序 三 单片机简介 3.1 STM32F103C8T6最小系统板 四 接线说明 …

计算机网络 实验指导 实验17

实验17 配置无线网络实验 1.实验拓扑图 Table PC0 和 Table PC1 最开始可能还会连Access Point0&#xff0c;无影响后面会改 名称接口IP地址网关地址Router0fa0/0210.10.10.1fa0/1220.10.10.2Tablet PC0210.10.10.11Tablet PC1210.10.10.12Wireless互联网220.10.10.2LAN192.16…

YOLOv9/YOLOv8算法改进【NO.117】 使用Wasserstein Distance Loss改进小目标的检测效果

前 言 YOLO算法改进系列出到这&#xff0c;很多朋友问改进如何选择是最佳的&#xff0c;下面我就根据个人多年的写作发文章以及指导发文章的经验来看&#xff0c;按照优先顺序进行排序讲解YOLO算法改进方法的顺序选择。具体有需求的同学可以私信我沟通&#xff1a; 首推…

Blender表面细分的操作

在使用Blender的过程中,刚开始创建的模型,都会比较少面,这样操作起来比较流畅,减少电脑的计算量,当设计快要完成时,就会增加表面细分,这样更加圆滑,看起来更加顺眼。 比如创建一个猴头,它会默认显示如下: 从上图可以看到,有一些表面会比较大,棱角很多。 这时候你…

02 MySQL 之 DQL专题

3. 数据库中仅有月薪字段&#xff08;month_salary&#xff09;&#xff0c;要求查询所有员工的年薪&#xff0c;并以年薪(year_salary)输出&#xff1a; 分析&#xff1a; 查询操作中&#xff0c;字段可以参与数学运算as 起别名&#xff0c;但实际上可以省略 #以下两句效果…

Linux的文件操作中的静态库的制作

Linux操作系统支持的函数库分为&#xff1a; 静态库&#xff0c;libxxx.a&#xff0c;在编译时就将库编译进可执行程序中。 优点&#xff1a;程序的运行环境中不需要外部的函数库。 缺点&#xff1a;可执行程序大 &#xff08;因为需要 编译&#xff09; 动态库&#xff0c…

Unity 人形骨骼动画模型嘴巴张开

最近搞Daz3D玩&#xff0c;导入后挂上动画模型嘴巴张开&#xff0c;其丑无比。 Google了一下&#xff0c;得知原因是Unity没有对下巴那根骨骼做控制&#xff0c;动画系统就会把它放到默认的位置&#xff0c;嘴巴就张开了。找到了3种解决办法。 1.移除动画中对下巴这个骨骼的转…

stm32报错问题集锦

PS&#xff1a;本文负责记录本人日常遇到的报错问题&#xff0c;以及问题描述、原因以及解决办法等&#xff0c;解决办法百分百亲测有效。本篇会不定期更新&#xff0c;更新频率就看遇到的问题多不多了 更换工程芯片型号 问题描述 例程最开始用的芯片型号是STM32F103VE&#…

stm32开发之threadx+modulex组合开发使用记录

前言 参考博客 论坛官方资料: 微软开发板核心芯片使用的是stm32f407zgtx&#xff0c;烧录工具使用的是jlink模块的构建使用的是脚本进行构建网上针对modulex的资料较少&#xff0c;这里做个记录 项目结构 逻辑框架 主程序代码 主函数 /** Copyright (c) 2024-2024&#xff0…

【Web】VS Code 插件及快捷键

专栏文章索引&#xff1a;Web 有问题可私聊&#xff1a;QQ&#xff1a;3375119339 目录 一、安装步骤 二、插件 1.Chinese (Simplified) (简体中文) 2.open in browser 3.vscode-icons 4.Live Server 5.Live Server Preview 6.翻译(英汉词典) 三、快捷键 1.缩放代码…