第十讲 g2o_custonbundle/common/projection.h和BundleParams.h

这个类实现了整个投影过程,对应书上10.2.1里面一直到图10-2 

#ifndef PROJECTION_H
#define PROJECTION_H

#include "tools/rotation.h"

/**
 * 这个头文件中只有一个内联函数:带畸变的相机投影
 * inline bool CamProjectionWithDistortion(const T* camera, const T* point, T* predictions){}
 * 整个这个函数就是P246页图10-2的代码实现。
 *
 * @tparam T 很明显要用模板类,以包含float和double这些类型,主要是这两种,int的还没见过
 * @param camera 相机内外参,9维数组。0-2旋转向量、3-5平移向量、6-8相机内参(f,二阶径向畸变系数,四阶径向畸变系数)
 * @param point 投影空间点
 * @param predictions 投影得到的以图像中心为坐标原点下的像素坐标,取名为预测值,因为性质上这个坐标确是估计值。
 * 这里注意一下,这里不是一般意义上像素坐标,一般意义下的像素坐标是以图像左上角为原点。最后面有一些体现~
 * @return 整个投影过程成功的话,返回true。
 */

// camera : 9 dims array with 
// [0-2] : angle-axis rotation 
// [3-5] : translateion
// [6-8] : camera parameter, [6] focal length, [7-8] second and forth order radial distortion
// point : 3D location. 
// predictions : 2D predictions with center of the image plane. 

template<typename T>
inline bool CamProjectionWithDistortion(const T* camera, const T* point, T* predictions)
{
    // Rodrigues' formula
    //创建一个中间变量,这个p就是相机坐标系下的空间点的坐标。
    T p[3];
    //通过tool文件夹中的rotation.h中的AngleAxisRotatePoint()函数计算在相机仅旋转的情况下,新坐标系下的坐标。说白就是p=R*point。
    //这里有个小现象点开此函数定义发现,它的第一个参数需要的是个三元素数组,而这里的camera数组是9元素的,也是能用的。对应只取到前三维。
    //由数组名的本质可知为什么
    AngleAxisRotatePoint(camera, point, p);//p=camrea(前三维)*point
    // camera[3,4,5] are the translation
    //旋转完之后,平移直接加上就好了。此时的p=R*point+t。即是相机坐标系下空间点的坐标了。也就是式10.36的p`
    p[0] += camera[3]; p[1] += camera[4]; p[2] += camera[5];

    //得到相机坐标系下空间点的坐标后,下面就是纯粹的相机本身的投影过程了,跟外部没有关系了。

    // Compute the center fo distortion
    //归一化坐标,也就是在求式10.37的Pc,这里的xp yp就是书上的uc vc。
    //问题:这个负号是什么鬼?
    T xp = -p[0]/p[2];
    T yp = -p[1]/p[2];

    // Apply second and fourth order radial distortion
    // 这四步将二四阶畸变系数取出来,构造成一个畸变distortion。也就是式10.38中()中的东西
    const T& l1 = camera[7];
    const T& l2 = camera[8];
    T r2 = xp*xp + yp*yp;
    T distortion = T(1.0) + l1 * r2  + l2 * r2*r2;

    //distortion*xp为式10.39中的Uc’和Vc‘,再乘上焦距f得到式10.39中的fx*Uc’和fx*Vc‘。
    //注意,到此为止了,并没有算得整个式10.39中的Us和Vs。
    //也就是predictions的坐标是以图像正中心为原点坐标系下的像素坐标。不是一般意义的以图像左上角为原点开始的坐标。
    //再回头看整个函数,camera参数压根没有传进来Cx和Cy,所以也就无从算起了。也好搞,根据图像大小直接就能算出来一般意义下的像素坐标
    //这里猜测一下为什么只到这里结束了,应该还是为了不同分辨率下图像程序通用性而考虑。
    const T& focal = camera[6];
    predictions[0] = focal * distortion * xp;//(xp,yp)为归一化坐标
    predictions[1] = focal * distortion * yp;

    return true;
}

#endif // projection.h
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67

这个文件就是定义BA优化中用到的所有参数变量。并利用CommandArgs类进行变量管理。比如赋默认值等。 
这里再啰嗦一遍,CommandArgs类只是一个变量(这里就是BA用到的所有参数了)管理类,真正的变量(这里就是参数集了)定义是在这个头文件中,也就是所有参数都定义在BundleParams这个结构体中。 
其中有一些参数因为还没看BA的代码,所以没搞清楚,只是大概写了写,但是在这里不是重点,重点是,这个结构体中定义BA所需要的所有参数,不管干啥用的,肯定是个参数而已。

贴代码:

#ifndef BUNDLEPARAMS_H
#define BUNDLEPARAMS_H

#include <string>
#include "flags/command_args.h"

using namespace std;
/**
 * 这个结构体定义了Bundle Adjustment使用所有参数。
 * 说一下整体的结构和逻辑:
 * 结构体名称非常直观,就是BA的参数,当然成员就是一堆参数了
 * 那在最后用CommandArgs arg;这么一句,相当于创建了一个参数描述类,
 * 结构成员定义完毕,开始构造函数。
 * 构造函数中首先调用arg这个类中的.param()函数,这个函数有两个功能:
 * 1、给上面定义的每一个参数后面挂一个结构体类型的描述,name、type等等描述
 * 2、给这这些参数赋了一些值,也就是默认值了。
 * 然后构造函数又调用了arg这个类中的.parseArgs()函数。这个函数功能就是检查一下命令行中有没有用户自定义的参数值,有的话读进来将默认值覆盖。
 */

struct BundleParams{
public:
    //构造函数,在后面定义,这里只声明。
    BundleParams(int argc, char** argv);
    //析构函数
    virtual ~BundleParams(){};

public:
    //这里的一堆参数才是实打实的BA程序中要用的参数变量!!
    //输入,那个文件被处理
    string input;
    //信赖域策略
    string trust_region_strategy;
    //线性求解器
    string linear_solver;
    //稀疏的线性代数求解器
    string sparse_linear_algebra_library;
    //稠密的线性代数求解器
    string dense_linear_algebra_library;

    //是否鲁棒??还没整明白
    bool robustify; // loss function
    // double eta;

    //迭代次数
    int num_iterations;

    // for making noise
    //噪声发生器
    //随机种子
    int random_seed;
    //旋转sigma
    double rotation_sigma;
    //变换sigma
    double translation_sigma;
    //空间点sigma
    double point_sigma;

    // for point cloud file...
    //原始点云
    string initial_ply;
    //优化后点云
    string final_ply;

    //此类在command_args.h中,用于解析用户输入的参数
    //创建一个命令行参数类实例,通过下面的构造函数,对这个实例的成员进行赋值。
    CommandArgs arg;

};

//构造函数定义,注意看,前面还是要加上类名称空间BundleParams::
//这里看见,直接处理的命令行,也就是main()中的第一句:BundleParams params(argc,argv),用命令行实例化一个BundleParams
BundleParams::BundleParams(int argc, char** argv)
{
    /**
     * 这一堆瞅着有点蛋疼和复杂。。。
     * 慢慢看用法结构:.para()是个函数,下面用法有多种,参数列表也有很多种,明显是一个重载。
     * 点开定义去看,.param()在CommandArgs类中。
     * 从用法上看出来:(参数名称,参数,参数值,参数描述)
     */

    //这个input就是要被BA的数据集。也就是要被处理的文件名。在这个程序里用的就是data文件夹下的problem-16-22106-pre.txt文件。
    //发现默认值是空字符串,所以这种就是肯定要通过命令行输入进来值的参数。
    arg.param("input", input, "", "file which will be processed");
    arg.param("trust_region_strategy", trust_region_strategy, "levenberg_marquardt",
              "Options are: levenberg_marquardt, dogleg.");
    arg.param("linear_solver", linear_solver, "dense_schur",                             // iterative schur and cgnr(pcg) leave behind...
              "Options are: sparse_schur, dense_schur");

    // arg.param("sparse_linear_algebra_library", sparse_linear_algebra_library, "suite_sparse", "Options are: suite_sparse and cx_sparse.");
    // arg.param("dense_linear_algebra_library", dense_linear_algebra_library, "eigen", "Options are: eigen and lapack.");


    // arg.param("ordering",ordering,"automatic","Options are: automatic, user.");
    arg.param("robustify", robustify, false, "Use a robust loss function");


    // arg.param("num_threads",num_threads,1, "Number of threads.");
    arg.param("num_iterations", num_iterations,20, "Number of iterations.");
    arg.param("rotation_sigma", rotation_sigma, 0.0, "Standard deviation of camera rotation "
            "perturbation.");
    arg.param("translation_sigma", translation_sigma,0.0, "translation perturbation.");
    arg.param("point_sigma",point_sigma,0.0,"Standard deviation of the point "
            "perturbation.");
    arg.param("random_seed", random_seed, 38401,"Random seed used to set the state ");
    arg.param("initial_ply", initial_ply,"initial.ply","Export the BAL file data as a PLY file.");
    arg.param("final_ply", final_ply, "final.ply", "Export the refined BAL file data as a PLY");


    //解析命令行中的参数,看看有没有新值过来,有的话就覆盖。
    arg.parseArgs(argc, argv);
}

#endif
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
解释根据给出的代码,可以将其转化为以下CMake代码: 复制 cmake_minimum_required(VERSION 3.5) project(UavRectifyLoadLIb LANGUAGES CXX) set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) set(CMAKE_AUTOUIC ON) find_package(Qt5Core REQUIRED) add_executable(UavRectifyLoadLIb main.cpp ) target_link_libraries(UavRectifyLoadLIb PRIVATE Qt5::Core UAVAutoRectifyMt UAVAutoRectify UAVAutoRectifyFi DEMDriver Projection IImage_gC opencv_core opencv_highgui opencv_imgproc opencv_features2d opencv_imgcodecs ) target_include_directories(UavRectifyLoadLIb PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../../../include/gdal1101 ${CMAKE_CURRENT_SOURCE_DIR}/../include ${CMAKE_CURRENT_SOURCE_DIR}/../../../lib/opencvf249 ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../../usr/local/include ) if(UNIX AND NOT APPLE) target_link_directories(UavRectifyLoadLIb PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../../../product/release32 ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../../usr/local/lib ) endif() if(WIN32) if(CMAKE_BUILD_TYPE STREQUAL "Debug") set_target_properties(UavRectifyLoadLIb PROPERTIES RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_CURRENT_SOURCE_DIR}/../../../../RasterManager/bin/Debug ) else() set_target_properties(UavRectifyLoadLIb PROPERTIES RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_CURRENT_SOURCE_DIR}/../../../../RasterManager/bin/release ) endif() else() if(CMAKE_BUILD_TYPE STREQUAL "Debug") set_target_properties(UavRectifyLoadLIb PROPERTIES RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_CURRENT_SOURCE_DIR}/../../../product/release32 ) else() set_target_properties(UavRectifyLoadLIb PROPERTIES RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_CURRENT_SOURCE_DIR}/../../../product/release32 ) endif() endif()
最新发布
06-11
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值