视觉SLAM十四讲-高翔 ch3

前言

第三章介绍了三维空间刚体运动,包括数理基础和程序实现。
个人认为最难啃的部分是数理基础。在读书的时候发觉上学期学的线代基本忘光了(明明感觉当时考的还不赖来着o(╥﹏╥)o)
但正好借此机会复习+实践学过的数学知识,能够把理论应用起来也挺好的。
不过也多亏上学期看的3b1b的《线性代数的本质》让我能够理解矩阵左乘对空间变换的意义(推荐看b站up主汉语配音的)
这一章啃了大概两天半才啃完(还没看带星号的部分)(包括复习上学期线代的时间)终于可以看下一章了!

代码

这次大部分知识点都写在代码注释里了。文字总结。。。以后再说吧

实践1:

#include<iostream>
#include<ctime>

using namespace std;

#include<Eigen/Core>
#include<Eigen/Dense>  //Eigen头文件,包含Eigen库里所有的类

#define MATRIX_SIZE 50;

int main( int argc, char** argv){

    Eigen::Matrix<float, 2, 3> matrix_23;//float类型的 2*3矩阵

    Eigen::Vector3d v_3d;//列向量 

    Eigen::Matrix3d matrix_33 = Eigen::Matrix3d::Zero();
/*
Matrix3d:Eigen库中typedef的数据类型,即“3*3矩阵(d表示矩阵内部数据类型为double类型)”

rotation_matrix:该3*3矩阵的变量名
*/

    Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic > matrix_dynamic;

    Eigen::MatrixXd matrix_x;
/*
动态矩阵在编译的时候不知道其大小,需要在运行的时候才能确定其大小。
typedef Matrix <double,Dynamic,Dynamic> MatrixXd;
例如我们可以这样定义一个动态矩阵:

MatrixXd m(3,4) ;  // 指定矩阵大小为3X4,也可以不指定

*/

    matrix_23 << 1, 2, 3, 4, 5, 6;

    //逗号初始化:
/*
  Eigen提供了一种逗号初始化器语法,该语法使用户可以轻松设置矩阵,向
量或数组的所有系数。只需列出系数,从左上角开始,从左到右,从上到下
移动。需要预先指定对象的大小。如果列出的系数太少或太多,编译器就会报错。
  此外,初始化列表的元素本身可以是向量或矩阵。通常的用途是将向量或矩
阵连接在一起。请记住,必须先设置大小,然后才能使用逗号初始化程序。

*/
    cout<< matrix_23 << endl;//Eigen重载了<<运算符,可直接输出矩阵的值
/*
重载运算符是指在C++中可以为已有的运算符重新定义新的行为。重载运算符的操作数至少
有一个是用户定义的类型,并且不能违反运算符原来的语法规则。需要注意的是,不能创建新
的运算符,而且有一些运算符是不能被重载的,例如sizeof。另外,=、()、[]、->操作符
只能被类的成员函数重载。
*/

    for(int i=0; i<1;i++)
        for(int j=0;j<2;j++)
            cout<<matrix_23(i,j)<<endl;//matrix_23(i,j)表示i行j列
    v_3d<< 3,2,1;
    Eigen::Matrix<double, 2, 1> result = matrix_23.cast<double>() * v_3d;//cast将矩阵里的值的类型都转换成了double
    cout <<endl<<result << endl;
/* 矩阵和向量相乘(实际上仍是矩阵和矩阵)
   但是在这里你不能混合两种不同类型的矩阵,像这样是错的(matrix_23的值是float类型,v_3d的是double类型)
   Eigen::Matrix<double, 2, 1> result_wrong_type = matrix_23 * v_3d;
*/  
    Eigen::Matrix<double, 2, 1> result_wrong_type = matrix_23 * v_3d;
    matrix_33 = Eigen::Matrix3d::Random();
    cout<<matrix_33<<endl<<endl<<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() <<endl<<endl<<endl;

    Eigen::SelfAdjointEigenSolver<Eigen::Matrix3d> eigen_solver (matrix_33.transpose()*matrix_33);
    cout<< "Eigen values = " << eigen_solver.eigenvalues() <<endl;
    cout<< "Eigen vectors = " << eigen_solver.eigenvectors() <<endl;


    
    return 0;
}

实践2:

#include<iostream>
#include<cmath>
using namespace std;

#include<Eigen/Core>
#include<Eigen/Geometry>//此模块提供了各种旋转和平移的表示

// 几何模块的用法

int main(){

    //3d旋转矩阵直接使用Matrix3d或matrix3f
    Eigen::Matrix3d rotation_matrix = Eigen::Matrix3d::Identity();
    //Matrix3d::Identity():在定义该矩阵变量时,创建一个同尺寸同数据类型的单位阵,对其初始化。
    //线性代数有时把单位阵用I表示,应该就取自Identity的首字母吧? 

    //旋转向量使用AngleAxis,它底层不直接是 Matrix ,但运算可以当作矩阵(因为重载了运算符)
    Eigen::AngleAxisd rotation_vector (M_PI/4, Eigen::Vector3d (0,0,1));//沿Z轴旋转45°
    cout .precision(3);
/*
    代表有效数字是3位
    想要保留有效的数据位数,通过cout.precision(var);   var 代表有效位数
*/

    cout<<"rotation matrix =\n"<<rotation_vector.matrix()<<endl;//用.matrix()转换成矩阵
    rotation_matrix = rotation_vector;

    rotation_matrix = rotation_vector.toRotationMatrix();
    //用旋转向量给旋转矩阵赋值

    Eigen::Vector3d v (1,0,0);
    Eigen::Vector3d v_rotated = rotation_vector * v;//用旋转向量表示旋转 


    cout<<"(1,0,0) after rotation ="<<v_rotated.transpose()<<endl;
    
    v_rotated = rotation_matrix * v;//用旋转矩阵表示旋转.
    cout<<"(1,0,0) after rotation ="<<v_rotated.transpose()<<endl;

    //可用旋转矩阵直接转换成欧拉角    
    Eigen::Vector3d euler_angles = rotation_matrix.eulerAngles( 2,1,0 );//按ZYX顺序转   euler即欧拉

    cout<<"yaw pitch roll = "<<euler_angles.transpose()<<endl;//为什么去掉.transpose()就编译错误????

    //欧氏变换矩阵使用Eigen::Isometry3d
    Eigen::Isometry3d T=Eigen::Isometry3d::Identity();//虽为3d,实际上是 4*4
    T.rotate (rotation_vector) ;//按照rotation_vector进行旋转
    T.pretranslate(Eigen::Vector3d ( 1,3,4 ) );//按照( 1,3,4 )进行平移
    cout << "Transform matrix = \n"<< T.matrix()<<endl;
    
    //用变换矩阵进行坐标变换
    Eigen::Vector3d v_transformed = T*v;
    cout<<"v transformed = "<<v_transformed.transpose()<<endl;

    //四元数
    //可以直接把AngleAxis赋值给四元数,反之亦然
    Eigen::Quaterniond q = Eigen::Quaterniond (rotation_vector);
    cout<<"quaternion = \n"<<q.coeffs()<<endl;//coeffs的顺序是(x,y,z,w),w为实部,x、y、z为虚部
    
    //亦可将旋转矩阵赋给它
    q = Eigen::Quaterniond( rotation_matrix );
    cout<<"quaternion = \n"<<q.coeffs()<<endl;

    //使用四元数旋转一个向量,使用重载的乘法即可
    v_rotated = q*v;// 数学上是qvq^{-1}
    cout<<"(1,0,0) after rotation = "<<v_rotated.transpose()<<endl;


    return 0;
}
/*

Eigen 中对各种形式的表达方式总结如下。请注意每种类型都有单精度和双精度两种
数据类型,而且和之前一样,不能由编译器自动转换。下面以双精度为例,你可以把最后
的 d 改成 f,即得到单精度的数据结构。
• 旋转矩阵(3 × 3)
:Eigen::Matrix3d。
• 旋转向量(3 × 1)
:Eigen::AngleAxisd。
• 欧拉角(3 × 1)
:Eigen::Vector3d。
• 四元数(4 × 1)
:Eigen::Quaterniond。
• 欧氏变换矩阵(4 × 4)
:Eigen::Isometry3d。
• 仿射变换(4 × 4)
:Eigen::Affine3d。
• 射影变换(4 × 4)
:Eigen::Projective3d。

*/

遗留问题:

第三章有一个可视化的程序需要pangolin,但在编译安装pangolin的源代码时报错:

error: ‘PixelFormat’ does not name a type; did you mean ‘AVPixelFormat’?
PixelFormat fmtout;
^~~~~~~~~~~

根据qin__han的帖子修改代码后编译成功,但找不到可执行文件。尚未解决此问题

### 回答1: 《视觉SLAM十四》第三章主要介绍了视觉SLAM中的关键技术——特征提取和描述子。本章首先介绍了特征点的概念和特征点的选择原则。特征点即图像中具有鲁棒性和区分度的点,可以通过对其进行检测和描述来进行特征匹配和跟踪。在进行特征提取时,作者介绍了常见的特征检测算法,如Harris角点检测、SIFT和SURF算法等,并对其进行了比较和分析。 接着,本章详细阐述了特征描述子的概念和作用。特征描述子是对特征点周围区域的图像信息进行编码,以实现特征匹配和跟踪。常见的特征描述子包括SIFT、SURF和ORB等。作者从描述子的表示形式、计算方式和匹配方法等方面进行了介绍,并对它们进行了比较和评价。同时,还提到了基于二进制描述子的方法,如BRIEF、BRISK和FREAK等。 在特征匹配方面,本章介绍了特征描述子匹配的基本原理和流程。以基于特征点的视觉SLAM为例,作者详细解释了特征点的匹配过程,包括特征点的选择、特征点描述子匹配和筛选等步骤。并介绍了如何通过验证特征点的三角化和PnP求解来估计相机的位姿。 此外,本章还介绍了一些特定场景下的特征点选择和提取策略,如动态环境下的特征点追踪和关键帧选择等。 综上所述,《视觉SLAM十四》第三章主要介绍了特征提取和描述子在视觉SLAM中的重要性和应用。通过对特征点的检测和描述,可以实现特征匹配和跟踪,为后续的相机位姿估计和建图提供基础。该章内容详细且通俗易懂,对于学习和理解视觉SLAM有着重要的指导作用。 ### 回答2: 《视觉SLAM十四-Ch3》主要介绍了视觉SLAM(同时定位与建图)技术的基本原理和实现方法。本章主要涵盖了三维几何表示和变换、相机模型和相机姿态以及特征提取与匹配等内容。 首先,本章介绍了三维几何表示和变换的概念。通过介绍欧氏空间中的点、向量和坐标变换,深入解释了相机在三维空间中的位置和朝向的表示方式。同时,引入了齐次坐标和投影矩阵的概念,为后续的相机模型和姿态估计打下了基础。 其次,本章详细解了相机模型和相机姿态的原理与应用。其中,介绍了针孔相机模型,分析了图像坐标和相机坐标之间的映射关系。通过投影矩阵的推导,给出了透视投影和仿射投影的公式,并解释了相机焦距和主点的含义。此外,还介绍了如何通过计算相机的外参矩阵来估计相机的姿态,以及如何将图像坐标转换为相机坐标。 最后,本章介绍了特征提取与匹配的技术。首先,介绍了角点和边缘点的概念,以及如何利用差分和梯度计算来检测图像中的角点和边缘点。然后,介绍了如何通过特征描述符来表示图像中的特征点,并通过特征匹配算法找到两幅图像之间的对应关系。特征提取与匹配是视觉SLAM中非常重要的步骤,对于后续的相机定位和建图至关重要。 综上所述,《视觉SLAM十四-Ch3》通过系统地介绍了视觉SLAM技术的基本概念和实现方法,包括三维几何表示和变换、相机模型和相机姿态的原理与应用,以及特征提取与匹配的技术。这些内容为读者深入理解和掌握SLAM技术提供了很好的基础。 ### 回答3: 视觉SLAM(Simultaneous Localization and Mapping)是一种通过计算机视觉技术,实现机器智能的同时实时定位和地图构建的方法。在《视觉SLAM十四》第三中,主要介绍了视觉SLAM的基本概念和关键技术。 首先,解了视觉SLAM的理论基础,包括自我运动估计和地图构建两个部分。自我运动估计是通过相邻帧之间的视觉信息,计算相机在三维空间中的运动,从而实现机器的实时定位;地图构建是通过对场景中特征点的观测和跟踪,建立起一个三维空间中的地图。这两个过程相互影响,通过不断迭代优化,实现高精度的定位和地图构建。 接着,解了基于特征的视觉SLAM算法。特征提取与描述是建立视觉SLAM系统的关键步骤,通过提取场景中的特征点,并为其生成描述子,来实现特征点的匹配和跟踪。同时,还介绍了一些常用的特征点提取和匹配算法,如FAST、SIFT等。 在SLAM框架方面,本节还介绍了基于视觉的前端和后端优化。前端主要负责实时的特征跟踪和估计相机运动,后端则是通过优化技术,对前端输出的轨迹和地图进行优化求解,从而提高系统的精度和鲁棒性。 最后,本节提到了几个视觉SLAM的应用场景,如自主导航、增强现实等。这些应用对于实时高精度的定位和地图建立都有着很高的要求,因此,视觉SLAM的技术在这些领域有着广泛的应用前景。 总的来说,《视觉SLAM十四》第三视觉SLAM的基本概念和关键技术进行了系统的介绍。理论基础、特征提取与描述、SLAM框架和应用场景等方面的内容都给出了详细的解释和案例,有助于读者更好地理解和应用视觉SLAM技术。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值