赞
踩
eigen库是C++中的线性代数库,实现了线性代数以及矩阵分析中所有计算方法。既然已经要学eigen库了,想必,线性代数的基本知识肯定是有的。如果你是做三维重建的,那么这个库必学。
另外,eigen库内部实现的操作基本都是高度优化的,计算顺序可能并不像我们平时计算那样从左到右,一般情况下,我们是不需要去管这个的。
eigen官方库使用官方教程链接: link
只有一个模板类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
可能有人会问,什么时候用动态矩阵。什么时候用固定矩阵?
这个没有必然的答案,只有更合适。比如,在你知道矩阵大小,且维度小于16的情况下,使用固定矩阵对于性能计算会更好。反之则使用动态矩阵。另外,动态矩阵是在堆上申请的,固定矩阵是在栈上申请的。
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;
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;
只要记住是逐元素操作就行,其它的所有操作都跟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;
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;
切片和块操作差不多,都支持左值和右值计算。不同的是,切片更灵活,切片得到的矩阵布局跟切片时输入的行列顺序一样。
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;
//用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;
零矩阵、单位阵、常矩阵、随机矩阵
//零矩阵 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;
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。