Basic Image AlgorithmS Library  2.8.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
ExampleRANSACPlane.cpp
1 #include <Base/Common/BIASpragma.hh>
2 
3 #include "Base/Math/Random.hh"
4 #include <vector>
5 #include <iostream>
6 #include <fstream>
7 #include <iomanip>
8 #include <float.h>
9 #include "ExampleRANSACPlane.hh"
10 
11 using namespace BIAS;
12 using namespace std;
13 
14 void Read3DPointsFromFile(char *filename, std::vector<HomgPoint3D> &points)
15 {
16  ifstream infile(filename);
17  if (!infile) {
18  BIASERR("Failed to open file " << filename);
19  return;
20  }
21  char c;
22  HomgPoint3D point(0,0,0,1);
23  int i = 0;
24  while (!infile.eof()) {
25  infile >> point[0] >> point[1] >> point[2] >> c;
26  if (!infile.eof()) {
27  points.push_back(point);
28  cout << "- point " << i << " : "<< point << endl;
29  i++;
30  }
31  }
32 }
33 
34 
35 void GeneratePlanar3DPoints(std::vector<HomgPoint3D>& points,
36  unsigned int numInliers, unsigned int numOutliers)
37 {
38  // generate points on x/y-plane at z-coordinate = 2
39  Random randomizer;
40  double range = 10.0;
41  double noise = 0.1;
42  const double z = 2.0;
43  HomgPoint3D point3D;
44  for (unsigned int i = 0; i < (numInliers + numOutliers); i++){
45  point3D[0] = randomizer.GetUniformDistributed(-range, range);
46  point3D[1] = randomizer.GetUniformDistributed(-range, range);
47  point3D[2] = z + randomizer.GetUniformDistributed(-noise, noise);;
48  point3D[3] = 1.0;
49  if (i >= numInliers) {
50  // make this point an outlier
51  point3D[2] = randomizer.GetUniformDistributed(-range, range);
52  }
53  points.push_back(point3D);
54  cout << "- point " << i << " : " << point3D << " ("
55  << (i >= numInliers ? "outlier" : "inlier") << ")" << endl;
56  }
57 }
58 
59 // -----------------------------------------------------------------
60 
61 /** @example ExampleRANSACPlane.cpp
62  @relates PlaneRANSAC, RANSAC
63  @ingroup g_examples
64  @brief Simple example for 3D plane fitting with RANSAC class
65  BIAS::PlaneRANSAC.
66 
67  This is an example file on how to use the RANSAC algorithm.
68  It tries to find a dominant plane in a number of 3D points.
69 
70  @author MIP
71 */
72 
73 int main(int argc, char *argv[])
74 {
75  int res = 0;
76  const unsigned int numPoints = 20;
77 
78  // inlier_fraction is passed onto SolveMaster and contains the assumed
79  // fraction of inliers in the data. This parameter is used to determine
80  // the number of samples drawn and is therefore important, unless the
81  // number of samples is set explicitly
82  double inlier_fraction = 0.8;
83 
84  // determines if promising solutions are to be refined based on all inliers or not
85  bool refine_solution = true;
86 
87  // max distance between point and plane for point to be classified as inlier
88  double maxsquareddistance = 0.01;
89 
90  HomgPlane3D solution;
91  vector<bool> inliers;
92  bool debug = false; //true;
93  PlaneRANSAC ransac;
94  vector<HomgPoint3D> points;
95 
96  // set ground truth plane
97  HomgPlane3D gt_plane(0, 0, -1, 2); // x/y-plane with z = 2
98 
99  // load or create input data
100  if (argc < 2) {
101  cout << endl << "Generating " << numPoints << " random noisy points "
102  << "for testing..." << endl;
103  const unsigned int outliers = (int)rint((1.0 - inlier_fraction) * numPoints);
104  GeneratePlanar3DPoints(points, numPoints - outliers, outliers);
105  } else {
106  cout << endl << "Reading 3d points for testing from file " << argv[1] << "..." << endl;
107  Read3DPointsFromFile(argv[1], points);
108  }
109 
110  if (debug) {
111  ransac.AddDebugLevel("D_RANSAC_SAMPLES");
112  ransac.AddDebugLevel("D_RANSAC_SOLVE_MASTER");
113  ransac.AddDebugLevel("D_DOUBLE_RANSAC_SOLUTION");
114  }
115 
116  // initialize RANSAC parameters
117  ransac.Init(points, maxsquareddistance, refine_solution, inlier_fraction, -1.0);
118 
119  // start computation
120  ransac.SolveMaster(inlier_fraction, solution, inliers);
121 
122  // show results
123  cout << endl << "Inlier/outlier points after computation : " << endl;
124  for (unsigned int i = 0; i < inliers.size(); i++){
125  cout << "- point " << i << " is " << (inliers[i] ? "inlier" : "outlier") << endl;
126  }
127  cout << endl << "Final solution : " << solution << endl
128  << "Ground truth : " << gt_plane << endl
129  << "Difference : " << (solution - gt_plane).NormL2() << endl << endl;
130 
131  return res;
132 }
void Init(std::vector< HomgPoint3D > &data, double inlier_distance_threshold, bool refine_solution, double expected_inlier_fraction, double solution_error_threshold)
Initializes RANSAC.
void AddDebugLevel(const long int lv)
Definition: Debug.hh:355
Robust fitting of 3D plane to 3D point set using RANSAC.
virtual int SolveMaster(double inlying_data_fraction, SolutionType &solution, std::vector< bool > &inliers)
Main computation function called by user.
Definition: RANSAC.hh:378
double GetUniformDistributed(const double min, const double max)
on succesive calls return uniform distributed random variable between min and max ...
Definition: Random.hh:84
class HomgPoint3D describes a point with 3 degrees of freedom in projective coordinates.
Definition: HomgPoint3D.hh:61
class for producing random numbers from different distributions
Definition: Random.hh:51
A homogeneous plane (in P^3) All points X on the plane p fulfill p &#39; * X = 0.
Definition: HomgPlane3D.hh:46