Apollo  v5.5.0
Open source self driving car software
i_ransac.h
Go to the documentation of this file.
1 /******************************************************************************
2  * Copyright 2018 The Apollo Authors. All Rights Reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *****************************************************************************/
16 #pragma once
17 
21 
22 #include <limits>
23 
24 namespace apollo {
25 namespace perception {
26 namespace common {
27 // Compute the number of trials for Ransac. Number of trials is chosen
28 // sufficiently high to ensure with a probability "confidence" that at
29 // least one of the random samples of data is free from outliers.
30 // "inlierprob" is the probability that any selected data point is an inlier
31 inline int IRansacTrials(int sample_size, double confidence,
32  double inlierprob) {
33  return inlierprob > 0.0
34  ? IRound(IDiv(ILog(1.0 - confidence),
35  ILog(1.0 - IPow(inlierprob, sample_size))))
36  : std::numeric_limits<int>::max();
37 }
38 
39 // Using Ransac to fit a model to data set which contains outliers
40 // The function needs 2n entries of scratch space in inliers
41 template <typename T, int l, int lp, int k, int s,
42  void (*HypogenFunc)(const T* x, const T* xp, T* model),
43  void (*CostFunc)(const T* model, const T* x, const T* xp, int n,
44  int* nr_liner, int* inliers, T* cost, T error_tol),
45  void (*RefitFunc)(T* x, T* xp, int* inliers, T* model, int n,
46  int nr_liner)>
47 bool RobustBinaryFitRansac(T* x, T* xp, int n, T* model, int* consensus_size,
48  int* inliers, T error_tol,
49  bool re_est_model_w_inliers = false,
50  bool adaptive_trial_count = false,
51  double confidence = 0.99, double inlierprob = 0.5,
52  int min_nr_inliers = s,
53  bool random_shuffle_inputs = false) {
54  const int kSize = s;
55  const int kLength = l;
56  const int kLp = lp;
57  const int kKsize = k;
58  int indices[kSize];
59  T samples_x[kLength * kSize];
60  T samples_xp[kLp * kSize];
61  T tmp_model[kKsize];
62  T cost = std::numeric_limits<T>::max();
63  T best_cost = std::numeric_limits<T>::max();
64 
65  if (n < min_nr_inliers) {
66  return false;
67  }
68 
69  double actual_inlierprob = 0.0, tmp_inlierprob;
70  int nr_trials = IRansacTrials(s, confidence, inlierprob);
71 
72  int nr_inliers = 0;
73  int rseed = I_DEFAULT_SEED;
74  int sample_count = 0;
75  int i, idxl, idxlp, il, ilp;
76  *consensus_size = 0; // initialize the size of the consensus set to zero
77  IZero(model, k); // initialize the model with zeros
78 
79  if (random_shuffle_inputs) {
80  IRandomizedShuffle(x, xp, n, l, lp, &rseed);
81  }
82 
83  while (nr_trials > sample_count) {
84  // generate random indices
85  IRandomSample(indices, s, n, &rseed);
86  // prepare data for model fitting
87  for (i = 0; i < s; ++i) {
88  idxl = indices[i] * l;
89  idxlp = indices[i] * lp;
90  il = i * l;
91  ilp = i * lp;
92  ICopy(x + idxl, samples_x + il, l);
93  ICopy(xp + idxlp, samples_xp + ilp, lp);
94  }
95 
96  // estimate model
97  HypogenFunc(samples_x, samples_xp, tmp_model);
98 
99  // validate model
100  CostFunc(tmp_model, x, xp, n, &nr_inliers, inliers + n, &cost, error_tol);
101  if ((nr_inliers > *consensus_size) ||
102  (nr_inliers == *consensus_size && cost < best_cost)) {
103  *consensus_size = nr_inliers;
104  best_cost = cost;
105  ICopy(tmp_model, model, k);
106  ICopy(inliers + n, inliers, *consensus_size); // record inlier indices
107  if (adaptive_trial_count) {
108  tmp_inlierprob = IDiv(static_cast<double>(*consensus_size), n);
109  if (tmp_inlierprob > actual_inlierprob) {
110  actual_inlierprob = tmp_inlierprob;
111  nr_trials = IRansacTrials(s, confidence, actual_inlierprob);
112  }
113  }
114  }
115  sample_count++;
116  }
117  bool succeeded = *consensus_size >= min_nr_inliers;
118 
119  if (succeeded && re_est_model_w_inliers && RefitFunc != nullptr) {
120  RefitFunc(x, xp, inliers, model, n, *consensus_size);
121  }
122  return succeeded;
123 }
124 
125 } // namespace common
126 } // namespace perception
127 } // namespace apollo
void ICopy(const T *src, T *dst, int n)
Definition: i_blas.h:27
int IRound(int a)
Definition: i_basic.h:197
Definition: blob.h:72
float IPow(float a, float b)
Definition: i_basic.h:142
float ILog(float x)
Definition: i_basic.h:126
void IRandomizedShuffle(T *A, int n, int l, int *s)
Definition: i_rand.h:78
float IDiv(float a, float b)
Definition: i_basic.h:35
int IRansacTrials(int sample_size, double confidence, double inlierprob)
Definition: i_ransac.h:31
const int I_DEFAULT_SEED
Definition: i_rand.h:24
void IRandomSample(int *sample, int n, int pool_size, int *s)
Definition: i_rand.h:47
void IZero(T *a, int n)
Definition: i_blas.h:320
bool RobustBinaryFitRansac(T *x, T *xp, int n, T *model, int *consensus_size, int *inliers, T error_tol, bool re_est_model_w_inliers=false, bool adaptive_trial_count=false, double confidence=0.99, double inlierprob=0.5, int min_nr_inliers=s, bool random_shuffle_inputs=false)
Definition: i_ransac.h:47