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