OpenCV - Ransac fitting line

匿名 (未验证) 提交于 2019-12-03 03:03:02

问题:

What's the best and most efficient way to fit one or more good lines using Ransac with a set of points in an image using OpenCV?

Ransac is the most efficient way to fit a line?

回答1:

Take a look at Least Mean Square metod. It's faster and simplier than RANSAC.

Also take look at OpenCV's fitLine method.

RANSAC performs better when you have a lot of outliers in your data, or a complex hypothesis.



回答2:

RANSAC is not the most efficient but it is better for a large number of outliers. Here is how to do it using opencv:

A useful structure-

struct SLine {     SLine():         numOfValidPoints(0),         params(-1.f, -1.f, -1.f, -1.f)     {}     cv::Vec4f params;//(cos(t), sin(t), X0, Y0)     int numOfValidPoints; }; 

Total Least squares used to make a fit for a successful pair

cv::Vec4f TotalLeastSquares(     std::vector<cv::Point>& nzPoints,     std::vector<int> ptOnLine) {     //if there are enough inliers calculate model     float x = 0, y = 0, x2 = 0, y2 = 0, xy = 0, w = 0;     float dx2, dy2, dxy;     float t;     for( size_t i = 0; i < nzPoints.size(); ++i )     {         x += ptOnLine[i] * nzPoints[i].x;         y += ptOnLine[i] * nzPoints[i].y;         x2 += ptOnLine[i] * nzPoints[i].x * nzPoints[i].x;         y2 += ptOnLine[i] * nzPoints[i].y * nzPoints[i].y;         xy += ptOnLine[i] * nzPoints[i].x * nzPoints[i].y;         w += ptOnLine[i];     }      x /= w;     y /= w;     x2 /= w;     y2 /= w;     xy /= w;      //Covariance matrix     dx2 = x2 - x * x;     dy2 = y2 - y * y;     dxy = xy - x * y;      t = (float) atan2( 2 * dxy, dx2 - dy2 ) / 2;     cv::Vec4f line;     line[0] = (float) cos( t );     line[1] = (float) sin( t );      line[2] = (float) x;     line[3] = (float) y;      return line; } 

The actual RANSAC

SLine LineFitRANSAC(     float t,//distance from main line     float p,//chance of hitting a valid pair     float e,//percentage of outliers     int T,//number of expected minimum inliers      std::vector<cv::Point>& nzPoints) {     int s = 2;//number of points required by the model     int N = (int)ceilf(log(1-p)/log(1 - pow(1-e, s)));//number of independent trials      std::vector<SLine> lineCandidates;     std::vector<int> ptOnLine(nzPoints.size());//is inlier     RNG rng((uint64)-1);     SLine line;     for (int i = 0; i < N; i++)     {         //pick two points         int idx1 = (int)rng.uniform(0, (int)nzPoints.size());         int idx2 = (int)rng.uniform(0, (int)nzPoints.size());         cv::Point p1 = nzPoints[idx1];         cv::Point p2 = nzPoints[idx2];          //points too close - discard         if (cv::norm(p1- p2) < t)         {             continue;         }          //line equation ->  (y1 - y2)X + (x2 - x1)Y + x1y2 - x2y1 = 0          float a = static_cast<float>(p1.y - p2.y);         float b = static_cast<float>(p2.x - p1.x);         float c = static_cast<float>(p1.x*p2.y - p2.x*p1.y);         //normalize them         float scale = 1.f/sqrt(a*a + b*b);         a *= scale;         b *= scale;         c *= scale;          //count inliers         int numOfInliers = 0;         for (size_t i = 0; i < nzPoints.size(); ++i)         {             cv::Point& p0 = nzPoints[i];             float rho      = abs(a*p0.x + b*p0.y + c);             bool isInlier  = rho  < t;             if ( isInlier ) numOfInliers++;             ptOnLine[i]    = isInlier;         }          if ( numOfInliers < T)         {             continue;         }          line.params = TotalLeastSquares( nzPoints, ptOnLine);         line.numOfValidPoints = numOfInliers;         lineCandidates.push_back(line);     }      int bestLineIdx = 0;     int bestLineScore = 0;     for (size_t i = 0; i < lineCandidates.size(); i++)     {         if (lineCandidates[i].numOfValidPoints > bestLineScore)         {             bestLineIdx = i;             bestLineScore = lineCandidates[i].numOfValidPoints;         }     }      if ( lineCandidates.empty() )     {         return SLine();     }     else     {         return lineCandidates[bestLineIdx];     } } 


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!