opencv 任意2D集合的RANSAC类实现

mw3dktmi  于 2023-06-24  发布在  其他
关注(0)|答案(4)|浏览(129)

TL;DR:是否有RANSAC或其他鲁棒对应算法的C实现,可以自由地用于任意2D点集?
我知道存在许多包括或使用对应算法的实现,例如RANSAC(随机采样共识)。它们通常用于计算机视觉应用程序,并在OpenCVPCL等库中找到。通用算法是众所周知的,各种站点lists的不同步骤。
现在,我发现的所有“高级”实现(针对OpenCV、PCL等)都是针对特定类型的问题,并有一套基本假设。在OpenCV中,您希望找到第一个图像和第二个图像的一部分之间的单应性矩阵(本示例)。在PCL中,你处于3D点云的领域,你(据我所知)只能匹配特定的、已经定义的形状(直线、球体等)。
我“简单地”想做的是取一个任意的2D点集(可能包含一些噪声),并在一个更大的2D点集(包含一些噪声和其他点)中找到对应关系。除了输入两组点之外,它不需要任何特定的模型训练。我正在用C
实现它,但是:

  • 我决不是一个有经验的程序员,我需要整个事情执行相当快;由我自己完成的公知算法(边缘检测、高斯模糊等)的先前实现已被证明比已证明的实现慢得多(> 10倍)。
  • 简单地剥离一个已经存在的开源实现(例如OpenCV的)已经被证明超出了我目前的能力(太多的依赖和虚拟实现模板等等...)

所以,如果有人知道我错过的一个免费可用(像BSD一样)和经过验证的C++实现...

6jjcrrmo

6jjcrrmo1#

很难找到一个流行的、轻量级的、通用的RANSAC ++实现。我刚刚在MIT许可下发布了我的通用RANSAC实现。
https://github.com/drsrinathsridhar/GRANSAC
GRANSAC是通用的、模板化的、仅头文件的和多线程的。用户必须实现继承AbstractModel的类。然后可以针对任何类型的模型(例如:2D线、3D平面)。
我已经测试了这只为二维线拟合,但应该工作的其他问题了。会很乐意添加更多的特性(比如自动选择迭代次数等)

q3qa4bjr

q3qa4bjr2#

一个好看的RANSAC,LMedS,MSAC,MLESAC C实现Windows和Linux在这里: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

kkbh8khc

kkbh8khc3#

我正在寻找类似的东西,然后我发现了this
代码是在C++在底部的一部分。
下面的函数最初是从class中提取的。

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;

}
wwwo4jvm

wwwo4jvm4#

可能为时已晚,但我发现Theiasfm的RANSAC实现非常高效,编写得很好,易于实现。库的作者还介绍了如何在documentation中包含自己的估计器模块。这可能是一个矫枉过正,以获得整个库为这样一个小的要求,但我张贴在这里,因为它的工作超级好。一件事是它使用Eigen v3.3.7和Ceres v1.14。要了解它是如何工作的,您可以查看作者为RANSAC编写的单元测试。此外,它实现了RANSAC的几个版本,例如:USAC、PROSAC等...

相关问题