28 #include <Base/Common/BIASpragmaStart.hh>
30 #include <Base/Debug/Debug.hh>
31 #include <Base/Math/Random.hh>
39 #define D_MSAC_SOLVEM 0x00000001
40 #define D_MSAC_SAMPLES 0x00000002
41 #define D_MSAC_INIT 0x00000004
50 template <
class SolutionType>
58 int Init(
int data_size);
60 int Init(
int data_size,
double terminate_score,
int solution_count);
62 int SolveMaster(SolutionType &solution,
63 std::vector<bool> &inliers);
66 int GetSampleSolution(std::vector<unsigned int> &which_samples,
67 SolutionType &solutions);
70 bool EvaluateSolution(
const SolutionType& solution,
71 std::vector<bool>& inlier,
int& num_inliers,
72 double& evaluate_score);
75 bool RefineSolution(std::vector<unsigned int>& which_samples,
76 SolutionType& solution,std::vector<bool>& new_inliers);
79 bool GenerateSamples(
int sample_index,
80 std::vector<unsigned int>& which_samples);
94 bool _GenerateSamplesRandom(
int sample_index,
95 std::vector<unsigned int>& which_samples);
97 double _CalculateTerminateScore(
double sigma,
98 double expected_inlier_fraction);
100 int _CalculateSampleCount(
double expected_inlier_fraction);
112 template <
class SolutionType>
127 template <
class SolutionType>
132 template <
class SolutionType>
135 _iDataSize=data_size;
136 _dTerminateScore=_CalculateTerminateScore(_dExpectedSigma,
137 _dExpectedInlierFraction);
139 _iSolutionCount=_CalculateSampleCount(_dExpectedInlierFraction);
141 return Init(data_size, _dTerminateScore, _iSolutionCount);
144 template <
class SolutionType>
148 _iDataSize=data_size;
149 _dTerminateScore=terminate_score;
151 _iSolutionCount=solution_count;
153 BIASCDOUT(D_MSAC_INIT, _iDataSize<<
" data points whereof "
154 <<_dExpectedInlierFraction*data_size<<
" are expected to be "
155 <<
"inliers.\n Inliers are assumed normal distributed with sigma "
156 <<_dExpectedSigma<<
".\n Using confidence in solution of "
157 <<_MSACConfidenceThresh
158 <<
" % with sample set size "<<_iSampleSize<<
" leads to at most "
160 <<
" solutions to be evaluated.\n MSAC will abort on score below "
161 <<_dTerminateScore<<
"\n");
162 BIASASSERT(_iDataSize>=_iSampleSize);
167 template <
class SolutionType>
169 std::vector<bool>& inliers)
171 SolutionType best_sol, act_sol;
172 std::vector<unsigned> which_samples;
173 std::vector<bool> tmp(_iDataSize,
false);
174 std::vector<std::vector<bool> > inliervec(_iSolutionCount, tmp);
175 double act_score, best_score=numeric_limits<double>::max();
176 int sample_index, best_index=-1, act_num_inlier, best_num_inlier=0;
178 which_samples.resize(_iSampleSize);
179 inliers.resize(_iSolutionCount);
181 for (sample_index = 0; sample_index < _iSolutionCount; sample_index++){
184 if (GenerateSamples(sample_index, which_samples)){
185 if (!GetSampleSolution(which_samples, act_sol)){
186 BIASERR(
"GetSampleSolution failed");
189 if (!EvaluateSolution(act_sol, inliervec[sample_index],
190 act_num_inlier, act_score)){
191 BIASERR(
"Evaluate Solution failed");
194 BIASCDOUT(D_MSAC_SOLVEM, setw(3)<<sample_index<<
"th solution: "
195 <<act_sol<<
" with score "<<act_score<<
" and "<<act_num_inlier
198 if (_MSACRefineSolution &&
true){
199 which_samples.clear();
200 for (
int i=0; i<_iDataSize; i++){
201 if (inliervec[sample_index][i]){
202 which_samples.push_back(i);
206 if (!RefineSolution(which_samples, act_sol,
207 inliervec[sample_index])){
208 BIASERR(
"RefineSolution returned false");
211 if (!EvaluateSolution(act_sol, inliervec[sample_index],
212 act_num_inlier, act_score)){
213 BIASERR(
"Evaluate Solution failed");
216 BIASCDOUT(D_MSAC_SOLVEM, setw(3)<<sample_index
217 <<
"th refined solution: "
218 <<act_sol<<
" with score "<<act_score<<
" and "
219 <<act_num_inlier<<
" inliers\n");
224 if (sample_index!=0){
225 BIASCDOUT(D_MSAC_SOLVEM,
"(best: "<<best_sol<<
"/"<<best_score<<
"/"
226 <<best_num_inlier<<std::endl);
229 if (best_score>act_score){
230 best_score=act_score;
231 best_index=sample_index;
232 best_num_inlier=act_num_inlier;
235 if (best_score<_dTerminateScore){
236 BIASCDOUT(D_MSAC_SOLVEM,
"finished sampling, got a good score "
237 <<best_score<<std::endl);
242 BIASERR(
"GenerateSamples failed");
247 if (!_MSACRefineSolution){
249 BIASCDOUT(D_MSAC_SOLVEM,
"now refining solution "<<solution<<std::endl);
250 which_samples.clear();
251 for (
int i=0; i<_iDataSize; i++){
252 if (inliervec[best_index][i]){
253 which_samples.push_back(i);
257 if (!RefineSolution(which_samples, solution, inliers)){
258 BIASERR(
"RefineSolution returned false");
262 inliers=inliervec[best_index];
265 BIASCDOUT(D_MSAC_SOLVEM,
"finished: score "<<best_score<<
" with "
266 <<best_num_inlier<<
" inlier, solution is "<<solution<<std::endl);
270 template <
class SolutionType>
273 SolutionType &solutions)
275 BIASERR(
"this function should be implemented in derived class");
281 template <
class SolutionType>
284 int& num_inliers,
double& evaluate_score)
286 BIASERR(
"this function should be implemented in derived class");
293 template <
class SolutionType>
296 SolutionType& solution, std::vector<bool>& new_inliers)
298 BIASERR(
"this function should be implemented in derived class");
304 template <
class SolutionType>
308 return _GenerateSamplesRandom(sample_index, which_samples);
314 template <
class SolutionType>
317 std::vector<unsigned int>& which_samples)
321 if (_iSampleSize==0){
322 BIASERR(
"call Init or appropriate constructor befor using MSAC");
326 if (_iSampleSize>=_iDataSize){
327 BIASERR(
"_iDataSize should be set in derived class befor using MSAC"
328 <<
" _iSampleSize="<<_iSampleSize<<
" _iDataSize : "
338 which_samples.clear();
342 if (find(which_samples.begin(), which_samples.end(), index)==
343 which_samples.end()){
344 which_samples.push_back(index);
347 }
while (count<_iSampleSize);
350 if ((GetDebugLevel() & D_MSAC_SAMPLES)!=0){
351 BIASCDOUT(D_MSAC_SAMPLES,
"---------- sample "<<sample_index
352 <<
" ---------------------------------"<<
"\nnow using data: ");
353 std::ostream_iterator<int> oi(GetDebugStream(),
" ");
354 std::copy(which_samples.begin(), which_samples.end(), oi);
355 GetDebugStream() << std::endl;
365 template <
class SolutionType>
370 res += _iDataSize * expected_inlier_fraction * sigma;
371 res += _iDataSize * (1.0-expected_inlier_fraction) *
372 _MSACSigmaFac * sigma;
379 template <
class SolutionType>
383 if (expected_inlier_fraction == 1.0)
388 int res = int(log (1.0 - (_MSACConfidenceThresh)) /
389 log (1.0 - pow (expected_inlier_fraction,
390 (
double) _iSampleSize)));
397 #include <Base/Common/BIASpragmaEnd.hh>
399 #endif // __MSAC_hh__
virtual bool EvaluateSolution(const SolutionType &solution, std::vector< bool > &inlier, int &num_inliers, double &evaluate_score)
virtual bool GenerateSamples(int sample_index, std::vector< unsigned int > &which_samples)
int _CalculateSampleCount(double expected_inlier_fraction)
int GetUniformDistributedInt(const int min, const int max)
get uniform distributed random variable including min/max
int SolveMaster(SolutionType &solution, std::vector< bool > &inliers)
bool _GenerateSamplesRandom(int sample_index, std::vector< unsigned int > &which_samples)
double _MSACConfidenceThresh
virtual int GetSampleSolution(std::vector< unsigned int > &which_samples, SolutionType &solutions)
double _CalculateTerminateScore(double sigma, double expected_inlier_fraction)
virtual bool RefineSolution(std::vector< unsigned int > &which_samples, SolutionType &solution, std::vector< bool > &new_inliers)
this class does something, but WHAT? Is it the M-Estimator SAmple Consensus ??
double _dExpectedInlierFraction
class for producing random numbers from different distributions