前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >SLAM初探:Eigen库简单使用

SLAM初探:Eigen库简单使用

作者头像
小白学视觉
发布2019-11-07 15:50:59
2.9K1
发布2019-11-07 15:50:59
举报

Eigen是一个高层次的C ++库,有效支持线性代数,矩阵和矢量运算,数值分析及其相关的算法。Eigen是一个开源库,从3.1.1版本开始遵从MPL2许可。

固定大小的矩阵和和向量

代码语言:javascript
复制
#include <iostream>
#include <Eigen/Core>

using namespace Eigen;  
using namespace std;  

// import most common Eigen types
int main(int, char *[])
{
  Matrix3f m3; //3x3单精度矩阵
  m3 << 1, 2, 3, 4, 5, 6, 7, 8, 9;
  Matrix4f m4 = Matrix4f::Identity(); //4x4单位矩阵(单精度)
  Vector4i v4(1, 2, 3, 4); // 长度为4的整型向量

  // 输出结果
  std::cout << "m3\n" << m3 << "\nm4:\n"
    << m4 << "\nv4:\n" << v4 << std::endl;
}

Matrix表示矩阵,Vector表示向量,数字表示维度,最后的f和i分别表示单精度和整型数据类型。

固定大小表示编译时,行数和列数是固定的。这时,Eigen不会分配动态内存。这对于比较小的尺寸比较适合,比如16x16。

动态大小的矩阵和向量

代码语言:javascript
复制
// 参考链接:http://eigen.tuxfamily.org/dox-2.0/TutorialCore.html#TutorialCoreGettingStarted

#include <iostream>
#include <Eigen/Core>

using namespace Eigen;  
using namespace std;  

int main(int, char *[])
{
  // 动态矩阵
  for (int size=1; size<=4; ++size)
  {
    MatrixXi m(size,size+1); // 一个整型的大小为 (size)x(size+1) 的矩阵
    for (int j=0; j<m.cols(); ++j) // 遍历列
      for (int i=0; i<m.rows(); ++i) // 遍历行
        m(i,j) = i+j*m.rows(); // 使用圆括号m(i,j)访问矩阵的元素
    std::cout << m << "\n\n"; //打印矩阵
  }

  // 动态向量
  VectorXf v(4); // 定义一个4维单精度向量
  // 使用圆括号()或方括号[]访问向量元素
  v[0] = 1; v[1] = 2; v(2) = 3; v(3) = 4;
  std::cout << "\nv:\n" << v << std::endl;
}

小结:X表示动态大小。

#include <Eigen/Eigen>将包含所有的Eigen函数。

#include <Eigen/Dense>包含所有普通矩阵函数,不包括稀疏矩阵函数。它们会增加编译时间。

矩阵和向量类型

Eigen中的所有密集矩阵和向量都是通过Matrix类来表示的。Matrix通过一系列的模板参数来生成具体的类别。

Matrix<Scalar, RowsAtCompileTime, ColsAtCompileTime>中,Scalar表示数据类型,RowsAtCompileTime和ColsAtCompileTime分别表示编译时的行数和列数。

Vector3d 定义为 Matrix<double, 3, 1>

对于动态大小的类型,在编译时不指定行数和列数,使用Eigen::Dynamic。比如,VectorXd定义为Matrix<double, Dynamic, 1>。

访问元素

Eigen支持以下的读/写元素语法:

代码语言:javascript
复制
matrix(i,j);
vector(i)
vector[i]
vector.x() // first coefficient
vector.y() // second coefficient
vector.z() // third coefficient
vector.w() // fourth coefficient

矩阵只能通过圆括号()访问;

向量可以通过圆括号()和方括号[]访问。

上述的元素访问方法都通过断言检查范围,代价比较大。

通过定义EIGEN_NO_DEBUG 或 NDEBUG,取消断言。

通过使用coeff()和coeffRef(),来取消检查。比如,MatrixBase::coeff(int,int) const, MatrixBase::coeffRef(int,int)等。

创建固定大小的矩阵和向量

代码语言:javascript
复制
#include <iostream>
#include <Eigen/Core>

using namespace Eigen;  
using namespace std;  

int main(int, char *[])
{
  float value = 3.0;
  Matrix3f x; // 创建一个3x3的单精度矩阵
  x = Matrix3f::Zero(); //全零矩阵
  cout << x << endl << endl;
  x = Matrix3f::Ones(); //全一矩阵
  cout << x << endl << endl;
  x = Matrix3f::Constant(value); //全value矩阵
  cout << x << endl << endl;
  x = Matrix3f::Identity(); //单位矩阵
  cout << x << endl << endl;
  x = Matrix3f::Random(); // 随机矩阵
  cout << x << endl << endl;
  x.setZero();
  cout << x << endl << endl;
  x.setOnes();
  cout << x << endl << endl;
  x.setIdentity();
  cout << x << endl << endl;
  x.setConstant(value);
  cout << x << endl << endl;
  x.setRandom();
  cout << x << endl << endl;
}
创建动态大小的矩阵
代码语言:javascript
复制
#include <iostream>
#include <Eigen/Core>

using namespace Eigen;  
using namespace std;  

int main(int, char *[])
{
  float value = 3.0f;
  int rows = 3;
  int cols = 4;
  MatrixXf x;
  x = MatrixXf::Zero(rows, cols);
  cout << x << endl << endl;
  x = MatrixXf::Ones(rows, cols);
  cout << x << endl << endl;
  x = MatrixXf::Constant(rows, cols, value);
  cout << x << endl << endl;
  x = MatrixXf::Identity(rows, cols);
  cout << x << endl << endl;
  x = MatrixXf::Random(rows, cols);
  cout << x << endl << endl;
  x.setZero(rows, cols);
  cout << x << endl << endl;
  x.setOnes(rows, cols);
  cout << x << endl << endl;
  x.setConstant(rows, cols, value);
  cout << x << endl << endl;
  x.setIdentity(rows, cols);
  cout << x << endl << endl;
  x.setRandom(rows, cols);
  cout << x << endl << endl;
  return 0;
}
创建动态大小的向量
代码语言:javascript
复制
#include <iostream>
#include <Eigen/Core>

using namespace Eigen;  
using namespace std;  

int main(int, char *[])
{
  int size = 3;
  float value = 3.0f;
  VectorXf x; // 定义动态向量
  x = VectorXf::Zero(size); //全0向量
  cout << x << endl << endl;
  x = VectorXf::Ones(size); //全1向量
  cout << x << endl << endl;
  x = VectorXf::Constant(size, value);//全value向量
  cout << x << endl << endl;
  //x = VectorXf::Identity(size);//报错
  x = VectorXf::Random(size);
  cout << x << endl << endl;
  x.setZero(size);
  cout << x << endl << endl;
  x.setOnes(size);
  cout << x << endl << endl;
  x.setConstant(size, value);
  cout << x << endl << endl;
  //x.setIdentity(size);
  x.setRandom(size);
  cout << x << endl << endl;
  return 0;
}
创建固定大小的基向量
代码语言:javascript
复制
#include <iostream>
#include <Eigen/Core>

using namespace Eigen;  
using namespace std;  

int main(int, char *[])
{
  Vector3f x;
  x = Vector3f::UnitX(); // 1 0 0
  cout << x << endl << endl;
  x = Vector3f::UnitY(); // 0 1 0
  cout << x << endl << endl;
  x = Vector3f::UnitZ(); // 0 0 1
  cout << x << endl << endl;

  return 0;
}
创建动态大小的基向量
代码语言:javascript
复制
#include <iostream>
#include <Eigen/Core>

using namespace Eigen;  
using namespace std;  

int main(int, char *[])
{
  VectorXf x;
  x = VectorXf::Unit(4,1);
  cout << x << endl << endl;
  x = Vector4f(0,1,0,0);
  cout << x << endl << endl;
  x = Vector4f::UnitY();
  cout << x << endl << endl;

  return 0;
}
通过Cast的方式初始化
相同尺寸的矩阵兼容

元素类型通过MatrixBase::cast()自动转换。

代码语言:javascript
复制
#include <iostream>
#include <Eigen/Core>
#include <Eigen/Eigen>

using namespace Eigen;  
using namespace std;  

int main(int, char *[])
{
  Vector3d md(1,2,3);
  Vector3f mf = md.cast<float>();
  cout << "md = " << md << endl;
  cout << "mf = " << mf << endl;
  return 0;
}
相同类型的矩阵兼容
代码语言:javascript
复制
#include <iostream>
#include <Eigen/Core>

using namespace Eigen;  
using namespace std;  

int main(int, char *[])
{
  MatrixXf res(10,10);
  Matrix3f a, b;
  a = Matrix3f::Identity();
  b = Matrix3f::Constant(3);
  res = a+b; // OK: res is resized to size 3x3

  cout << a << endl << endl;
  cout << b << endl << endl;
  cout << res << endl << endl;
  return 0;
}
通过Map方式初始化
代码语言:javascript
复制
#include <iostream>
#include <vector>
#include <Eigen/Core>

using namespace Eigen;  
using namespace std;  

int main(int, char *[])
{
  std::vector<float> stlarray(10);
  VectorXf::Map(&stlarray[0], stlarray.size()).squaredNorm();

  return 0;
}
通过逗号初始化
代码语言:javascript
复制
#include <iostream>
#include <vector>
#include <Eigen/Core>

using namespace Eigen;  
using namespace std;  

int main(int, char *[])
{
  Matrix3f m;
  m << 1, 2, 3,
    4, 5, 6,
    7, 8, 9;
  cout << m << endl;
  return 0;
}

使用逗号和子矩阵,初始化矩阵。

代码语言:javascript
复制
#include <iostream>
#include <vector>
#include <Eigen/Core>

using namespace Eigen;  
using namespace std;  

int main(int, char *[])
{
  int rows=5, cols=5;
  MatrixXf m(rows,cols);
  m << (Matrix3f() << 1, 2, 3, 4, 5, 6, 7, 8, 9).finished(),//左上角3x3
    MatrixXf::Zero(3,cols-3), //右上角3x2
    MatrixXf::Zero(rows-3,3), //左下角2x3
    MatrixXf::Identity(rows-3,cols-3); //右下角2x2

  cout << m << endl;
  return 0;
}
  • .finished()用于当临时矩阵初始化完成时,获取实际的矩阵对象。尽管看起来很复杂,但实际上编译时已经优化。

算术操作

传统的数学运算

矩阵/向量乘法:

代码语言:javascript
复制
col2 = mat1 * col1; //矩阵x列向量
row2 = row1 * mat1;  // 行向量x矩阵
row1 *= mat1;
mat3 = mat1 * mat2; 
mat3 *= mat1;

矩阵/向量加法/减法:

代码语言:javascript
复制
mat3 = mat1 + mat2; 
mat3 += mat1;
mat3 = mat1 - mat2; 
mat3 -= mat1;

标量加法/减法:

代码语言:javascript
复制
mat3 = mat1 * s1; 
mat3 = s1 * mat1; 
mat3 *= s1;
mat3 = mat1 / s1; 
mat3 /= s1;
逐元素的操作

逐元素的操作,请查阅.cwise()

逐元素乘法

代码语言:javascript
复制
mat3 = mat1.cwise() * mat2;

加/减标量

代码语言:javascript
复制
//需要Array模块 #include <Eigen/Array>
mat3 = mat1.cwise() + scalar;
mat3.cwise() += scalar;
mat3.cwise() -= scalar;

逐元素除法

代码语言:javascript
复制
//需要Array模块 #include <Eigen/Array>
mat3 = mat1.cwise() / mat2;

逐元素取倒数

代码语言:javascript
复制
//需要Array模块 #include <Eigen/Array>
mat3 = mat1.cwise().inverse();

逐元素比较运算

代码语言:javascript
复制
//需要Array模块 #include <Eigen/Array>
mat3 = mat1.cwise() < mat2;
mat3 = mat1.cwise() <= mat2;
mat3 = mat1.cwise() > mat2;
//等

三角余弦

sin(), cos()等。

代码语言:javascript
复制
//需要Array模块 #include <Eigen/Array>
mat3 = mat1.cwise().sin();
// 等

指数

  • pow(), square(), cube(), sqrt(), exp(), log()等
代码语言:javascript
复制
//需要Array模块 #include <Eigen/Array>
mat3 = mat1.cwise().square();
mat3 = mat1.cwise().pow(5);
mat3 = mat1.cwise().log();
//等

最小值,最大值,绝对值

代码语言:javascript
复制
mat3 = mat1.cwise().min(mat2);
mat3 = mat1.cwise().max(mat2);
mat3 = mat1.cwise().abs();
mat3 = mat1.cwise().abs2();

各种乘法运算

矩阵乘法:m1*m2

逐元素乘法:mat1.cwise()*mat2

点积:scalar = vec1.dot(vec2);

外积:mat = vec1 * vec2.transpose();

交叉积:#include <Eigen/Geometry> vec3 = vec1.cross(vec2);

逐元素操作示例:

代码语言:javascript
复制
#include <iostream>
#include <vector>
#include <Eigen/Eigen>

using namespace Eigen;  
using namespace std;  

int main(int, char *[])
{
  Matrix3f x, y;
  x << 5,3,1,2,-7,8,9,-4,6;
  y << 5,3,1,2,-7,8,9,4,7;
  cout << x << endl << endl;
  cout << x.cwiseAbs() << endl << endl;//绝对值
  cout << x.cwiseAbs2() << endl << endl; //平方
  cout << x.cwiseEqual(y) << endl << endl; //是否相等
  cout << x.cwiseMax(y) << endl << endl; //逐元素最大值
  cout << x.cwiseMin(y) << endl << endl;
  cout << x.cwiseInverse() << endl << endl; //倒数
  cout << x.cwiseNotEqual(y) << endl << endl; //不相等
  cout << x.cwiseProduct(y) << endl << endl; //逐元素乘法
  cout << x.cwiseQuotient(y) << endl << endl; //除法
  cout << x.cwiseSqrt() << endl << endl; //
  return 0;
}

Reductions

Eigen提供了一些reduction方法:minCoeff() , maxCoeff() , sum() , trace() , norm() , squaredNorm() , all() , 和 any()。

上述这些方法都可以逐列或逐行的执行。如下所示:

代码语言:javascript
复制
#include <iostream>
#include <vector>
#include <Eigen/Core>

using namespace Eigen;  
using namespace std;  

int main(int, char *[])
{
  Matrix3f x;
  x << 5,3,1,2,7,8,9,4,6;
  cout << x.minCoeff() << endl;
  cout << x.colwise().minCoeff() << endl;
  cout << x.rowwise().minCoeff() << endl;

  return 0;
}

maxCoeff()和minCoeff()函数可以通过设置可选参数,返回最大/小值的位置:maxCoeff(int* i, int* j) , minCoeff(int* i, int* j) 。

all() 和 any()在使用逐元素操作时,非常有用。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-11-03,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 小白学视觉 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 固定大小的矩阵和和向量
  • 动态大小的矩阵和向量
  • 矩阵和向量类型
  • 访问元素
    • 创建动态大小的矩阵
      • 创建动态大小的向量
        • 创建固定大小的基向量
          • 创建动态大小的基向量
            • 通过Cast的方式初始化
              • 相同尺寸的矩阵兼容
              • 相同类型的矩阵兼容
            • 通过Map方式初始化
              • 通过逗号初始化
              • 算术操作
                • 传统的数学运算
                  • 逐元素的操作
                  领券
                  问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档