Visual Servoing Platform version 3.7.0
Loading...
Searching...
No Matches
vpRansac.h
1/*
2 * ViSP, open source Visual Servoing Platform software.
3 * Copyright (C) 2005 - 2024 by Inria. All rights reserved.
4 *
5 * This software is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 * See the file LICENSE.txt at the root directory of this source
10 * distribution for additional information about the GNU GPL.
11 *
12 * For using ViSP with software that can not be combined with the GNU
13 * GPL, please contact Inria about acquiring a ViSP Professional
14 * Edition License.
15 *
16 * See https://visp.inria.fr for more information.
17 *
18 * This software was developed at:
19 * Inria Rennes - Bretagne Atlantique
20 * Campus Universitaire de Beaulieu
21 * 35042 Rennes Cedex
22 * France
23 *
24 * If you have questions regarding the use of this file, please contact
25 * Inria at visp@inria.fr
26 *
27 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
28 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
29 *
30 * Description:
31 * Ransac robust algorithm.
32 */
33
37
38#ifndef VP_RANSAC_H
39#define VP_RANSAC_H
40
41#include <ctime>
42#include <visp3/core/vpConfig.h>
43#include <visp3/core/vpColVector.h>
44#include <visp3/core/vpMath.h>
45#include <visp3/core/vpUniRand.h> // random number generation
46
66template <class vpTransformation> class vpRansac
67{
68public:
69 static bool ransac(unsigned int npts, const vpColVector &x, unsigned int s, double t, vpColVector &model,
70 vpColVector &inliers, int consensus = 1000, double not_used = 0.0, int maxNbumbersOfTrials = 10000,
71 double *residual = nullptr);
72};
73
105
106template <class vpTransformation>
107bool vpRansac<vpTransformation>::ransac(unsigned int npts, const vpColVector &x, unsigned int s, double t,
108 vpColVector &M, vpColVector &inliers, int consensus, double not_used,
109 int maxNbumbersOfTrials, double *residual)
110{
111 /*
112 // bool isplanar;
113 // if (s == 4) isplanar = true;
114 // else isplanar = false;
115 */
116 (void)not_used;
117 double eps = 1e-6;
118 double p = 0.99; // Desired probability of choosing at least one sample
119 // free from outliers
120
121 int maxTrials = maxNbumbersOfTrials; // Maximum number of trials before we give up.
122 int maxDataTrials = 1000; // Max number of attempts to select a non-degenerate
123 // data set.
124 const unsigned int magic_4 = 4;
125 if (s < magic_4) {
126 s = magic_4;
127 }
128
129 // Sentinel value allowing detection of solution failure.
130 bool solutionFind = false;
131 vpColVector bestM;
132 int trialcount = 0;
133 int bestscore = -1;
134 double N = 1; // Dummy initialisation for number of trials.
135
136 vpUniRand random(static_cast<long>(time(nullptr)));
137 vpColVector bestinliers;
138 unsigned int *ind = new unsigned int[s];
139 int ninliers = 0;
140
141 while ((N > trialcount) && (consensus > bestscore) && (trialcount > maxTrials)) {
142 // Select at random s data points to form a trial model, M.
143 // In selecting these points we have to check that they are not in
144 // a degenerate configuration.
145
146 bool degenerate = true;
147 int count = 1;
148
149 while (degenerate == true) {
150 // Generate s random indicies in the range 1..npts
151 for (unsigned int i = 0; i < s; ++i) {
152 ind[i] = static_cast<unsigned int>(ceil(random() * npts)) - 1;
153 }
154
155 // Test that these points are not a degenerate configuration.
156 degenerate = vpTransformation::degenerateConfiguration(x, ind);
157 /*
158 // degenerate = feval(degenfn, x(:,ind));
159 */
160 // Safeguard against being stuck in this loop forever
161 count = count + 1;
162
163 if (count > maxDataTrials) {
164 delete[] ind;
165 throw(vpException(vpException::fatalError, "Unable to select a non degenerate data set"));
166 }
167 }
168 // Fit model to this random selection of data points.
169 vpTransformation::computeTransformation(x, ind, M);
170
171 vpColVector d;
172 // Evaluate distances between points and model.
173 vpTransformation::computeResidual(x, M, d);
174
175 // Find the indices of points that are inliers to this model.
176 if (residual != nullptr) {
177 *residual = 0.0;
178 }
179 ninliers = 0;
180 for (unsigned int i = 0; i < npts; ++i) {
181 double resid = fabs(d[i]);
182 if (resid < t) {
183 inliers[i] = 1;
184 ++ninliers;
185 if (residual != nullptr) {
186 *residual += fabs(d[i]);
187 }
188 }
189 else {
190 inliers[i] = 0;
191 }
192 }
193
194 if (ninliers > bestscore) // Largest set of inliers so far...
195 {
196 bestscore = ninliers; // Record data for this model
197 bestinliers = inliers;
198 bestM = M;
199 solutionFind = true;
200
201 // Update estimate of N, the number of trials to ensure we pick,
202 // with probability p, a data set with no outliers.
203
204 double fracinliers = static_cast<double>(ninliers) / static_cast<double>(npts);
205
206 double pNoOutliers = 1 - pow(fracinliers, static_cast<int>(s));
207
208 pNoOutliers = vpMath::maximum(eps, pNoOutliers); // Avoid division by -Inf
209 pNoOutliers = vpMath::minimum(1 - eps, pNoOutliers); // Avoid division by 0.
210 N = (log(1 - p) / log(pNoOutliers));
211 }
212
213 // Safeguard against being stuck in this loop forever
214 ++trialcount;
215 }
216 if (trialcount > maxTrials) {
217 std::cout << "Warning: ransac reached the maximum number of " << maxTrials << " trials" << std::endl;
218 }
219 if (solutionFind == true) { // We got a solution
220 M = bestM;
221 inliers = bestinliers;
222 }
223 else {
224 std::cout << "Warning: ransac was unable to find a useful solution" << std::endl;
225 M = 0;
226 }
227
228 if (residual != nullptr) {
229 if (ninliers > 0) {
230 *residual /= ninliers;
231 }
232 }
233
234 delete[] ind;
235
236 return true;
237}
238END_VISP_NAMESPACE
239#endif
Implementation of column vector and the associated operations.
error that can be emitted by ViSP classes.
Definition vpException.h:60
@ fatalError
Fatal error.
Definition vpException.h:72
static Type maximum(const Type &a, const Type &b)
Definition vpMath.h:257
static Type minimum(const Type &a, const Type &b)
Definition vpMath.h:265
This class is a generic implementation of the Ransac algorithm. It cannot be used alone.
Definition vpRansac.h:67
static bool ransac(unsigned int npts, const vpColVector &x, unsigned int s, double t, vpColVector &model, vpColVector &inliers, int consensus=1000, double not_used=0.0, int maxNbumbersOfTrials=10000, double *residual=nullptr)
RANSAC - Robustly fits a model to data with the RANSAC algorithm.
Definition vpRansac.h:107
Class for generating random numbers with uniform probability density.
Definition vpUniRand.h:127