RANSAC直線フィットアルゴリズム
1.参考文献
2.アルゴリズム実装
RANSAC
2.アルゴリズム実装
#include
#include
#include
#include
#include
// Date: 2018-01-09
// Author: HSW
//
// RANSAC
//
//
using namespace std;
typedef struct st_Point
{
double x;
double y;
}st_Point;
// RANSAC
// pstData:
// dataCnt:
// lineParameterK:
// lineParameterB:
// minCnt: ( )
// maxIterCnt:
// maxErrorThreshold:
// consensusCntThreshold:
// modelMeanError:
// : 0 ,
int ransacLiner(st_Point* pstData, int dataCnt, int minCnt, double maxIterCnt, int consensusCntThreshold, double maxErrorThreshod, double& A, double& B, double& C, double& modelMeanError)
{
default_random_engine rng;
uniform_int_distribution uniform(0, dataCnt - 1);
rng.seed(10); //
set selectIndexs; //
vector selectPoints; //
set consensusIndexs; //
double line_A = 0;
double line_B = 0;
double line_C = 0;
modelMeanError = 0;
int isNonFind = 1;
unsigned int bestConsensusCnt = 0; //
int iter = 0;
while(iter < maxIterCnt)
{
selectIndexs.clear();
selectPoints.clear();
// Step1: minCnt
while(1)
{
unsigned int index = uniform(rng);
selectIndexs.insert(index);
if(selectIndexs.size() == minCnt)
{
break;
}
}
// Step2: (y2 - y1)*x - (x2 - x1)*y + (y2 - y1)x2 - (x2 - x1)y2= 0
set::iterator selectIter = selectIndexs.begin();
while(selectIter != selectIndexs.end())
{
unsigned int index = *selectIter;
selectPoints.push_back(pstData[index]);
selectIter++;
}
double deltaY = (selectPoints[1]).y - (selectPoints[0]).y;
double deltaX = (selectPoints[1]).x - (selectPoints[0]).x;
line_A = deltaY;
line_B = -deltaX;
line_C = -deltaY * (selectPoints[0]).x + deltaX * (selectPoints[0]).y;
// Step3: :
int dataIter = 0;
double meanError = 0;
set tmpConsensusIndexs;
while(dataIter < dataCnt)
{
double distance = (line_A * pstData[dataIter].x + line_B * pstData[dataIter].y + line_C) / sqrt(line_A*line_A + line_B*line_B);
distance = distance > 0 ? distance : -distance;
if(distance < maxErrorThreshod)
{
tmpConsensusIndexs.insert(dataIter);
}
meanError += distance;
dataIter++;
}
// Step4: : +
if(tmpConsensusIndexs.size() >= bestConsensusCnt && tmpConsensusIndexs.size() >= consensusCntThreshold)
{
bestConsensusCnt = consensusIndexs.size(); //
modelMeanError = meanError / dataCnt;
consensusIndexs.clear();
consensusIndexs = tmpConsensusIndexs; //
A = line_A;
B = line_B;
C = line_C;
isNonFind = 0;
}
iter++;
}
return isNonFind;
}
#define MAX_LINE_CORRECT_POINT_CNT (40)
#define MAX_LINE_NOISE_POINT_CNT (5)
int main()
{
st_Point dataPoints[MAX_LINE_CORRECT_POINT_CNT + MAX_LINE_NOISE_POINT_CNT];
memset(dataPoints, 0, sizeof(dataPoints));
int iter;
for(iter = 0; iter < MAX_LINE_CORRECT_POINT_CNT; ++iter)
{
dataPoints[iter].x = iter;
dataPoints[iter].y = iter*2 + 5; // y = 2 * x + 5
}
int totalCnt = MAX_LINE_CORRECT_POINT_CNT + MAX_LINE_NOISE_POINT_CNT;
for(iter = MAX_LINE_CORRECT_POINT_CNT; iter < totalCnt; ++iter)
{
dataPoints[iter].x = iter;
dataPoints[iter].y = iter*2 + 1; // y = 2 * x + 1
}
double A = 0;
double B = 0;
double C = 0;
double meanError = 0;
//
if(!ransacLiner(dataPoints, totalCnt, 2, 20, 35, 0.1, A, B, C, meanError))
{
cout << "A = " << A << endl;
cout << "B = " << B << endl;
cout << "C = " << C << endl;
cout << "meanError = " << meanError << endl;
}
else
{
cout << "RANSAC Failed " << endl;
}
//
if(!ransacLiner(dataPoints, totalCnt, 2, 50, 35, 0.1, A, B, C, meanError))
{
cout << "A = " << A << endl;
cout << "B = " << B << endl;
cout << "C = " << C << endl;
cout << "meanError = " << meanError << endl;
}
else
{
cout << "RANSAC Failed " << endl;
}
return 0;
}