深蓝学院视觉slam十四讲第4章作业

在这里插入图片描述

cmake_minimum_required(VERSION 3.10)
project(UndistortImg)

set(CMAKE_BUILD_TYPE "Release")
set(CMAKE_CXX_FLAGS "-std=c++11 -O2")
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/bin)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/lib)

# 寻找OpenCV库
find_package(OpenCV REQUIRED)
# 添加头文件
include_directories(${OpenCV_INCLUDE_DIRS})

add_executable(UndistortImg undistort_image.cpp)
target_link_libraries(UndistortImg ${OpenCV_LIBS})
#include <opencv2/opencv.hpp>
#include <string>

using namespace std;

string image_file = "../test.png";   // 请确保路径正确

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

    // 本程序需要你自己实现去畸变部分的代码。尽管我们可以调用OpenCV的去畸变,但自己实现一遍有助于理解。
    // 畸变参数
    double k1 = -0.28340811, k2 = 0.07395907, p1 = 0.00019359, p2 = 1.76187114e-05;
    // 内参
    double fx = 458.654, fy = 457.296, cx = 367.215, cy = 248.375;

    cv::Mat image = cv::imread(image_file,0);   // 图像是灰度图,CV_8UC1
    int rows = image.rows, cols = image.cols;
    cv::Mat image_undistort = cv::Mat(rows, cols, CV_8UC1);   // 去畸变以后的图

    // 计算去畸变后图像的内容
    for (int v = 0; v < rows; v++)
        for (int u = 0; u < cols; u++) {

            double u_distorted = 0, v_distorted = 0;
            // TODO 按照公式,计算点(u,v)对应到畸变图像中的坐标(u_distorted, v_distorted) (~6 lines)
            // start your code here
            double x = (u - cx) / fx, y = (v - cy) / fy;
            double r = sqrt(x * x + y * y);
            double x_distorted = x * (1 + k1 * r * r + k2 * r * r * r * r) + 2 * p1 * x * y + p2 * (r * r + 2 * x * x);
            double y_distorted = y * (1 + k1 * r * r + k2 * r * r * r * r) + p1 * (r * r + 2 * y * y) + 2 * p2 * x * y;
            u_distorted = fx * x_distorted + cx;
            v_distorted = fy * y_distorted + cy;
            // end your code here

            // 赋值 (最近邻插值)
            if (u_distorted >= 0 && v_distorted >= 0 && u_distorted < cols && v_distorted < rows) {
                image_undistort.at<uchar>(v, u) = image.at<uchar>((int) v_distorted, (int) u_distorted);
            } else {
                image_undistort.at<uchar>(v, u) = 0;
            }
        }

    // 画图去畸变后图像
    cv::imshow("image undistorted", image_undistort);
    cv::waitKey();
    cv::imwrite("undistorted.jpg", image_undistort);

    return 0;
}

运行结果:
在这里插入图片描述
在这里插入图片描述

cmake_minimum_required(VERSION 3.10)
project(Disparity)

set(CMAKE_BUILD_TYPE "Release")
set(CMAKE_CXX_FLAGS "-std=c++11 -O2")
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/bin)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/lib)

find_package(OpenCV REQUIRED)
find_package(Pangolin REQUIRED)
include_directories("/usr/include/eigen3" ${OpenCV_INCLUDE_DIRS} ${Pangolin_INCLUDE_DIRS})

add_executable(Disparity disparity.cpp)
target_link_libraries(Disparity ${OpenCV_LIBS} ${Pangolin_LIBRARIES})
#include <opencv2/opencv.hpp>
#include <string>
#include <Eigen/Core>
#include <pangolin/pangolin.h>
#include <unistd.h>

using namespace std;
using namespace Eigen;

// 文件路径,如果不对,请调整
string left_file = "../left.png";
string right_file = "../right.png";
string disparity_file = "../disparity.png";

// 在panglin中画图,已写好,无需调整
void showPointCloud(const vector<Vector4d, Eigen::aligned_allocator<Vector4d>> &pointcloud);

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

    // 内参
    double fx = 718.856, fy = 718.856, cx = 607.1928, cy = 185.2157;
    // 间距
    double d = 0.573;

    // 读取图像
    cv::Mat left = cv::imread(left_file, 0);
    cv::Mat right = cv::imread(right_file, 0);
//    cv::imshow("left", left);
//    cv::waitKey(0);

    cv::Mat disparity = cv::imread(disparity_file, 0); // disparty 为CV_8U,单位为像素

    // 生成点云
    vector<Vector4d, Eigen::aligned_allocator<Vector4d>> pointcloud;

    // TODO 根据双目模型计算点云
    // 如果你的机器慢,请把后面的v++和u++改成v+=2, u+=2
    for (int v = 0; v < left.rows; v++)
        for (int u = 0; u < left.cols; u++) {

            Vector4d point(0, 0, 0, left.at<uchar>(v, u) / 255.0); // 前三维为xyz,第四维为颜色

            // start your code here (~6 lines)
            // 根据双目模型计算 point 的位置
            double x = (u - cx) / fx;
            double y = (v - cy) / fy;
            double depth = fx * d / (disparity.at<char>(v, u));
            point[0] = x * depth;
            point[1] = y * depth;
            point[2] = depth;

            pointcloud.push_back(point);
            // end your code here
        }

    // 画出点云
    showPointCloud(pointcloud);
    return 0;
}

void showPointCloud(const vector<Vector4d, Eigen::aligned_allocator<Vector4d>> &pointcloud) {

    if (pointcloud.empty()) {
        cerr << "Point cloud is empty!" << endl;
        return;
    }

    pangolin::CreateWindowAndBind("Point Cloud Viewer", 1024, 768);
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

    pangolin::OpenGlRenderState s_cam(
            pangolin::ProjectionMatrix(1024, 768, 500, 500, 512, 389, 0.1, 1000),
            pangolin::ModelViewLookAt(0, -0.1, -1.8, 0, 0, 0, 0.0, -1.0, 0.0)
    );

    pangolin::View &d_cam = pangolin::CreateDisplay()
            .SetBounds(0.0, 1.0, pangolin::Attach::Pix(175), 1.0, -1024.0f / 768.0f)
            .SetHandler(new pangolin::Handler3D(s_cam));

    while (pangolin::ShouldQuit() == false) {
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        d_cam.Activate(s_cam);
        glClearColor(1.0f, 1.0f, 1.0f, 1.0f);

        glPointSize(2);
        glBegin(GL_POINTS);
        for (auto &p: pointcloud) {
            glColor3f(p[3], p[3], p[3]);
            glVertex3d(p[0], p[1], p[2]);
        }
        glEnd();
        pangolin::FinishFrame();
        usleep(5000);   // sleep 5 ms
    }
    return;
}

运行结果:
在这里插入图片描述

在这里插入图片描述在这里插入图片描述

4.1

d ( A x ) d x T = ∂ ( A x ) ∂ x T d x d x T = ∂ ( A x ) ∂ x T ⋅ I = A \frac {d(\mathbf A \mathbf x)}{d\mathbf x^T} =\frac{\frac {\partial(\mathbf A \mathbf x)}{\partial \mathbf x^T}d\mathbf x}{d\mathbf x^T} = \frac {\partial(\mathbf A \mathbf x)}{\partial \mathbf x^T} \cdot \mathbf I = \mathbf A dxTd(Ax)=dxTxT(Ax)dx=xT(Ax)I=A
d ( A x ) d x = A T \frac {d(\mathbf A \mathbf x)}{d\mathbf x} = \mathbf A^T dxd(Ax)=AT

4.2

d x T A x d x T = d x T A x + x T A d x d x T = x T A T d x + x T A d x d x T = x T ( A + A T ) \frac{d \mathbf{x}^T\mathbf{A}\mathbf{x}}{d \mathbf{x}^T} = \frac{ d\mathbf x^{T}\mathbf A\mathbf x + \mathbf x^{T}\mathbf Ad\mathbf x}{d \mathbf{x}^T} = \frac{ \mathbf x^{T}\mathbf A^{T} d \mathbf x + \mathbf x^{T}\mathbf Ad\mathbf x}{d \mathbf{x}^T} =\mathbf{x}^T(\mathbf{A}+ \mathbf{A}^T) dxTdxTAx=dxTdxTAx+xTAdx=dxTxTATdx+xTAdx=xT(A+AT)
d x T A x d x = d x T A x + x T A d x d x = d x T A x + d x T A T x d x = ( A + A T ) x \frac{d \mathbf{x}^T\mathbf{A}\mathbf{x}}{d \mathbf{x}}= \frac{ d\mathbf x^{T}\mathbf A\mathbf x + \mathbf x^{T}\mathbf Ad\mathbf x}{d \mathbf{x}} = \frac{ d\mathbf x^{T}\mathbf A\mathbf x + d\mathbf x^{T} \mathbf A^T \mathbf x}{d \mathbf{x}} = (\mathbf{A}+ \mathbf{A}^T)\mathbf{x} dxdxTAx=dxdxTAx+xTAdx=dxdxTAx+dxTATx=(A+AT)x

4.3

t r ( A x x T ) = t r ( [ a 11 a 12 … a 1 n a 21 a 22 … a 2 n ⋮ ⋮ ⋮ a n 1 a n 2 … a n n ] ⋅ [ x 1 x 2 ⋮ x n ] ⋅ [ x 1 ,   x 2 ,   … x n ] ) tr(\mathbf A \mathbf x\mathbf x^T)=tr\left(\begin{bmatrix} a_{11} & a_{12} & \dots & a_{1n} \\ a_{21} & a_{22} & \dots & a_{2n} \\ \vdots & \vdots & & \vdots \\ a_{n1} & a_{n2} & \dots & a_{nn} \\ \end{bmatrix} \cdot \begin{bmatrix} x_1 \\ x_2 \\ \vdots \\ x_n \end{bmatrix} \cdot[x_1,\ x_2,\ \dots x_n] \right) tr(AxxT)=tra11a21an1a12a22an2a1na2nannx1x2xn[x1, x2, xn]

= t r ( [ a 11 a 12 … a 1 n a 21 a 22 … a 2 n ⋮ ⋮ ⋮ a n 1 a n 2 … a n n ] ⋅ [ x 1 x 1 x 1 x 2 … x 1 x n x 2 x 1 x 2 x 2 … x n x n ⋮ ⋮ ⋮ x n x 1 x n x 2 … x n x n ] ) =tr\left(\begin{bmatrix} a_{11} & a_{12} & \dots & a_{1n} \\ a_{21} & a_{22} & \dots & a_{2n} \\ \vdots & \vdots & & \vdots \\ a_{n1} & a_{n2} & \dots & a_{nn} \\ \end{bmatrix}\cdot \begin{bmatrix} x_1x_1 & x_1x_2 & \dots & x_1x_n \\ x_2x_1 & x_2x_2 & \dots & x_nx_n \\ \vdots & \vdots & & \vdots \\ x_nx_1 & x_nx_2 & \dots & x_nx_n \\ \end{bmatrix}\right) =tra11a21an1a12a22an2a1na2nannx1x1x2x1xnx1x1x2x2x2xnx2x1xnxnxnxnxn

= ∑ i = 1 n a 1 i x i x 1 + ∑ i = 1 n a 2 i x i x 2 + ⋯ + ∑ i = 1 n a n i x i x n =\sum_{i=1}^n a_{1i}x_ix_1+\sum_{i=1}^n a_{2i}x_ix_2+\cdots +\sum_{i=1}^n a_{ni}x_ix_n =i=1na1ixix1+i=1na2ixix2++i=1nanixixn

= x 1 ∑ i = 1 n a 1 i x i + x 2 ∑ i = 1 n a 2 i x i + ⋯ + x n ∑ i = 1 n a n i x i =x_1\sum_{i=1}^n a_{1i}x_i+x_2\sum_{i=1}^n a_{2i}x_i+\cdots +x_n\sum_{i=1}^n a_{ni}x_i =x1i=1na1ixi+x2i=1na2ixi++xni=1nanixi

x T A x = [ x 1 ,   x 2 ,   … x n ] ⋅ [ a 11 a 12 … a 1 n a 21 a 22 … a 2 n ⋮ ⋮ ⋮ a n 1 a n 2 … a n n ] ⋅ [ x 1 x 2 ⋮ x n ] = [ x 1 ,   x 2 ,   … x n ] ⋅ [ ∑ i = 1 n a 1 i x i ∑ i = 1 n a 2 i x i ⋮ ∑ i = 1 n a n i x i ] = x 1 ∑ i = 1 n a 1 i x i + x 2 ∑ i = 1 n a 2 i x i + ⋯ + x n ∑ i = 1 n a n i x i \mathbf x^T\mathbf A\mathbf x= [x_1,\ x_2,\ \dots x_n] \cdot \begin{bmatrix} a_{11} & a_{12} & \dots & a_{1n} \\ a_{21} & a_{22} & \dots & a_{2n} \\ \vdots & \vdots & & \vdots \\ a_{n1} & a_{n2} & \dots & a_{nn} \\ \end{bmatrix} \cdot \begin{bmatrix} x_1 \\ x_2 \\ \vdots \\ x_n \end{bmatrix} =\\ [x_1,\ x_2,\ \dots x_n] \cdot \begin{bmatrix} \sum_{i=1}^n a_{1i}x_i \\ \sum_{i=1}^n a_{2i}x_i \\ \vdots \\ \sum_{i=1}^n a_{ni}x_i \end{bmatrix}=x_1\sum_{i=1}^n a_{1i}x_i+x_2\sum_{i=1}^n a_{2i}x_i+\cdots +x_n\sum_{i=1}^n a_{ni}x_i xTAx=[x1, x2, xn]a11a21an1a12a22an2a1na2nannx1x2xn=[x1, x2, xn]i=1na1ixii=1na2ixii=1nanixi=x1i=1na1ixi+x2i=1na2ixi++xni=1nanixi

所以得到 x T A x = t r ( A x x T ) \mathbf x^T\mathbf A\mathbf x=tr(\mathbf A\mathbf x\mathbf x^T) xTAx=tr(AxxT)

在这里插入图片描述

cmake_minimum_required(VERSION 3.10)
project(GaussNewton)

set(CMAKE_BUILD_TYPE "Release")#Release
set(CMAKE_CXX_FLAGS "-std=c++11 -O2")
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/bin)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/lib)

find_package(OpenCV REQUIRED)
include_directories("/usr/include/eigen3" ${OpenCV_INCLUDE_DIRS})
add_executable(GaussNewton gaussnewton.cpp)
target_link_libraries(GaussNewton ${OpenCV_LIBS} )
#include <iostream>
#include <opencv2/opencv.hpp>
#include <Eigen/Core>
#include <Eigen/Dense>

using namespace std;
using namespace Eigen;

int main(int argc, char **argv) {
    double ar = 1.0, br = 2.0, cr = 1.0;         // 真实参数值
    double ae = 2.0, be = -1.0, ce = 5.0;        // 估计参数值
    int N = 100;                                 // 数据点
    double w_sigma = 1.0;                        // 噪声Sigma值
    cv::RNG rng;                                 // OpenCV随机数产生器

    cout << "(x_data,y_data):" ;
    vector<double> x_data, y_data;      // 数据
    for (int i = 0; i < N; i++) {
        double x = i / 100.0;
        x_data.push_back(x);
        y_data.push_back(exp(ar * x * x + br * x + cr) + rng.gaussian(w_sigma));
        cout << "(" << x_data[i] << "," << y_data[i] << ") " ;
    }
    cout << endl ;

    // 开始Gauss-Newton迭代
    int iterations = 100;    // 迭代次数
    double cost = 0, lastCost = 0;  // 本次迭代的cost和上一次迭代的cost

    for (int iter = 0; iter < iterations; iter++) {

        Matrix3d H = Matrix3d::Zero();             // Hessian = J^T J in Gauss-Newton
        Vector3d b = Vector3d::Zero();             // bias
        cost = 0;

        for (int i = 0; i < N; i++) {
            double xi = x_data[i], yi = y_data[i];  // 第i个数据点
            // start your code here
            double error = 0;   // 第i个数据点的计算误差
            error = yi - exp(ae * xi * xi + be * xi + ce); // 填写计算error的表达式
            Vector3d J; // 雅可比矩阵
            J[0] = -xi * xi * exp(ae * xi * xi + be * xi + ce);  // de/da
            J[1] = -xi * exp(ae * xi * xi + be * xi + ce);  // de/db
            J[2] = -exp(ae * xi * xi + be * xi + ce);  // de/dc

            H += J * J.transpose(); // GN近似的H
            b += -error * J;
            // end your code here

            cost += error * error;
        }

        // 求解线性方程 Hx=b,建议用ldlt
 	// start your code here
        Vector3d dx = H.ldlt().solve(b);
	// end your code here

        if (isnan(dx[0])) {
            cout << "result is nan!" << endl;
            break;
        }

        if (iter > 0 && cost > lastCost) {
            // 误差增长了,说明近似的不够好
            cout << "cost: " << cost << ", last cost: " << lastCost << endl;
            break;
        }

        // 更新abc估计值
        ae += dx[0];
        be += dx[1];
        ce += dx[2];

        lastCost = cost;

        cout << "total cost: " << cost << endl;
    }

    cout << "estimated abc = " << ae << ", " << be << ", " << ce << endl;
    return 0;
}

运行结果:
在这里插入图片描述
在这里插入图片描述

6.1

H = [ 1 − 1 0 0 0 1 − 1 0 0 0 1 − 1 0 1 0 0 0 0 1 0 0 0 0 1 ] \bm{H} = \left[ {\begin{array}{cccc} 1&{ - 1}&0&0\\ 0&1&{ - 1}&0\\ 0&0&1&{ - 1}\\ \hline 0&1&0&0\\ 0&0&1&0\\ 0&0&0&1 \end{array}} \right] H=100000110100011010001001

6.2

W = d i a g ( Q 1 , Q 2 , Q 3 , R 1 , R 2 , R 3 ) \bm{W}=\mathrm{diag}(Q_1, Q_2, Q_3, R_1, R_2, R_3) W=diag(Q1,Q2,Q3,R1,R2,R3)

6.3

有唯一解:
x m a p ∗ = ( H T W − 1 H ) − 1 H T W − 1 z \bm{x}^*_{\mathrm{map}} = (\bm{H}^\mathrm{T} \boldsymbol{W}^{-1} \bm{H})^{-1} \bm{H}^\mathrm{T} \boldsymbol{W}^{-1} \bm{z} xmap=(HTW1H)1HTW1z

  • 7
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 《视觉SLAM十四》第二版PDF是一本关于视觉定位与地图构建技术的经典教材,由国内知名专家学者合作撰写而成。本书系统地介绍了基于视觉传感器的SLAM技术的各个方面,包括相机模型、图像特征提取、初始姿态估计、运动估计、地图构建、回环检测等。同时,本书还特别关注了SLAM方法的实际应用,解了多个真实场景下的SLAM应用案例,并介绍了如何使用OpenCV、G2O等开源工具实现SLAM算法。此外,本书还对SLAM技术的最新进展进行了介绍,如基于深度学习的特征提取与描述、多目标视觉SLAM、无人机视觉SLAM等。本书所涉及的内容深入浅出,既适合初学者入门,也适合高级研究人员深入了解SLAM技术的最新进展。该书是目前国内最权威、最全面的视觉SLAM入门教材之一,值得广大从事机器人、计算机视觉、机器人自主导航、无人机等相关领域的科研人员、工程师和学生学习使用。 ### 回答2: 《视觉SLAM十四第二版PDF》是一本关于算法技术的经典教材,主要介绍了SLAM技术的应用和原理。本教材全面详细地介绍了视觉SLAM的相关知识,从基础的数学知识开始,述了传感器、滤波、3D点云和视觉测量等原理,帮助读者逐步深入了解SLAM技术的实现过程。 此外,《视觉SLAM十四第二版PDF》还详细介绍了几种常用的视觉SLAM算法,包括基于特征匹配的视觉SLAM算法VFH、基于直接法的RGB-D SLAM算法和基于半稠密法的DSO算法。对于学习SLAM的人来说,这些算法的深入掌握能够让他们更好地理解SLAM的各种应用场景和内部原理。 此外,本教材还包括各种真实案例以及实验代码,帮助读者更好地了解SLAM技术的应用和实现方法。总体而言,对于想要深入了解SLAM技术和拓展相关应用的读者来说,《视觉SLAM十四第二版PDF》是一本经典的参考教材,具有极高的价值和实用性。 ### 回答3: 《视觉slam十四 第二版 pdf》是一本涉及到计算机视觉和机器人技术的重要书籍。这本书主要介绍了基于视觉技术的跟踪和定位算法SLAMSLAM是一种用来对无人机、自动驾驶汽车和机器人等进行实时建图、路径规划和导航的技术。 本书包括十四个主题,内容涉及相机模型、卡尔曼滤波器、非线性优化、回环检测等各个方面。这本书适合于计算机视觉和机器人领域的专业人员和学生,以及对这些领域感兴趣的人。 此外,本书不仅仅是介绍了SLAM算法,还对视觉slam的一些经典算法进行了详细的解,同时也包括最新的研究成果,以及许多高质量的实验结果和实际应用案例。 通过阅读这本书,读者将能够全面了解视觉slam技术的基础和应用,对理解和掌握slam算法具有很大的帮助和作用。除此之外,本书也是一个很好的参考工具,尤其适合从事相关技术研究和开发的人员。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值