View Javadoc
1   /*
2    * Copyright (C) 2015 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.AffineTransformation3D;
20  import com.irurueta.geometry.Plane;
21  import com.irurueta.geometry.Point3D;
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 for algorithms to robustly find the best affine
30   * 3D transformation for collections of matching 3D points, or 3D planes.
31   * Implementations of this class should be able to detect and discard outliers
32   * in order to find the best solution.
33   */
34  public abstract class AffineTransformation3DRobustEstimator {
35  
36      /**
37       * Minimum number of matched points or matched planes required to estimate
38       * an affine 3D transformation.
39       */
40      public static final int MINIMUM_SIZE = 4;
41  
42      /**
43       * Default amount of progress variation before notifying a change in
44       * estimation progress. By default, this is set to 5%.
45       */
46      public static final float DEFAULT_PROGRESS_DELTA = 0.05f;
47  
48      /**
49       * Minimum allowed value for progress delta.
50       */
51      public static final float MIN_PROGRESS_DELTA = 0.0f;
52  
53      /**
54       * Maximum allowed value for progress delta.
55       */
56      public static final float MAX_PROGRESS_DELTA = 1.0f;
57  
58      /**
59       * Constant defining default confidence of the estimated result, which is
60       * 99%. This means that with a probability of 99% estimation will be
61       * accurate because chosen sub-samples will be inliers.
62       */
63      public static final double DEFAULT_CONFIDENCE = 0.99;
64  
65      /**
66       * Default maximum allowed number of iterations.
67       */
68      public static final int DEFAULT_MAX_ITERATIONS = 5000;
69  
70      /**
71       * Minimum allowed confidence value.
72       */
73      public static final double MIN_CONFIDENCE = 0.0;
74  
75      /**
76       * Maximum allowed confidence value.
77       */
78      public static final double MAX_CONFIDENCE = 1.0;
79  
80      /**
81       * Minimum allowed number of iterations.
82       */
83      public static final int MIN_ITERATIONS = 1;
84  
85      /**
86       * Indicates that result is refined by default using Levenberg-Marquardt
87       * fitting algorithm over found inliers.
88       */
89      public static final boolean DEFAULT_REFINE_RESULT = true;
90  
91      /**
92       * Indicates that covariance is not kept by default after refining result.
93       */
94      public static final boolean DEFAULT_KEEP_COVARIANCE = false;
95  
96      /**
97       * Listener to be notified of events such as when estimation starts, ends
98       * or its progress significantly changes.
99       */
100     protected AffineTransformation3DRobustEstimatorListener listener;
101 
102     /**
103      * Indicates if this estimator is locked because an estimation is being
104      * computed.
105      */
106     protected volatile boolean locked;
107 
108     /**
109      * Amount of progress variation before notifying a progress change during
110      * estimation.
111      */
112     protected float progressDelta;
113 
114     /**
115      * Amount of confidence expressed as a value between 0.0 and 1.0 (which is
116      * equivalent to 100%). The amount of confidence indicates the probability
117      * that the estimated result is correct. Usually this value will be close
118      * to 1.0, but not exactly 1.0.
119      */
120     protected double confidence;
121 
122     /**
123      * Maximum allowed number of iterations. When the maximum number of
124      * iterations is exceeded, result will not be available, however an
125      * approximate result will be available for retrieval.
126      */
127     protected int maxIterations;
128 
129     /**
130      * Data related to inliers found after estimation.
131      */
132     protected InliersData inliersData;
133 
134     /**
135      * Indicates whether result must be refined using Levenberg-Marquardt
136      * fitting algorithm over found inliers.
137      * If true, inliers will be computed and kept in any implementation
138      * regardless of the settings.
139      */
140     protected boolean refineResult;
141 
142     /**
143      * Indicates whether covariance must be kept after refining result.
144      * This setting is only taken into account if result is refined.
145      */
146     protected boolean keepCovariance;
147 
148     /**
149      * Estimated covariance of estimated 2D affine transformation.
150      * This is only available when result has been refined and covariance is
151      * kept.
152      */
153     protected Matrix covariance;
154 
155     /**
156      * Constructor.
157      */
158     protected AffineTransformation3DRobustEstimator() {
159         progressDelta = DEFAULT_PROGRESS_DELTA;
160         confidence = DEFAULT_CONFIDENCE;
161         maxIterations = DEFAULT_MAX_ITERATIONS;
162         refineResult = DEFAULT_REFINE_RESULT;
163         keepCovariance = DEFAULT_KEEP_COVARIANCE;
164     }
165 
166     /**
167      * Constructor.
168      *
169      * @param listener listener to be notified of events such as when estimation
170      *                 stars, ends or its progress significantly changes.
171      */
172     protected AffineTransformation3DRobustEstimator(final AffineTransformation3DRobustEstimatorListener listener) {
173         this.listener = listener;
174         progressDelta = DEFAULT_PROGRESS_DELTA;
175         confidence = DEFAULT_CONFIDENCE;
176         maxIterations = DEFAULT_MAX_ITERATIONS;
177         refineResult = DEFAULT_REFINE_RESULT;
178         keepCovariance = DEFAULT_KEEP_COVARIANCE;
179     }
180 
181     /**
182      * Returns reference to listener to be notified of events such as when
183      * estimation starts, ends or its progress significantly changes
184      *
185      * @return listener to be notified of events.
186      */
187     public AffineTransformation3DRobustEstimatorListener getListener() {
188         return listener;
189     }
190 
191     /**
192      * Sets listener to be notified of events such as when estimation starts,
193      * ends or its progress significantly changes.
194      *
195      * @param listener listener to be notified of events.
196      * @throws LockedException if robust estimator is locked.
197      */
198     public void setListener(
199             final AffineTransformation3DRobustEstimatorListener listener) throws LockedException {
200         if (isLocked()) {
201             throw new LockedException();
202         }
203         this.listener = listener;
204     }
205 
206     /**
207      * Indicates whether listener has been provided and is available for
208      * retrieval.
209      *
210      * @return true if available, false otherwise.
211      */
212     public boolean isListenerAvailable() {
213         return listener != null;
214     }
215 
216     /**
217      * Indicates if this instance is locked because estimation is being
218      * computed.
219      *
220      * @return true if locked, false otherwise.
221      */
222     public boolean isLocked() {
223         return locked;
224     }
225 
226     /**
227      * Returns amount of progress variation before notifying a progress change
228      * during estimation.
229      *
230      * @return amount of progress variation before notifying a progress change
231      * during estimation.
232      */
233     public float getProgressDelta() {
234         return progressDelta;
235     }
236 
237     /**
238      * Sets amount of progress variation before notifying a progress change
239      * during estimation.
240      *
241      * @param progressDelta amount of progress variation before notifying a
242      *                      progress change during estimation.
243      * @throws IllegalArgumentException if progress delta is less than zero or
244      *                                  greater than 1.
245      * @throws LockedException          if this estimator is locked because an estimation
246      *                                  is being computed.
247      */
248     public void setProgressDelta(final float progressDelta) throws LockedException {
249         if (isLocked()) {
250             throw new LockedException();
251         }
252         if (progressDelta < MIN_PROGRESS_DELTA || progressDelta > MAX_PROGRESS_DELTA) {
253             throw new IllegalArgumentException();
254         }
255         this.progressDelta = progressDelta;
256     }
257 
258     /**
259      * Returns amount of confidence expressed as a value between 0.0 and 1.0
260      * (which is equivalent to 100%). The amount of confidence indicates the
261      * probability that the estimated result is correct. Usually this value will
262      * be close to 1.0, but not exactly 1.0.
263      *
264      * @return amount of confidence as a value between 0.0 and 1.0.
265      */
266     public double getConfidence() {
267         return confidence;
268     }
269 
270     /**
271      * Sets amount of confidence expressed as a value between 0.0 and 1.0 (which
272      * is equivalent to 100%). The amount of confidence indicates the
273      * probability that the estimated result is correct. Usually this value will
274      * be close to 1.0, but not exactly 1.0.
275      *
276      * @param confidence confidence to be set as a value between 0.0 and 1.0
277      * @throws IllegalArgumentException if provided value is not between 0.0 and
278      *                                  1.0.
279      * @throws LockedException          if this estimator is locked because an estimator
280      *                                  is being computed.
281      */
282     public void setConfidence(final double confidence) throws LockedException {
283         if (isLocked()) {
284             throw new LockedException();
285         }
286         if (confidence < MIN_CONFIDENCE || confidence > MAX_CONFIDENCE) {
287             throw new IllegalArgumentException();
288         }
289         this.confidence = confidence;
290     }
291 
292     /**
293      * Returns maximum allowed number of iterations. If maximum allowed number
294      * of iterations is achieved without converging to a result when calling
295      * estimate(), a RobustEstimatorException will be raised.
296      *
297      * @return maximum allowed number of iterations.
298      */
299     public int getMaxIterations() {
300         return maxIterations;
301     }
302 
303     /**
304      * Sets maximum allowed number of iterations. When the maximum number of
305      * iterations is exceeded, result will not be available, however an
306      * approximate result will be available for retrieval.
307      *
308      * @param maxIterations maximum allowed number of iterations to be set.
309      * @throws IllegalArgumentException if provided value is less than 1.
310      * @throws LockedException          if this estimator is locked because an estimation
311      *                                  is being computed.
312      */
313     public void setMaxIterations(final int maxIterations) throws LockedException {
314         if (isLocked()) {
315             throw new LockedException();
316         }
317         if (maxIterations < MIN_ITERATIONS) {
318             throw new IllegalArgumentException();
319         }
320         this.maxIterations = maxIterations;
321     }
322 
323     /**
324      * Gets data related to inliers found after estimation.
325      *
326      * @return data related to inliers found after estimation.
327      */
328     public InliersData getInliersData() {
329         return inliersData;
330     }
331 
332     /**
333      * Indicates whether result must be refined using Levenberg-Marquardt
334      * fitting algorithm over found inliers.
335      * If ture, inliers will be computed and kept in any implementation
336      * regardless of the settings.
337      *
338      * @return true to refine result, false to simply use result found by
339      * robust estimator without further refining.
340      */
341     public boolean isResultRefined() {
342         return refineResult;
343     }
344 
345     /**
346      * Specifies whether result must be refined using Levenberg-Marquardt
347      * fitting algorithm over found inliers.
348      *
349      * @param refineResult true to refine result, false to simply use result
350      *                     found by robust estimator without further refining.
351      * @throws LockedException if estimator is locked.
352      */
353     public void setResultRefined(final boolean refineResult) throws LockedException {
354         if (isLocked()) {
355             throw new LockedException();
356         }
357         this.refineResult = refineResult;
358     }
359 
360     /**
361      * Indicates whether covariance must be kept after refining result.
362      * This setting is only taken into account if result is refined.
363      *
364      * @return true if covariance must be kept after refining result, false
365      * otherwise.
366      */
367     public boolean isCovarianceKept() {
368         return keepCovariance;
369     }
370 
371     /**
372      * Specifies whether covariance must be kept after refining result.
373      * This setting is only taken into account if result is refined.
374      *
375      * @param keepCovariance true if covariance must be kept after refining
376      *                       result, false otherwise.
377      * @throws LockedException if estimator is locked.
378      */
379     public void setCovarianceKept(final boolean keepCovariance) throws LockedException {
380         if (isLocked()) {
381             throw new LockedException();
382         }
383         this.keepCovariance = keepCovariance;
384     }
385 
386     /**
387      * Gets estimated covariance of estimated 3D point if available.
388      * This is only available when result has been refined and covariance is
389      * kept.
390      *
391      * @return estimated covariance or null.
392      */
393     public Matrix getCovariance() {
394         return covariance;
395     }
396 
397     /**
398      * Estimates an affine 3D transformation using a robust estimator and
399      * the best set of matched 3D point correspondences found using the robust
400      * estimator.
401      *
402      * @return an affine 3D transformation.
403      * @throws LockedException          if robust estimator is locked because an
404      *                                  estimation is already in progress.
405      * @throws NotReadyException        if provided input data is not enough to start
406      *                                  the estimation.
407      * @throws RobustEstimatorException if estimation fails for any reason
408      *                                  (i.e. numerical instability, no solution available, etc).
409      */
410     public abstract AffineTransformation3D estimate() throws LockedException, NotReadyException,
411             RobustEstimatorException;
412 
413     /**
414      * Returns method being used for robust estimation.
415      *
416      * @return method being used for robust estimation.
417      */
418     public abstract RobustEstimatorMethod getMethod();
419 
420     /**
421      * Creates an affine 3D transformation estimator based on 3D point
422      * correspondences and using provided robust estimator method.
423      *
424      * @param inputPoints  list of input points to be used to estimate an
425      *                     affine 3D transformation.
426      * @param outputPoints list of output points to be used to estimate an
427      *                     affine 3D transformation.
428      * @param method       method of a robust estimator algorithm to estimate
429      *                     the best affine 3D transformation.
430      * @return an instance of affine 3D transformation estimator.
431      * @throws IllegalArgumentException if provided lists of points don't have
432      *                                  the same size or their size is smaller than MINIMUM_SIZE.
433      */
434     public static AffineTransformation3DRobustEstimator createFromPoints(
435             final List<Point3D> inputPoints, final List<Point3D> outputPoints, final RobustEstimatorMethod method) {
436         return PointCorrespondenceAffineTransformation3DRobustEstimator.create(inputPoints, outputPoints, method);
437     }
438 
439     /**
440      * Creates an affine 3D transformation estimator based on 3D point
441      * correspondences and using provided robust estimator method.
442      *
443      * @param listener     listener to be notified of events such as when estimation
444      *                     starts, ends or its progress significantly changes.
445      * @param inputPoints  list of input points to be used to estimate an
446      *                     affine 3D transformation.
447      * @param outputPoints list of output points to be used to estimate an
448      *                     affine 3D transformation.
449      * @param method       method of a robust estimator algorithm to estimate
450      *                     the best affine 3D transformation.
451      * @return an instance of affine 3D transformation estimator.
452      * @throws IllegalArgumentException if provided lists of points don't have
453      *                                  the same size or their size is smaller than MINIMUM_SIZE.
454      */
455     public static AffineTransformation3DRobustEstimator createFromPoints(
456             final AffineTransformation3DRobustEstimatorListener listener, final List<Point3D> inputPoints,
457             final List<Point3D> outputPoints, final RobustEstimatorMethod method) {
458         return PointCorrespondenceAffineTransformation3DRobustEstimator.create(listener, inputPoints, outputPoints,
459                 method);
460     }
461 
462     /**
463      * Creates an affine 3D transformation estimator based on 2D point
464      * correspondences and using provided robust estimator method.
465      *
466      * @param inputPoints   list of input points to be used to estimate an
467      *                      affine 3D transformation.
468      * @param outputPoints  list of output points to be used to estimate an
469      *                      affine 3D transformation.
470      * @param qualityScores quality scores corresponding to each pair of matched
471      *                      points.
472      * @param method        method of a robust estimator algorithm to estimate
473      *                      the best affine 3D transformation.
474      * @return an instance of affine 3D transformation estimator.
475      * @throws IllegalArgumentException if provided lists of points don't have
476      *                                  the same size or their size is smaller than MINIMUM_SIZE.
477      */
478     public static AffineTransformation3DRobustEstimator createFromPoints(
479             final List<Point3D> inputPoints, final List<Point3D> outputPoints, final double[] qualityScores,
480             final RobustEstimatorMethod method) {
481         return PointCorrespondenceAffineTransformation3DRobustEstimator.create(inputPoints, outputPoints, qualityScores,
482                 method);
483     }
484 
485     /**
486      * Creates an affine 3D transformation estimator based on 3D point
487      * correspondences and using provided robust estimator method.
488      *
489      * @param listener      listener to be notified of events such as when estimation
490      *                      starts, ends or its progress significantly changes.
491      * @param inputPoints   list of input points to be used to estimate an
492      *                      affine 3D transformation.
493      * @param outputPoints  list of output points to be used to estimate an
494      *                      affine 3D transformation.
495      * @param qualityScores quality scores corresponding to each pair of matched
496      *                      points.
497      * @param method        method of a robust estimator algorithm to estimate
498      *                      the best affine 3D transformation.
499      * @return an instance of affine 3D transformation estimator.
500      * @throws IllegalArgumentException if provided lists of points don't have
501      *                                  the same size or their size is smaller than MINIMUM_SIZE.
502      */
503     public static AffineTransformation3DRobustEstimator createFromPoints(
504             final AffineTransformation3DRobustEstimatorListener listener, final List<Point3D> inputPoints,
505             final List<Point3D> outputPoints, final double[] qualityScores, final RobustEstimatorMethod method) {
506         return PointCorrespondenceAffineTransformation3DRobustEstimator.create(listener, inputPoints, outputPoints,
507                 qualityScores, method);
508     }
509 
510     /**
511      * Creates an affine 3D transformation estimator based on 3D point
512      * correspondences and using default robust estimator method.
513      *
514      * @param inputPoints  list of input points to be used to estimate an
515      *                     affine 3D transformation.
516      * @param outputPoints list of output points to be used to estimate an
517      *                     affine 3D transformation.
518      * @return an instance of affine 3D transformation estimator.
519      * @throws IllegalArgumentException if provided lists of points don't have
520      *                                  the same size or their size is smaller than MINIMUM_SIZE.
521      */
522     public static AffineTransformation3DRobustEstimator createFromPoints(
523             final List<Point3D> inputPoints, final List<Point3D> outputPoints) {
524         return PointCorrespondenceAffineTransformation3DRobustEstimator.create(inputPoints, outputPoints);
525     }
526 
527     /**
528      * Creates an affine 3D transformation estimator based on 3D point
529      * correspondences and using default robust estimator method.
530      *
531      * @param listener     listener to be notified of events such as when estimation
532      *                     starts, ends or its progress significantly changes.
533      * @param inputPoints  list of input points to be used to estimate an
534      *                     affine 3D transformation.
535      * @param outputPoints list of output points to be used to estimate an
536      *                     affine 3D transformation.
537      * @return an instance of affine 3D transformation estimator.
538      * @throws IllegalArgumentException if provided lists of points don't have
539      *                                  the same size or their size is smaller than MINIMUM_SIZE.
540      */
541     public static AffineTransformation3DRobustEstimator createFromPoints(
542             final AffineTransformation3DRobustEstimatorListener listener, final List<Point3D> inputPoints,
543             final List<Point3D> outputPoints) {
544         return PointCorrespondenceAffineTransformation3DRobustEstimator.create(listener, inputPoints, outputPoints);
545     }
546 
547     /**
548      * Creates an affine 3D transformation estimator based on 3D point
549      * correspondences and using default robust estimator method.
550      *
551      * @param inputPoints   list of input points to be used to estimate an
552      *                      affine 3D transformation.
553      * @param outputPoints  list of output points to be used to estimate an
554      *                      affine 3D transformation.
555      * @param qualityScores quality scores corresponding to each pair of matched
556      *                      points.
557      * @return an instance of affine 3D transformation estimator.
558      * @throws IllegalArgumentException if provided lists of points don't have
559      *                                  the same size or their size is smaller than MINIMUM_SIZE.
560      */
561     public static AffineTransformation3DRobustEstimator createFromPoints(
562             final List<Point3D> inputPoints, final List<Point3D> outputPoints, final double[] qualityScores) {
563         return PointCorrespondenceAffineTransformation3DRobustEstimator.create(inputPoints, outputPoints,
564                 qualityScores);
565     }
566 
567     /**
568      * Creates an affine 3D transformation estimator based on 3D point
569      * correspondences and using default robust estimator method.
570      *
571      * @param listener      listener to be notified of events such as when estimation
572      *                      starts, ends or its progress significantly changes.
573      * @param inputPoints   list of input points to be used to estimate an
574      *                      affine 3D transformation.
575      * @param outputPoints  list of output points to be used to estimate an
576      *                      affine 3D transformation.
577      * @param qualityScores quality scores corresponding to each pair of matched
578      *                      points.
579      * @return an instance of affine 3D transformation estimator.
580      * @throws IllegalArgumentException if provided lists of points don't have
581      *                                  the same size or their size is smaller than MINIMUM_SIZE.
582      */
583     public static AffineTransformation3DRobustEstimator createFromPoints(
584             final AffineTransformation3DRobustEstimatorListener listener, final List<Point3D> inputPoints,
585             final List<Point3D> outputPoints, final double[] qualityScores) {
586         return PointCorrespondenceAffineTransformation3DRobustEstimator.create(listener, inputPoints, outputPoints,
587                 qualityScores);
588     }
589 
590     /**
591      * Creates an affine 3D transformation estimator based on plane
592      * correspondences and using provided robust estimator method.
593      *
594      * @param inputPlanes  list of input planes to be used to estimate an
595      *                     affine 3D transformation.
596      * @param outputPlanes list of output planes to be used to estimate an
597      *                     affine 3D transformation.
598      * @param method       method of a robust estimator algorithm to estimate
599      *                     the best affine 3D transformation.
600      * @return an instance of affine 3D transformation estimator.
601      * @throws IllegalArgumentException if provided lists of planes don't have
602      *                                  the same size or their size is smaller than MINIMUM_SIZE.
603      */
604     public static AffineTransformation3DRobustEstimator createFromPlanes(
605             final List<Plane> inputPlanes, final List<Plane> outputPlanes, final RobustEstimatorMethod method) {
606         return PlaneCorrespondenceAffineTransformation3DRobustEstimator.create(inputPlanes, outputPlanes, method);
607     }
608 
609     /**
610      * Creates an affine 3D transformation estimator based on plane
611      * correspondences and using provided robust estimator method.
612      *
613      * @param listener     listener to be notified of events such as when estimation
614      *                     starts, ends or its progress significantly changes.
615      * @param inputPlanes  list of input planes to be used to estimate an affine
616      *                     3D transformation.
617      * @param outputPlanes list of output planes to be used to estimate an
618      *                     affine 3D transformation.
619      * @param method       method of a robust estimator algorithm to estimate the best
620      *                     affine 3D transformation.
621      * @return an instance of affine 3D transformation estimator.
622      * @throws IllegalArgumentException if provided lists of planes don't have
623      *                                  the same size or their size is smaller than MINIMUM_SIZE.
624      */
625     public static AffineTransformation3DRobustEstimator createFromPlanes(
626             final AffineTransformation3DRobustEstimatorListener listener, final List<Plane> inputPlanes,
627             final List<Plane> outputPlanes, final RobustEstimatorMethod method) {
628         return PlaneCorrespondenceAffineTransformation3DRobustEstimator.create(listener, inputPlanes, outputPlanes,
629                 method);
630     }
631 
632     /**
633      * Creates an affine 3D transformation estimator based on plane
634      * correspondences and using provided robust estimator method.
635      *
636      * @param inputPlanes   list of input planes to be used to estimate an
637      *                      affine 3D transformation.
638      * @param outputPlanes  list of output planes to be used to estimate an
639      *                      affine 3D transformation.
640      * @param qualityScores quality scores corresponding to each pair of matched
641      *                      lines.
642      * @param method        method of a robust estimator algorithm to estimate the best
643      *                      affine 3D transformation.
644      * @return an instance of affine 3D transformation estimator.
645      * @throws IllegalArgumentException if provided lists of planes don't have
646      *                                  the same size or their size is smaller than MINIMUM_SIZE.
647      */
648     public static AffineTransformation3DRobustEstimator createFromPlanes(
649             final List<Plane> inputPlanes, final List<Plane> outputPlanes, final double[] qualityScores,
650             final RobustEstimatorMethod method) {
651         return PlaneCorrespondenceAffineTransformation3DRobustEstimator.create(inputPlanes, outputPlanes, qualityScores,
652                 method);
653     }
654 
655     /**
656      * Creates an affine 3D transformation estimator based on plane
657      * correspondences and using provided robust estimator method.
658      *
659      * @param listener      listener to be notified of events such as when estimation
660      *                      starts, ends or its progress significantly changes.
661      * @param inputPlanes   list of input planes to be used to estimate an affine
662      *                      3D transformation.
663      * @param outputPlanes  list of output planes to be used to estimate an
664      *                      affine 3D transformation.
665      * @param qualityScores quality scores corresponding to each pair of matched
666      *                      lines.
667      * @param method        method of a robust estimator algorithm to estimate the best
668      *                      affine 3D transformation.
669      * @return an instance of affine 3D transformation estimator.
670      * @throws IllegalArgumentException if provided lists of planes don't have
671      *                                  the same size or their size is smaller than MINIMUM_SIZE.
672      */
673     public static AffineTransformation3DRobustEstimator createFromPlanes(
674             final AffineTransformation3DRobustEstimatorListener listener, final List<Plane> inputPlanes,
675             final List<Plane> outputPlanes, final double[] qualityScores, final RobustEstimatorMethod method) {
676         return PlaneCorrespondenceAffineTransformation3DRobustEstimator.create(listener, inputPlanes, outputPlanes,
677                 qualityScores, method);
678     }
679 
680     /**
681      * Creates an affine 3D transformation estimator based on plane
682      * correspondences and using default robust estimator method.
683      *
684      * @param inputPlanes  list of input planes to be used to estimate an
685      *                     affine 3D transformation.
686      * @param outputPlanes list of output planes to be used to estimate an
687      *                     affine 3D transformation.
688      * @return an instance of affine 3D transformation estimator.
689      * @throws IllegalArgumentException if provided lists of planes don't have
690      *                                  the same size or their size is smaller than MINIMUM_SIZE.
691      */
692     public static AffineTransformation3DRobustEstimator createFromPlanes(
693             final List<Plane> inputPlanes, final List<Plane> outputPlanes) {
694         return PlaneCorrespondenceAffineTransformation3DRobustEstimator.create(inputPlanes, outputPlanes);
695     }
696 
697     /**
698      * Creates an affine 3D transformation estimator based on plane
699      * correspondences and using default robust estimator method.
700      *
701      * @param listener     listener to be notified of events such as when estimation
702      *                     starts, ends or its progress significantly changes.
703      * @param inputPlanes  list of input planes to be used to estimate an affine
704      *                     3D transformation.
705      * @param outputPlanes list of output planes to be used to estimate an
706      *                     affine 3D transformation.
707      * @return an instance of affine 3D transformation estimator.
708      * @throws IllegalArgumentException if provided lists of planes don't have
709      *                                  the same size or their size is smaller than MINIMUM_SIZE.
710      */
711     public static AffineTransformation3DRobustEstimator createFromPlanes(
712             final AffineTransformation3DRobustEstimatorListener listener, final List<Plane> inputPlanes,
713             final List<Plane> outputPlanes) {
714         return PlaneCorrespondenceAffineTransformation3DRobustEstimator.create(listener, inputPlanes, outputPlanes);
715     }
716 
717     /**
718      * Creates an affine 3D transformation estimator based on plane
719      * correspondences and using default robust estimator method.
720      *
721      * @param inputPlanes   list of input planes to be used to estimate an affine
722      *                      3D transformation.
723      * @param outputPlanes  list of output planes to be used to estimate an
724      *                      affine 3D transformation.
725      * @param qualityScores quality scores corresponding to each pair of matched
726      *                      points.
727      * @return an instance of affine 3D transformation estimator.
728      * @throws IllegalArgumentException if provided lists of planes don't have
729      *                                  the same size or their size is smaller than MINIMUM_SIZE.
730      */
731     public static AffineTransformation3DRobustEstimator createFromPlanes(
732             final List<Plane> inputPlanes, final List<Plane> outputPlanes, final double[] qualityScores) {
733         return PlaneCorrespondenceAffineTransformation3DRobustEstimator.create(inputPlanes, outputPlanes,
734                 qualityScores);
735     }
736 
737     /**
738      * Creates an affine 3D transformation estimator based on 3D line
739      * correspondences and using default robust estimator method.
740      *
741      * @param listener      listener to be notified of events such as when estimation
742      *                      starts, ends or its progress significantly changes.
743      * @param inputPlanes   list of input planes to be used to estimate an affine
744      *                      3D transformation.
745      * @param outputPlanes  list of output planes to be used to estimate an
746      *                      affine 3D transformation.
747      * @param qualityScores quality scores corresponding to each pair of matched
748      *                      lines.
749      * @return an instance of affine 3D transformation estimator.
750      * @throws IllegalArgumentException if provided lists of lines don't have
751      *                                  the same size or their size is smaller than MINIMUM_SIZE.
752      */
753     public static AffineTransformation3DRobustEstimator createFromPlanes(
754             final AffineTransformation3DRobustEstimatorListener listener, final List<Plane> inputPlanes,
755             final List<Plane> outputPlanes, final double[] qualityScores) {
756         return PlaneCorrespondenceAffineTransformation3DRobustEstimator.create(listener, inputPlanes, outputPlanes,
757                 qualityScores);
758     }
759 
760     /**
761      * Gets standard deviation used for Levenberg-Marquardt fitting during
762      * refinement.
763      * Returned value gives an indication of how much variance each residual
764      * has.
765      * Typically, this value is related to the threshold used on each robust
766      * estimation, since residuals of found inliers are within the range of
767      * such threshold.
768      *
769      * @return standard deviation used for refinement.
770      */
771     protected abstract double getRefinementStandardDeviation();
772 }