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.EuclideanTransformation2D;
20 import com.irurueta.geometry.Point2D;
21 import com.irurueta.geometry.refiners.EuclideanTransformation2DRefiner;
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 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 EuclideanTransformation2DRobustEstimator {
36
37 /**
38 * Minimum number of matched points required to estimate an Euclidean 2D
39 * transformation.
40 */
41 public static final int MINIMUM_SIZE = EuclideanTransformation2DEstimator.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 = EuclideanTransformation2DEstimator.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 EuclideanTransformation2DRobustEstimatorListener 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 an Euclidean 2D 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 an Euclidean 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 /**
192 * Constructor.
193 */
194 protected EuclideanTransformation2DRobustEstimator() {
195 progressDelta = DEFAULT_PROGRESS_DELTA;
196 confidence = DEFAULT_CONFIDENCE;
197 maxIterations = DEFAULT_MAX_ITERATIONS;
198 refineResult = DEFAULT_REFINE_RESULT;
199 keepCovariance = DEFAULT_KEEP_COVARIANCE;
200 }
201
202 /**
203 * Constructor.
204 *
205 * @param listener listener to be notified of events such as when estimation
206 * starts, ends or its progress significantly changes.
207 */
208 protected EuclideanTransformation2DRobustEstimator(
209 final EuclideanTransformation2DRobustEstimatorListener listener) {
210 this();
211 this.listener = listener;
212 }
213
214 /**
215 * Constructor with lists of points to be used to estimate an Euclidean 2D
216 * transformation.
217 * Points in the list located at the same position are considered to be
218 * matched. Hence, both lists must have the same size, and their size must
219 * be greater or equal than MINIMUM_SIZE.
220 *
221 * @param inputPoints list of input points to be used to estimate an
222 * Euclidean 2D transformation.
223 * @param outputPoints list of output points to be used to estimate an
224 * Euclidean 2D transformation.
225 * @throws IllegalArgumentException if provided lists of points don't have
226 * the same size or their size is smaller than MINIMUM_SIZE.
227 */
228 protected EuclideanTransformation2DRobustEstimator(
229 final List<Point2D> inputPoints, final List<Point2D> outputPoints) {
230 this();
231 internalSetPoints(inputPoints, outputPoints);
232 }
233
234 /**
235 * Constructor with listener and lists of points to be used to estimate an
236 * Euclidean 2D transformation.
237 * Points in the list located at the same position are considered to be
238 * matched. Hence, both lists must have the same size, and their size must
239 * be greater or equal than MINIMUM_SIZE.
240 *
241 * @param listener listener to be notified of events such as when estimation
242 * starts, ends or its progress significantly changes.
243 * @param inputPoints list of input points to be used to estimate an
244 * Euclidean 2D transformation.
245 * @param outputPoints list of output points to be used to estimate an
246 * Euclidean 2D transformation.
247 * @throws IllegalArgumentException if provided lists of points don't have
248 * the same size or their size is smaller than MINIMUM_SIZE.
249 */
250 protected EuclideanTransformation2DRobustEstimator(
251 final EuclideanTransformation2DRobustEstimatorListener listener, final List<Point2D> inputPoints,
252 final List<Point2D> outputPoints) {
253 this(listener);
254 internalSetPoints(inputPoints, outputPoints);
255 }
256
257 /**
258 * Constructor.
259 *
260 * @param weakMinimumSizeAllowed true allows 2 points, false requires 3.
261 */
262 protected EuclideanTransformation2DRobustEstimator(final boolean weakMinimumSizeAllowed) {
263 this();
264 this.weakMinimumSizeAllowed = weakMinimumSizeAllowed;
265 }
266
267 /**
268 * Constructor.
269 *
270 * @param listener listener to be notified of events such as when estimation
271 * starts, ends or its progress significantly changes.
272 * @param weakMinimumSizeAllowed true allows 2 points, false requires 3.
273 */
274 protected EuclideanTransformation2DRobustEstimator(
275 final EuclideanTransformation2DRobustEstimatorListener listener, final boolean weakMinimumSizeAllowed) {
276 this();
277 this.listener = listener;
278 this.weakMinimumSizeAllowed = weakMinimumSizeAllowed;
279 }
280
281 /**
282 * Constructor with lists of points to be used to estimate an Euclidean 2D
283 * transformation.
284 * Points in the list located at the same position are considered to be
285 * matched. Hence, both lists must have the same size, and their size must
286 * be greater or equal than MINIMUM_SIZE.
287 *
288 * @param inputPoints list of input points to be used to estimate an
289 * Euclidean 2D transformation.
290 * @param outputPoints list of output points to be used to estimate an
291 * Euclidean 2D transformation.
292 * @param weakMinimumSizeAllowed true allows 2 points, false requires 3.
293 * @throws IllegalArgumentException if provided lists of points don't have
294 * the same size or their size is smaller than MINIMUM_SIZE.
295 */
296 protected EuclideanTransformation2DRobustEstimator(
297 final List<Point2D> inputPoints, final List<Point2D> outputPoints, final boolean weakMinimumSizeAllowed) {
298 this();
299 this.weakMinimumSizeAllowed = weakMinimumSizeAllowed;
300 internalSetPoints(inputPoints, outputPoints);
301 }
302
303 /**
304 * Constructor with listener and lists of points to be used to estimate an
305 * Euclidean 2D transformation.
306 * Points in the list located at the same position are considered to be
307 * matched. Hence, both lists must have the same size, and their size must
308 * be greater or equal than MINIMUM_SIZE.
309 *
310 * @param listener listener to be notified of events such as when estimation
311 * starts, ends or its progress significantly changes.
312 * @param inputPoints list of input points to be used to estimate an
313 * Euclidean 2D transformation.
314 * @param outputPoints list of output points to be used to estimate an
315 * Euclidean 2D transformation.
316 * @param weakMinimumSizeAllowed true allows 2 points, false requires 3.
317 * @throws IllegalArgumentException if provided lists of points don't have
318 * the same size or their size is smaller than MINIMUM_SIZE.
319 */
320 protected EuclideanTransformation2DRobustEstimator(
321 final EuclideanTransformation2DRobustEstimatorListener listener, final List<Point2D> inputPoints,
322 final List<Point2D> outputPoints, final boolean weakMinimumSizeAllowed) {
323 this(listener);
324 this.weakMinimumSizeAllowed = weakMinimumSizeAllowed;
325 internalSetPoints(inputPoints, outputPoints);
326 }
327
328 /**
329 * Returns list of input points to be used to estimate an Euclidean 2D
330 * transformation.
331 * Each point in the list of input points must be matched with the
332 * corresponding point in the list of output points located at the same
333 * position. Hence, both input points and output points must have the same
334 * size, and their size must be greater or equal than MINIMUM_SIZE.
335 *
336 * @return list of input points to be used to estimate an Euclidean 2D
337 * transformation.
338 */
339 public List<Point2D> getInputPoints() {
340 return inputPoints;
341 }
342
343 /**
344 * Returns list of output points to be used to estimate an Euclidean 2D
345 * transformation.
346 * Each point in the list of output points must be matched with the
347 * corresponding point in the list of input points located at the same
348 * position. Hence, both input points and output points must have the same
349 * size, and their size must be greater or equal than MINIMUM_SIZE.
350 *
351 * @return list of output points to be used to estimate an Euclidean 2D
352 * transformation.
353 */
354 public List<Point2D> getOutputPoints() {
355 return outputPoints;
356 }
357
358 /**
359 * Sets list of points to be used to estimate an Euclidean 2D
360 * transformation.
361 * Points in the list located at the same position are considered to be
362 * matched. Hence, both lists must have the same size, and their size must
363 * be greater or equal than MINIMUM_SIZE.
364 *
365 * @param inputPoints list of input points to be used to estimate an
366 * Euclidean 2D transformation.
367 * @param outputPoints list of output points to be used to estimate an
368 * Euclidean 2D transformation.
369 * @throws IllegalArgumentException if provided lists of points don't have
370 * the same size or their size is smaller than MINIMUM_SIZE.
371 * @throws LockedException if estimator is locked because a computation is
372 * already in progress.
373 */
374 public void setPoints(final List<Point2D> inputPoints, final List<Point2D> outputPoints) throws LockedException {
375 if (isLocked()) {
376 throw new LockedException();
377 }
378 internalSetPoints(inputPoints, outputPoints);
379 }
380
381 /**
382 * Indicates if estimator is ready to start the Euclidean 2D transformation
383 * estimation.
384 * This is true when input data (i.e. lists of matched points) are provided
385 * and a minimum of MINIMUM_SIZE points are available.
386 *
387 * @return true if estimator is ready, false otherwise.
388 */
389 public boolean isReady() {
390 return inputPoints != null && outputPoints != null && inputPoints.size() == outputPoints.size()
391 && inputPoints.size() >= getMinimumPoints();
392 }
393
394 /**
395 * Returns quality scores corresponding to each pair of matched points.
396 * The larger the score value the better the quality of the matching.
397 * This implementation always returns null.
398 * Subclasses using quality scores must implement proper behaviour.
399 *
400 * @return quality scores corresponding to each pair of matched points.
401 */
402 public double[] getQualityScores() {
403 return null;
404 }
405
406 /**
407 * Sets quality scores corresponding to each pair of matched points.
408 * The larger the score value the better the quality of the matching.
409 * This implementation makes no action.
410 * Subclasses using quality scores must implement proper behaviour.
411 *
412 * @param qualityScores quality scores corresponding to each pair of matched
413 * points.
414 * @throws LockedException if robust estimator is locked because an
415 * estimation is already in progress.
416 * @throws IllegalArgumentException if provided quality scores length is
417 * smaller than MINIMUM_SIZE (i.e. 3 samples).
418 */
419 public void setQualityScores(final double[] qualityScores) throws LockedException {
420 }
421
422 /**
423 * Returns reference to listener to be notified of events such as when
424 * estimation starts, ends or its progress significantly changes.
425 *
426 * @return listener to be notified of events.
427 */
428 public EuclideanTransformation2DRobustEstimatorListener getListener() {
429 return listener;
430 }
431
432 /**
433 * Sets listener to be notified of events such as when estimation starts,
434 * ends or its progress significantly changes.
435 *
436 * @param listener listener to be notified of events.
437 * @throws LockedException if robust estimator is locked.
438 */
439 public void setListener(final EuclideanTransformation2DRobustEstimatorListener listener) throws LockedException {
440 if (isLocked()) {
441 throw new LockedException();
442 }
443 this.listener = listener;
444 }
445
446 /**
447 * Indicates whether listener has been provided and is available for
448 * retrieval.
449 *
450 * @return true if available, false otherwise.
451 */
452 public boolean isListenerAvailable() {
453 return listener != null;
454 }
455
456 /**
457 * Indicates whether estimation can start with only 2 points or not.
458 *
459 * @return true allows 2 points, false requires 3.
460 */
461 public boolean isWeakMinimumSizeAllowed() {
462 return weakMinimumSizeAllowed;
463 }
464
465 /**
466 * Specifies whether estimation can start with only 2 points or not.
467 *
468 * @param weakMinimumSizeAllowed true allows 2 points, false requires 3.
469 * @throws LockedException if estimator is locked.
470 */
471 public void setWeakMinimumSizeAllowed(final boolean weakMinimumSizeAllowed) throws LockedException {
472 if (isLocked()) {
473 throw new LockedException();
474 }
475 this.weakMinimumSizeAllowed = weakMinimumSizeAllowed;
476 }
477
478 /**
479 * Required minimum number of point correspondences to start the estimation.
480 * Can be either 2 or 3.
481 *
482 * @return minimum number of point correspondences.
483 */
484 public int getMinimumPoints() {
485 return weakMinimumSizeAllowed ? WEAK_MINIMUM_SIZE : MINIMUM_SIZE;
486 }
487
488 /**
489 * Indicates if this instance is locked because estimation is being
490 * computed.
491 *
492 * @return true if locked, false otherwise.
493 */
494 public boolean isLocked() {
495 return locked;
496 }
497
498 /**
499 * Returns amount of progress variation before notifying a progress change
500 * during estimation.
501 *
502 * @return amount of progress variation before notifying a progress change
503 * during estimation.
504 */
505 public float getProgressDelta() {
506 return progressDelta;
507 }
508
509 /**
510 * Sets amount of progress variation before notifying a progress change
511 * during estimation.
512 *
513 * @param progressDelta amount of progress variation before notifying a
514 * progress change during estimation.
515 * @throws IllegalArgumentException if progress delta is less than zero or
516 * greater than 1.
517 * @throws LockedException if this estimator is locked because an estimation
518 * is being computed.
519 */
520 public void setProgressDelta(final float progressDelta) throws LockedException {
521 if (isLocked()) {
522 throw new LockedException();
523 }
524 if (progressDelta < MIN_PROGRESS_DELTA || progressDelta > MAX_PROGRESS_DELTA) {
525 throw new IllegalArgumentException();
526 }
527 this.progressDelta = progressDelta;
528 }
529
530 /**
531 * Returns amount of confidence expressed as a value between 0.0 and 1.0
532 * (which is equivalent to 100%). The amount of confidence indicates the
533 * probability that the estimated result is correct. Usually this value will
534 * be close to 1.0, but not exactly 1.0.
535 *
536 * @return amount of confidence as a value between 0.0 and 1.0.
537 */
538 public double getConfidence() {
539 return confidence;
540 }
541
542 /**
543 * Sets amount of confidence expressed as a value between 0.0 and 1.0 (which
544 * is equivalent to 100%). The amount of confidence indicates the
545 * probability that the estimated result is correct. Usually this value will
546 * be close to 1.0, but not exactly 1.0.
547 *
548 * @param confidence confidence to be set as a value between 0.0 and 1.0.
549 * @throws IllegalArgumentException if provided value is not between 0.0 and
550 * 1.0.
551 * @throws LockedException if this estimator is locked because an estimator
552 * is being computed.
553 */
554 public void setConfidence(final double confidence) throws LockedException {
555 if (isLocked()) {
556 throw new LockedException();
557 }
558 if (confidence < MIN_CONFIDENCE || confidence > MAX_CONFIDENCE) {
559 throw new IllegalArgumentException();
560 }
561 this.confidence = confidence;
562 }
563
564 /**
565 * Returns maximum allowed number of iterations. If maximum allowed number
566 * of iterations is achieved without converging to a result when calling
567 * estimate(), a RobustEstimatorException will be raised.
568 *
569 * @return maximum allowed number of iterations.
570 */
571 public int getMaxIterations() {
572 return maxIterations;
573 }
574
575 /**
576 * Sets maximum allowed number of iterations. When the maximum number of
577 * iterations is exceeded, result will not be available, however an
578 * approximate result will be available for retrieval.
579 *
580 * @param maxIterations maximum allowed number of iterations to be set.
581 * @throws IllegalArgumentException if provided value is less than 1.
582 * @throws LockedException if this estimator is locked because an estimation
583 * is being computed.
584 */
585 public void setMaxIterations(final int maxIterations) throws LockedException {
586 if (isLocked()) {
587 throw new LockedException();
588 }
589 if (maxIterations < MIN_ITERATIONS) {
590 throw new IllegalArgumentException();
591 }
592 this.maxIterations = maxIterations;
593 }
594
595 /**
596 * Gets data related to inliers found after estimation.
597 *
598 * @return data related to inliers found after estimation.
599 */
600 public InliersData getInliersData() {
601 return inliersData;
602 }
603
604 /**
605 * Indicates whether result must be refined using Levenberg-Marquardt
606 * fitting algorithm over found inliers.
607 * If ture, inliers will be computed and kept in any implementation
608 * regardless of the settings.
609 *
610 * @return true to refine result, false to simply use result found by
611 * robust estimator without further refining.
612 */
613 public boolean isResultRefined() {
614 return refineResult;
615 }
616
617 /**
618 * Specifies whether result must be refined using Levenberg-Marquardt
619 * fitting algorithm over found inliers.
620 *
621 * @param refineResult true to refine result, false to simply use result
622 * found by robust estimator without further refining.
623 * @throws LockedException if estimator is locked.
624 */
625 public void setResultRefined(final boolean refineResult) throws LockedException {
626 if (isLocked()) {
627 throw new LockedException();
628 }
629 this.refineResult = refineResult;
630 }
631
632 /**
633 * Indicates whether covariance must be kept after refining result.
634 * This setting is only taken into account if result is refined.
635 *
636 * @return true if covariance must be kept after refining result, false
637 * otherwise.
638 */
639 public boolean isCovarianceKept() {
640 return keepCovariance;
641 }
642
643 /**
644 * Specifies whether covariance must be kept after refining result.
645 * This setting is only taken into account if result is refined.
646 *
647 * @param keepCovariance true if covariance must be kept after refining
648 * result, false otherwise.
649 * @throws LockedException if estimator is locked.
650 */
651 public void setCovarianceKept(final boolean keepCovariance) throws LockedException {
652 if (isLocked()) {
653 throw new LockedException();
654 }
655 this.keepCovariance = keepCovariance;
656 }
657
658 /**
659 * Gets estimated covariance of estimated 3D point if available.
660 * This is only available when result has been refined and covariance is
661 * kept.
662 *
663 * @return estimated covariance or null.
664 */
665 public Matrix getCovariance() {
666 return covariance;
667 }
668
669 /**
670 * Estimates an Euclidean 2D transformation using a robust estimator and the
671 * best set of matched 2D point correspondences found using the robust
672 * estimator.
673 *
674 * @return an Euclidean 2D transformation.
675 * @throws LockedException if robust estimator is locked because an
676 * estimation is already in progress.
677 * @throws NotReadyException if provided input data is not enough to start
678 * the estimation.
679 * @throws RobustEstimatorException if estimation fails for any reason
680 * (i.e. numerical instability, no solution available, etc).
681 */
682 public abstract EuclideanTransformation2D estimate() throws LockedException, NotReadyException,
683 RobustEstimatorException;
684
685 /**
686 * Returns method being used for robust estimation.
687 *
688 * @return method being used for robust estimation.
689 */
690 public abstract RobustEstimatorMethod getMethod();
691
692 /**
693 * Creates an Euclidean 2D transformation estimator based on 2D point
694 * correspondences and using provided robust estimator method.
695 *
696 * @param method method of a robust estimator algorithm to estimate the
697 * best Euclidean 2D transformation.
698 * @return an instance of Euclidean 2D transformation estimator.
699 */
700 public static EuclideanTransformation2DRobustEstimator create(final RobustEstimatorMethod method) {
701 return switch (method) {
702 case LMEDS -> new LMedSEuclideanTransformation2DRobustEstimator();
703 case MSAC -> new MSACEuclideanTransformation2DRobustEstimator();
704 case PROSAC -> new PROSACEuclideanTransformation2DRobustEstimator();
705 case PROMEDS -> new PROMedSEuclideanTransformation2DRobustEstimator();
706 default -> new RANSACEuclideanTransformation2DRobustEstimator();
707 };
708 }
709
710 /**
711 * Creates an Euclidean 2D transformation estimator based on 2D point
712 * correspondences and using provided estimator method.
713 *
714 * @param inputPoints list of input points to be used to estimate an
715 * Euclidean 2D transformation.
716 * @param outputPoints list of output points to be used to estimate an
717 * Euclidean 2D transformation.
718 * @param method method of a robust estimator algorithm to estimate the best
719 * Euclidean 2D transformation.
720 * @return an instance of Euclidean 2D 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 EuclideanTransformation2DRobustEstimator create(
725 final List<Point2D> inputPoints, final List<Point2D> outputPoints, final RobustEstimatorMethod method) {
726 return switch (method) {
727 case LMEDS -> new LMedSEuclideanTransformation2DRobustEstimator(inputPoints, outputPoints);
728 case MSAC -> new MSACEuclideanTransformation2DRobustEstimator(inputPoints, outputPoints);
729 case PROSAC -> new PROSACEuclideanTransformation2DRobustEstimator(inputPoints, outputPoints);
730 case PROMEDS -> new PROMedSEuclideanTransformation2DRobustEstimator(inputPoints, outputPoints);
731 default -> new RANSACEuclideanTransformation2DRobustEstimator(inputPoints, outputPoints);
732 };
733 }
734
735 /**
736 * Creates an Euclidean 2D transformation estimator based on 2D 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 2D transformation.
743 * @return an instance of Euclidean 2D transformation estimator.
744 */
745 public static EuclideanTransformation2DRobustEstimator create(
746 final EuclideanTransformation2DRobustEstimatorListener listener, final RobustEstimatorMethod method) {
747 return switch (method) {
748 case LMEDS -> new LMedSEuclideanTransformation2DRobustEstimator(listener);
749 case MSAC -> new MSACEuclideanTransformation2DRobustEstimator(listener);
750 case PROSAC -> new PROSACEuclideanTransformation2DRobustEstimator(listener);
751 case PROMEDS -> new PROMedSEuclideanTransformation2DRobustEstimator(listener);
752 default -> new RANSACEuclideanTransformation2DRobustEstimator(listener);
753 };
754 }
755
756 /**
757 * Creates an Euclidean 2D transformation estimator based on 2D 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 2D transformation.
764 * @param outputPoints list of output points to be used to estimate an
765 * Euclidean 2D transformation.
766 * @param method method of a robust estimator algorithm to estimate the best
767 * Euclidean 2D transformation.
768 * @return an instance of Euclidean 2D 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 EuclideanTransformation2DRobustEstimator create(
773 final EuclideanTransformation2DRobustEstimatorListener listener, final List<Point2D> inputPoints,
774 final List<Point2D> outputPoints, final RobustEstimatorMethod method) {
775 return switch (method) {
776 case LMEDS -> new LMedSEuclideanTransformation2DRobustEstimator(listener, inputPoints, outputPoints);
777 case MSAC -> new MSACEuclideanTransformation2DRobustEstimator(listener, inputPoints, outputPoints);
778 case PROSAC -> new PROSACEuclideanTransformation2DRobustEstimator(listener, inputPoints, outputPoints);
779 case PROMEDS -> new PROMedSEuclideanTransformation2DRobustEstimator(listener, inputPoints, outputPoints);
780 default -> new RANSACEuclideanTransformation2DRobustEstimator(listener, inputPoints, outputPoints);
781 };
782 }
783
784 /**
785 * Creates an Euclidean 2D transformation estimator based on 2D 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 2D transformation.
792 * @return an instance of Euclidean 2D 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 EuclideanTransformation2DRobustEstimator create(
797 final double[] qualityScores, final RobustEstimatorMethod method) {
798 return switch (method) {
799 case LMEDS -> new LMedSEuclideanTransformation2DRobustEstimator();
800 case MSAC -> new MSACEuclideanTransformation2DRobustEstimator();
801 case PROSAC -> new PROSACEuclideanTransformation2DRobustEstimator(qualityScores);
802 case PROMEDS -> new PROMedSEuclideanTransformation2DRobustEstimator(qualityScores);
803 default -> new RANSACEuclideanTransformation2DRobustEstimator();
804 };
805 }
806
807 /**
808 * Creates an Euclidean 2D transformation estimator based on 2D 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 2D transformation.
813 * @param outputPoints list of output points to be used to estimate an
814 * Euclidean 2D 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 2D transformation.
819 * @return an instance of Euclidean 2D 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 EuclideanTransformation2DRobustEstimator create(
824 final List<Point2D> inputPoints, final List<Point2D> outputPoints, final double[] qualityScores,
825 final RobustEstimatorMethod method) {
826 return switch (method) {
827 case LMEDS -> new LMedSEuclideanTransformation2DRobustEstimator(inputPoints, outputPoints);
828 case MSAC -> new MSACEuclideanTransformation2DRobustEstimator(inputPoints, outputPoints);
829 case PROSAC -> new PROSACEuclideanTransformation2DRobustEstimator(inputPoints, outputPoints, qualityScores);
830 case PROMEDS -> new PROMedSEuclideanTransformation2DRobustEstimator(
831 inputPoints, outputPoints, qualityScores);
832 default -> new RANSACEuclideanTransformation2DRobustEstimator(inputPoints, outputPoints);
833 };
834 }
835
836 /**
837 * Creates an Euclidean 2D transformation estimator based on 2D 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 2D transformation.
846 * @return an instance of Euclidean 2D transformation estimator.
847 * @throws IllegalArgumentException if provided quality scores don't have
848 * the required minimum size.
849 */
850 public static EuclideanTransformation2DRobustEstimator create(
851 final EuclideanTransformation2DRobustEstimatorListener listener, final double[] qualityScores,
852 final RobustEstimatorMethod method) {
853 return switch (method) {
854 case LMEDS -> new LMedSEuclideanTransformation2DRobustEstimator(listener);
855 case MSAC -> new MSACEuclideanTransformation2DRobustEstimator(listener);
856 case PROSAC -> new PROSACEuclideanTransformation2DRobustEstimator(listener, qualityScores);
857 case PROMEDS -> new PROMedSEuclideanTransformation2DRobustEstimator(listener, qualityScores);
858 default -> new RANSACEuclideanTransformation2DRobustEstimator(listener);
859 };
860 }
861
862 /**
863 * Creates an Euclidean 2D transformation estimator based on 2D 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 2D transformation.
870 * @param outputPoints list of output points to be used to estimate an
871 * Euclidean 2D 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 2D transformation.
876 * @return an instance of Euclidean 2D 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 EuclideanTransformation2DRobustEstimator create(
881 final EuclideanTransformation2DRobustEstimatorListener listener, final List<Point2D> inputPoints,
882 final List<Point2D> outputPoints, final double[] qualityScores, final RobustEstimatorMethod method) {
883 return switch (method) {
884 case LMEDS -> new LMedSEuclideanTransformation2DRobustEstimator(listener, inputPoints, outputPoints);
885 case MSAC -> new MSACEuclideanTransformation2DRobustEstimator(listener, inputPoints, outputPoints);
886 case PROSAC -> new PROSACEuclideanTransformation2DRobustEstimator(
887 listener, inputPoints, outputPoints, qualityScores);
888 case PROMEDS -> new PROMedSEuclideanTransformation2DRobustEstimator(
889 listener, inputPoints, outputPoints, qualityScores);
890 default -> new RANSACEuclideanTransformation2DRobustEstimator(listener, inputPoints, outputPoints);
891 };
892 }
893
894 /**
895 * Creates an Euclidean 2D transformation estimator based on 2D point
896 * correspondences and using provided robust estimator method.
897 *
898 * @param weakMinimumSizeAllowed true allows 2 points, false requires 3.
899 * @param method method of a robust estimator algorithm to estimate
900 * the best Euclidean 2D transformation.
901 * @return an instance of Euclidean 2D transformation estimator.
902 */
903 public static EuclideanTransformation2DRobustEstimator create(
904 final boolean weakMinimumSizeAllowed, final RobustEstimatorMethod method) {
905 return switch (method) {
906 case LMEDS -> new LMedSEuclideanTransformation2DRobustEstimator(weakMinimumSizeAllowed);
907 case MSAC -> new MSACEuclideanTransformation2DRobustEstimator(weakMinimumSizeAllowed);
908 case PROSAC -> new PROSACEuclideanTransformation2DRobustEstimator(weakMinimumSizeAllowed);
909 case PROMEDS -> new PROMedSEuclideanTransformation2DRobustEstimator(weakMinimumSizeAllowed);
910 default -> new RANSACEuclideanTransformation2DRobustEstimator(weakMinimumSizeAllowed);
911 };
912 }
913
914 /**
915 * Creates an Euclidean 2D transformation estimator based on 2D point
916 * correspondences and using provided estimator method.
917 *
918 * @param inputPoints list of input points to be used to estimate an
919 * Euclidean 2D transformation.
920 * @param outputPoints list of output points to be used to estimate an
921 * Euclidean 2D transformation.
922 * @param weakMinimumSizeAllowed true allows 2 points, false requires 3.
923 * @param method method of a robust estimator algorithm to estimate the best
924 * Euclidean 2D transformation.
925 * @return an instance of Euclidean 2D transformation estimator.
926 * @throws IllegalArgumentException if provided lists of points don't have
927 * the same size or their size is smaller than MINIMUM_SIZE.
928 */
929 public static EuclideanTransformation2DRobustEstimator create(
930 final List<Point2D> inputPoints, final List<Point2D> outputPoints, final boolean weakMinimumSizeAllowed,
931 final RobustEstimatorMethod method) {
932 return switch (method) {
933 case LMEDS -> new LMedSEuclideanTransformation2DRobustEstimator(
934 inputPoints, outputPoints, weakMinimumSizeAllowed);
935 case MSAC -> new MSACEuclideanTransformation2DRobustEstimator(
936 inputPoints, outputPoints, weakMinimumSizeAllowed);
937 case PROSAC -> new PROSACEuclideanTransformation2DRobustEstimator(
938 inputPoints, outputPoints, weakMinimumSizeAllowed);
939 case PROMEDS -> new PROMedSEuclideanTransformation2DRobustEstimator(
940 inputPoints, outputPoints, weakMinimumSizeAllowed);
941 default -> new RANSACEuclideanTransformation2DRobustEstimator(
942 inputPoints, outputPoints, weakMinimumSizeAllowed);
943 };
944 }
945
946 /**
947 * Creates an Euclidean 2D transformation estimator based on 2D point
948 * correspondences and using provided robust estimator method.
949 *
950 * @param listener listener to be notified of events such as when estimation
951 * starts, ends or its progress significantly changes.
952 * @param weakMinimumSizeAllowed true allows 2 points, false requires 3.
953 * @param method method of a robust estimator algorithm to estimate the best
954 * Euclidean 2D transformation.
955 * @return an instance of Euclidean 2D transformation estimator.
956 */
957 public static EuclideanTransformation2DRobustEstimator create(
958 final EuclideanTransformation2DRobustEstimatorListener listener, final boolean weakMinimumSizeAllowed,
959 final RobustEstimatorMethod method) {
960 return switch (method) {
961 case LMEDS -> new LMedSEuclideanTransformation2DRobustEstimator(listener, weakMinimumSizeAllowed);
962 case MSAC -> new MSACEuclideanTransformation2DRobustEstimator(listener, weakMinimumSizeAllowed);
963 case PROSAC -> new PROSACEuclideanTransformation2DRobustEstimator(listener, weakMinimumSizeAllowed);
964 case PROMEDS -> new PROMedSEuclideanTransformation2DRobustEstimator(listener, weakMinimumSizeAllowed);
965 default -> new RANSACEuclideanTransformation2DRobustEstimator(listener, weakMinimumSizeAllowed);
966 };
967 }
968
969 /**
970 * Creates an Euclidean 2D transformation estimator based on 2D point
971 * correspondences and using provided robust estimator method.
972 *
973 * @param listener listener to be notified of events such as when estimation
974 * starts, ends or its progress significantly changes.
975 * @param inputPoints list of input points to be used to estimate an
976 * Euclidean 2D transformation.
977 * @param outputPoints list of output points to be used to estimate an
978 * Euclidean 2D transformation.
979 * @param weakMinimumSizeAllowed true allows 2 points, false requires 3.
980 * @param method method of a robust estimator algorithm to estimate the best
981 * Euclidean 2D transformation.
982 * @return an instance of Euclidean 2D transformation estimator.
983 * @throws IllegalArgumentException if provided lists of points don't have
984 * the same size or their size is smaller than MINIMUM_SIZE.
985 */
986 public static EuclideanTransformation2DRobustEstimator create(
987 final EuclideanTransformation2DRobustEstimatorListener listener, final List<Point2D> inputPoints,
988 final List<Point2D> outputPoints, final boolean weakMinimumSizeAllowed,
989 final RobustEstimatorMethod method) {
990 return switch (method) {
991 case LMEDS -> new LMedSEuclideanTransformation2DRobustEstimator(
992 listener, inputPoints, outputPoints, weakMinimumSizeAllowed);
993 case MSAC -> new MSACEuclideanTransformation2DRobustEstimator(
994 listener, inputPoints, outputPoints, weakMinimumSizeAllowed);
995 case PROSAC -> new PROSACEuclideanTransformation2DRobustEstimator(
996 listener, inputPoints, outputPoints, weakMinimumSizeAllowed);
997 case PROMEDS -> new PROMedSEuclideanTransformation2DRobustEstimator(
998 listener, inputPoints, outputPoints, weakMinimumSizeAllowed);
999 default -> new RANSACEuclideanTransformation2DRobustEstimator(
1000 listener, inputPoints, outputPoints, weakMinimumSizeAllowed);
1001 };
1002 }
1003
1004 /**
1005 * Creates an Euclidean 2D transformation estimator based on 2D point
1006 * correspondences and using provided robust estimator method.
1007 *
1008 * @param qualityScores quality scores corresponding to each pair of matched
1009 * points.
1010 * @param weakMinimumSizeAllowed true allows 2 points, false requires 3.
1011 * @param method method of a robust estimator algorithm to estimate the best
1012 * Euclidean 2D transformation.
1013 * @return an instance of Euclidean 2D transformation estimator.
1014 * @throws IllegalArgumentException if provided quality scores length is
1015 * smaller than MINIMUM_SIZE (i.e. 3 matched points).
1016 */
1017 public static EuclideanTransformation2DRobustEstimator create(
1018 final double[] qualityScores, final boolean weakMinimumSizeAllowed, final RobustEstimatorMethod method) {
1019 return switch (method) {
1020 case LMEDS -> new LMedSEuclideanTransformation2DRobustEstimator(weakMinimumSizeAllowed);
1021 case MSAC -> new MSACEuclideanTransformation2DRobustEstimator(weakMinimumSizeAllowed);
1022 case PROSAC -> new PROSACEuclideanTransformation2DRobustEstimator(qualityScores, weakMinimumSizeAllowed);
1023 case PROMEDS -> new PROMedSEuclideanTransformation2DRobustEstimator(qualityScores, weakMinimumSizeAllowed);
1024 default -> new RANSACEuclideanTransformation2DRobustEstimator(weakMinimumSizeAllowed);
1025 };
1026 }
1027
1028 /**
1029 * Creates an Euclidean 2D transformation estimator based on 2D point
1030 * correspondences and using provided robust estimator method.
1031 *
1032 * @param inputPoints list of input points to be used to estimate an
1033 * Euclidean 2D transformation.
1034 * @param outputPoints list of output points to be used to estimate an
1035 * Euclidean 2D transformation.
1036 * @param qualityScores quality scores corresponding to each pair of matched
1037 * points.
1038 * @param weakMinimumSizeAllowed true allows 2 points, false requires 3.
1039 * @param method method of a robust estimator algorithm to estimate the best
1040 * Euclidean 2D transformation.
1041 * @return an instance of Euclidean 2D transformation estimator.
1042 * @throws IllegalArgumentException if provided lists of points or scores
1043 * don't have the same size or their size is smaller than MINIMUM_SIZE.
1044 */
1045 public static EuclideanTransformation2DRobustEstimator create(
1046 final List<Point2D> inputPoints, final List<Point2D> outputPoints, final double[] qualityScores,
1047 final boolean weakMinimumSizeAllowed, final RobustEstimatorMethod method) {
1048 return switch (method) {
1049 case LMEDS -> new LMedSEuclideanTransformation2DRobustEstimator(
1050 inputPoints, outputPoints, weakMinimumSizeAllowed);
1051 case MSAC -> new MSACEuclideanTransformation2DRobustEstimator(
1052 inputPoints, outputPoints, weakMinimumSizeAllowed);
1053 case PROSAC -> new PROSACEuclideanTransformation2DRobustEstimator(
1054 inputPoints, outputPoints, qualityScores, weakMinimumSizeAllowed);
1055 case PROMEDS -> new PROMedSEuclideanTransformation2DRobustEstimator(
1056 inputPoints, outputPoints, qualityScores, weakMinimumSizeAllowed);
1057 default -> new RANSACEuclideanTransformation2DRobustEstimator(
1058 inputPoints, outputPoints, weakMinimumSizeAllowed);
1059 };
1060 }
1061
1062 /**
1063 * Creates an Euclidean 2D transformation estimator based on 2D point
1064 * correspondences and using provided robust estimator method.
1065 *
1066 * @param listener listener to be notified of events such as when estimation
1067 * starts, ends or its progress significantly changes.
1068 * @param qualityScores quality scores corresponding to each pair of matched
1069 * points.
1070 * @param weakMinimumSizeAllowed true allows 2 points, false requires 3.
1071 * @param method method of a robust estimator algorithm to estimate the best
1072 * Euclidean 2D transformation.
1073 * @return an instance of Euclidean 2D transformation estimator.
1074 * @throws IllegalArgumentException if provided quality scores don't have
1075 * the required minimum size.
1076 */
1077 public static EuclideanTransformation2DRobustEstimator create(
1078 final EuclideanTransformation2DRobustEstimatorListener listener, final double[] qualityScores,
1079 final boolean weakMinimumSizeAllowed, final RobustEstimatorMethod method) {
1080 return switch (method) {
1081 case LMEDS -> new LMedSEuclideanTransformation2DRobustEstimator(listener, weakMinimumSizeAllowed);
1082 case MSAC -> new MSACEuclideanTransformation2DRobustEstimator(listener, weakMinimumSizeAllowed);
1083 case PROSAC -> new PROSACEuclideanTransformation2DRobustEstimator(
1084 listener, qualityScores, weakMinimumSizeAllowed);
1085 case PROMEDS -> new PROMedSEuclideanTransformation2DRobustEstimator(
1086 listener, qualityScores, weakMinimumSizeAllowed);
1087 default -> new RANSACEuclideanTransformation2DRobustEstimator(listener, weakMinimumSizeAllowed);
1088 };
1089 }
1090
1091 /**
1092 * Creates an Euclidean 2D transformation estimator based on 2D point
1093 * correspondences and using provided robust estimator method.
1094 *
1095 * @param listener listener to be notified of events such as when estimation
1096 * starts, ends or its progress significantly changes.
1097 * @param inputPoints list of input points to be used to estimate an
1098 * Euclidean 2D transformation.
1099 * @param outputPoints list of output points to be used to estimate an
1100 * Euclidean 2D transformation.
1101 * @param qualityScores quality scores corresponding to each pair of matched
1102 * points.
1103 * @param weakMinimumSizeAllowed true allows 2 points, false requires 3.
1104 * @param method method of a robust estimator algorithm to estimate the best
1105 * Euclidean 2D transformation.
1106 * @return an instance of Euclidean 2D transformation estimator.
1107 * @throws IllegalArgumentException if provided lists of points don't have
1108 * the same size of their size is smaller than MINIMUM_SIZE.
1109 */
1110 public static EuclideanTransformation2DRobustEstimator create(
1111 final EuclideanTransformation2DRobustEstimatorListener listener, final List<Point2D> inputPoints,
1112 final List<Point2D> outputPoints, final double[] qualityScores, final boolean weakMinimumSizeAllowed,
1113 final RobustEstimatorMethod method) {
1114 return switch (method) {
1115 case LMEDS -> new LMedSEuclideanTransformation2DRobustEstimator(
1116 listener, inputPoints, outputPoints, weakMinimumSizeAllowed);
1117 case MSAC -> new MSACEuclideanTransformation2DRobustEstimator(
1118 listener, inputPoints, outputPoints, weakMinimumSizeAllowed);
1119 case PROSAC -> new PROSACEuclideanTransformation2DRobustEstimator(
1120 listener, inputPoints, outputPoints, qualityScores, weakMinimumSizeAllowed);
1121 case PROMEDS -> new PROMedSEuclideanTransformation2DRobustEstimator(
1122 listener, inputPoints, outputPoints, qualityScores, weakMinimumSizeAllowed);
1123 default -> new RANSACEuclideanTransformation2DRobustEstimator(
1124 listener, inputPoints, outputPoints, weakMinimumSizeAllowed);
1125 };
1126 }
1127
1128
1129 /**
1130 * Creates an Euclidean 2D transformation estimator based on 2D point
1131 * correspondences and using default robust estimator method.
1132 *
1133 * @return an instance of Euclidean 2D transformation estimator.
1134 */
1135 public static EuclideanTransformation2DRobustEstimator create() {
1136 return create(DEFAULT_ROBUST_METHOD);
1137 }
1138
1139 /**
1140 * Creates an Euclidean 2D transformation estimator based on 2D 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 2D transformation.
1145 * @param outputPoints list of output points to be used to estimate an
1146 * Euclidean 2D transformation.
1147 * @return an instance of Euclidean 2D 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 EuclideanTransformation2DRobustEstimator create(
1152 final List<Point2D> inputPoints, final List<Point2D> outputPoints) {
1153 return create(inputPoints, outputPoints, DEFAULT_ROBUST_METHOD);
1154 }
1155
1156 /**
1157 * Creates an Euclidean 2D transformation estimator based on 2D 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 2D transformation estimator.
1163 */
1164 public static EuclideanTransformation2DRobustEstimator create(
1165 final EuclideanTransformation2DRobustEstimatorListener listener) {
1166 return create(listener, DEFAULT_ROBUST_METHOD);
1167 }
1168
1169 /**
1170 * Creates an Euclidean 2D transformation estimator based on 2D 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 2D transformation.
1177 * @param outputPoints list of output points to be used to estimate an
1178 * Euclidean 2D transformation.
1179 * @return an instance of Euclidean 2D 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 EuclideanTransformation2DRobustEstimator create(
1184 final EuclideanTransformation2DRobustEstimatorListener listener, final List<Point2D> inputPoints,
1185 final List<Point2D> outputPoints) {
1186 return create(listener, inputPoints, outputPoints, DEFAULT_ROBUST_METHOD);
1187 }
1188
1189 /**
1190 * Creates an Euclidean 2D transformation estimator based on 2D 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 2D transformation estimator.
1196 */
1197 public static EuclideanTransformation2DRobustEstimator create(final double[] qualityScores) {
1198 return create(qualityScores, DEFAULT_ROBUST_METHOD);
1199 }
1200
1201 /**
1202 * Creates an Euclidean 2D transformation estimator based on 2D 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 2D transformation.
1207 * @param outputPoints list of output points ot be used to estimate an
1208 * Euclidean 2D transformation.
1209 * @param qualityScores quality scores corresponding to each pair of points.
1210 * @return an instance of Euclidean 2D 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 EuclideanTransformation2DRobustEstimator create(
1215 final List<Point2D> inputPoints, final List<Point2D> outputPoints, final double[] qualityScores) {
1216 return create(inputPoints, outputPoints, qualityScores, DEFAULT_ROBUST_METHOD);
1217 }
1218
1219 /**
1220 * Creates an Euclidean 2D transformation estimator based on 2D 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 2D transformation estimator.
1228 */
1229 public static EuclideanTransformation2DRobustEstimator create(
1230 final EuclideanTransformation2DRobustEstimatorListener listener, final double[] qualityScores) {
1231 return create(listener, qualityScores, DEFAULT_ROBUST_METHOD);
1232 }
1233
1234 /**
1235 * Creates an Euclidean 2D transformation estimator based on 2D 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 2D transformation.
1242 * @param outputPoints list of output points ot be used to estimate an
1243 * Euclidean 2D transformation.
1244 * @param qualityScores quality scores corresponding to each pair of matched
1245 * points.
1246 * @return an instance of Euclidean 2D 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 EuclideanTransformation2DRobustEstimator create(
1251 final EuclideanTransformation2DRobustEstimatorListener listener, final List<Point2D> inputPoints,
1252 final List<Point2D> outputPoints, final double[] qualityScores) {
1253 return create(listener, inputPoints, outputPoints, qualityScores, DEFAULT_ROBUST_METHOD);
1254 }
1255
1256 /**
1257 * Creates an Euclidean 2D transformation estimator based on 2D point
1258 * correspondences and using default robust estimator method.
1259 *
1260 * @param weakMinimumSizeAllowed true allows 2 points, false requires 3.
1261 * @return an instance of Euclidean 2D transformation estimator.
1262 */
1263 public static EuclideanTransformation2DRobustEstimator create(final boolean weakMinimumSizeAllowed) {
1264 return create(weakMinimumSizeAllowed, DEFAULT_ROBUST_METHOD);
1265 }
1266
1267 /**
1268 * Creates an Euclidean 2D transformation estimator based on 2D 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 2D transformation.
1273 * @param outputPoints list of output points to be used to estimate an
1274 * Euclidean 2D transformation.
1275 * @param weakMinimumSizeAllowed true allows 2 points, false requires 3.
1276 * @return an instance of Euclidean 2D 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 EuclideanTransformation2DRobustEstimator create(
1281 final List<Point2D> inputPoints, final List<Point2D> outputPoints, final boolean weakMinimumSizeAllowed) {
1282 return create(inputPoints, outputPoints, weakMinimumSizeAllowed, DEFAULT_ROBUST_METHOD);
1283 }
1284
1285 /**
1286 * Creates an Euclidean 2D transformation estimator based on 2D 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 2 points, false requires 3.
1292 * @return an instance of Euclidean 2D transformation estimator.
1293 */
1294 public static EuclideanTransformation2DRobustEstimator create(
1295 final EuclideanTransformation2DRobustEstimatorListener listener, final boolean weakMinimumSizeAllowed) {
1296 return create(listener, weakMinimumSizeAllowed, DEFAULT_ROBUST_METHOD);
1297 }
1298
1299 /**
1300 * Creates an Euclidean 2D transformation estimator based on 2D 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 2D transformation.
1307 * @param outputPoints list of output points to be used to estimate an
1308 * Euclidean 2D transformation.
1309 * @param weakMinimumSizeAllowed true allows 2 points, false requires 3.
1310 * @return an instance of Euclidean 2D 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 EuclideanTransformation2DRobustEstimator create(
1315 final EuclideanTransformation2DRobustEstimatorListener listener, final List<Point2D> inputPoints,
1316 final List<Point2D> outputPoints, final boolean weakMinimumSizeAllowed) {
1317 return create(listener, inputPoints, outputPoints, weakMinimumSizeAllowed, DEFAULT_ROBUST_METHOD);
1318 }
1319
1320 /**
1321 * Creates an Euclidean 2D transformation estimator based on 2D 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 2 points, false requires 3.
1327 * @return an instance of Euclidean 2D transformation estimator.
1328 */
1329 public static EuclideanTransformation2DRobustEstimator create(
1330 final double[] qualityScores, final boolean weakMinimumSizeAllowed) {
1331 return create(qualityScores, weakMinimumSizeAllowed, DEFAULT_ROBUST_METHOD);
1332 }
1333
1334 /**
1335 * Creates an Euclidean 2D transformation estimator based on 2D 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 2D transformation.
1340 * @param outputPoints list of output points ot be used to estimate an
1341 * Euclidean 2D transformation.
1342 * @param qualityScores quality scores corresponding to each pair of points.
1343 * @param weakMinimumSizeAllowed true allows 2 points, false requires 3.
1344 * @return an instance of Euclidean 2D 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 EuclideanTransformation2DRobustEstimator create(
1349 final List<Point2D> inputPoints, final List<Point2D> outputPoints, final double[] qualityScores,
1350 final boolean weakMinimumSizeAllowed) {
1351 return create(inputPoints, outputPoints, qualityScores, weakMinimumSizeAllowed, DEFAULT_ROBUST_METHOD);
1352 }
1353
1354 /**
1355 * Creates an Euclidean 2D transformation estimator based on 2D 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 2 points, false requires 3.
1363 * @return an instance of Euclidean 2D transformation estimator.
1364 */
1365 public static EuclideanTransformation2DRobustEstimator create(
1366 final EuclideanTransformation2DRobustEstimatorListener listener, final double[] qualityScores,
1367 final boolean weakMinimumSizeAllowed) {
1368 return create(listener, qualityScores, weakMinimumSizeAllowed, DEFAULT_ROBUST_METHOD);
1369 }
1370
1371 /**
1372 * Creates an Euclidean 2D transformation estimator based on 2D 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 2D transformation.
1379 * @param outputPoints list of output points ot be used to estimate an
1380 * Euclidean 2D transformation.
1381 * @param qualityScores quality scores corresponding to each pair of matched
1382 * points.
1383 * @param weakMinimumSizeAllowed true allows 2 points, false requires 3.
1384 * @return an instance of Euclidean 2D 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 EuclideanTransformation2DRobustEstimator create(
1389 final EuclideanTransformation2DRobustEstimatorListener listener, final List<Point2D> inputPoints,
1390 final List<Point2D> outputPoints, final double[] qualityScores, final boolean weakMinimumSizeAllowed) {
1391 return create(listener, inputPoints, outputPoints, qualityScores, weakMinimumSizeAllowed,
1392 DEFAULT_ROBUST_METHOD);
1393 }
1394
1395
1396 /**
1397 * Internal method to set lists of points to be used to estimate an
1398 * Euclidean 2D transformation.
1399 * This method does not check whether estimator is locked or not.
1400 *
1401 * @param inputPoints list of input points to be used to estimate an
1402 * Euclidean 2D transformation.
1403 * @param outputPoints list of output points to be used to estimate an
1404 * Euclidean 2D transformation.
1405 * @throws IllegalArgumentException if provided lists of points don't have
1406 * the same size or their size is smaller than MINIMUM_SIZE.
1407 */
1408 private void internalSetPoints(final List<Point2D> inputPoints, final List<Point2D> outputPoints) {
1409 if (inputPoints.size() < getMinimumPoints()) {
1410 throw new IllegalArgumentException();
1411 }
1412 if (inputPoints.size() != outputPoints.size()) {
1413 throw new IllegalArgumentException();
1414 }
1415 this.inputPoints = inputPoints;
1416 this.outputPoints = outputPoints;
1417 }
1418
1419 /**
1420 * Attempts to refine provided solution if refinement is requested.
1421 * This method returns a refined solution of the same provided solution
1422 * if refinement is not requested or has failed.
1423 * If refinement is enabled, and it is requested to keep covariance, this
1424 * method will also keep covariance of refined transformation.
1425 *
1426 * @param transformation transformation estimated by a robust estimator
1427 * without refinement.
1428 * @return solution after refinement (if requested) or the provided
1429 * non-refined solution if not requested or refinement failed.
1430 */
1431 protected EuclideanTransformation2D attemptRefine(final EuclideanTransformation2D transformation) {
1432 if (refineResult) {
1433 final var refiner = new EuclideanTransformation2DRefiner(transformation, keepCovariance, getInliersData(),
1434 inputPoints, outputPoints, getRefinementStandardDeviation());
1435
1436 try {
1437 final var result = new EuclideanTransformation2D();
1438 final var improved = refiner.refine(result);
1439
1440 if (keepCovariance) {
1441 // keep covariance
1442 covariance = refiner.getCovariance();
1443 }
1444
1445 return improved ? result : transformation;
1446 } catch (final Exception e) {
1447 // refinement failed, so we return input value
1448 return transformation;
1449 }
1450 } else {
1451 return transformation;
1452 }
1453 }
1454
1455 /**
1456 * Gets standard deviation used for Levenberg-Marquardt fitting during
1457 * refinement.
1458 * Returned value gives an indication of how much variance each residual
1459 * has.
1460 * Typically, this value is related to the threshold used on each robust
1461 * estimation, since residuals of found inliers are within the range of
1462 * such threshold.
1463 *
1464 * @return standard deviation used for refinement.
1465 */
1466 protected abstract double getRefinementStandardDeviation();
1467 }