• 2 OpenCV实现的F矩阵+RANSAC原理与实践


    前文
    1 基于SIFT图像特征识别的匹配方法比较与实现

    1 RANSAC 筛选

    1.1 大致原理

    Random sample consensus (RANSAC),即随机抽样一致性,其是一种用于估计模型参数的迭代方法,特别适用于处理包含离群点(outliers)的数据集

    RANSAC 的主要思想是随机采样数据点,用这些采样点拟合一个模型,然后计算其他数据点到这个模型的拟合误差;根据误差和阈值,将数据点分为内点(inliers)外点(outliers);重复这个过程多次,选择具有最多内点的模型作为最终的估计

    大致步骤为:

    1. 随机采样

      从数据集中随机选择一小部分数据点,通常是与所估计模型参数数量相等的数据点

    2. 模型拟合

      使用这些随机采样的数据点拟合一个模型,例如直线

    3. 内点检测

      计算所有数据点到模型的拟合误差,并将与模型拟合误差小于某个阈值的数据点标记为内点

    4. 判断是否满足条件

      如果内点的数量达到了某个设定的阈值,且模型参数的估计是合理的(例如,模型的拟合误差小于一定阈值),则认为找到了一个满足条件的模型

    5. 重复迭代

      重复上述过程多次(通常几百甚至上千次),并且记录具有最多内点的模型,以及该模型估计的内点

    6. 输出最佳模型

      在所有迭代中,选择具有最多内点的模型作为最终的估计模型。这些内点被认为是满足模型的数据点

    1.2 优缺点

    RANSAC 的一个优点是它能够对模型参数进行鲁棒估计,能够在存在大量噪声的情况下找到合适的模

    RANSAC 的缺点是计算这些参数所需的时间没有上限,其需要进行大量的随机采样和模型拟合,因此对于大规模数据集来说,计算复杂度较高,可能需要较长的时间来运行

    1.3 实践效果

    请见 3 实践操作 步骤二

    2 F矩阵

    2.1 基本原理

    基本矩阵(Fundamental Matrix)描述了两个摄像机之间的基本几何关系

    在对极几何中,对于立体图像对中对应点的齐次图像坐标 p1p2F*p1描述了另一图像上的对应点 p2 必须位于其上的线(对极线)这意味着,对于所有对应点对都成立:
    p 2 T ∗ F ∗ p 1 = 0 p_2^T * F * p_1 = 0 p2TFp1=0

    2.2 函数实现

    在 OpenCV 中,提供了 findFundamentalMat 函数,用于估计两幅图像之间的F矩阵

    以下是 findFundamentalMat 函数的基本用法:

    Mat fundamental_matrix = findFundamentalMat(points1, points2, mask, method, ransacReprojThreshold, confidence);
    
    • 1

    其中各参数的含义如下:

    • points1points2:两幅图像中的匹配点坐标,通常是 vector 类型,表示两幅图像中匹配点的像素坐标
    • mask:是一个输出数组通常是 vector 类型,用于指示哪些匹配点被视为内点(inliers)和哪些被视为外点(outliers
    • method:用于指定计算基本矩阵的方法,可以是以下几种选项之一:
      • cv::FM_RANSAC:使用 RANSAC 算法进行估计,用于排除离群点
      • cv::FM_LMEDS:使用最小中值误差估计方法
      • cv::FM_8POINT:使用 8 点法估计基本矩阵
    • ransacReprojThreshold:RANSAC 算法中的重投影误差阈值,用于判断内点和外点,通常需要根据具体问题来选择适当的阈值,默认值为 3.0
    • confidence:置信度,通常为默认值 0.99

    3 实践操作

    之前通过SIFT+Flann+ratio=0.7的图像匹配和初步筛选,得到了 good_matchesvector 类型)

    步骤一:保存匹配点对坐标

    vector 类型的 good_matches 中的坐标信息提取出来存入 vector 类型的 matchedPoints1/2 ;以便于后续的几何计算将匹配点对的坐标提取出来,以便于后续的几何计算

    // 声明用于保存匹配点对的容器
    vector<Point2f> matchedPoints1, matchedPoints2;
    for (int i = 0; i < good_matches.size(); ++i)
    {
        matchedPoints1.push_back(keypoints1[good_matches[i].queryIdx].pt);
        matchedPoints2.push_back(keypoints2[good_matches[i].trainIdx].pt);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    步骤二:进行基本矩阵F的估计

    直接使用 findFundamentalMat 函数

    这个函数在内部已经包含了 RANSAC 筛选步骤;具体来说,findFundamentalMat 函数会计算基本矩阵 F,同时使用 RANSAC 迭代方法来排除离群点,确保得到的基本矩阵对于图像匹配是稳健的

    // 使用RANSAC进行基本矩阵F的估计
    Mat F;
    vector<uchar> inliers;
    F = findFundamentalMat(matchedPoints1, matchedPoints2, inliers, RANSAC);
    
    • 1
    • 2
    • 3
    • 4
    • 为了查看 RANSAC 筛选的效果我们进行如下操作
      inliers 是一个二进制向量,指示哪些匹配点对被视为内点(符合基本矩阵约束),哪些被视为外点;我们接下来使用内点来进一步筛选匹配,只保留通过 RANSAC 筛选的匹配对在ransac_filtered_matches中,并打印出来

      // 进一步筛选匹配
      vector<DMatch> ransac_filtered_matches;
      for (int i = 0; i < inliers.size(); ++i)
      {
          if (inliers[i])
          {
              ransac_filtered_matches.push_back(good_matches[i]);
          }
      }
      // ransac_filtered_matches 包含了通过RANSAC筛选后的匹配对
      Mat ransac_filtered_img_matches;
      drawMatches(img1, keypoints1, img2, keypoints2, ransac_filtered_matches, ransac_filtered_img_matches);    
      imwrite(SAVE_PATH, ransac_filtered_img_matches);
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      匹配点数量图像效果
      RANSAC 筛选前2949img_matches_3&4
      RANSAC 筛选后2581img_matches_3&4_

      可以明显看出,在 RANSAC 筛选后,消除了 368 对离群匹配,达到了非常好的匹配效果

  • 相关阅读:
    Xilinx IDDR与ODDR原语的使用
    actuator--基础--6.1--端点解析--health端点
    Vue3基础知识-1
    xcode打包macos报错:FlutterInputs.xcfilelist 和 FlutterOutputs.xcfilelist
    Centos7安装redis详细步骤
    Promise、Fetch、Response:ES6中新的AJAX解决方案
    java网络通信:Springboot整合Websocket
    抖音小店和商品橱窗一样吗?有什么区别?新手适合做哪个?
    95.qt qml-诺谦通用可扩展多功能QML界面
    Dijkstra算法求最短路
  • 原文地址:https://blog.csdn.net/WJwwwwwww/article/details/133064830