视觉SLAM十四讲理论与实践习题(二)

文章介绍了Eigen库在矩阵运算中的QR分解和Cholesky分解方法,以及如何使用这些方法求解线性方程组和进行几何变换,如正交矩阵的性质和单位正交基向量的表示。
2 熟悉Eigen矩阵运算
  1. x x x有解且唯一 ⇔ \Leftrightarrow r ( A ) = r ( A ∣ b ) = n r(A)=r(A|b)=n r(A)=r(Ab)=n
  2. 首先,将方程组未知数系数通过消元变换为上三角矩阵。
    其次,使用回带法,根据上三角矩阵特点,得出方程的解
  3. QR方法是用于求解矩阵所有特征值的算法,QR分解就是把矩阵分解成一个正交矩阵和一个上三角矩阵。
  4. Cholesky 分解是把一个对称正定的矩阵表示成一个下三角矩阵L和其转置的乘积的分解。它要求矩阵的所有特征值必须大于零,故分解的下三角的对角元也是大于零的。Cholesky分解法又称平方根法,是当A为实对称正定矩阵时,LU三角分解法的变形。
#include <iostream>

using namespace std;

#include <ctime>
// Eigen 核心部分
#include <Eigen/Core>
// 稠密矩阵的代数运算(逆,特征值等)
#include <Eigen/Dense>

using namespace Eigen;

#define MATRIX_SIZE 100

int main(int argc, char** argv) {
    Matrix<double, Dynamic, Dynamic> matrix_NN
        = MatrixXd::Random(MATRIX_SIZE, MATRIX_SIZE);
    matrix_NN = matrix_NN * matrix_NN.transpose();  // 保证半正定
    Matrix<double, Dynamic, 1> v_Nd = MatrixXd::Random(MATRIX_SIZE, 1);
    VectorXd x(100);

    // 通常用矩阵分解来求,例如QR分解,速度会快很多
    x = matrix_NN.colPivHouseholderQr().solve(v_Nd);
    cout << "x = " << x.transpose() << endl;

    return 0;
}
3 几何运算练习
#include <iostream>
#include <vector>

#include <algorithm>

#include <Eigen/Core>
#include <Eigen/Geometry>

using namespace std;
using namespace Eigen;

int main(int argc, char** argv) {
    Quaterniond q1(0.55, 0.3, 0.2, 0.2), q2(-0.1, 0.3, -0.7, 0.2);
    q1.normalize();
    q2.normalize();
    Vector3d t1(0.7,1.1,0.2),t2(-0.1,0.4,0.8);
    Vector3d p1(0.5,-0.1,0.2);

    Isometry3d T1w(q1),T2w(q2);

    T1w.pretranslate(t1);
    T2w.pretranslate(t2);

    Vector3d p2=T2w*T1w.inverse()*p1;
    cout<<endl<<p2.transpose()<<endl;

    return 0;
}

在这里插入图片描述

  1. 前置知识:
  • 单位正交基
  • 向量的坐标:设 η 1 , η 2 , . . . η k {\eta _1},{\eta _2},{...\eta _k} η1,η2,...ηk V V V的一个基,则 V V V的每个元素 α \alpha α都可以用 η 1 , η 2 , . . . η k {\eta _1},{\eta _2},{...\eta _k} η1,η2,...ηk唯一线性表示:
    α = c 1 η 1 + c 2 η 2 + . . . + c k η k \alpha = c_1{\eta _1}+c_2{\eta _2}+{...+c_k\eta _k} α=c1η1+c2η2+...+ckηk
    称其中的系数 c 1 , c 2 , . . . , c k c_1,c_2,...,c_k c1,c2,...,ck α \alpha α关于基 η 1 , η 2 , . . . η k {\eta _1},{\eta _2},{...\eta _k} η1,η2,...ηk的坐标,它是一个 k k k维向量。
  • 正交矩阵: A A T = I AA^T=I AAT=I
    在这里插入图片描述
    R R T = I RR^T=I RRT=I两边取行列式,有 ∣ R ∣ 2 = 1 |R|^2=1 R2=1。故 R R R的行列式等于正负1,认为规定旋转矩阵行列式为1

参考:https://blog.youkuaiyun.com/lhxez6868/article/details/100165447

### 关于《视觉SLAM十四》第版第三习题答案解析 #### 一、关于第三习题的内容概述 《视觉SLAM十四》第版第三主要围绕相机模型展开讨论,涉及针孔相机模型、畸变校正等内容。习题通常会要求读者通过理论推导和实际操作加深对这些概念的理解。 以下是针对该章节可能涉及的典型问题及其解析: --- #### 、具体题目分析解答 ##### 题目1:解释针孔相机模型中的参数含义,并说明如何利用这些参数完成图像坐标系到世界坐标系的转换。 针孔相机模型的核心在于描述空间点其在成像平面上投影之间的关系。其基本方程可以表示为: \[ \begin{bmatrix} u \\ v \\ 1 \end{bmatrix} = K \cdot [R | t] \cdot \begin{bmatrix} X_w \\ Y_w \\ Z_w \\ 1 \end{bmatrix}, \] 其中 \(K\) 是内参矩阵,\(R\) 和 \(t\) 分别代表旋转和平移向量[^1]。 - **内参矩阵 \(K\)** 包含焦距 \(f_x, f_y\) 和主点偏移 \(c_x, c_y\),用于定义相机内部几何特性。 - **外参矩阵 \([R|t]\)** 描述了相机相对于世界坐标系的姿态和位置。 为了实现从世界坐标系到图像坐标的映射,需依次应用上述变换过程。反之,则可通过求解逆矩阵来恢复世界坐标。 ```python import numpy as np def project_points(K, R, t, points_world): """ 将世界坐标系下的点投影至图像平面。 参数: K (np.ndarray): 内参矩阵 (3x3). R (np.ndarray): 旋转矩阵 (3x3). t (np.ndarray): 平移向量 (3x1). points_world (np.ndarray): 世界坐标系下点集 (Nx3). 返回: image_coords (np.ndarray): 图像坐标系下点集 (Nx2). """ P = np.hstack((R, t)) @ np.vstack((points_world.T, np.ones((1, points_world.shape[0])))) uvw = K @ P uv = uvw[:2, :] / uvw[2:, :] return uv.T ``` --- ##### 题目2:设计实验验证径向畸变的影响并尝试对其进行矫正。 径向畸变是一种常见的镜头失真现象,表现为直线在成像过程中发生弯曲。可以通过多项式形式建模: \[ x_{distorted} = x(1 + k_1r^2 + k_2r^4), \quad y_{distorted} = y(1 + k_1r^2 + k_2r^4). \] 纠正方法包括获取合适的畸变系数 (\(k_1, k_2\)) 及重新计算无畸变后的像素位置。 代码示例如下所示: ```python def undistort_point(x_distorted, y_distorted, k1, k2): r_squared = x_distorted**2 + y_distorted**2 correction_factor = 1 + k1 * r_squared + k2 * r_squared**2 x_corrected = x_distorted / correction_factor y_corrected = y_distorted / correction_factor return x_corrected, y_corrected ``` --- ##### 题目3:基于标定板数据估算相机内参。 此部分实践性强,推荐使用 OpenCV 提供的相关工具函数 `cv2.calibrateCamera` 完成自动化标定流程[^4]。输入条件应包含多组拍摄图片中标定点的真实三维坐标及对应维投影坐标。 调用方式如下: ```python import cv2 criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001) objp = np.zeros((6*9, 3), np.float32) objp[:, :2] = np.mgrid[0:9, 0:6].T.reshape(-1, 2) # 储存每张图的世界坐标图像坐标 objpoints = [] imgpoints = [] for fname in images: img = cv2.imread(fname) gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) ret, corners = cv2.findChessboardCorners(gray, (9, 6), None) if ret: objpoints.append(objp) refined_corners = cv2.cornerSubPix(gray, corners, (11, 11), (-1, -1), criteria) imgpoints.append(refined_corners) ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, gray.shape[::-1], None, None) print("Intrinsic Matrix:\n", mtx) ``` --- #### 三、总结 以上是对《视觉SLAM十四》第版第三习题的部分解析。需要注意的是,实际动手能力对于掌握 SLAM 技术至关重要,建议配合真实设备开展更多探索性工作。 --- ####
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值