1. 介绍
Eigen是一个C++的开源线性代数库。它提供快速的有关矩阵的线性代数运算,还包括解方程等。许多上层软件库也使用Eigen进行矩阵运算,包括g2o,Spphus等。
2. 安装
在Linux -- Ubuntu 16.04 的系统下:
sudo apt-get install libeigen3-dev
默认安装目录: /usr/include/eigen3/
可以通过以下命令找到位置:
sudo updatedb
locate eigen3
这里说一个很有意思的事情,它是纯用头文件搭建起来的库。所以你只能找到它的头文件,没有.so 或者.a 那样的二进制文件。在使用的时候只需要引入头文件即可,不需要链接库文件(因为它没有库文件)。
3. 使用
```
#include <iostream>
#include <ctime>
using namespace std;
//Eigen部分
#include <Eigen/Core>
//稠密矩阵的代数运算(逆、特征值)
#include <Eigen/Dense>
#define MATRIX_SIZE 50
int main( int argc, char** argv){
//Eigen 以矩阵位基本数据单元。他是一个模板类。它的前三个参数为:数据类型,行,列
//声明一个 2X3 的 float 矩阵
Eigen::Matrix<float, 2, 3> matrix_23;
//同时,Eigen 通过 typedef 提供了很多内置类型,不过底层仍然是Eigen::Matrix
//例如 Vector3d 实质上是 Eigen::Matrix<double, 3, 1>
Eigen::Vector3d v_3d;
//还有Matrix3d的实质是Eigen::Matrix<double, 3, 3>
Eigen::Matrix3d matrix_33 = Eigen::Matrix3d::Zero() //初始化为0
//如果不确定矩阵的大小可以使用动态大小的矩阵
Eigen::Matrix<double , Egien::Dynamic, Eigen::Dynamic > matrix_dynamic;
//更简单的
Eigen::MatrixXd matrix_x;
//下面是对矩阵的操作
//输入数据
matrix_23 << 1,2,3,4,5,6;
//输出
cout << matrix_23 << endl;
//用()访问矩阵的元素
for ( int i = 0 ; i < 1 ; i++){
for(int j = 0 ; j < 2 ; j++ ){
cout<< matrix_23(i , j) << endl;
}
}
v_3d << 3 , 2 , 1
// 矩阵和向量相乘(实际上还是两个矩阵)
//但是不能混合两种不同类型的矩阵,下面是个错误的例子
// Eigen::Matrix<double, 2, 1> result_wrong_type = matrix_23 * v_3d; //v_3d 是double,matrix_23是float
//要显式的转换
Eigne::Matrix<double, 2, 1> result = matrix_23.cast<double>() * v_3d;
cout << result << endl;
//同样,不能搞错矩阵的维度
//Eigen::Matrix<double, 2, 3> result_wrong_dimension = matrix_23.cast<double>() * v_3d; //结果是2X1,但是定义是2X3
//一些矩阵运算
matrix_33 = Eigen::Matrix3d::Random();
cout << matrix_33 <<endl <<endl ;
cout << matrix_33.transpose() << endl; // 转置
cout << matrix_33.sum() << endl; //各元素和
cout << matrix_33.trace() << endl; //迹,对角线元素的和
cout << 10 * matrix_33 << endl; //数乘
cout << matrix_33.inverse() << endl; // 逆
cout << matrix_33.determinant() << end; //行列式
//解方程
//我们求解 matrix_NN * x = v_Nd 这个方程
//N 的大小在前边的宏里定义,矩阵由随机数生成
//直接求逆自然是最直接的,但是求逆预算量很大
Eigen::Matrix <double, MATRIX_SIZE, MATRIX_SIZE> matrix_NN;
matrix_NN = Eigen::MatrixXd::Random( MATRIX_SIZE, MATRIX_SIZE );
Eigen::Matrix< double, MATRIX_SIZE, 1> v_Nd;
v_Nd = Eigen::MatrixXd::Random( MATRIX_SIZE, 1);
clock_t time_stt = clock();
// 直接求逆
Eigen::Matrix<double , MATRIX_SIZE, 1> x = matrix_NN.inverse() * v_Nd;
cout << "Time use in normal inverse is " <<1000 * (clock() - time_set) / (double) CLOCKS_PER_SEC >> "ms" << endl;
//通常用矩阵分解来求, 例如QR分解, 速度会快很多
time_stt = clock();
x = matrix_NN.colPivHouseholderQr().solve(v_Nd);
cout <<"Time use in Qr composition is " << 1000 * (clock() - time_stt) / (double) CLOCK_PER_SEC << "ms" << endl;
return 0;
}
```
4. 注意
Eigen 提供的矩阵和MATLAB很相似,所有的数据都当做矩阵来处理。但是Egien为了效率,需要定义矩阵的大小。在编译时期就知道大小的矩阵,处理起来会比动态变化的矩阵更快一些。因此,旋转矩阵、变换矩阵这些,可以在编译时期确定他们的大小和数据类型。
Eigen不支持自动类型转换。在C+中我们可以把一个float数据和double数据相加、相乘,编译器会自动把数据类型转换为最适合的那个。在Eigen中,出于对性能的考虑,必须显示的进行类型转换。
Eigen同样要求矩阵维数的正确性。
参考:
《视觉SLAM十四讲》