13

TL;DR:是否有 RANSAC 的 C++ 实现或其他可自由用于任意二维点集的鲁棒对应算法?

我知道存在许多包含或使用对应算法的实现,例如 RANSAC(随机采样共识)。它们通常用于计算机视觉应用程序,并在OpenCVPCL等库中找到。通用算法是众所周知的,并且各个站点列出了不同的步骤。

现在,我发现的所有“高级”实现(为 OpenCV、PCL 等完成)都是针对特定类型的问题以及一组基础假设。在 OpenCV 中,您想要找到第一张图像和第二张图像的一部分之间的单应矩阵(本例)。在 PCL 中,您处于 3D 点云领域,并且(据我所知)您只能匹配特定的、已定义的形状(线、球体等)。

我“简单地”想要做的是获取任意 2D 点集(可能包含一些噪声)并在更大的 2D 点集(也包含一些噪声和其他点)中找到对应关系。除了输入两组点之外,它不需要特定的模型训练。我正在用 C++ 自己实现它,但是:

  • 我绝不是一个经验丰富的程序员,我需要快速执行整个事情;我之前对众所周知的算法(边缘检测、高斯模糊等)的实现已被证明比经过验证的实现慢得多(>10 倍)。

  • 简单地撕掉一个已经存在的开源实现(例如 OpenCV 的)已被证明超出了我目前的能力(太多的依赖和虚拟实现模板等等......)

所以,如果有人知道我错过的可自由使用(类似 BSD)和经过验证的 C++ 实现......

4

3 回答 3

20

很难找到一个流行的、轻量级的、通用的 RANSAC 的 C++ 实现。我刚刚在 MIT 许可下发布了我的通用 RANSAC 实现。

https://github.com/drsrinathsridhar/GRANSAC

GRANSAC 是通用的、模板化的、仅标头的和多线程的。用户必须实现一个继承 AbstractModel 的类。然后可以对任何类型的模型(例如:2D 线、3D 平面)进行 RANSAC 估计。

我仅针对 2D 线拟合进行了测试,但也适用于其他问题。很乐意添加更多功能(例如自动选择迭代次数等)

在此处输入图像描述

于 2015-09-05T14:06:43.527 回答
3

适用于 Windows 和 Linux 的漂亮 RANSAC、LMedS、MSAC、MLESAC C++ 实现在这里:https ://github.com/sunglok/rtl 。

RTL:RANSAC 模板库 RANSAC 模板库 (RTL) 是一种开源强大的回归工具,尤其适用于 RANSAC 系列。RTL 旨在提供快速、准确和简单的方法来估计任何带有异常值(不正确数据)污染的数据的模型参数。RTL 包括最近的 RANSAC 变体及其性能评估,其中包含多个具有合成和真实数据的模型。RTL 以通用编程风格(C++ 中的模板)编写,用于用户定义模型的进一步应用。RTL 在Simplified BSD License下分发。

基础类是 RANSAC:

template <class Model, class Datum, class Data>
class RANSAC;

其他类继承自它:

template <class Model, class Datum, class Data>
class MLESAC : virtual public RANSAC<Model, Datum, Data>
...

用法很简单(README 中的一个示例):

// Find the best model using RANSAC
LineEstimator estimator;
RTL::RANSAC<Line, Point, std::vector<Point> > ransac(&estimator);
Line model;
double loss = ransac.FindBest(model, data, data.size(), 2);

// Determine inliers using the best model if necessary
std::vector<int> inliers = ransac.FindInliers(model, data, data.size());

在此处输入图像描述

论文:https ://sites.google.com/site/sunglok/files/Choi09_bmvc.pdf?attredirects=0

于 2018-02-21T09:44:38.473 回答
1

我一直在寻找类似的东西,然后我找到了这个

代码在底部的 c++ 中。

下面的函数最初是从这个中提取的。

cv::Mat ransacTest(const std::vector<cv::DMatch>& matches, const std::vector<cv::KeyPoint>& keypoints1,const std::vector<cv::KeyPoint>& keypoints2, std::vector<cv::DMatch>& outMatches) {

   // Convert keypoints into Point2f
   std::vector<cv::Point2f> points1, points2;
   cv::Mat fundemental;

   for (std::vector<cv::DMatch>::const_iterator it= matches.begin(); it!= matches.end(); ++it) {
       // Get the position of left keypoints
       float x= keypoints1[it->queryIdx].pt.x;
       float y= keypoints1[it->queryIdx].pt.y;
       points1.push_back(cv::Point2f(x,y));
       // Get the position of right keypoints
       x= keypoints2[it->trainIdx].pt.x;
       y= keypoints2[it->trainIdx].pt.y;
       points2.push_back(cv::Point2f(x,y));
   }

   // Compute F matrix using RANSAC
   std::vector<uchar> inliers(points1.size(),0);

   if ( points1.size() > 0 && points2.size() > 0 ){

      cv::Mat fundemental= cv::findFundamentalMat(
            cv::Mat(points1),cv::Mat(points2), // matching points
            inliers,       // match status (inlier or outlier)
            CV_FM_RANSAC,  // RANSAC method
            3.0,           // distance to epipolar line
            0.99);         // confidence probability

      // extract the surviving (inliers) matches
      std::vector<uchar>::const_iterator itIn= inliers.begin();
      std::vector<cv::DMatch>::const_iterator itM= matches.begin();

      // for all matches
      for ( ;itIn!= inliers.end(); ++itIn, ++itM) {
         if (*itIn) { // it is a valid match
            outMatches.push_back(*itM);
         }
      }

      // The F matrix will be recomputed with all accepted matches
      // Convert keypoints into Point2f for final F computation

      points1.clear();
      points2.clear();

      for (std::vector<cv::DMatch>::const_iterator it= outMatches.begin(); it!=outMatches.end(); ++it) {
        // Get the position of left keypoints
        float x= keypoints1[it->queryIdx].pt.x;
        float y= keypoints1[it->queryIdx].pt.y;
        points1.push_back(cv::Point2f(x,y));
        // Get the position of right keypoints
        x= keypoints2[it->trainIdx].pt.x;
        y= keypoints2[it->trainIdx].pt.y;
        points2.push_back(cv::Point2f(x,y));
     }

     // Compute 8-point F from all accepted matches
     if( points1.size() > 0 && points2.size() > 0){
        fundemental= cv::findFundamentalMat(
        cv::Mat(points1),cv::Mat(points2), // matches
        CV_FM_8POINT); // 8-point method
     }

   }

   return fundemental;

}
于 2015-10-29T13:51:02.543 回答