Vins-Fusion之 相机—IMU在线标定(两帧间旋转估计)(十)

重点理解以下几点:

a.程序的过程

b.包含的数据计算公式(暂时未完全明白,还要理解:本质矩阵分解R/T、三角化验证)

c.怎么得到最优解?

在函数solveRelativeR(corres) 得到的是视觉两帧的相对旋转,具体代码如下:

cpp 复制代码
//从一对帧之间的归一化特征匹配点集 corres 中,估计这两帧相机之间的相对旋转矩阵
Matrix3d InitialEXRotation::solveRelativeR(const vector<pair<Vector3d, Vector3d>> &corres)
{
    if (corres.size() >= 9)
    {
        vector<cv::Point2f> ll, rr;
        for (int i = 0; i < int(corres.size()); i++)
        {
            ll.push_back(cv::Point2f(corres[i].first(0), corres[i].first(1)));
            rr.push_back(cv::Point2f(corres[i].second(0), corres[i].second(1)));
        }
        cv::Mat E = cv::findFundamentalMat(ll, rr);//估计基础矩阵E,用于后续分解得到相对旋转矩阵R1和R2
        cv::Mat_<double> R1, R2, t1, t2;
        decomposeE(E, R1, R2, t1, t2);//从 E 分解出 两个可能的旋转 R1, R2 和两个平移 t1, t2,共有 4 种姿态组合

        if (determinant(R1) + 1.0 < 1e-09)
        {
            E = -E;
            decomposeE(E, R1, R2, t1, t2);
        }
        //四种组合分别做三角化测试
        double ratio1 = max(testTriangulation(ll, rr, R1, t1), testTriangulation(ll, rr, R1, t2));
        double ratio2 = max(testTriangulation(ll, rr, R2, t1), testTriangulation(ll, rr, R2, t2));
        cv::Mat_<double> ans_R_cv = ratio1 > ratio2 ? R1 : R2;//选择三角化测试得分更高的组合作为最终的相对旋转矩阵

        Matrix3d ans_R_eigen;
        for (int i = 0; i < 3; i++)
            for (int j = 0; j < 3; j++)
                ans_R_eigen(j, i) = ans_R_cv(i, j);
        return ans_R_eigen;
    }
    return Matrix3d::Identity();
}

输入:两帧之间的特征匹配点对

输出:两帧相机之间的相对旋转矩阵 R

步骤1:提取归一化坐标

cpp 复制代码
vector<cv::Point2f> ll, rr;
for (int i = 0; i < int(corres.size()); i++)
{
    ll.push_back(cv::Point2f(corres[i].first(0),  corres[i].first(1)));
    rr.push_back(cv::Point2f(corres[i].second(0), corres[i].second(1)));
}
步骤2:估计基础矩
cpp 复制代码
cv::Mat E = cv::findFundamentalMat(ll, rr);

从两幅图像中的对应点计算基本矩阵。

cv::findFundamentalMat 是 OpenCV 中用于计算两幅图像之间基本矩阵(Fundamental Matrix)的函数。基本矩阵描述了两个未校准摄像机之间的几何关系,它在计算机视觉中用于立体视觉、运动结构恢复(Structure from Motion, SfM)、视觉里程计等任务。

  • 基础矩阵 FF(代码中变量名为 E)满足:p2TFp1=0
  • 从匹配点对估计 F
步骤3:分解基础矩阵得到候选姿态
cpp 复制代码
cv::Mat_<double> R1, R2, t1, t2;
decomposeE(E, R1, R2, t1, t2);

数学原理:

  • 从基础矩阵 FF 可分解出本质矩阵 E(归一化坐标下)
  • 本质矩阵 E=[t]×RE,其中 [t]×[t]× 是平移的反对称矩阵
  • SVD 分解 E=UΣVT 后,可构造两个旋转和两个平移方向

结果:4 种候选姿态组合

  • (R1, t1)
  • (R1, t2)
  • (R2, t1)
  • (R2, t2)
步骤4:三角化测试选择正确解
cpp 复制代码
double InitialEXRotation::testTriangulation(...)
{
    // 1. 构建两个相机的投影矩阵
    cv::Matx34f P = cv::Matx34f(1, 0, 0, 0,   // 第一帧:单位矩阵(参考帧)
                                 0, 1, 0, 0,
                                 0, 0, 1, 0);
    cv::Matx34f P1 = cv::Matx34f(R(0,0), R(0,1), R(0,2), t(0),  // 第二帧:R|t
                                  R(1,0), R(1,1), R(1,2), t(1),
                                  R(2,0), R(2,1), R(2,2), t(2));
    
    // 2. 三角化得到3D点云
    cv::triangulatePoints(P, P1, l, r, pointcloud);
    
    // 3. 统计在两相机前方(深度>0)的点数
    int front_count = 0;
    for (int i = 0; i < pointcloud.cols; i++)
    {
        // 将齐次坐标转为3D坐标
        cv::Mat_<double> p_3d_l = cv::Mat(P) * (pointcloud.col(i) / normal_factor);
        cv::Mat_<double> p_3d_r = cv::Mat(P1) * (pointcloud.col(i) / normal_factor);
        
        // 检查深度是否为正(点在相机前方)
        if (p_3d_l(2) > 0 && p_3d_r(2) > 0)
            front_count++;
    }
    
    // 4. 返回前方点的比例
    return 1.0 * front_count / pointcloud.cols;
}

原理(Cheirality Constraint):

  • 真实姿态下,大部分三角化点应在两相机前方(深度 > 0)
  • 错误姿态会导致大量点在后方(深度 < 0)
  • 选择前方点比例最高的旋转

完整流程图:

**输入: corres (特征匹配点对)

提取归一化坐标 (ll, rr)

估计基础矩阵 F (cv::findFundamentalMat)

SVD分解得到4种候选姿态:
(R1, t1), (R1, t2), (R2, t1), (R2, t2)

修正符号(确保旋转矩阵行列式=+1)

对4种组合分别做三角化测试:

  • 三角化得到3D点云
  • 统计深度>0的点数
  • 计算前方点比例

    选择比例最高的旋转矩阵

    转换为Eigen格式并返回**
相关推荐
星越华夏5 小时前
计算机视觉:YOLOv12安装环境
人工智能·yolo·计算机视觉
Yolanda946 小时前
【人工智能】《从零搭建AI问答助手项目(九):Prompt优化》
人工智能·prompt
wj3055853786 小时前
课程 9:模型测试记录与 Prompt 策略
linux·人工智能·python·comfyui
小和尚同志6 小时前
深入使用 skill-creator:结合真实生产级实践
人工智能·aigc
DevSecOps选型指南6 小时前
安全419专访悬镜安全 | 穿越周期在 AI 浪潮中定义数字供应链安全新范式
人工智能
沪漂阿龙7 小时前
面试题详解:GraphRAG 全面解析——知识图谱增强 RAG、Local Search、Global Search、社区摘要、工程落地与评估指标一次讲透
人工智能·知识图谱
WangN27 小时前
Unitree RL Lab 学习笔记【通识】
人工智能·机器学习
吃好睡好便好7 小时前
在Matlab中绘制横直方图
开发语言·学习·算法·matlab
haina20197 小时前
海纳AI亮相《科创中国》,解码招聘“智”变之路
人工智能·ai面试·ai招聘
阿星AI工作室7 小时前
刘润年中大课笔记:一句话说清AI落地之战的本质
大数据·人工智能·创业创新·商业