24 #include <bias_config.h>
25 #include <Base/Common/BIASpragmaStart.hh>
27 #include <Base/Debug/Debug.hh>
28 #include <Base/Debug/Error.hh>
29 #include <Base/Debug/Exception.hh>
30 #include <Base/Math/BinomialCoefficient.hh>
31 #include <MathAlgo/RANSACEvaluatorInterface.hh>
39 # define NAN sqrt(-1.0)
42 #define COSAC_TOO_MANY_SOLUTIONS -5
43 #define COSAC_NOT_ENOUGH_MEASUREMENTS -4
44 #define COSAC_NO_SOLUTION_LEFT -3
45 #define COSAC_INVALID_ARGUMENTS -2
46 #define COSAC_NO_SOLUTIONS -1
48 #define COSAC_NOT_ENOUGH_INLIERS 1
49 #define COSAC_SCORE_TOO_BIG 2
78 template <
class SolutionType>
92 int SolveMaster(
const double inlying_data_fraction,
const double max_score,
93 SolutionType &solution, std::vector<bool> &inliers,
94 unsigned &num_inliers,
double& score);
129 const unsigned data_size);
141 const unsigned data_size,
142 std::vector<unsigned> &which_samples);
144 int GetSolution_(
const unsigned min_num_inliers,
const double max_score,
145 SolutionType& solution, std::vector<bool>& inliers,
146 unsigned& num_inliers,
double & score)
const;
148 bool IsInlier_(
typename std::list<SolStruct>::iterator solution,
149 const unsigned eval_index,
double& score);
153 const double max_score)
const
156 unsigned max_inliers = 0;
157 double min_score = std::numeric_limits<double>::max();
158 typename std::list<SolStruct>::const_iterator it;
160 BCDOUT(D_COSAC_GetSolution,
"solution: "<<it->solution<<std::endl);
161 if (it->num_inliers>max_inliers){
162 max_inliers = it->num_inliers;
163 min_score = it->score;
164 BCDOUT(D_COSAC_GetSolution,
" is best (num inliers "<<max_inliers
165 <<
", score "<<min_score<<
")"<<std::endl);
168 BCDOUT(D_COSAC_GetSolution,
" (num inliers "<<max_inliers
169 <<
", score "<<min_score<<
")"<<std::endl);
171 if (it->num_inliers==max_inliers && it->score < min_score){
172 min_score = it->score;
174 BCDOUT(D_COSAC_GetSolution,
" new best score "<<min_score
182 const struct SolStruct *
184 const double max_score)
const
187 double min_score = std::numeric_limits<double>::max();
188 typename std::list<SolStruct>::const_iterator it;
190 BCDOUT(D_COSAC_GetSolution,
"solution: "<<it->solution
192 if (it->score < min_score){
193 min_score = it->score;
195 BCDOUT(D_COSAC_GetSolution,
" is best (min_score "<<min_score
196 <<
" / num inliers: "<<it->num_inliers<<
" )"<<std::endl);
198 BCDOUT(D_COSAC_GetSolution,
" score: "<<it->score
199 <<
" / num inliers: "<<it->num_inliers<<std::endl);
211 template <
class SolutionType>
214 : RANSACEvaluator_(shi), _uiSampleSize(0), _uiDataSize(0),
215 _bRefineSolutions(true), _Solutions()
218 BEXCEPTION(
"COSAC::COSAC(): Invalid (null) argument.");
229 template <
class SolutionType>
231 SolveMaster(
const double inlying_data_fraction,
const double max_score,
232 SolutionType &solution, std::vector<bool> &inliers,
233 unsigned &num_inliers,
double& score)
235 _uiDataSize = RANSACEvaluator_->GetNumMeasurements();
236 if (_uiDataSize < _uiSampleSize){
237 return COSAC_NOT_ENOUGH_MEASUREMENTS;
242 unsigned num_solutions =
244 const unsigned max_num_solutions = 5000;
245 if (num_solutions>max_num_solutions){
246 BIASERR(
"COSAC::SolveMaster(): The number of solutions is very big "
248 <<max_num_solutions<<
") and evaluation of every solution "
249 <<
"might take a very long time. The usage of "
250 <<
"PreemptiveRANSAC instead of COSAC is suggested for this"
252 return COSAC_TOO_MANY_SOLUTIONS;
255 BIASERR(
"COSAC::SolveMaster(): The number of solutions is very big (>"
256 <<std::numeric_limits<unsigned>::max()
257 <<
") and evaluation of every solution "
258 <<
"might take a very long time. The usage of "
259 <<
"PreemptiveRANSAC instead of COSAC is suggested for this"
260 <<
" case."<<ex.
What());
261 return COSAC_TOO_MANY_SOLUTIONS;
264 if (inlying_data_fraction<0.0 || inlying_data_fraction>1.0){
265 return COSAC_INVALID_ARGUMENTS;
267 GenerateSolutions_(_uiSampleSize, _uiDataSize);
268 if (_Solutions.empty()){
269 return COSAC_NO_SOLUTIONS;
272 EvaluateSolutions_(_uiDataSize);
274 if (_bRefineSolutions){
275 GenerateRefinedSolutions_(_uiDataSize);
276 if (_Solutions.empty()){
277 return COSAC_NO_SOLUTIONS;
280 EvaluateSolutions_(_uiDataSize);
283 const unsigned min_num_inliers =
284 (unsigned)floor(inlying_data_fraction*_uiDataSize);
285 BIASASSERT(min_num_inliers<=_uiDataSize);
286 int res = GetSolution_(min_num_inliers, max_score,
287 solution, inliers, num_inliers, score);
293 template <
class SolutionType>
297 unsigned num_solutions = 0;
298 std::vector<unsigned> which_samples;
299 std::vector<SolutionType> solutions;
306 while (GetNextCombination_(sample_size, data_size, which_samples)){
307 int res = RANSACEvaluator_->GetSampleSolutions(which_samples, solutions);
309 for (
unsigned sol_idx=0; sol_idx<solutions.size(); sol_idx++){
311 BIASASSERT(st.
inliers.size()==data_size);
312 _Solutions.push_back(st);
317 return num_solutions;
321 template <
class SolutionType>
325 typename std::list<SolStruct>::iterator it;
332 unsigned num_refined = 0;
333 for (it = _Solutions.begin(); it !=_Solutions.end(); it++){
335 bool res = RANSACEvaluator_->RefineSolution(it->inliers, st.
solution);
337 BIASASSERT(st.
inliers.size()==data_size);
338 _Solutions.push_back(st);
346 template <
class SolutionType>
350 typename std::list<SolStruct>::iterator it;
352 for (
unsigned data_idx=0; data_idx<data_size; data_idx++){
353 for (it=_Solutions.begin(); it!=_Solutions.end(); it++){
354 IsInlier_(it, data_idx, score);
402 template <
class SolutionType>
404 IsInlier_(
typename std::list<SolStruct>::iterator solution,
405 const unsigned eval_index,
double& score)
407 BCDOUT(D_COSAC_Inlier,
"eval_index: "<<eval_index<<
" ");
408 BCDOUT(D_COSAC_Inlier,
"solution->eval_index: "<<solution->eval_index);
409 if (solution->eval_index<=eval_index){
411 if (solution->inliers.size()<=eval_index){
412 std::cout <<
"eval_index: "<<eval_index<<
"\ninliers.size(): "
413 <<solution->inliers.size()<<std::endl;
415 BIASASSERT(solution->eval_index==eval_index);
416 BIASASSERT(solution->inliers.size()>eval_index);
417 BCDOUT(D_COSAC_Inlier,
" (new score) "<<std::endl);
418 solution->inliers[eval_index] =
419 RANSACEvaluator_->IsInlier(solution->solution, eval_index, score);
420 solution->score += score;
421 if (solution->inliers[eval_index]){
422 solution->num_inliers++;
424 solution->eval_index++;
426 BCDOUT(D_COSAC_Inlier,
" (already scored) "<<std::endl);
429 BCDOUT(D_COSAC_Inlier,
"inlier: "<<std::boolalpha
430 <<solution->inliers[eval_index]<<std::endl);
431 return solution->inliers[eval_index];
435 template <
class SolutionType>
438 SolutionType& solution, std::vector<bool>& inliers,
439 unsigned& num_inliers,
double & score)
const
441 if (_Solutions.empty()) {
442 return COSAC_NO_SOLUTION_LEFT;
446 GetSolutionMinScore_(min_num_inliers, max_score);
450 score = best_sol->
score;
453 BCDOUT(D_COSAC_GetSolution,
"\nbest solution is: "
454 <<solution<<
" score: "<<score<<
" / num inliers: "
455 <<num_inliers<<std::endl);
457 bool enough_inliers = (best_sol->
num_inliers >= min_num_inliers);
458 bool score_smaller_than_max_score = (best_sol->
score <= max_score);
459 if (enough_inliers && score_smaller_than_max_score){
460 BCDOUT(D_COSAC_GetSolution,
"num_inliers: "<<num_inliers
461 <<
"\nscore: "<<score<<
"\n");
465 BCDOUT(D_COSAC_GetSolution,
"minimum quality criteria not met "
466 "(max_score: "<<max_score<<
" / min inliers "<<min_num_inliers
468 if (!enough_inliers){
469 BCDOUT(D_COSAC_GetSolution,
"not enough inliers "
470 <<
"(found: "<<best_sol->
num_inliers<<
" / expected: "
471 <<min_num_inliers<<
")\n");
472 res = res | COSAC_NOT_ENOUGH_INLIERS;
474 if (!score_smaller_than_max_score){
475 BCDOUT(D_COSAC_GetSolution,
"score too big "
476 <<
"(found: "<<best_sol->
score<<
" / expected: "
478 res = res | COSAC_SCORE_TOO_BIG;
483 BIASERR(
"no best solution returned");
487 return COSAC_NO_SOLUTION_LEFT;
491 template <
class SolutionType>
494 const unsigned data_size,
495 std::vector<unsigned> &which_samples)
497 if (data_size<sample_size) {
500 if (sample_size<=0) {
return false; }
501 if (which_samples.empty()){
502 for (
unsigned i=0; i<sample_size; i++){
503 which_samples.push_back(i);
507 BIASASSERT(which_samples.size()==sample_size);
509 for (
int i=0; i<(int)sample_size; i++){
510 int index = sample_size-i-1;
511 if (which_samples[index]+1 < data_size-i){
512 which_samples[index]++;
513 BIASASSERT(which_samples[index]<data_size);
514 for (
int k=index+1; k<(int)sample_size; k++){
515 which_samples[k] = which_samples[index]+k-index;
516 BIASASSERT(which_samples[k]<data_size);
527 #endif // __COSAC_hh__
Interface for computation of solutions and evaluation of measurements.
static long long unsigned Compute(const unsigned n, const unsigned k)
Computation of the binomial coefficient "n over k" The function throws an exception when overflow occ...
std::list< SolStruct > _Solutions
all solutions
bool refined
has a refined version of this solution already been added?
void EvaluateSolutions_(const unsigned data_size)
evaluates the solutions
Complete Sampling Consesus.
bool GetNextCombination_(const unsigned sample_size, const unsigned data_size, std::vector< unsigned > &which_samples)
Returns the next combination of samples from which a solution can be computed.
int SolveMaster(const double inlying_data_fraction, const double max_score, SolutionType &solution, std::vector< bool > &inliers, unsigned &num_inliers, double &score)
bool IsInlier_(typename std::list< SolStruct >::iterator solution, const unsigned eval_index, double &score)
std::vector< bool > inliers
inlier indicator for the data in the order given by _EvaluationOrder i.e.
COSAC(RANSACEvaluatorInterface< SolutionType > *shi)
c'tor
struct SolStruct * GetSolutionMinScore_(const unsigned min_num_inliers, const double max_score) const
unsigned _uiDataSize
the number of data for evaluation
unsigned eval_index
evaluation of the solution has taken place up to eval_index
bool _bRefineSolutions
should the solutions be refined?
long int NewDebugLevel(const std::string &name)
creates a new debuglevel
struct SolStruct * GetSolutionMaxInliers_(const unsigned min_num_inliers, const double max_score) const
void SetRefineSolutions(const unsigned refine_solutions)
RANSACEvaluatorInterface< SolutionType > * RANSACEvaluator_
the helper class for solution computation and sample evaluation
int GenerateSolutions_(const unsigned sample_size, const unsigned data_size)
returns the number of generated solution
virtual ~COSAC()
d'tor
int GenerateRefinedSolutions_(const unsigned data_size)
returns the number of succesfully refined solutions
int GetSolution_(const unsigned min_num_inliers, const double max_score, SolutionType &solution, std::vector< bool > &inliers, unsigned &num_inliers, double &score) const
unsigned _uiSampleSize
the number of samples needed by GetSampleSolutions
virtual const std::string & What() const