1 /*
2 * Copyright (C) 2017 Alberto Irurueta Carro (alberto@irurueta.com)
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 package com.irurueta.geometry.estimators;
17
18 import com.irurueta.algebra.Matrix;
19 import com.irurueta.geometry.EuclideanTransformation3D;
20 import com.irurueta.geometry.Point3D;
21 import com.irurueta.geometry.refiners.EuclideanTransformation3DRefiner;
22 import com.irurueta.numerical.robust.InliersData;
23 import com.irurueta.numerical.robust.RobustEstimatorException;
24 import com.irurueta.numerical.robust.RobustEstimatorMethod;
25
26 import java.util.List;
27
28 /**
29 * This is an abstract class to robustly find the best Euclidean transformation
30 * for collections mof matching 3D points.
31 * Implementations of this class should be able to detect and discard outliers
32 * in order to find the best solution.
33 */
34 @SuppressWarnings("DuplicatedCode")
35 public abstract class EuclideanTransformation3DRobustEstimator {
36 /**
37 * Minimum number of matched points required to estimate an Euclidean 2D
38 * transformation.
39 */
40 public static final int MINIMUM_SIZE = EuclideanTransformation3DEstimator.MINIMUM_SIZE;
41
42 /**
43 * For some point configurations a solution can be found with only 3 points.
44 */
45 public static final int WEAK_MINIMUM_SIZE = EuclideanTransformation3DEstimator.WEAK_MINIMUM_SIZE;
46
47 /**
48 * Default amount of progress variation before notifying a change in
49 * estimation progress. By default, this is set to 5%.
50 */
51 public static final float DEFAULT_PROGRESS_DELTA = 0.05f;
52
53 /**
54 * Minimum allowed value for progress delta.
55 */
56 public static final float MIN_PROGRESS_DELTA = 0.0f;
57
58 /**
59 * Maximum allowed value for progress delta.
60 */
61 public static final float MAX_PROGRESS_DELTA = 1.0f;
62
63 /**
64 * Constant defining default confidence of the estimated result, which is
65 * 99%. This means that with a probability of 99% estimation will be
66 * accurate because chosen sub-samples will be inliers.
67 */
68 public static final double DEFAULT_CONFIDENCE = 0.99;
69
70 /**
71 * Default maximum allowed number of iterations.
72 */
73 public static final int DEFAULT_MAX_ITERATIONS = 5000;
74
75 /**
76 * Minimum allowed confidence value.
77 */
78 public static final double MIN_CONFIDENCE = 0.0;
79
80 /**
81 * Maximum allowed confidence value.
82 */
83 public static final double MAX_CONFIDENCE = 1.0;
84
85 /**
86 * Minimum allowed number of iterations.
87 */
88 public static final int MIN_ITERATIONS = 1;
89
90 /**
91 * Indicates that is refined by default using Levenberg-Marquardt
92 * fitting algorithm over found inliers.
93 */
94 public static final boolean DEFAULT_REFINE_RESULT = true;
95
96 /**
97 * Indicates that covariance is not kept by default after refining result.
98 */
99 public static final boolean DEFAULT_KEEP_COVARIANCE = false;
100
101 /**
102 * Default robust estimator method when none is provided.
103 */
104 public static final RobustEstimatorMethod DEFAULT_ROBUST_METHOD = RobustEstimatorMethod.PROMEDS;
105
106 /**
107 * Listener to be notified of events such as when estimation starts, ends
108 * or its progress significantly changes.
109 */
110 protected EuclideanTransformation3DRobustEstimatorListener listener;
111
112 /**
113 * Indicates if this estimator is locked because an estimation is being
114 * computed.
115 */
116 protected boolean locked;
117
118 /**
119 * Amount of progress variation before notifying a progress change during
120 * estimation.
121 */
122 protected float progressDelta;
123
124 /**
125 * Amount of confidence expressed as a value between 0.0 and 1.0 (which is
126 * equivalent to 100%). The amount of confidence indicates the probability
127 * that the estimated result is correct. Usually this value will be close
128 * to 1.0, but not exactly 1.0.
129 */
130 protected double confidence;
131
132 /**
133 * Maximum allowed number of iterations. When the maximum number of
134 * iterations is exceeded, result will not be available, however an
135 * approximate result will be available for retrieval.
136 */
137 protected int maxIterations;
138
139 /**
140 * Data related to inliers found after estimation.
141 */
142 protected InliersData inliersData;
143
144 /**
145 * Indicates whether result must be refined using Levenberg-Marquardt
146 * fitting algorithm over found inliers.
147 * If true, inliers will be computed and kept in any implementation
148 * regardless of the settings.
149 */
150 protected boolean refineResult;
151
152 /**
153 * Indicates whether covariance must be kept after refining result.
154 * This setting is only taken into account if result is refined.
155 */
156 private boolean keepCovariance;
157
158 /**
159 * Estimated covariance of estimated 2D Euclidean transformation.
160 * This is only available when result has been refined and covariance is
161 * kept.
162 */
163 private Matrix covariance;
164
165 /**
166 * List of points to be used to estimate an Euclidean 3D transformation.
167 * Each point in the list of input points must be matched with the
168 * corresponding point in the list of output points located at the same
169 * position. Hence, both input points and output points must have the same
170 * size, and their size must be greater or equal than MINIMUM_SIZE.
171 */
172 protected List<Point3D> inputPoints;
173
174 /**
175 * List of points to be used to estimate an Euclidean 3D transformation.
176 * Each point in the lis tof output points must be matched with the
177 * corresponding point in the list of input points located at the same
178 * position. Hence, both input points and output points must have the same
179 * size, and their size must be greater or equal than MINIMUM_SIZE.
180 */
181 protected List<Point3D> outputPoints;
182
183 /**
184 * Indicates whether estimation can start with only 3 points or not.
185 * True allows 3 points, false requires 4.
186 */
187 private boolean weakMinimumSizeAllowed;
188
189 /**
190 * Constructor.
191 */
192 protected EuclideanTransformation3DRobustEstimator() {
193 progressDelta = DEFAULT_PROGRESS_DELTA;
194 confidence = DEFAULT_CONFIDENCE;
195 maxIterations = DEFAULT_MAX_ITERATIONS;
196 refineResult = DEFAULT_REFINE_RESULT;
197 keepCovariance = DEFAULT_KEEP_COVARIANCE;
198 }
199
200 /**
201 * Constructor.
202 *
203 * @param listener listener to be notified of events such as when estimation
204 * starts, ends or its progress significantly changes.
205 */
206 protected EuclideanTransformation3DRobustEstimator(
207 final EuclideanTransformation3DRobustEstimatorListener listener) {
208 this();
209 this.listener = listener;
210 }
211
212 /**
213 * Constructor with lists of points to be used to estimate an Euclidean 3D
214 * transformation.
215 * Points in the list located at the same position are considered to be
216 * matched. Hence, both lists must have the same size, and their size must
217 * be greater or equal than MINIMUM_SIZE.
218 *
219 * @param inputPoints list of input points to be used to estimate an
220 * Euclidean 3D transformation.
221 * @param outputPoints list of output points to be used to estimate an
222 * Euclidean 3D transformation.
223 * @throws IllegalArgumentException if provided lists of points don't have
224 * the same size or their size is smaller than MINIMUM_SIZE.
225 */
226 protected EuclideanTransformation3DRobustEstimator(
227 final List<Point3D> inputPoints, final List<Point3D> outputPoints) {
228 this();
229 internalSetPoints(inputPoints, outputPoints);
230 }
231
232 /**
233 * Constructor with listener and lists of points to be used to estimate an
234 * Euclidean 3D transformation.
235 * Points in the list located at the same position are considered to be
236 * matched. Hence, both lists must have the same size, and their size must
237 * be greater or equal than MINIMUM_SIZE.
238 *
239 * @param listener listener to be notified of events such as when estimation
240 * starts, ends or its progress significantly changes.
241 * @param inputPoints list of input points to be used to estimate an
242 * Euclidean 3D transformation.
243 * @param outputPoints list of output points to be used to estimate an
244 * Euclidean 3D transformation.
245 * @throws IllegalArgumentException if provided lists of points don't have
246 * the same size or their size is smaller than MINIMUM_SIZE.
247 */
248 protected EuclideanTransformation3DRobustEstimator(
249 final EuclideanTransformation3DRobustEstimatorListener listener,
250 final List<Point3D> inputPoints, final List<Point3D> outputPoints) {
251 this(listener);
252 internalSetPoints(inputPoints, outputPoints);
253 }
254
255 /**
256 * Constructor.
257 *
258 * @param weakMinimumSizeAllowed true allows 3 points, false requires 4.
259 */
260 protected EuclideanTransformation3DRobustEstimator(
261 final boolean weakMinimumSizeAllowed) {
262 this();
263 this.weakMinimumSizeAllowed = weakMinimumSizeAllowed;
264 }
265
266 /**
267 * Constructor.
268 *
269 * @param listener listener to be notified of events such as when estimation
270 * starts, ends or its progress significantly changes.
271 * @param weakMinimumSizeAllowed true allows 3 points, false requires 4.
272 */
273 protected EuclideanTransformation3DRobustEstimator(
274 final EuclideanTransformation3DRobustEstimatorListener listener, final boolean weakMinimumSizeAllowed) {
275 this();
276 this.listener = listener;
277 this.weakMinimumSizeAllowed = weakMinimumSizeAllowed;
278 }
279
280 /**
281 * Constructor with lists of points to be used to estimate an Euclidean 3D
282 * transformation.
283 * Points in the list located at the same position are considered to be
284 * matched. Hence, both lists must have the same size, and their size must
285 * be greater or equal than MINIMUM_SIZE.
286 *
287 * @param inputPoints list of input points to be used to estimate an
288 * Euclidean 3D transformation.
289 * @param outputPoints list of output points to be used to estimate an
290 * Euclidean 3D transformation.
291 * @param weakMinimumSizeAllowed true allows 3 points, false requires 4.
292 * @throws IllegalArgumentException if provided lists of points don't have
293 * the same size or their size is smaller than MINIMUM_SIZE.
294 */
295 protected EuclideanTransformation3DRobustEstimator(
296 final List<Point3D> inputPoints, final List<Point3D> outputPoints, final boolean weakMinimumSizeAllowed) {
297 this();
298 this.weakMinimumSizeAllowed = weakMinimumSizeAllowed;
299 internalSetPoints(inputPoints, outputPoints);
300 }
301
302 /**
303 * Constructor with listener and lists of points to be used to estimate an
304 * Euclidean 3D transformation.
305 * Points in the list located at the same position are considered to be
306 * matched. Hence, both lists must have the same size, and their size must
307 * be greater or equal than MINIMUM_SIZE.
308 *
309 * @param listener listener to be notified of events such as when estimation
310 * starts, ends or its progress significantly changes.
311 * @param inputPoints list of input points to be used to estimate an
312 * Euclidean 3D transformation.
313 * @param outputPoints list of output points to be used to estimate an
314 * Euclidean 3D transformation.
315 * @param weakMinimumSizeAllowed true allows 3 points, false requires 4.
316 * @throws IllegalArgumentException if provided lists of points don't have
317 * the same size or their size is smaller than MINIMUM_SIZE.
318 */
319 protected EuclideanTransformation3DRobustEstimator(
320 final EuclideanTransformation3DRobustEstimatorListener listener,
321 final List<Point3D> inputPoints, final List<Point3D> outputPoints, final boolean weakMinimumSizeAllowed) {
322 this(listener);
323 this.weakMinimumSizeAllowed = weakMinimumSizeAllowed;
324 internalSetPoints(inputPoints, outputPoints);
325 }
326
327 /**
328 * Returns list of input points to be used to estimate an Euclidean 3D
329 * transformation.
330 * Each point in the list of input points must be matched with the
331 * corresponding point in the list of output points located at the same
332 * position. Hence, both input points and output points must have the same
333 * size, and their size must be greater or equal than MINIMUM_SIZE.
334 *
335 * @return list of input points to be used to estimate an Euclidean 3D
336 * transformation.
337 */
338 public List<Point3D> getInputPoints() {
339 return inputPoints;
340 }
341
342 /**
343 * Returns list of output points to be used to estimate an Euclidean 3D
344 * transformation.
345 * Each point in the list of output points must be matched with the
346 * corresponding point in the list of input points located at the same
347 * position. Hence, both input points and output points must have the same
348 * size, and their size must be greater or equal than MINIMUM_SIZE.
349 *
350 * @return list of output points to be used to estimate an Euclidean 3D
351 * transformation.
352 */
353 public List<Point3D> getOutputPoints() {
354 return outputPoints;
355 }
356
357 /**
358 * Sets list of points to be used to estimate an Euclidean 3D
359 * transformation.
360 * Points in the list located at the same position are considered to be
361 * matched. Hence, both lists must have the same size, and their size must
362 * be greater or equal than MINIMUM_SIZE.
363 *
364 * @param inputPoints list of input points to be used to estimate an
365 * Euclidean 3D transformation.
366 * @param outputPoints list of output points to be used to estimate an
367 * Euclidean 3D transformation.
368 * @throws IllegalArgumentException if provided lists of points don't have
369 * the same size or their size is smaller than MINIMUM_SIZE.
370 * @throws LockedException if estimator is locked because a computation is
371 * already in progress.
372 */
373 public void setPoints(final List<Point3D> inputPoints, final List<Point3D> outputPoints) throws LockedException {
374 if (isLocked()) {
375 throw new LockedException();
376 }
377 internalSetPoints(inputPoints, outputPoints);
378 }
379
380 /**
381 * Indicates if estimator is ready to start the Euclidean 3D transformation
382 * estimation.
383 * This is true when input data (i.e. lists of matched points) are provided
384 * and a minimum of MINIMUM_SIZE points are available.
385 *
386 * @return true if estimator is ready, false otherwise.
387 */
388 public boolean isReady() {
389 return inputPoints != null && outputPoints != null && inputPoints.size() == outputPoints.size()
390 && inputPoints.size() >= getMinimumPoints();
391 }
392
393 /**
394 * Returns quality scores corresponding to each pair of matched points.
395 * The larger the score value the better the quality of the matching.
396 * This implementation always returns null.
397 * Subclasses using quality scores must implement proper behaviour.
398 *
399 * @return quality scores corresponding to each pair of matched points.
400 */
401 public double[] getQualityScores() {
402 return null;
403 }
404
405 /**
406 * Sets quality scores corresponding to each pair of matched points.
407 * The larger the score value the better the quality of the matching.
408 * This implementation makes no action.
409 * Subclasses using quality scores must implement proper behaviour.
410 *
411 * @param qualityScores quality scores corresponding to each pair of matched
412 * points.
413 * @throws LockedException if robust estimator is locked because an
414 * estimation is already in progress.
415 * @throws IllegalArgumentException if provided quality scores length is
416 * smaller than MINIMUM_SIZE (i.e. 3 samples).
417 */
418 public void setQualityScores(final double[] qualityScores) throws LockedException {
419 }
420
421 /**
422 * Returns reference to listener to be notified of events such as when
423 * estimation starts, ends or its progress significantly changes.
424 *
425 * @return listener to be notified of events.
426 */
427 public EuclideanTransformation3DRobustEstimatorListener getListener() {
428 return listener;
429 }
430
431 /**
432 * Sets listener to be notified of events such as when estimation starts,
433 * ends or its progress significantly changes.
434 *
435 * @param listener listener to be notified of events.
436 * @throws LockedException if robust estimator is locked.
437 */
438 public void setListener(final EuclideanTransformation3DRobustEstimatorListener listener) throws LockedException {
439 if (isLocked()) {
440 throw new LockedException();
441 }
442 this.listener = listener;
443 }
444
445 /**
446 * Indicates whether listener has been provided and is available for
447 * retrieval.
448 *
449 * @return true if available, false otherwise.
450 */
451 public boolean isListenerAvailable() {
452 return listener != null;
453 }
454
455 /**
456 * Indicates whether estimation can start with only 3 points or not.
457 *
458 * @return true allows 3 points, false requires 4.
459 */
460 public boolean isWeakMinimumSizeAllowed() {
461 return weakMinimumSizeAllowed;
462 }
463
464 /**
465 * Specifies whether estimation can start with only 3 points or not.
466 *
467 * @param weakMinimumSizeAllowed true allows 3 points, false requires 4.
468 * @throws LockedException if estimator is locked.
469 */
470 public void setWeakMinimumSizeAllowed(final boolean weakMinimumSizeAllowed) throws LockedException {
471 if (isLocked()) {
472 throw new LockedException();
473 }
474 this.weakMinimumSizeAllowed = weakMinimumSizeAllowed;
475 }
476
477 /**
478 * Required minimum number of point correspondences to start the estimation.
479 * Can be either 3 or 4.
480 *
481 * @return minimum number of point correspondences.
482 */
483 public int getMinimumPoints() {
484 return weakMinimumSizeAllowed ? WEAK_MINIMUM_SIZE : MINIMUM_SIZE;
485 }
486
487 /**
488 * Indicates if this instance is locked because estimation is being
489 * computed.
490 *
491 * @return true if locked, false otherwise.
492 */
493 public boolean isLocked() {
494 return locked;
495 }
496
497 /**
498 * Returns amount of progress variation before notifying a progress change
499 * during estimation.
500 *
501 * @return amount of progress variation before notifying a progress change
502 * during estimation.
503 */
504 public float getProgressDelta() {
505 return progressDelta;
506 }
507
508 /**
509 * Sets amount of progress variation before notifying a progress change
510 * during estimation.
511 *
512 * @param progressDelta amount of progress variation before notifying a
513 * progress change during estimation.
514 * @throws IllegalArgumentException if progress delta is less than zero or
515 * greater than 1.
516 * @throws LockedException if this estimator is locked because an estimation
517 * is being computed.
518 */
519 public void setProgressDelta(final float progressDelta) throws LockedException {
520 if (isLocked()) {
521 throw new LockedException();
522 }
523 if (progressDelta < MIN_PROGRESS_DELTA || progressDelta > MAX_PROGRESS_DELTA) {
524 throw new IllegalArgumentException();
525 }
526 this.progressDelta = progressDelta;
527 }
528
529 /**
530 * Returns amount of confidence expressed as a value between 0.0 and 1.0
531 * (which is equivalent to 100%). The amount of confidence indicates the
532 * probability that the estimated result is correct. Usually this value will
533 * be close to 1.0, but not exactly 1.0.
534 *
535 * @return amount of confidence as a value between 0.0 and 1.0.
536 */
537 public double getConfidence() {
538 return confidence;
539 }
540
541 /**
542 * Sets amount of confidence expressed as a value between 0.0 and 1.0 (which
543 * is equivalent to 100%). The amount of confidence indicates the
544 * probability that the estimated result is correct. Usually this value will
545 * be close to 1.0, but not exactly 1.0.
546 *
547 * @param confidence confidence to be set as a value between 0.0 and 1.0.
548 * @throws IllegalArgumentException if provided value is not between 0.0 and
549 * 1.0.
550 * @throws LockedException if this estimator is locked because an estimator
551 * is being computed.
552 */
553 public void setConfidence(final double confidence) throws LockedException {
554 if (isLocked()) {
555 throw new LockedException();
556 }
557 if (confidence < MIN_CONFIDENCE || confidence > MAX_CONFIDENCE) {
558 throw new IllegalArgumentException();
559 }
560 this.confidence = confidence;
561 }
562
563 /**
564 * Returns maximum allowed number of iterations. If maximum allowed number
565 * of iterations is achieved without converging to a result when calling
566 * estimate(), a RobustEstimatorException will be raised.
567 *
568 * @return maximum allowed number of iterations.
569 */
570 public int getMaxIterations() {
571 return maxIterations;
572 }
573
574 /**
575 * Sets maximum allowed number of iterations. When the maximum number of
576 * iterations is exceeded, result will not be available, however an
577 * approximate result will be available for retrieval.
578 *
579 * @param maxIterations maximum allowed number of iterations to be set.
580 * @throws IllegalArgumentException if provided value is less than 1.
581 * @throws LockedException if this estimator is locked because an estimation
582 * is being computed.
583 */
584 public void setMaxIterations(final int maxIterations) throws LockedException {
585 if (isLocked()) {
586 throw new LockedException();
587 }
588 if (maxIterations < MIN_ITERATIONS) {
589 throw new IllegalArgumentException();
590 }
591 this.maxIterations = maxIterations;
592 }
593
594 /**
595 * Gets data related to inliers found after estimation.
596 *
597 * @return data related to inliers found after estimation.
598 */
599 public InliersData getInliersData() {
600 return inliersData;
601 }
602
603 /**
604 * Indicates whether result must be refined using Levenberg-Marquardt
605 * fitting algorithm over found inliers.
606 * If ture, inliers will be computed and kept in any implementation
607 * regardless of the settings.
608 *
609 * @return true to refine result, false to simply use result found by
610 * robust estimator without further refining.
611 */
612 public boolean isResultRefined() {
613 return refineResult;
614 }
615
616 /**
617 * Specifies whether result must be refined using Levenberg-Marquardt
618 * fitting algorithm over found inliers.
619 *
620 * @param refineResult true to refine result, false to simply use result
621 * found by robust estimator without further refining.
622 * @throws LockedException if estimator is locked.
623 */
624 public void setResultRefined(final boolean refineResult) throws LockedException {
625 if (isLocked()) {
626 throw new LockedException();
627 }
628 this.refineResult = refineResult;
629 }
630
631 /**
632 * Indicates whether covariance must be kept after refining result.
633 * This setting is only taken into account if result is refined.
634 *
635 * @return true if covariance must be kept after refining result, false
636 * otherwise.
637 */
638 public boolean isCovarianceKept() {
639 return keepCovariance;
640 }
641
642 /**
643 * Specifies whether covariance must be kept after refining result.
644 * This setting is only taken into account if result is refined.
645 *
646 * @param keepCovariance true if covariance must be kept after refining
647 * result, false otherwise.
648 * @throws LockedException if estimator is locked.
649 */
650 public void setCovarianceKept(final boolean keepCovariance) throws LockedException {
651 if (isLocked()) {
652 throw new LockedException();
653 }
654 this.keepCovariance = keepCovariance;
655 }
656
657 /**
658 * Gets estimated covariance of estimated 3D point if available.
659 * This is only available when result has been refined and covariance is
660 * kept.
661 *
662 * @return estimated covariance or null.
663 */
664 public Matrix getCovariance() {
665 return covariance;
666 }
667
668 /**
669 * Estimates an Euclidean 3D transformation using a robust estimator and the
670 * best set of matched 3D point correspondences found using the robust
671 * estimator.
672 *
673 * @return an Euclidean 3D transformation.
674 * @throws LockedException if robust estimator is locked because an
675 * estimation is already in progress.
676 * @throws NotReadyException if provided input data is not enough to start
677 * the estimation.
678 * @throws RobustEstimatorException if estimation fails for any reason
679 * (i.e. numerical instability, no solution available, etc).
680 */
681 public abstract EuclideanTransformation3D estimate() throws LockedException, NotReadyException,
682 RobustEstimatorException;
683
684 /**
685 * Returns method being used for robust estimation.
686 *
687 * @return method being used for robust estimation.
688 */
689 public abstract RobustEstimatorMethod getMethod();
690
691
692 /**
693 * Creates an Euclidean 3D transformation estimator based on 3D point
694 * correspondences and using provided robust estimator method.
695 *
696 * @param method method of a robust estimator algorithm to estimate
697 * the best Euclidean 3D transformation.
698 * @return an instance of Euclidean 3D transformation estimator.
699 */
700 public static EuclideanTransformation3DRobustEstimator create(final RobustEstimatorMethod method) {
701 return switch (method) {
702 case LMEDS -> new LMedSEuclideanTransformation3DRobustEstimator();
703 case MSAC -> new MSACEuclideanTransformation3DRobustEstimator();
704 case PROSAC -> new PROSACEuclideanTransformation3DRobustEstimator();
705 case PROMEDS -> new PROMedSEuclideanTransformation3DRobustEstimator();
706 default -> new RANSACEuclideanTransformation3DRobustEstimator();
707 };
708 }
709
710 /**
711 * Creates an Euclidean 3D transformation estimator based on 3D point
712 * correspondences and using provided estimator method.
713 *
714 * @param inputPoints list of input points to be used to estimate an
715 * Euclidean 3D transformation.
716 * @param outputPoints list of output points to be used to estimate an
717 * Euclidean 3D transformation.
718 * @param method method of a robust estimator algorithm to estimate the best
719 * Euclidean 3D transformation.
720 * @return an instance of Euclidean 3D transformation estimator.
721 * @throws IllegalArgumentException if provided lists of points don't have
722 * the same size or their size is smaller than MINIMUM_SIZE.
723 */
724 public static EuclideanTransformation3DRobustEstimator create(
725 final List<Point3D> inputPoints, final List<Point3D> outputPoints, final RobustEstimatorMethod method) {
726 return switch (method) {
727 case LMEDS -> new LMedSEuclideanTransformation3DRobustEstimator(inputPoints, outputPoints);
728 case MSAC -> new MSACEuclideanTransformation3DRobustEstimator(inputPoints, outputPoints);
729 case PROSAC -> new PROSACEuclideanTransformation3DRobustEstimator(inputPoints, outputPoints);
730 case PROMEDS -> new PROMedSEuclideanTransformation3DRobustEstimator(inputPoints, outputPoints);
731 default -> new RANSACEuclideanTransformation3DRobustEstimator(inputPoints, outputPoints);
732 };
733 }
734
735 /**
736 * Creates an Euclidean 3D transformation estimator based on 3D point
737 * correspondences and using provided robust estimator method.
738 *
739 * @param listener listener to be notified of events such as when estimation
740 * starts, ends or its progress significantly changes.
741 * @param method method of a robust estimator algorithm to estimate the best
742 * Euclidean 3D transformation.
743 * @return an instance of Euclidean 3D transformation estimator.
744 */
745 public static EuclideanTransformation3DRobustEstimator create(
746 final EuclideanTransformation3DRobustEstimatorListener listener, final RobustEstimatorMethod method) {
747 return switch (method) {
748 case LMEDS -> new LMedSEuclideanTransformation3DRobustEstimator(listener);
749 case MSAC -> new MSACEuclideanTransformation3DRobustEstimator(listener);
750 case PROSAC -> new PROSACEuclideanTransformation3DRobustEstimator(listener);
751 case PROMEDS -> new PROMedSEuclideanTransformation3DRobustEstimator(listener);
752 default -> new RANSACEuclideanTransformation3DRobustEstimator(listener);
753 };
754 }
755
756 /**
757 * Creates an Euclidean 3D transformation estimator based on 3D point
758 * correspondences and using provided robust estimator method.
759 *
760 * @param listener listener to be notified of events such as when estimation
761 * starts, ends or its progress significantly changes.
762 * @param inputPoints list of input points to be used to estimate an
763 * Euclidean 3D transformation.
764 * @param outputPoints list of output points to be used to estimate an
765 * Euclidean 3D transformation.
766 * @param method method of a robust estimator algorithm to estimate the best
767 * Euclidean 3D transformation.
768 * @return an instance of Euclidean 3D transformation estimator.
769 * @throws IllegalArgumentException if provided lists of points don't have
770 * the same size or their size is smaller than MINIMUM_SIZE.
771 */
772 public static EuclideanTransformation3DRobustEstimator create(
773 final EuclideanTransformation3DRobustEstimatorListener listener,
774 final List<Point3D> inputPoints, final List<Point3D> outputPoints, final RobustEstimatorMethod method) {
775 return switch (method) {
776 case LMEDS -> new LMedSEuclideanTransformation3DRobustEstimator(listener, inputPoints, outputPoints);
777 case MSAC -> new MSACEuclideanTransformation3DRobustEstimator(listener, inputPoints, outputPoints);
778 case PROSAC -> new PROSACEuclideanTransformation3DRobustEstimator(listener, inputPoints, outputPoints);
779 case PROMEDS -> new PROMedSEuclideanTransformation3DRobustEstimator(listener, inputPoints, outputPoints);
780 default -> new RANSACEuclideanTransformation3DRobustEstimator(listener, inputPoints, outputPoints);
781 };
782 }
783
784 /**
785 * Creates an Euclidean 3D transformation estimator based on 3D point
786 * correspondences and using provided robust estimator method.
787 *
788 * @param qualityScores quality scores corresponding to each pair of matched
789 * points.
790 * @param method method of a robust estimator algorithm to estimate the best
791 * Euclidean 3D transformation.
792 * @return an instance of Euclidean 3D transformation estimator.
793 * @throws IllegalArgumentException if provided quality scores length is
794 * smaller than MINIMUM_SIZE (i.e. 3 matched points).
795 */
796 public static EuclideanTransformation3DRobustEstimator create(
797 final double[] qualityScores, final RobustEstimatorMethod method) {
798 return switch (method) {
799 case LMEDS -> new LMedSEuclideanTransformation3DRobustEstimator();
800 case MSAC -> new MSACEuclideanTransformation3DRobustEstimator();
801 case PROSAC -> new PROSACEuclideanTransformation3DRobustEstimator(qualityScores);
802 case PROMEDS -> new PROMedSEuclideanTransformation3DRobustEstimator(qualityScores);
803 default -> new RANSACEuclideanTransformation3DRobustEstimator();
804 };
805 }
806
807 /**
808 * Creates an Euclidean 3D transformation estimator based on 3D point
809 * correspondences and using provided robust estimator method.
810 *
811 * @param inputPoints list of input points to be used to estimate an
812 * Euclidean 3D transformation.
813 * @param outputPoints list of output points to be used to estimate an
814 * Euclidean 3D transformation.
815 * @param qualityScores quality scores corresponding to each pair of matched
816 * points.
817 * @param method method of a robust estimator algorithm to estimate the best
818 * Euclidean 3D transformation.
819 * @return an instance of Euclidean 3D transformation estimator.
820 * @throws IllegalArgumentException if provided lists of points or scores
821 * don't have the same size or their size is smaller than MINIMUM_SIZE.
822 */
823 public static EuclideanTransformation3DRobustEstimator create(
824 final List<Point3D> inputPoints, final List<Point3D> outputPoints, final double[] qualityScores,
825 final RobustEstimatorMethod method) {
826 return switch (method) {
827 case LMEDS -> new LMedSEuclideanTransformation3DRobustEstimator(inputPoints, outputPoints);
828 case MSAC -> new MSACEuclideanTransformation3DRobustEstimator(inputPoints, outputPoints);
829 case PROSAC -> new PROSACEuclideanTransformation3DRobustEstimator(inputPoints, outputPoints, qualityScores);
830 case PROMEDS -> new PROMedSEuclideanTransformation3DRobustEstimator(
831 inputPoints, outputPoints, qualityScores);
832 default -> new RANSACEuclideanTransformation3DRobustEstimator(inputPoints, outputPoints);
833 };
834 }
835
836 /**
837 * Creates an Euclidean 3D transformation estimator based on 3D point
838 * correspondences and using provided robust estimator method.
839 *
840 * @param listener listener to be notified of events such as when estimation
841 * starts, ends or its progress significantly changes.
842 * @param qualityScores quality scores corresponding to each pair of matched
843 * points.
844 * @param method method of a robust estimator algorithm to estimate the best
845 * Euclidean 3D transformation.
846 * @return an instance of Euclidean 3D transformation estimator.
847 * @throws IllegalArgumentException if provided quality scores don't have
848 * the required minimum size.
849 */
850 public static EuclideanTransformation3DRobustEstimator create(
851 final EuclideanTransformation3DRobustEstimatorListener listener, final double[] qualityScores,
852 final RobustEstimatorMethod method) {
853 return switch (method) {
854 case LMEDS -> new LMedSEuclideanTransformation3DRobustEstimator(listener);
855 case MSAC -> new MSACEuclideanTransformation3DRobustEstimator(listener);
856 case PROSAC -> new PROSACEuclideanTransformation3DRobustEstimator(listener, qualityScores);
857 case PROMEDS -> new PROMedSEuclideanTransformation3DRobustEstimator(listener, qualityScores);
858 default -> new RANSACEuclideanTransformation3DRobustEstimator(listener);
859 };
860 }
861
862 /**
863 * Creates an Euclidean 3D transformation estimator based on 3D point
864 * correspondences and using provided robust estimator method.
865 *
866 * @param listener listener to be notified of events such as when estimation
867 * starts, ends or its progress significantly changes.
868 * @param inputPoints list of input points to be used to estimate an
869 * Euclidean 3D transformation.
870 * @param outputPoints list of output points to be used to estimate an
871 * Euclidean 3D transformation.
872 * @param qualityScores quality scores corresponding to each pair of matched
873 * points.
874 * @param method method of a robust estimator algorithm to estimate the best
875 * Euclidean 3D transformation.
876 * @return an instance of Euclidean 3D transformation estimator.
877 * @throws IllegalArgumentException if provided lists of points don't have
878 * the same size of their size is smaller than MINIMUM_SIZE.
879 */
880 public static EuclideanTransformation3DRobustEstimator create(
881 final EuclideanTransformation3DRobustEstimatorListener listener,
882 final List<Point3D> inputPoints, final List<Point3D> outputPoints,
883 final double[] qualityScores, final RobustEstimatorMethod method) {
884 return switch (method) {
885 case LMEDS -> new LMedSEuclideanTransformation3DRobustEstimator(listener, inputPoints, outputPoints);
886 case MSAC -> new MSACEuclideanTransformation3DRobustEstimator(listener, inputPoints, outputPoints);
887 case PROSAC -> new PROSACEuclideanTransformation3DRobustEstimator(
888 listener, inputPoints, outputPoints, qualityScores);
889 case PROMEDS -> new PROMedSEuclideanTransformation3DRobustEstimator(
890 listener, inputPoints, outputPoints, qualityScores);
891 default -> new RANSACEuclideanTransformation3DRobustEstimator(listener, inputPoints, outputPoints);
892 };
893 }
894
895 /**
896 * Creates an Euclidean 3D transformation estimator based on 3D point
897 * correspondences and using provided robust estimator method.
898 *
899 * @param weakMinimumSizeAllowed true allows 3 points, false requires 4.
900 * @param method method of a robust estimator algorithm to estimate
901 * the best Euclidean 3D transformation.
902 * @return an instance of Euclidean 3D transformation estimator.
903 */
904 public static EuclideanTransformation3DRobustEstimator create(
905 final boolean weakMinimumSizeAllowed, final RobustEstimatorMethod method) {
906 return switch (method) {
907 case LMEDS -> new LMedSEuclideanTransformation3DRobustEstimator(weakMinimumSizeAllowed);
908 case MSAC -> new MSACEuclideanTransformation3DRobustEstimator(weakMinimumSizeAllowed);
909 case PROSAC -> new PROSACEuclideanTransformation3DRobustEstimator(weakMinimumSizeAllowed);
910 case PROMEDS -> new PROMedSEuclideanTransformation3DRobustEstimator(weakMinimumSizeAllowed);
911 default -> new RANSACEuclideanTransformation3DRobustEstimator(weakMinimumSizeAllowed);
912 };
913 }
914
915 /**
916 * Creates an Euclidean 3D transformation estimator based on 3D point
917 * correspondences and using provided estimator method.
918 *
919 * @param inputPoints list of input points to be used to estimate an
920 * Euclidean 3D transformation.
921 * @param outputPoints list of output points to be used to estimate an
922 * Euclidean 3D transformation.
923 * @param weakMinimumSizeAllowed true allows 3 points, false requires 4.
924 * @param method method of a robust estimator algorithm to estimate the best
925 * Euclidean 3D transformation.
926 * @return an instance of Euclidean 3D transformation estimator.
927 * @throws IllegalArgumentException if provided lists of points don't have
928 * the same size or their size is smaller than MINIMUM_SIZE.
929 */
930 public static EuclideanTransformation3DRobustEstimator create(
931 final List<Point3D> inputPoints, final List<Point3D> outputPoints,
932 final boolean weakMinimumSizeAllowed, final RobustEstimatorMethod method) {
933 return switch (method) {
934 case LMEDS -> new LMedSEuclideanTransformation3DRobustEstimator(
935 inputPoints, outputPoints, weakMinimumSizeAllowed);
936 case MSAC -> new MSACEuclideanTransformation3DRobustEstimator(
937 inputPoints, outputPoints, weakMinimumSizeAllowed);
938 case PROSAC -> new PROSACEuclideanTransformation3DRobustEstimator(
939 inputPoints, outputPoints, weakMinimumSizeAllowed);
940 case PROMEDS -> new PROMedSEuclideanTransformation3DRobustEstimator(
941 inputPoints, outputPoints, weakMinimumSizeAllowed);
942 default -> new RANSACEuclideanTransformation3DRobustEstimator(
943 inputPoints, outputPoints, weakMinimumSizeAllowed);
944 };
945 }
946
947 /**
948 * Creates an Euclidean 3D transformation estimator based on 3D point
949 * correspondences and using provided robust estimator method.
950 *
951 * @param listener listener to be notified of events such as when estimation
952 * starts, ends or its progress significantly changes.
953 * @param weakMinimumSizeAllowed true allows 3 points, false requires 4.
954 * @param method method of a robust estimator algorithm to estimate the best
955 * Euclidean 3D transformation.
956 * @return an instance of Euclidean 3D transformation estimator.
957 */
958 public static EuclideanTransformation3DRobustEstimator create(
959 final EuclideanTransformation3DRobustEstimatorListener listener, final boolean weakMinimumSizeAllowed,
960 final RobustEstimatorMethod method) {
961 return switch (method) {
962 case LMEDS -> new LMedSEuclideanTransformation3DRobustEstimator(listener, weakMinimumSizeAllowed);
963 case MSAC -> new MSACEuclideanTransformation3DRobustEstimator(listener, weakMinimumSizeAllowed);
964 case PROSAC -> new PROSACEuclideanTransformation3DRobustEstimator(listener, weakMinimumSizeAllowed);
965 case PROMEDS -> new PROMedSEuclideanTransformation3DRobustEstimator(listener, weakMinimumSizeAllowed);
966 default -> new RANSACEuclideanTransformation3DRobustEstimator(listener, weakMinimumSizeAllowed);
967 };
968 }
969
970 /**
971 * Creates an Euclidean 3D transformation estimator based on 3D point
972 * correspondences and using provided robust estimator method.
973 *
974 * @param listener listener to be notified of events such as when estimation
975 * starts, ends or its progress significantly changes.
976 * @param inputPoints list of input points to be used to estimate an
977 * Euclidean 3D transformation.
978 * @param outputPoints list of output points to be used to estimate an
979 * Euclidean 3D transformation.
980 * @param weakMinimumSizeAllowed true allows 3 points, false requires 4.
981 * @param method method of a robust estimator algorithm to estimate the best
982 * Euclidean 3D transformation.
983 * @return an instance of Euclidean 3D transformation estimator.
984 * @throws IllegalArgumentException if provided lists of points don't have
985 * the same size or their size is smaller than MINIMUM_SIZE.
986 */
987 public static EuclideanTransformation3DRobustEstimator create(
988 final EuclideanTransformation3DRobustEstimatorListener listener,
989 final List<Point3D> inputPoints, final List<Point3D> outputPoints,
990 final boolean weakMinimumSizeAllowed, final RobustEstimatorMethod method) {
991 return switch (method) {
992 case LMEDS -> new LMedSEuclideanTransformation3DRobustEstimator(listener, inputPoints, outputPoints,
993 weakMinimumSizeAllowed);
994 case MSAC -> new MSACEuclideanTransformation3DRobustEstimator(listener, inputPoints, outputPoints,
995 weakMinimumSizeAllowed);
996 case PROSAC -> new PROSACEuclideanTransformation3DRobustEstimator(listener, inputPoints, outputPoints,
997 weakMinimumSizeAllowed);
998 case PROMEDS -> new PROMedSEuclideanTransformation3DRobustEstimator(listener, inputPoints, outputPoints,
999 weakMinimumSizeAllowed);
1000 default -> new RANSACEuclideanTransformation3DRobustEstimator(listener, inputPoints, outputPoints,
1001 weakMinimumSizeAllowed);
1002 };
1003 }
1004
1005 /**
1006 * Creates an Euclidean 3D transformation estimator based on 3D point
1007 * correspondences and using provided robust estimator method.
1008 *
1009 * @param qualityScores quality scores corresponding to each pair of matched
1010 * points.
1011 * @param weakMinimumSizeAllowed true allows 3 points, false requires 4.
1012 * @param method method of a robust estimator algorithm to estimate the best
1013 * Euclidean 3D transformation.
1014 * @return an instance of Euclidean 3D transformation estimator.
1015 * @throws IllegalArgumentException if provided quality scores length is
1016 * smaller than MINIMUM_SIZE (i.e. 3 matched points).
1017 */
1018 public static EuclideanTransformation3DRobustEstimator create(
1019 final double[] qualityScores, final boolean weakMinimumSizeAllowed, final RobustEstimatorMethod method) {
1020 return switch (method) {
1021 case LMEDS -> new LMedSEuclideanTransformation3DRobustEstimator(weakMinimumSizeAllowed);
1022 case MSAC -> new MSACEuclideanTransformation3DRobustEstimator(weakMinimumSizeAllowed);
1023 case PROSAC -> new PROSACEuclideanTransformation3DRobustEstimator(qualityScores, weakMinimumSizeAllowed);
1024 case PROMEDS -> new PROMedSEuclideanTransformation3DRobustEstimator(qualityScores, weakMinimumSizeAllowed);
1025 default -> new RANSACEuclideanTransformation3DRobustEstimator(weakMinimumSizeAllowed);
1026 };
1027 }
1028
1029 /**
1030 * Creates an Euclidean 3D transformation estimator based on 3D point
1031 * correspondences and using provided robust estimator method.
1032 *
1033 * @param inputPoints list of input points to be used to estimate an
1034 * Euclidean 3D transformation.
1035 * @param outputPoints list of output points to be used to estimate an
1036 * Euclidean 3D transformation.
1037 * @param qualityScores quality scores corresponding to each pair of matched
1038 * points.
1039 * @param weakMinimumSizeAllowed true allows 3 points, false requires 4.
1040 * @param method method of a robust estimator algorithm to estimate the best
1041 * Euclidean 3D transformation.
1042 * @return an instance of Euclidean 3D transformation estimator.
1043 * @throws IllegalArgumentException if provided lists of points or scores
1044 * don't have the same size or their size is smaller than MINIMUM_SIZE.
1045 */
1046 public static EuclideanTransformation3DRobustEstimator create(
1047 final List<Point3D> inputPoints, final List<Point3D> outputPoints, final double[] qualityScores,
1048 final boolean weakMinimumSizeAllowed, final RobustEstimatorMethod method) {
1049 return switch (method) {
1050 case LMEDS -> new LMedSEuclideanTransformation3DRobustEstimator(
1051 inputPoints, outputPoints, weakMinimumSizeAllowed);
1052 case MSAC -> new MSACEuclideanTransformation3DRobustEstimator(
1053 inputPoints, outputPoints, weakMinimumSizeAllowed);
1054 case PROSAC -> new PROSACEuclideanTransformation3DRobustEstimator(
1055 inputPoints, outputPoints, qualityScores, weakMinimumSizeAllowed);
1056 case PROMEDS -> new PROMedSEuclideanTransformation3DRobustEstimator(
1057 inputPoints, outputPoints, qualityScores, weakMinimumSizeAllowed);
1058 default -> new RANSACEuclideanTransformation3DRobustEstimator(
1059 inputPoints, outputPoints, weakMinimumSizeAllowed);
1060 };
1061 }
1062
1063 /**
1064 * Creates an Euclidean 3D transformation estimator based on 3D point
1065 * correspondences and using provided robust estimator method.
1066 *
1067 * @param listener listener to be notified of events such as when estimation
1068 * starts, ends or its progress significantly changes.
1069 * @param qualityScores quality scores corresponding to each pair of matched
1070 * points.
1071 * @param weakMinimumSizeAllowed true allows 3 points, false requires 4.
1072 * @param method method of a robust estimator algorithm to estimate the best
1073 * Euclidean 3D transformation.
1074 * @return an instance of Euclidean 3D transformation estimator.
1075 * @throws IllegalArgumentException if provided quality scores don't have
1076 * the required minimum size.
1077 */
1078 public static EuclideanTransformation3DRobustEstimator create(
1079 final EuclideanTransformation3DRobustEstimatorListener listener, final double[] qualityScores,
1080 final boolean weakMinimumSizeAllowed, final RobustEstimatorMethod method) {
1081 return switch (method) {
1082 case LMEDS -> new LMedSEuclideanTransformation3DRobustEstimator(listener, weakMinimumSizeAllowed);
1083 case MSAC -> new MSACEuclideanTransformation3DRobustEstimator(listener, weakMinimumSizeAllowed);
1084 case PROSAC -> new PROSACEuclideanTransformation3DRobustEstimator(
1085 listener, qualityScores, weakMinimumSizeAllowed);
1086 case PROMEDS -> new PROMedSEuclideanTransformation3DRobustEstimator(
1087 listener, qualityScores, weakMinimumSizeAllowed);
1088 default -> new RANSACEuclideanTransformation3DRobustEstimator(listener, weakMinimumSizeAllowed);
1089 };
1090 }
1091
1092 /**
1093 * Creates an Euclidean 3D transformation estimator based on 3D point
1094 * correspondences and using provided robust estimator method.
1095 *
1096 * @param listener listener to be notified of events such as when estimation
1097 * starts, ends or its progress significantly changes.
1098 * @param inputPoints list of input points to be used to estimate an
1099 * Euclidean 3D transformation.
1100 * @param outputPoints list of output points to be used to estimate an
1101 * Euclidean 3D transformation.
1102 * @param qualityScores quality scores corresponding to each pair of matched
1103 * points.
1104 * @param weakMinimumSizeAllowed true allows 3 points, false requires 4.
1105 * @param method method of a robust estimator algorithm to estimate the best
1106 * Euclidean 3D transformation.
1107 * @return an instance of Euclidean 3D transformation estimator.
1108 * @throws IllegalArgumentException if provided lists of points don't have
1109 * the same size of their size is smaller than MINIMUM_SIZE.
1110 */
1111 public static EuclideanTransformation3DRobustEstimator create(
1112 final EuclideanTransformation3DRobustEstimatorListener listener,
1113 final List<Point3D> inputPoints, final List<Point3D> outputPoints, final double[] qualityScores,
1114 final boolean weakMinimumSizeAllowed, final RobustEstimatorMethod method) {
1115 return switch (method) {
1116 case LMEDS -> new LMedSEuclideanTransformation3DRobustEstimator(
1117 listener, inputPoints, outputPoints, weakMinimumSizeAllowed);
1118 case MSAC -> new MSACEuclideanTransformation3DRobustEstimator(
1119 listener, inputPoints, outputPoints, weakMinimumSizeAllowed);
1120 case PROSAC -> new PROSACEuclideanTransformation3DRobustEstimator(
1121 listener, inputPoints, outputPoints, qualityScores, weakMinimumSizeAllowed);
1122 case PROMEDS -> new PROMedSEuclideanTransformation3DRobustEstimator(
1123 listener, inputPoints, outputPoints, qualityScores, weakMinimumSizeAllowed);
1124 default -> new RANSACEuclideanTransformation3DRobustEstimator(
1125 listener, inputPoints, outputPoints, weakMinimumSizeAllowed);
1126 };
1127 }
1128
1129 /**
1130 * Creates an Euclidean 3D transformation estimator based on 3D point
1131 * correspondences and using default robust estimator method.
1132 *
1133 * @return an instance of Euclidean 3D transformation estimator.
1134 */
1135 public static EuclideanTransformation3DRobustEstimator create() {
1136 return create(DEFAULT_ROBUST_METHOD);
1137 }
1138
1139 /**
1140 * Creates an Euclidean 3D transformation estimator based on 3D point
1141 * correspondences and using default robust estimator method.
1142 *
1143 * @param inputPoints list of input points to be used to estimate an
1144 * Euclidean 3D transformation.
1145 * @param outputPoints list of output points to be used to estimate an
1146 * Euclidean 3D transformation.
1147 * @return an instance of Euclidean 3D transformation estimator.
1148 * @throws IllegalArgumentException if provided lists of points don't have
1149 * the same size of their size is smaller than MINIMUM_SIZE.
1150 */
1151 public static EuclideanTransformation3DRobustEstimator create(
1152 final List<Point3D> inputPoints, final List<Point3D> outputPoints) {
1153 return create(inputPoints, outputPoints, DEFAULT_ROBUST_METHOD);
1154 }
1155
1156 /**
1157 * Creates an Euclidean 3D transformation estimator based on 3D point
1158 * correspondences and using default robust estimator method.
1159 *
1160 * @param listener listener to be notified of events such as when estimation
1161 * starts, ends or its progress significantly changes.
1162 * @return an instance of Euclidean 3D transformation estimator.
1163 */
1164 public static EuclideanTransformation3DRobustEstimator create(
1165 final EuclideanTransformation3DRobustEstimatorListener listener) {
1166 return create(listener, DEFAULT_ROBUST_METHOD);
1167 }
1168
1169 /**
1170 * Creates an Euclidean 3D transformation estimator based on 3D point
1171 * correspondences and using default robust estimator method.
1172 *
1173 * @param listener listener to be notified of events such as when estimation
1174 * starts, ends or its progress significantly changes.
1175 * @param inputPoints list of input points to be used to estimate an
1176 * Euclidean 3D transformation.
1177 * @param outputPoints list of output points to be used to estimate an
1178 * Euclidean 3D transformation.
1179 * @return an instance of Euclidean 3D transformation estimator.
1180 * @throws IllegalArgumentException if provided lists of points don't have
1181 * the same size or their size is smaller than MINIMUM_SIZE.
1182 */
1183 public static EuclideanTransformation3DRobustEstimator create(
1184 final EuclideanTransformation3DRobustEstimatorListener listener,
1185 final List<Point3D> inputPoints, final List<Point3D> outputPoints) {
1186 return create(listener, inputPoints, outputPoints, DEFAULT_ROBUST_METHOD);
1187 }
1188
1189 /**
1190 * Creates an Euclidean 3D transformation estimator based on 3D point
1191 * correspondences and using default robust estimator method.
1192 *
1193 * @param qualityScores quality scores corresponding to each pair of matched
1194 * points.
1195 * @return an instance of Euclidean 3D transformation estimator.
1196 */
1197 public static EuclideanTransformation3DRobustEstimator create(final double[] qualityScores) {
1198 return create(qualityScores, DEFAULT_ROBUST_METHOD);
1199 }
1200
1201 /**
1202 * Creates an Euclidean 3D transformation estimator based on 3D point
1203 * correspondences and using default robust estimator method.
1204 *
1205 * @param inputPoints list of input points to be used to estimate an
1206 * Euclidean 3D transformation.
1207 * @param outputPoints list of output points ot be used to estimate an
1208 * Euclidean 3D transformation.
1209 * @param qualityScores quality scores corresponding to each pair of points.
1210 * @return an instance of Euclidean 3D transformation estimator.
1211 * @throws IllegalArgumentException if provided lists of points don't have
1212 * the same size or their size is smaller than MINIMUM_SIZE.
1213 */
1214 public static EuclideanTransformation3DRobustEstimator create(
1215 final List<Point3D> inputPoints, final List<Point3D> outputPoints, final double[] qualityScores) {
1216 return create(inputPoints, outputPoints, qualityScores, DEFAULT_ROBUST_METHOD);
1217 }
1218
1219 /**
1220 * Creates an Euclidean 3D transformation estimator based on 3D point
1221 * correspondences and using default robust estimator method.
1222 *
1223 * @param listener listener to be notified of events such as when estimation
1224 * starts, ends or its progress significantly changes.
1225 * @param qualityScores quality scores corresponding to each pair of matched
1226 * points.
1227 * @return an instance of Euclidean 3D transformation estimator.
1228 */
1229 public static EuclideanTransformation3DRobustEstimator create(
1230 final EuclideanTransformation3DRobustEstimatorListener listener, final double[] qualityScores) {
1231 return create(listener, qualityScores, DEFAULT_ROBUST_METHOD);
1232 }
1233
1234 /**
1235 * Creates an Euclidean 3D transformation estimator based on 3D point
1236 * correspondences and using default robust estimator method.
1237 *
1238 * @param listener listener to be notified of events such as when estimation
1239 * starts, ends or its progress significantly changes.
1240 * @param inputPoints list of input points to be used to estimate an
1241 * Euclidean 3D transformation.
1242 * @param outputPoints list of output points ot be used to estimate an
1243 * Euclidean 3D transformation.
1244 * @param qualityScores quality scores corresponding to each pair of matched
1245 * points.
1246 * @return an instance of Euclidean 3D transformation estimator.
1247 * @throws IllegalArgumentException if provided lists of points don't have
1248 * the same size or their size is smaller than MINIMUM_SIZE.
1249 */
1250 public static EuclideanTransformation3DRobustEstimator create(
1251 final EuclideanTransformation3DRobustEstimatorListener listener,
1252 final List<Point3D> inputPoints, final List<Point3D> outputPoints, final double[] qualityScores) {
1253 return create(listener, inputPoints, outputPoints, qualityScores, DEFAULT_ROBUST_METHOD);
1254 }
1255
1256 /**
1257 * Creates an Euclidean 3D transformation estimator based on 3D point
1258 * correspondences and using default robust estimator method.
1259 *
1260 * @param weakMinimumSizeAllowed true allows 3 points, false requires 4.
1261 * @return an instance of Euclidean 3D transformation estimator.
1262 */
1263 public static EuclideanTransformation3DRobustEstimator create(final boolean weakMinimumSizeAllowed) {
1264 return create(weakMinimumSizeAllowed, DEFAULT_ROBUST_METHOD);
1265 }
1266
1267 /**
1268 * Creates an Euclidean 3D transformation estimator based on 3D point
1269 * correspondences and using default robust estimator method.
1270 *
1271 * @param inputPoints list of input points to be used to estimate an
1272 * Euclidean 3D transformation.
1273 * @param outputPoints list of output points to be used to estimate an
1274 * Euclidean 3D transformation.
1275 * @param weakMinimumSizeAllowed true allows 3 points, false requires 4.
1276 * @return an instance of Euclidean 3D transformation estimator.
1277 * @throws IllegalArgumentException if provided lists of points don't have
1278 * the same size of their size is smaller than MINIMUM_SIZE.
1279 */
1280 public static EuclideanTransformation3DRobustEstimator create(
1281 final List<Point3D> inputPoints, final List<Point3D> outputPoints, final boolean weakMinimumSizeAllowed) {
1282 return create(inputPoints, outputPoints, weakMinimumSizeAllowed, DEFAULT_ROBUST_METHOD);
1283 }
1284
1285 /**
1286 * Creates an Euclidean 3D transformation estimator based on 3D point
1287 * correspondences and using default robust estimator method.
1288 *
1289 * @param listener listener to be notified of events such as when estimation
1290 * starts, ends or its progress significantly changes.
1291 * @param weakMinimumSizeAllowed true allows 3 points, false requires 4.
1292 * @return an instance of Euclidean 3D transformation estimator.
1293 */
1294 public static EuclideanTransformation3DRobustEstimator create(
1295 final EuclideanTransformation3DRobustEstimatorListener listener, final boolean weakMinimumSizeAllowed) {
1296 return create(listener, weakMinimumSizeAllowed, DEFAULT_ROBUST_METHOD);
1297 }
1298
1299 /**
1300 * Creates an Euclidean 3D transformation estimator based on 3D point
1301 * correspondences and using default robust estimator method.
1302 *
1303 * @param listener listener to be notified of events such as when estimation
1304 * starts, ends or its progress significantly changes.
1305 * @param inputPoints list of input points to be used to estimate an
1306 * Euclidean 3D transformation.
1307 * @param outputPoints list of output points to be used to estimate an
1308 * Euclidean 3D transformation.
1309 * @param weakMinimumSizeAllowed true allows 3 points, false requires 4.
1310 * @return an instance of Euclidean 3D transformation estimator.
1311 * @throws IllegalArgumentException if provided lists of points don't have
1312 * the same size or their size is smaller than MINIMUM_SIZE.
1313 */
1314 public static EuclideanTransformation3DRobustEstimator create(
1315 final EuclideanTransformation3DRobustEstimatorListener listener,
1316 final List<Point3D> inputPoints, final List<Point3D> outputPoints, final boolean weakMinimumSizeAllowed) {
1317 return create(listener, inputPoints, outputPoints, weakMinimumSizeAllowed, DEFAULT_ROBUST_METHOD);
1318 }
1319
1320 /**
1321 * Creates an Euclidean 3D transformation estimator based on 3D point
1322 * correspondences and using default robust estimator method.
1323 *
1324 * @param qualityScores quality scores corresponding to each pair of matched
1325 * points.
1326 * @param weakMinimumSizeAllowed true allows 3 points, false requires 4.
1327 * @return an instance of Euclidean 3D transformation estimator.
1328 */
1329 public static EuclideanTransformation3DRobustEstimator create(
1330 final double[] qualityScores, final boolean weakMinimumSizeAllowed) {
1331 return create(qualityScores, weakMinimumSizeAllowed, DEFAULT_ROBUST_METHOD);
1332 }
1333
1334 /**
1335 * Creates an Euclidean 3D transformation estimator based on 3D point
1336 * correspondences and using default robust estimator method.
1337 *
1338 * @param inputPoints list of input points to be used to estimate an
1339 * Euclidean 3D transformation.
1340 * @param outputPoints list of output points ot be used to estimate an
1341 * Euclidean 3D transformation.
1342 * @param qualityScores quality scores corresponding to each pair of points.
1343 * @param weakMinimumSizeAllowed true allows 3 points, false requires 4.
1344 * @return an instance of Euclidean 3D transformation estimator.
1345 * @throws IllegalArgumentException if provided lists of points don't have
1346 * the same size or their size is smaller than MINIMUM_SIZE.
1347 */
1348 public static EuclideanTransformation3DRobustEstimator create(
1349 final List<Point3D> inputPoints, final List<Point3D> outputPoints,
1350 final double[] qualityScores, final boolean weakMinimumSizeAllowed) {
1351 return create(inputPoints, outputPoints, qualityScores, weakMinimumSizeAllowed, DEFAULT_ROBUST_METHOD);
1352 }
1353
1354 /**
1355 * Creates an Euclidean 3D transformation estimator based on 3D point
1356 * correspondences and using default robust estimator method.
1357 *
1358 * @param listener listener to be notified of events such as when estimation
1359 * starts, ends or its progress significantly changes.
1360 * @param qualityScores quality scores corresponding to each pair of matched
1361 * points.
1362 * @param weakMinimumSizeAllowed true allows 3 points, false requires 4.
1363 * @return an instance of Euclidean 3D transformation estimator.
1364 */
1365 public static EuclideanTransformation3DRobustEstimator create(
1366 final EuclideanTransformation3DRobustEstimatorListener listener,
1367 final double[] qualityScores, final boolean weakMinimumSizeAllowed) {
1368 return create(listener, qualityScores, weakMinimumSizeAllowed, DEFAULT_ROBUST_METHOD);
1369 }
1370
1371 /**
1372 * Creates an Euclidean 3D transformation estimator based on 3D point
1373 * correspondences and using default robust estimator method.
1374 *
1375 * @param listener listener to be notified of events such as when estimation
1376 * starts, ends or its progress significantly changes.
1377 * @param inputPoints list of input points to be used to estimate an
1378 * Euclidean 3D transformation.
1379 * @param outputPoints list of output points ot be used to estimate an
1380 * Euclidean 3D transformation.
1381 * @param qualityScores quality scores corresponding to each pair of matched
1382 * points.
1383 * @param weakMinimumSizeAllowed true allows 3 points, false requires 4.
1384 * @return an instance of Euclidean 3D transformation estimator.
1385 * @throws IllegalArgumentException if provided lists of points don't have
1386 * the same size or their size is smaller than MINIMUM_SIZE.
1387 */
1388 public static EuclideanTransformation3DRobustEstimator create(
1389 final EuclideanTransformation3DRobustEstimatorListener listener,
1390 final List<Point3D> inputPoints, final List<Point3D> outputPoints,
1391 final double[] qualityScores, final boolean weakMinimumSizeAllowed) {
1392 return create(listener, inputPoints, outputPoints, qualityScores, weakMinimumSizeAllowed,
1393 DEFAULT_ROBUST_METHOD);
1394 }
1395
1396
1397 /**
1398 * Internal method to set lists of points to be used to estimate an
1399 * Euclidean 3D transformation.
1400 * This method does not check whether estimator is locked or not.
1401 *
1402 * @param inputPoints list of input points to be used to estimate an
1403 * Euclidean 3D transformation.
1404 * @param outputPoints list of output points to be used to estimate an
1405 * Euclidean 3D transformation.
1406 * @throws IllegalArgumentException if provided lists of points don't have
1407 * the same size or their size is smaller than MINIMUM_SIZE.
1408 */
1409 private void internalSetPoints(final List<Point3D> inputPoints, final List<Point3D> outputPoints) {
1410 if (inputPoints.size() < getMinimumPoints()) {
1411 throw new IllegalArgumentException();
1412 }
1413 if (inputPoints.size() != outputPoints.size()) {
1414 throw new IllegalArgumentException();
1415 }
1416 this.inputPoints = inputPoints;
1417 this.outputPoints = outputPoints;
1418 }
1419
1420 /**
1421 * Attempts to refine provided solution if refinement is requested.
1422 * This method returns a refined solution of the same provided solution
1423 * if refinement is not requested or has failed.
1424 * If refinement is enabled, and it is requested to keep covariance, this
1425 * method will also keep covariance of refined transformation.
1426 *
1427 * @param transformation transformation estimated by a robust estimator
1428 * without refinement.
1429 * @return solution after refinement (if requested) or the provided
1430 * non-refined solution if not requested or refinement failed.
1431 */
1432 protected EuclideanTransformation3D attemptRefine(final EuclideanTransformation3D transformation) {
1433 if (refineResult) {
1434 final var refiner = new EuclideanTransformation3DRefiner(transformation, keepCovariance, getInliersData(),
1435 inputPoints, outputPoints, getRefinementStandardDeviation());
1436
1437 try {
1438 final var result = new EuclideanTransformation3D();
1439 final var improved = refiner.refine(result);
1440
1441 if (keepCovariance) {
1442 // keep covariance
1443 covariance = refiner.getCovariance();
1444 }
1445
1446 return improved ? result : transformation;
1447 } catch (final Exception e) {
1448 // refinement failed, so we return input value
1449 return transformation;
1450 }
1451 } else {
1452 return transformation;
1453 }
1454 }
1455
1456 /**
1457 * Gets standard deviation used for Levenberg-Marquardt fitting during
1458 * refinement.
1459 * Returned value gives an indication of how much variance each residual
1460 * has.
1461 * Typically, this value is related to the threshold used on each robust
1462 * estimation, since residuals of found inliers are within the range of
1463 * such threshold.
1464 *
1465 * @return standard deviation used for refinement.
1466 */
1467 protected abstract double getRefinementStandardDeviation();
1468 }