54 #include <visp3/core/vpColVector.h> 55 #include <visp3/core/vpMath.h> 56 #include <visp3/core/vpRansac.h> 57 #include <visp3/vision/vpPose.h> 58 #include <visp3/vision/vpPoseException.h> 60 #if defined(VISP_HAVE_CPP11_COMPATIBILITY) 61 #include <unordered_map> 64 #if defined(VISP_HAVE_OPENMP) 73 struct ComparePointDuplicate {
74 bool operator()(
const vpPoint &point1,
const vpPoint &point2)
const 76 if (point1.
oP[0] < point2.
oP[0])
78 if (point1.
oP[0] > point2.
oP[0])
81 if (point1.
oP[1] < point2.
oP[1])
83 if (point1.
oP[1] > point2.
oP[1])
86 if (point1.
oP[2] < point2.
oP[2])
88 if (point1.
oP[2] > point2.
oP[2])
91 if (point1.
p[0] < point2.
p[0])
93 if (point1.
p[0] > point2.
p[0])
96 if (point1.
p[1] < point2.
p[1])
98 if (point1.
p[1] > point2.
p[1])
106 struct ComparePointAlmostDuplicate {
107 bool operator()(
const vpPoint &point1,
const vpPoint &point2)
const 109 if (point1.
oP[0] - point2.
oP[0] < -eps)
111 if (point1.
oP[0] - point2.
oP[0] > eps)
114 if (point1.
oP[1] - point2.
oP[1] < -eps)
116 if (point1.
oP[1] - point2.
oP[1] > eps)
119 if (point1.
oP[2] - point2.
oP[2] < -eps)
121 if (point1.
oP[2] - point2.
oP[2] > eps)
124 if (point1.
p[0] - point2.
p[0] < -eps)
126 if (point1.
p[0] - point2.
p[0] > eps)
129 if (point1.
p[1] - point2.
p[1] < -eps)
131 if (point1.
p[1] - point2.
p[1] > eps)
139 struct CompareObjectPointDegenerate {
140 bool operator()(
const vpPoint &point1,
const vpPoint &point2)
const 142 if (point1.
oP[0] - point2.
oP[0] < -eps)
144 if (point1.
oP[0] - point2.
oP[0] > eps)
147 if (point1.
oP[1] - point2.
oP[1] < -eps)
149 if (point1.
oP[1] - point2.
oP[1] > eps)
152 if (point1.
oP[2] - point2.
oP[2] < -eps)
154 if (point1.
oP[2] - point2.
oP[2] > eps)
162 struct CompareImagePointDegenerate {
163 bool operator()(
const vpPoint &point1,
const vpPoint &point2)
const 165 if (point1.
p[0] - point2.
p[0] < -eps)
167 if (point1.
p[0] - point2.
p[0] > eps)
170 if (point1.
p[1] - point2.
p[1] < -eps)
172 if (point1.
p[1] - point2.
p[1] > eps)
180 struct FindDegeneratePoint {
181 explicit FindDegeneratePoint(
const vpPoint &pt) : m_pt(pt) {}
183 bool operator()(
const vpPoint &pt)
185 return ((std::fabs(m_pt.oP[0] - pt.
oP[0]) < eps && std::fabs(m_pt.oP[1] - pt.
oP[1]) < eps &&
186 std::fabs(m_pt.oP[2] - pt.
oP[2]) < eps) ||
187 (std::fabs(m_pt.p[0] - pt.
p[0]) < eps && std::fabs(m_pt.p[1] - pt.
p[1]) < eps));
193 #if defined(VISP_HAVE_CPP11_COMPATIBILITY) 195 struct HashDuplicate {
196 std::size_t operator()(
const vpPoint &point)
const 202 res = res * 31 + hash<double>()(point.
oP[0]);
203 res = res * 31 + hash<double>()(point.
oP[1]);
204 res = res * 31 + hash<double>()(point.
oP[2]);
205 res = res * 31 + hash<double>()(point.
p[0]);
206 res = res * 31 + hash<double>()(point.
p[1]);
213 struct ComparePointDuplicateUnorderedMap {
214 bool operator()(
const vpPoint &point1,
const vpPoint &point2)
const 216 return (std::fabs(point1.
oP[0] - point2.
oP[0]) < std::numeric_limits<double>::epsilon() &&
217 std::fabs(point1.
oP[1] - point2.
oP[1]) < std::numeric_limits<double>::epsilon() &&
218 std::fabs(point1.
oP[2] - point2.
oP[2]) < std::numeric_limits<double>::epsilon() &&
219 std::fabs(point1.
p[0] - point2.
p[0]) < std::numeric_limits<double>::epsilon() &&
220 std::fabs(point1.
p[1] - point2.
p[1]) < std::numeric_limits<double>::epsilon());
226 bool vpPose::RansacFunctor::poseRansacImpl()
228 unsigned int size = (
unsigned int)m_listOfUniquePoints.size();
230 unsigned int nbMinRandom = 4;
232 #if defined(_WIN32) && (defined(_MSC_VER) || defined(__MINGW32__)) 233 srand(m_initial_seed);
238 bool foundSolution =
false;
239 while (nbTrials < m_ransacMaxTrials && m_nbInliers < (
unsigned int)m_ransacNbInlierConsensus) {
241 std::vector<unsigned int> cur_consensus;
243 std::vector<unsigned int> cur_outliers;
245 std::vector<unsigned int> cur_randoms;
248 std::vector<vpPoint> cur_inliers;
259 std::vector<bool> usedPt(size,
false);
262 for (
unsigned int i = 0; i < nbMinRandom;) {
263 if ((
size_t)std::count(usedPt.begin(), usedPt.end(),
true) == usedPt.size()) {
270 #if defined(_WIN32) && (defined(_MSC_VER) || defined(__MINGW32__)) 271 unsigned int r_ = (
unsigned int)rand() % size;
273 unsigned int r_ = (
unsigned int)rand_r(&m_initial_seed) % size;
278 #if defined(_WIN32) && (defined(_MSC_VER) || defined(__MINGW32__)) 279 r_ = (
unsigned int)rand() % size;
281 r_ = (
unsigned int)rand_r(&m_initial_seed) % size;
286 vpPoint pt = m_listOfUniquePoints[r_];
288 bool degenerate =
false;
289 if (m_checkDegeneratePoints) {
290 if (std::find_if(poseMin.listOfPoints.begin(), poseMin.listOfPoints.end(), FindDegeneratePoint(pt)) !=
291 poseMin.listOfPoints.end()) {
298 cur_randoms.push_back(r_);
304 if (poseMin.
npt < nbMinRandom) {
310 bool is_valid_lagrange =
false;
311 bool is_valid_dementhon =
false;
314 double r_lagrange = DBL_MAX;
315 double r_dementhon = DBL_MAX;
320 is_valid_lagrange =
true;
327 is_valid_dementhon =
true;
333 is_valid_lagrange =
false;
334 r_lagrange = DBL_MAX;
338 is_valid_dementhon =
false;
339 r_dementhon = DBL_MAX;
344 if (is_valid_lagrange || is_valid_dementhon) {
346 if (r_lagrange < r_dementhon) {
348 cMo_tmp = cMo_lagrange;
351 cMo_tmp = cMo_dementhon;
353 r = sqrt(r) / (double)nbMinRandom;
357 bool isPoseValid =
true;
358 if (m_func != NULL) {
359 isPoseValid = m_func(&cMo_tmp);
368 if (isPoseValid && r < m_ransacThreshold) {
369 unsigned int nbInliersCur = 0;
370 unsigned int iter = 0;
371 for (std::vector<vpPoint>::const_iterator it = m_listOfUniquePoints.begin(); it != m_listOfUniquePoints.end();
377 double error = sqrt(d);
378 if (error < m_ransacThreshold) {
379 bool degenerate =
false;
380 if (m_checkDegeneratePoints) {
381 if (std::find_if(cur_inliers.begin(), cur_inliers.end(), FindDegeneratePoint(*it)) != cur_inliers.end()) {
390 cur_consensus.push_back(iter);
391 cur_inliers.push_back(*it);
393 cur_outliers.push_back(iter);
396 cur_outliers.push_back(iter);
400 if (nbInliersCur > m_nbInliers) {
401 foundSolution =
true;
402 m_best_consensus = cur_consensus;
403 m_nbInliers = nbInliersCur;
408 if (nbTrials >= m_ransacMaxTrials) {
409 foundSolution =
true;
419 return foundSolution;
422 #if defined(VISP_HAVE_PTHREAD) || (defined(_WIN32) && !defined(WINRT_8_0)) 425 vpPose::RansacFunctor *f =
reinterpret_cast<vpPose::RansacFunctor *
>(arg);
444 if (listP.size() != listOfPoints.size()) {
445 std::cerr <<
"You should not modify vpPose::listP!" << std::endl;
446 listOfPoints = std::vector<vpPoint>(listP.begin(), listP.end());
449 ransacInliers.clear();
450 ransacInlierIndex.clear();
452 std::vector<unsigned int> best_consensus;
453 unsigned int nbInliers = 0;
457 if (listOfPoints.size() < 4) {
462 std::vector<vpPoint> listOfUniquePoints;
463 std::map<size_t, size_t> mapOfUniquePointIndex;
466 bool prefilterDuplicatePoints = (ransacFlags & PREFILTER_DUPLICATE_POINTS) != 0;
467 bool prefilterAlmostDuplicatePoints = (ransacFlags & PREFILTER_ALMOST_DUPLICATE_POINTS) != 0;
468 bool prefilterDegeneratePoints = (ransacFlags & PREFILTER_DEGENERATE_POINTS) != 0;
469 bool checkDegeneratePoints = (ransacFlags & CHECK_DEGENERATE_POINTS) != 0;
471 if (prefilterDuplicatePoints || prefilterAlmostDuplicatePoints || prefilterDegeneratePoints) {
473 if (prefilterDuplicatePoints) {
474 #if defined(VISP_HAVE_CPP11_COMPATIBILITY) 475 std::unordered_map<vpPoint, size_t, HashDuplicate, ComparePointDuplicateUnorderedMap> filterMap;
477 for (std::vector<vpPoint>::const_iterator it_pt = listOfPoints.begin(); it_pt != listOfPoints.end();
478 ++it_pt, index_pt++) {
479 if (filterMap.find(*it_pt) == filterMap.end()) {
480 filterMap[*it_pt] = index_pt;
482 listOfUniquePoints.push_back(*it_pt);
483 mapOfUniquePointIndex[listOfUniquePoints.size() - 1] = index_pt;
487 std::map<vpPoint, size_t, ComparePointDuplicate> filterMap;
489 for (std::vector<vpPoint>::const_iterator it_pt = listOfPoints.begin(); it_pt != listOfPoints.end();
490 ++it_pt, index_pt++) {
491 if (filterMap.find(*it_pt) == filterMap.end()) {
492 filterMap[*it_pt] = index_pt;
494 listOfUniquePoints.push_back(*it_pt);
495 mapOfUniquePointIndex[listOfUniquePoints.size() - 1] = index_pt;
499 }
else if (prefilterAlmostDuplicatePoints) {
500 std::map<vpPoint, size_t, ComparePointAlmostDuplicate> filterMap;
502 for (std::vector<vpPoint>::const_iterator it_pt = listOfPoints.begin(); it_pt != listOfPoints.end();
503 ++it_pt, index_pt++) {
504 if (filterMap.find(*it_pt) == filterMap.end()) {
505 filterMap[*it_pt] = index_pt;
507 listOfUniquePoints.push_back(*it_pt);
508 mapOfUniquePointIndex[listOfUniquePoints.size() - 1] = index_pt;
513 std::map<vpPoint, size_t, CompareObjectPointDegenerate> filterObjectPointMap;
515 for (std::vector<vpPoint>::const_iterator it_pt = listOfPoints.begin(); it_pt != listOfPoints.end();
516 ++it_pt, index_pt++) {
517 if (filterObjectPointMap.find(*it_pt) == filterObjectPointMap.end()) {
518 filterObjectPointMap[*it_pt] = index_pt;
522 std::map<vpPoint, size_t, CompareImagePointDegenerate> filterImagePointMap;
523 for (std::map<vpPoint, size_t>::const_iterator it = filterObjectPointMap.begin();
524 it != filterObjectPointMap.end(); ++it) {
525 if (filterImagePointMap.find(it->first) == filterImagePointMap.end()) {
526 filterImagePointMap[it->first] = it->second;
528 listOfUniquePoints.push_back(it->first);
529 mapOfUniquePointIndex[listOfUniquePoints.size() - 1] = it->second;
535 listOfUniquePoints = listOfPoints;
538 for (std::vector<vpPoint>::const_iterator it_pt = listOfPoints.begin(); it_pt != listOfPoints.end();
539 ++it_pt, index_pt++) {
540 mapOfUniquePointIndex[index_pt] = index_pt;
544 unsigned int size = (
unsigned int)listOfUniquePoints.
size();
549 bool executeParallelVersion = useParallelRansac;
551 #if defined(VISP_HAVE_PTHREAD) || (defined(_WIN32) && !defined(WINRT_8_0)) 556 if (executeParallelVersion) {
557 #if !defined(VP_THREAD_OK) && !defined(VISP_HAVE_OPENMP) 558 executeParallelVersion =
false;
559 std::cerr <<
"Pthread or WIN32 API or OpenMP is needed to use the " 560 "parallel RANSAC version." 562 #elif !defined(VP_THREAD_OK) 564 #define PARALLEL_RANSAC_OPEN_MP 565 #elif !defined(VISP_HAVE_OPENMP) 566 if (nbParallelRansacThreads <= 0) {
568 executeParallelVersion =
false;
569 std::cerr <<
"OpenMP is needed to get the number of CPU threads so use " 570 "the sequential mode instead." 573 nbThreads = nbParallelRansacThreads;
574 if (nbThreads == 1) {
575 executeParallelVersion =
false;
578 #elif defined(VP_THREAD_OK) && defined(VISP_HAVE_OPENMP) 579 if (nbParallelRansacThreads <= 0) {
581 nbThreads = omp_get_max_threads();
582 if (nbThreads <= 1) {
584 executeParallelVersion =
false;
590 bool foundSolution =
false;
592 if (executeParallelVersion) {
593 #if defined(PARALLEL_RANSAC_OPEN_MP) 603 #if defined(VISP_HAVE_OPENMP) 606 unsigned int initial_seed = (
unsigned int)omp_get_thread_num();
608 if (omp_get_num_threads() == 1) {
612 unsigned int initial_seed = 0;
615 #if defined(_WIN32) && (defined(_MSC_VER) || defined(__MINGW32__)) 619 unsigned int nbMinRandom = 4;
622 unsigned int nb_best_inliers = 0;
626 bool foundSolutionWithConsensus =
false;
631 for (
int nbTrials = 0; nbTrials < ransacMaxTrials; nbTrials++) {
634 if (!foundSolutionWithConsensus) {
637 std::vector<unsigned int> cur_consensus;
639 std::vector<unsigned int> cur_outliers;
641 std::vector<unsigned int> cur_randoms;
644 std::vector<vpPoint> cur_inliers;
650 std::vector<bool> usedPt(size,
false);
654 for (
unsigned int i = 0; i < nbMinRandom;) {
655 if ((
size_t)std::count(usedPt.begin(), usedPt.end(),
true) == usedPt.size()) {
662 #if defined(_WIN32) && (defined(_MSC_VER) || defined(__MINGW32__)) 663 unsigned int r_ = (
unsigned int)rand() % size;
665 unsigned int r_ = (
unsigned int)rand_r(&initial_seed) % size;
670 #if defined(_WIN32) && (defined(_MSC_VER) || defined(__MINGW32__)) 671 r_ = (
unsigned int)rand() % size;
673 r_ = (
unsigned int)rand_r(&initial_seed) % size;
678 vpPoint pt = listOfUniquePoints[r_];
680 bool degenerate =
false;
681 if (checkDegeneratePoints) {
682 if (std::find_if(poseMin.listOfPoints.begin(), poseMin.listOfPoints.end(), FindDegeneratePoint(pt)) !=
683 poseMin.listOfPoints.end()) {
690 cur_randoms.push_back(r_);
696 if (poseMin.
npt >= nbMinRandom) {
698 bool is_valid_lagrange =
false;
699 bool is_valid_dementhon =
false;
703 double r_lagrange = DBL_MAX;
704 double r_dementhon = DBL_MAX;
709 is_valid_lagrange =
true;
716 is_valid_dementhon =
true;
722 is_valid_lagrange =
false;
723 r_lagrange = DBL_MAX;
727 is_valid_dementhon =
false;
728 r_dementhon = DBL_MAX;
733 if (is_valid_lagrange || is_valid_dementhon) {
734 if (r_lagrange < r_dementhon) {
736 cMo_tmp = cMo_lagrange;
739 cMo_tmp = cMo_dementhon;
741 r = sqrt(r) / (double)nbMinRandom;
745 bool isPoseValid =
true;
747 isPoseValid = func(&cMo_tmp);
750 if (isPoseValid && r < ransacThreshold) {
751 unsigned int nbInliersCur = 0;
752 unsigned int iter = 0;
753 for (std::vector<vpPoint>::const_iterator it = listOfUniquePoints.begin();
754 it != listOfUniquePoints.end(); ++it, iter++) {
759 double error = sqrt(d);
760 if (error < ransacThreshold) {
761 bool degenerate =
false;
762 if (checkDegeneratePoints) {
763 if (std::find_if(cur_inliers.begin(), cur_inliers.end(), FindDegeneratePoint(*it)) !=
773 cur_consensus.push_back(iter);
774 cur_inliers.push_back(*it);
776 cur_outliers.push_back(iter);
779 cur_outliers.push_back(iter);
783 #pragma omp critical(update_best_consensus_set) 785 if (nbInliersCur > nb_best_inliers) {
786 foundSolution =
true;
787 best_consensus = cur_consensus;
789 nb_best_inliers = nbInliersCur;
791 if (nbInliersCur >= ransacNbInlierConsensus) {
792 foundSolutionWithConsensus =
true;
802 nbInliers = best_consensus.size();
804 #elif defined(VP_THREAD_OK) 805 std::vector<vpThread *> threads((
size_t)nbThreads);
806 std::vector<RansacFunctor> ransac_func((
size_t)nbThreads);
808 int splitTrials = ransacMaxTrials / nbThreads;
809 for (
size_t i = 0; i < (size_t)nbThreads; i++) {
810 unsigned int initial_seed = (
unsigned int)i;
811 if (i < (
size_t)nbThreads - 1) {
812 ransac_func[i] = RansacFunctor(cMo, ransacNbInlierConsensus, splitTrials, ransacThreshold, initial_seed,
813 checkDegeneratePoints, listOfUniquePoints, func);
815 int maxTrialsRemainder = ransacMaxTrials - splitTrials * (nbThreads - 1);
816 ransac_func[i] = RansacFunctor(cMo, ransacNbInlierConsensus, maxTrialsRemainder, ransacThreshold, initial_seed,
817 checkDegeneratePoints, listOfUniquePoints, func);
825 for (std::vector<vpPoint>::const_iterator it = listOfPoints.begin(); it != listOfPoints.end(); ++it) {
829 for (
size_t i = 0; i < (size_t)nbThreads; i++) {
834 bool successRansac =
false;
835 size_t best_consensus_size = 0;
836 for (
size_t i = 0; i < (size_t)nbThreads; i++) {
837 if (ransac_func[i].getResult()) {
838 successRansac =
true;
840 if (ransac_func[i].getBestConsensus().size() > best_consensus_size) {
841 nbInliers = ransac_func[i].getNbInliers();
842 best_consensus = ransac_func[i].getBestConsensus();
843 best_consensus_size = ransac_func[i].getBestConsensus().size();
848 foundSolution = successRansac;
852 RansacFunctor sequentialRansac(cMo, ransacNbInlierConsensus, ransacMaxTrials, ransacThreshold, 0,
853 checkDegeneratePoints, listOfUniquePoints, func);
855 foundSolution = sequentialRansac.getResult();
858 nbInliers = sequentialRansac.getNbInliers();
859 best_consensus = sequentialRansac.getBestConsensus();
864 unsigned int nbMinRandom = 4;
888 if (nbInliers >= nbMinRandom)
893 for (
size_t i = 0; i < best_consensus.size(); i++) {
894 vpPoint pt = listOfUniquePoints[best_consensus[i]];
897 ransacInliers.push_back(pt);
901 for (std::vector<unsigned int>::const_iterator it_index = best_consensus.begin();
902 it_index != best_consensus.end(); ++it_index) {
903 ransacInlierIndex.push_back((
unsigned int)mapOfUniquePointIndex[*it_index]);
907 bool is_valid_lagrange =
false;
908 bool is_valid_dementhon =
false;
911 double r_lagrange = DBL_MAX;
912 double r_dementhon = DBL_MAX;
917 is_valid_lagrange =
true;
924 is_valid_dementhon =
true;
930 is_valid_lagrange =
false;
931 r_lagrange = DBL_MAX;
935 is_valid_dementhon =
false;
936 r_dementhon = DBL_MAX;
939 if (is_valid_lagrange || is_valid_dementhon) {
940 if (r_lagrange < r_dementhon) {
952 if (func != NULL && !func(&cMo)) {
956 if (computeCovariance) {
957 covarianceMatrix = pose.covarianceMatrix;
965 return foundSolution;
986 probability = (std::max)(probability, 0.0);
987 probability = (std::min)(probability, 1.0);
988 epsilon = (std::max)(epsilon, 0.0);
989 epsilon = (std::min)(epsilon, 1.0);
996 if (maxIterations <= 0) {
997 maxIterations = std::numeric_limits<int>::max();
1000 double logarg, logval, N;
1001 logarg = -std::pow(1.0 - epsilon, sampleSize);
1002 #ifdef VISP_HAVE_FUNC_LOG1P 1003 logval = log1p(logarg);
1005 logval = log(1.0 + logarg);
1007 if (
vpMath::nul(logval, std::numeric_limits<double>::epsilon())) {
1008 std::cerr <<
"vpMath::nul(log(1.0 - std::pow(1.0 - epsilon, " 1009 "sampleSize)), std::numeric_limits<double>::epsilon())" 1014 N = log((std::max)(1.0 - probability, std::numeric_limits<double>::epsilon())) / logval;
1015 if (logval < 0.0 && N < maxIterations) {
1016 return (
int)ceil(N);
1019 return maxIterations;
1046 const unsigned int &numberOfInlierToReachAConsensus,
const double &threshold,
1048 const int &maxNbTrials)
1053 for (
unsigned int i = 0; i < p2D.size(); i++) {
1054 for (
unsigned int j = 0; j < p3D.size(); j++) {
1055 vpPoint pt(p3D[j].getWorldCoordinates());
1056 pt.
set_x(p2D[i].get_x());
1057 pt.
set_y(p2D[i].get_y());
1063 if (pose.
listP.size() < 4) {
1064 vpERROR_TRACE(
"Ransac method cannot be used in that case ");
1068 pose.
listP.size()));
Implementation of an homogeneous matrix and operations on such kind of matrices.
static bool isNaN(const double value)
void setRansacThreshold(const double &t)
void set_x(const double x)
Set the point x coordinate in the image plane.
void track(const vpHomogeneousMatrix &cMo)
unsigned int size() const
Return the number of elements of the 2D array.
something is not initialized
std::list< vpPoint > listP
Array of point (use here class vpPoint)
std::vector< vpPoint > getRansacInliers() const
Class that defines what is a point.
bool poseRansac(vpHomogeneousMatrix &cMo, bool(*func)(vpHomogeneousMatrix *)=NULL)
static void findMatch(std::vector< vpPoint > &p2D, std::vector< vpPoint > &p3D, const unsigned int &numberOfInlierToReachAConsensus, const double &threshold, unsigned int &ninliers, std::vector< vpPoint > &listInliers, vpHomogeneousMatrix &cMo, const int &maxNbTrials=10000)
static bool nul(double x, double s=0.001)
static double sqr(double x)
Class used for pose computation from N points (pose from point only). Some of the algorithms implemen...
void set_y(const double y)
Set the point y coordinate in the image plane.
bool computePose(vpPoseMethodType method, vpHomogeneousMatrix &cMo, bool(*func)(vpHomogeneousMatrix *)=NULL)
unsigned int npt
Number of point used in pose computation.
void setRansacMaxTrials(const int &rM)
void setRansacNbInliersToReachConsensus(const unsigned int &nbC)
void setWorldCoordinates(const double oX, const double oY, const double oZ)
Error that can be emited by the vpPose class and its derivates.
unsigned int getRansacNbInliers() const
double get_x() const
Get the point x coordinate in the image plane.
double get_y() const
Get the point y coordinate in the image plane.
double computeResidual(const vpHomogeneousMatrix &cMo) const
Compute and return the residual expressed in meter for the pose matrix 'cMo'.
void addPoint(const vpPoint &P)
static int computeRansacIterations(double probability, double epsilon, const int sampleSize=4, int maxIterations=2000)
void setCovarianceComputation(const bool &flag)