1.eigen库介绍
eigen库是C++中的线性代数库,实现了线性代数以及矩阵分析中所有计算方法。既然已经要学eigen库了,想必,线性代数的基本知识肯定是有的。如果你是做三维重建的,那么这个库必学。
另外,eigen库内部实现的操作基本都是高度优化的,计算顺序可能并不像我们平时计算那样从左到右,一般情况下,我们是不需要去管这个的。
eigen官方库使用官方教程链接: link
2.matrix对象创建
只有一个模板类Matrix,其他的所有数据类型3阶矩阵、2维向量等等都是由这个类模板定义的。如typedef Matrix<int,2,1> Vector2i;typedef Matrix<float,3,3> Matrix3f;
//固定大小的矩阵 Eigen::Matrix<int, 2, 2> mat1; Eigen::Matrix2i mat2; cout << "mat1:"<<endl<<mat1 << endl; cout << "mat2:" << endl<<mat2 << endl; //mat不支持构造时初始化,vec是可以构造时初始化 mat2 << 1, 2, 3, 4; cout << "输入值后,mat2:" << endl << mat2 << endl; Eigen::Vector2f vec2f(99.9, 88.8); cout << "输入值后,vec2f:" << endl << vec2f << endl; //如果支持C++11特性,则mat和vec都可以用列表初始化 Eigen::MatrixXi dymat{
{
1, 2, 3}, {
4,5,6 }}; cout << "dymat:" << endl << dymat << endl;
讯享网
运行结果:

讯享网
矩阵元素的访问
讯享网#include <iostream> #include <Eigen/Dense> int main() {
Eigen::MatrixXd m(2,2); m(0,0) = 3; m(1,0) = 2.5; m(0,1) = -1; m(1,1) = m(1,0) + m(0,1); std::cout << "Here is the matrix m:\n" << m << std::endl; Eigen::VectorXd v(2); v(0) = 4; v(1) = v(0) - 1; std::cout << "Here is the vector v:\n" << v << std::endl; }
动态矩阵–即矩阵维度是不确定的
用Eigen::MatrixXi来定义(其实是Eigen::Matrix<int,dynamic,dynamic>)。动态矩阵时可以改变大小的resize函数。
//如果支持C++11特性,则mat和vec都可以用列表初始化 Eigen::MatrixXi dymat{
{
1, 2, 3}, {
4,5,6 }}; cout << "dymat:" << endl << dymat << endl; cout << "行数:"<<dymat.rows() << endl; dymat.resize(3, 2); cout << "dymat:" << endl << dymat << endl; cout << "行数:" << dymat.rows() << endl;
注意:Eigen中矩阵的元素存储默认是列主序,即dymat在内存中是 1,4,2,5,3,6

3.矩阵四则运算
eigen库通过运算符重载来实现类似于普通常数的四则运算,当然也有一些函数方法。注意: Eigen库不支持数据类型的自动提升,所以执行四则运算的矩阵必须是相同数据类型,可以使用cast()成员函数进行数据类型强转。
加减
讯享网 Eigen::Matrix2d a; a << 1, 2, 3, 4; Eigen::MatrixXd b(2, 2); b << 2, 3, 1, 4; std::cout << "a + b =\n" << a + b << std::endl; std::cout << "a - b =\n" << a - b << std::endl; std::cout << "Doing a += b;" << std::endl; a += b; std::cout << "Now a =\n" << a << std::endl; Eigen::Vector3d v(1, 2, 3); Eigen::Vector3d w(1, 0, 0); std::cout << "-v + w - v =\n" << -v + w - v << std::endl;

标量乘除
Eigen::Matrix2d a{
{
1, 2}, {
3, 4 }}; cout << a << endl; cout << "" << endl; auto a1 = a * 2; auto a2 = a / 2; cout << a1 << endl; cout << "" << endl; cout << a2 << endl;

矩阵乘除
讯享网 Eigen::Matrix2d a{
{
1, 2}, {
3, 4 }}; Eigen::Matrix2d b = a.transpose(); cout << "a:" << endl << a << endl; cout << "b:" << endl << b << endl; cout << "a*b:" << endl << a * b << endl; Eigen::Vector2d c(1, 1); cout << "a * b * c" << endl << a * b * c << endl;

内积和外积–dot、cross
Eigen::Vector3d a(1, 1,1); Eigen::Vector3d b(3, 4,5); cout << "内积:" << a.dot(b) << endl; cout << "内积另一种计算:" << a.transpose()*b << endl; cout << "叉乘:" <<endl<< a.cross(b) << endl;


4. Array类实现逐元素的操作。类似于numpy中的广播机制。
只要记住是逐元素操作就行,其它的所有操作都跟Matrix差不多。
讯享网 Eigen::Array<int, 2, 3> a{
{
-1, -2, -1}, {
6,6,6 }}; Eigen::Array<int, 2, 3> b{
{
2, 2, 2}, {
2,3,2 }}; cout << "a:" << endl << a << endl; cout << "b:" << endl << b << endl; cout << "a+1:" << endl << a + 1 << endl; cout << "a+b:" << endl << a + b << endl; cout << "a*b:" << endl << a * b << endl; cout << "a的绝对值:" << a.abs() << endl; cout << "b的平方根:" << b.sqrt() << endl; cout << "返回a和b中对应元素位置最大的元素组成的array:" << endl << a.max(b) << endl;

5.矩阵块操作–block、()重载
Eigen::MatrixXf m(4, 4); m << 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16; //block方法返回值做右值 auto t = m.block<2, 2>(1, 1); cout << t << endl; //左值 m.block(1, 1, 2, 2) = Eigen::Array22f::Constant(0.5); cout << "m:\n" << m << endl;

注意: 块操作结果是可以作为左值的,即block函数返回的是引用。
取块的其他操作:
讯享网 Eigen::MatrixXf m(4, 4); m << 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16; //block方法返回值做右值 auto t = m.block<2, 2>(1, 1); cout << t << endl; //左值 m.block(1, 1, 2, 2) = Eigen::Array22f::Constant(0.5); cout << "m:\n" << m << endl << endl; //取第2行 cout << "第2行:" << m.row(1) << endl; //左上角2*3,并+1 m.topLeftCorner(2, 3) = m.topLeftCorner(2, 3).array() + 1; cout << endl << "左上角+1后:\n" << m << endl;

6.切片-seq,seqN,lastN,all,其它数组
切片和块操作差不多,都支持左值和右值计算。不同的是,切片更灵活,切片得到的矩阵布局跟切片时输入的行列顺序一样。
Eigen::MatrixXf m(4, 4); m << 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16; //matrix的切片 //用seq()生成数组 cout << m(Eigen::seq(1, 2),Eigen::seq(0,1) ) << endl; cout << "" << endl; //用seqN()生成间隔数组 cout << m(Eigen::seqN(0, 2, 2), Eigen::last) << endl; cout << "" << endl; //用一般的可遍历容器生成数组 int col[2] = {
0,1 }; cout << m(vector<int>{
1, 2, 3}, col) << endl; cout << "" << endl; //用lastN生成后面的数组 cout << m(Eigen::lastN(2), Eigen::all) << endl; cout << "" << endl;

讯享网 cout <<"m:\n"<< m << endl; cout << "" << endl; //逆序切片 cout << m(Eigen::seq(Eigen::last, 1, -1), vector<int>{
1, 2}) << endl; //任意行列切片 cout << "" << endl; Eigen::Array3i ainx{
1, 3, 2}; cout << m(vector<int>{
2, 1, 2}, ainx) << endl;

7.初始化的其它方法–用matrix初始化
//用matrix来初始化,实现堆叠 MatrixXi mat1(2, 2); mat1 << 1, 2, 3, 4; MatrixXi mat2(2, 3); mat2 << 1, 1, 1, 2, 2, 2; cout << "mat1:\n" << mat1 << endl; cout << "mat2:\n" << mat2 << endl; MatrixXi mat3(2, 5); mat3 << mat1, mat2; cout << "mat3:\n" << mat3 << endl; MatrixXi mat4(5, 5); mat4.row(0) << mat3.row(1); mat4.row(1).head(4) << 4, 4, 4, 4; mat4.row(1).tail(1) << 100; mat4.block(2, 0, 3, 5) << mat3, mat3.row(0); cout << "mat4:\n" << mat4 << endl;

8.常见的一些基本矩阵幅值
零矩阵、单位阵、常矩阵、随机矩阵
讯享网 //零矩阵 MatrixXi mat1 = MatrixXi::Zero(2, 3); cout << "mat1:\n" << mat1 << endl; Matrix3i mat2 = Matrix3i::Zero(); cout << "mat2:\n" << mat2 << endl; //常数矩阵 MatrixXf mat3 = MatrixXf::Constant(2, 3, 6.6); cout << "mat3:\n" << mat3 << endl; //随机矩阵 RowVectorXf vec1 = RowVector3f::Random();//-1~1随机浮点数 cout << "vec1:\n" << vec1 << endl; //单位阵 MatrixXi mat4 = Matrix3i::Identity(); cout << "mat4:\n" << mat4 << endl;

分块的常见矩阵赋值or原地赋值操作
const int size = 6; MatrixXd mat1(size, size); mat1.topLeftCorner(size / 2, size / 2) = MatrixXd::Zero(size / 2, size / 2); mat1.topRightCorner(size / 2, size / 2) = MatrixXd::Identity(size / 2, size / 2); mat1.bottomLeftCorner(size / 2, size / 2) = MatrixXd::Identity(size / 2, size / 2); mat1.bottomRightCorner(size / 2, size / 2) = MatrixXd::Zero(size / 2, size / 2); std::cout << mat1 << std::endl << std::endl; MatrixXd mat2(size, size); mat2.topLeftCorner(size / 2, size / 2).setZero(); mat2.topRightCorner(size / 2, size / 2).setIdentity(); mat2.bottomLeftCorner(size / 2, size / 2).setIdentity(); mat2.bottomRightCorner(size / 2, size / 2).setZero(); std::cout << mat2 << std::endl << std::endl; MatrixXd mat3(size, size); mat3 << MatrixXd::Zero(size / 2, size / 2), MatrixXd::Identity(size / 2, size / 2), MatrixXd::Identity(size / 2, size / 2), MatrixXd::Zero(size / 2, size / 2); std::cout << mat3 << std::endl;

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/41834.html