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.AffineTransformation2D;
20  import com.irurueta.geometry.Line2D;
21  import com.irurueta.geometry.Point2D;
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   * 2D transformation for collections of matching 2D points, or 2D lines.
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 AffineTransformation2DRobustEstimator {
35  
36      /**
37       * Minimum number of matched points or matched lines required to estimate an
38       * affine 2D transformation.
39       */
40      public static final int MINIMUM_SIZE = 3;
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 AffineTransformation2DRobustEstimatorListener mListener;
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 AffineTransformation2DRobustEstimator() {
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      *                 starts, ends or its progress significantly changes.
171      */
172     protected AffineTransformation2DRobustEstimator(final AffineTransformation2DRobustEstimatorListener listener) {
173         mListener = 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 AffineTransformation2DRobustEstimatorListener getListener() {
188         return mListener;
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(final AffineTransformation2DRobustEstimatorListener listener) throws LockedException {
199         if (isLocked()) {
200             throw new LockedException();
201         }
202         mListener = listener;
203     }
204 
205     /**
206      * Indicates whether listener has been provided and is available for
207      * retrieval.
208      *
209      * @return true if available, false otherwise.
210      */
211     public boolean isListenerAvailable() {
212         return mListener != null;
213     }
214 
215     /**
216      * Indicates if this instance is locked because estimation is being
217      * computed.
218      *
219      * @return true if locked, false otherwise.
220      */
221     public boolean isLocked() {
222         return locked;
223     }
224 
225     /**
226      * Returns amount of progress variation before notifying a progress change
227      * during estimation.
228      *
229      * @return amount of progress variation before notifying a progress change
230      * during estimation.
231      */
232     public float getProgressDelta() {
233         return progressDelta;
234     }
235 
236     /**
237      * Sets amount of progress variation before notifying a progress change
238      * during estimation.
239      *
240      * @param progressDelta amount of progress variation before notifying a
241      *                      progress change during estimation.
242      * @throws IllegalArgumentException if progress delta is less than zero or
243      *                                  greater than 1.
244      * @throws LockedException          if this estimator is locked because an estimation
245      *                                  is being computed.
246      */
247     public void setProgressDelta(final float progressDelta) throws LockedException {
248         if (isLocked()) {
249             throw new LockedException();
250         }
251         if (progressDelta < MIN_PROGRESS_DELTA || progressDelta > MAX_PROGRESS_DELTA) {
252             throw new IllegalArgumentException();
253         }
254         this.progressDelta = progressDelta;
255     }
256 
257     /**
258      * Returns amount of confidence expressed as a value between 0.0 and 1.0
259      * (which is equivalent to 100%). The amount of confidence indicates the
260      * probability that the estimated result is correct. Usually this value will
261      * be close to 1.0, but not exactly 1.0.
262      *
263      * @return amount of confidence as a value between 0.0 and 1.0.
264      */
265     public double getConfidence() {
266         return confidence;
267     }
268 
269     /**
270      * Sets amount of confidence expressed as a value between 0.0 and 1.0 (which
271      * is equivalent to 100%). The amount of confidence indicates the
272      * probability that the estimated result is correct. Usually this value will
273      * be close to 1.0, but not exactly 1.0.
274      *
275      * @param confidence confidence to be set as a value between 0.0 and 1.0.
276      * @throws IllegalArgumentException if provided value is not between 0.0 and
277      *                                  1.0.
278      * @throws LockedException          if this estimator is locked because an estimator
279      *                                  is being computed.
280      */
281     public void setConfidence(final double confidence) throws LockedException {
282         if (isLocked()) {
283             throw new LockedException();
284         }
285         if (confidence < MIN_CONFIDENCE || confidence > MAX_CONFIDENCE) {
286             throw new IllegalArgumentException();
287         }
288         this.confidence = confidence;
289     }
290 
291     /**
292      * Returns maximum allowed number of iterations. If maximum allowed number
293      * of iterations is achieved without converging to a result when calling
294      * estimate(), a RobustEstimatorException will be raised.
295      *
296      * @return maximum allowed number of iterations.
297      */
298     public int getMaxIterations() {
299         return maxIterations;
300     }
301 
302     /**
303      * Sets maximum allowed number of iterations. When the maximum number of
304      * iterations is exceeded, result will not be available, however an
305      * approximate result will be available for retrieval.
306      *
307      * @param maxIterations maximum allowed number of iterations to be set.
308      * @throws IllegalArgumentException if provided value is less than 1.
309      * @throws LockedException          if this estimator is locked because an estimation
310      *                                  is being computed.
311      */
312     public void setMaxIterations(final int maxIterations) throws LockedException {
313         if (isLocked()) {
314             throw new LockedException();
315         }
316         if (maxIterations < MIN_ITERATIONS) {
317             throw new IllegalArgumentException();
318         }
319         this.maxIterations = maxIterations;
320     }
321 
322     /**
323      * Gets data related to inliers found after estimation.
324      *
325      * @return data related to inliers found after estimation.
326      */
327     public InliersData getInliersData() {
328         return inliersData;
329     }
330 
331     /**
332      * Indicates whether result must be refined using Levenberg-Marquardt
333      * fitting algorithm over found inliers.
334      * If ture, inliers will be computed and kept in any implementation
335      * regardless of the settings.
336      *
337      * @return true to refine result, false to simply use result found by
338      * robust estimator without further refining.
339      */
340     public boolean isResultRefined() {
341         return refineResult;
342     }
343 
344     /**
345      * Specifies whether result must be refined using Levenberg-Marquardt
346      * fitting algorithm over found inliers.
347      *
348      * @param refineResult true to refine result, false to simply use result
349      *                     found by robust estimator without further refining.
350      * @throws LockedException if estimator is locked.
351      */
352     public void setResultRefined(final boolean refineResult) throws LockedException {
353         if (isLocked()) {
354             throw new LockedException();
355         }
356         this.refineResult = refineResult;
357     }
358 
359     /**
360      * Indicates whether covariance must be kept after refining result.
361      * This setting is only taken into account if result is refined.
362      *
363      * @return true if covariance must be kept after refining result, false
364      * otherwise.
365      */
366     public boolean isCovarianceKept() {
367         return keepCovariance;
368     }
369 
370     /**
371      * Specifies whether covariance must be kept after refining result.
372      * This setting is only taken into account if result is refined.
373      *
374      * @param keepCovariance true if covariance must be kept after refining
375      *                       result, false otherwise.
376      * @throws LockedException if estimator is locked.
377      */
378     public void setCovarianceKept(final boolean keepCovariance) throws LockedException {
379         if (isLocked()) {
380             throw new LockedException();
381         }
382         this.keepCovariance = keepCovariance;
383     }
384 
385     /**
386      * Gets estimated covariance of estimated 3D point if available.
387      * This is only available when result has been refined and covariance is
388      * kept.
389      *
390      * @return estimated covariance or null.
391      */
392     public Matrix getCovariance() {
393         return covariance;
394     }
395 
396     /**
397      * Estimates an affine 2D transformation using a robust estimator and
398      * the best set of matched 2D point or line correspondences found using the
399      * robust estimator.
400      *
401      * @return an affine 2D transformation.
402      * @throws LockedException          if robust estimator is locked because an
403      *                                  estimation is already in progress.
404      * @throws NotReadyException        if provided input data is not enough to start
405      *                                  the estimation.
406      * @throws RobustEstimatorException if estimation fails for any reason
407      *                                  (i.e. numerical instability, no solution available, etc).
408      */
409     public abstract AffineTransformation2D estimate() throws LockedException, NotReadyException,
410             RobustEstimatorException;
411 
412     /**
413      * Returns method being used for robust estimation
414      *
415      * @return method being used for robust estimation
416      */
417     public abstract RobustEstimatorMethod getMethod();
418 
419     /**
420      * Creates an affine 2D transformation estimator based on 2D point
421      * correspondences and using provided robust estimator method
422      *
423      * @param inputPoints  list of input points to be used to estimate an
424      *                     affine 2D transformation
425      * @param outputPoints list of output points to be used to estimate an
426      *                     affine 2D transformation
427      * @param method       method of a robust estimator algorithm to estimate
428      *                     the best affine 2D transformation
429      * @return an instance of affine 2D transformation estimator
430      * @throws IllegalArgumentException if provided lists of points don't have
431      *                                  the same size or their size is smaller than MINIMUM_SIZE
432      */
433     public static AffineTransformation2DRobustEstimator createFromPoints(
434             final List<Point2D> inputPoints, final List<Point2D> outputPoints, final RobustEstimatorMethod method) {
435         return PointCorrespondenceAffineTransformation2DRobustEstimator.create(inputPoints, outputPoints, method);
436     }
437 
438     /**
439      * Creates an affine 2D transformation estimator based on 2D point
440      * correspondences and using provided robust estimator method
441      *
442      * @param listener     listener to be notified of events such as when estimation
443      *                     starts, ends or its progress significantly changes
444      * @param inputPoints  list of input points to be used to estimate an
445      *                     affine 2D transformation
446      * @param outputPoints list of output points to be used to estimate an
447      *                     affine 2D transformation
448      * @param method       method of a robust estimator algorithm to estimate
449      *                     the best affine 2D transformation
450      * @return an instance of affine 2D transformation estimator
451      * @throws IllegalArgumentException if provided lists of points don't have
452      *                                  the same size or their size is smaller than MINIMUM_SIZE
453      */
454     public static AffineTransformation2DRobustEstimator createFromPoints(
455             final AffineTransformation2DRobustEstimatorListener listener, final List<Point2D> inputPoints,
456             final List<Point2D> outputPoints, final RobustEstimatorMethod method) {
457         return PointCorrespondenceAffineTransformation2DRobustEstimator.create(listener, inputPoints, outputPoints,
458                 method);
459     }
460 
461     /**
462      * Creates an affine 2D transformation estimator based on 2D point
463      * correspondences and using provided robust estimator method
464      *
465      * @param inputPoints   list of input points to be used to estimate an
466      *                      affine 2D transformation
467      * @param outputPoints  list of output points to be used to estimate an
468      *                      affine 2D transformation
469      * @param qualityScores quality scores corresponding to each pair of matched
470      *                      points.
471      * @param method        method of a robust estimator algorithm to estimate
472      *                      the best affine 2D transformation
473      * @return an instance of affine 2D transformation estimator
474      * @throws IllegalArgumentException if provided lists of points don't have
475      *                                  the same size or their size is smaller than MINIMUM_SIZE
476      */
477     public static AffineTransformation2DRobustEstimator createFromPoints(
478             final List<Point2D> inputPoints, final List<Point2D> outputPoints, final double[] qualityScores,
479             final RobustEstimatorMethod method) {
480         return PointCorrespondenceAffineTransformation2DRobustEstimator.create(inputPoints, outputPoints, qualityScores,
481                 method);
482     }
483 
484     /**
485      * Creates an affine 2D transformation estimator based on 2D point
486      * correspondences and using provided robust estimator method
487      *
488      * @param listener      listener to be notified of events such as when estimation
489      *                      starts, ends or its progress significantly changes
490      * @param inputPoints   list of input points to be used to estimate an
491      *                      affine 2D transformation
492      * @param outputPoints  list of output points to be used to estimate an
493      *                      affine 2D transformation
494      * @param qualityScores quality scores corresponding to each pair of matched
495      *                      points.
496      * @param method        method of a robust estimator algorithm to estimate
497      *                      the best affine 2D transformation
498      * @return an instance of affine 2D transformation estimator
499      * @throws IllegalArgumentException if provided lists of points don't have
500      *                                  the same size or their size is smaller than MINIMUM_SIZE
501      */
502     public static AffineTransformation2DRobustEstimator createFromPoints(
503             final AffineTransformation2DRobustEstimatorListener listener, final List<Point2D> inputPoints,
504             final List<Point2D> outputPoints, final double[] qualityScores, final RobustEstimatorMethod method) {
505         return PointCorrespondenceAffineTransformation2DRobustEstimator.create(listener, inputPoints, outputPoints,
506                 qualityScores, method);
507     }
508 
509     /**
510      * Creates an affine 2D transformation estimator based on 2D point
511      * correspondences and using default robust estimator method
512      *
513      * @param inputPoints  list of input points to be used to estimate an
514      *                     affine 2D transformation
515      * @param outputPoints list of output points to be used to estimate an
516      *                     affine 2D transformation
517      * @return an instance of affine 2D transformation estimator
518      * @throws IllegalArgumentException if provided lists of points don't have
519      *                                  the same size or their size is smaller than MINIMUM_SIZE
520      */
521     public static AffineTransformation2DRobustEstimator createFromPoints(
522             final List<Point2D> inputPoints, final List<Point2D> outputPoints) {
523         return PointCorrespondenceAffineTransformation2DRobustEstimator.create(inputPoints, outputPoints);
524     }
525 
526     /**
527      * Creates an affine 2D transformation estimator based on 2D point
528      * correspondences and using default robust estimator method
529      *
530      * @param listener     listener to be notified of events such as when estimation
531      *                     starts, ends or its progress significantly changes
532      * @param inputPoints  list of input points to be used to estimate an
533      *                     affine 2D transformation
534      * @param outputPoints list of output points to be used to estimate an
535      *                     affine 2D transformation
536      * @return an instance of affine 2D transformation estimator
537      * @throws IllegalArgumentException if provided lists of points don't have
538      *                                  the same size or their size is smaller than MINIMUM_SIZE
539      */
540     public static AffineTransformation2DRobustEstimator createFromPoints(
541             final AffineTransformation2DRobustEstimatorListener listener, final List<Point2D> inputPoints,
542             final List<Point2D> outputPoints) {
543         return PointCorrespondenceAffineTransformation2DRobustEstimator.create(listener, inputPoints, outputPoints);
544     }
545 
546     /**
547      * Creates an affine 2D transformation estimator based on 2D point
548      * correspondences and using default robust estimator method
549      *
550      * @param inputPoints   list of input points to be used to estimate an
551      *                      affine 2D transformation
552      * @param outputPoints  list of output points to be used to estimate an
553      *                      affine 2D transformation
554      * @param qualityScores quality scores corresponding to each pair of matched
555      *                      points.
556      * @return an instance of affine 2D transformation estimator
557      * @throws IllegalArgumentException if provided lists of points don't have
558      *                                  the same size or their size is smaller than MINIMUM_SIZE
559      */
560     public static AffineTransformation2DRobustEstimator createFromPoints(
561             final List<Point2D> inputPoints, final List<Point2D> outputPoints, final double[] qualityScores) {
562         return PointCorrespondenceAffineTransformation2DRobustEstimator.create(inputPoints, outputPoints,
563                 qualityScores);
564     }
565 
566     /**
567      * Creates an affine 2D transformation estimator based on 2D point
568      * correspondences and using default robust estimator method
569      *
570      * @param listener      listener to be notified of events such as when estimation
571      *                      starts, ends or its progress significantly changes
572      * @param inputPoints   list of input points to be used to estimate an
573      *                      affine 2D transformation
574      * @param outputPoints  list of output points to be used to estimate an
575      *                      affine 2D transformation
576      * @param qualityScores quality scores corresponding to each pair of matched
577      *                      points.
578      * @return an instance of affine 2D transformation estimator
579      * @throws IllegalArgumentException if provided lists of points don't have
580      *                                  the same size or their size is smaller than MINIMUM_SIZE
581      */
582     public static AffineTransformation2DRobustEstimator createFromPoints(
583             final AffineTransformation2DRobustEstimatorListener listener, final List<Point2D> inputPoints,
584             final List<Point2D> outputPoints, final double[] qualityScores) {
585         return PointCorrespondenceAffineTransformation2DRobustEstimator.create(listener, inputPoints, outputPoints,
586                 qualityScores);
587     }
588 
589     /**
590      * Creates an affine 2D transformation estimator based on 2D line
591      * correspondences and using provided robust estimator method
592      *
593      * @param inputLines  list of input lines to be used to estimate an
594      *                    affine 2D transformation
595      * @param outputLines list of output lines to be used to estimate an
596      *                    affine 2D transformation
597      * @param method      method of a robust estimator algorithm to estimate
598      *                    the best affine 2D transformation
599      * @return an instance of affine 2D transformation estimator
600      * @throws IllegalArgumentException if provided lists of lines don't have
601      *                                  the same size or their size is smaller than MINIMUM_SIZE
602      */
603     public static AffineTransformation2DRobustEstimator createFromLines(
604             final List<Line2D> inputLines, final List<Line2D> outputLines, final RobustEstimatorMethod method) {
605         return LineCorrespondenceAffineTransformation2DRobustEstimator.create(inputLines, outputLines, method);
606     }
607 
608     /**
609      * Creates an affine 2D transformation estimator based on 2D line
610      * correspondences and using provided robust estimator method
611      *
612      * @param listener    listener to be notified of events such as when estimation
613      *                    starts, ends or its progress significantly changes
614      * @param inputLines  list of input lines to be used to estimate an affine
615      *                    2D transformation
616      * @param outputLines list of output lines to be used to estimate an affine
617      *                    2D transformation
618      * @param method      method of a robust estimator algorithm to estimate the best
619      *                    affine 2D transformation
620      * @return an instance of affine 2D transformation estimator
621      * @throws IllegalArgumentException if provided lists of lines don't have
622      *                                  the same size or their size is smaller than MINIMUM_SIZE
623      */
624     public static AffineTransformation2DRobustEstimator createFromLines(
625             final AffineTransformation2DRobustEstimatorListener listener, final List<Line2D> inputLines,
626             final List<Line2D> outputLines, final RobustEstimatorMethod method) {
627         return LineCorrespondenceAffineTransformation2DRobustEstimator.create(listener, inputLines, outputLines,
628                 method);
629     }
630 
631     /**
632      * Creates an affine 2D transformation estimator based on 2D line
633      * correspondences and using provided robust estimator method
634      *
635      * @param inputLines    list of input lines to be used to estimate an
636      *                      affine 2D transformation
637      * @param outputLines   list of output lines to be used to estimate an
638      *                      affine 2D transformation
639      * @param qualityScores quality scores corresponding to each pair of matched
640      *                      lines.
641      * @param method        method of a robust estimator algorithm to estimate the best
642      *                      affine 2D transformation
643      * @return an instance of affine 2D transformation estimator
644      * @throws IllegalArgumentException if provided lists of lines don't have
645      *                                  the same size or their size is smaller than MINIMUM_SIZE
646      */
647     public static AffineTransformation2DRobustEstimator createFromLines(
648             final List<Line2D> inputLines, final List<Line2D> outputLines, final double[] qualityScores,
649             final RobustEstimatorMethod method) {
650         return LineCorrespondenceAffineTransformation2DRobustEstimator.create(inputLines, outputLines, qualityScores,
651                 method);
652     }
653 
654     /**
655      * Creates an affine 2D transformation estimator based on 2D line
656      * correspondences and using provided robust estimator method
657      *
658      * @param listener      listener to be notified of events such as when estimation
659      *                      starts, ends or its progress significantly changes
660      * @param inputLines    list of input lines to be used to estimate an affine
661      *                      2D transformation
662      * @param outputLines   list of output lines to be used to estimate an affine
663      *                      2D transformation
664      * @param qualityScores quality scores corresponding to each pair of matched
665      *                      lines.
666      * @param method        method of a robust estimator algorithm to estimate the best
667      *                      affine 2D transformation
668      * @return an instance of affine 2D transformation estimator
669      * @throws IllegalArgumentException if provided lists of lines don't have
670      *                                  the same size or their size is smaller than MINIMUM_SIZE
671      */
672     public static AffineTransformation2DRobustEstimator createFromLines(
673             final AffineTransformation2DRobustEstimatorListener listener,
674             final List<Line2D> inputLines, final List<Line2D> outputLines, final double[] qualityScores,
675             final RobustEstimatorMethod method) {
676         return LineCorrespondenceAffineTransformation2DRobustEstimator.create(listener, inputLines, outputLines,
677                 qualityScores, method);
678     }
679 
680     /**
681      * Creates an affine 2D transformation estimator based on 2D line
682      * correspondences and using default robust estimator method
683      *
684      * @param inputLines  list of input lines to be used to estimate an
685      *                    affine 2D transformation
686      * @param outputLines list of output lines to be used to estimate an
687      *                    affine 2D transformation
688      * @return an instance of affine 2D transformation estimator
689      * @throws IllegalArgumentException if provided lists of lines don't have
690      *                                  the same size or their size is smaller than MINIMUM_SIZE
691      */
692     public static AffineTransformation2DRobustEstimator createFromLines(
693             final List<Line2D> inputLines, final List<Line2D> outputLines) {
694         return LineCorrespondenceAffineTransformation2DRobustEstimator.create(inputLines, outputLines);
695     }
696 
697     /**
698      * Creates an affine 2D transformation estimator based on 2D line
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 inputLines  list of input lines to be used to estimate an affine
704      *                    2D transformation
705      * @param outputLines list of output lines to be used to estimate an affine
706      *                    2D transformation
707      * @return an instance of affine 2D transformation estimator
708      * @throws IllegalArgumentException if provided lists of lines don't have
709      *                                  the same size or their size is smaller than MINIMUM_SIZE
710      */
711     public static AffineTransformation2DRobustEstimator createFromLines(
712             final AffineTransformation2DRobustEstimatorListener listener, final List<Line2D> inputLines,
713             final List<Line2D> outputLines) {
714         return LineCorrespondenceAffineTransformation2DRobustEstimator.create(listener, inputLines, outputLines);
715     }
716 
717     /**
718      * Creates an affine 2D transformation estimator based on 2D line
719      * correspondences and using default robust estimator method
720      *
721      * @param inputLines    list of input lines to be used to estimate an affine
722      *                      2D transformation
723      * @param outputLines   list of output lines to be used to estimate an affine
724      *                      2D transformation
725      * @param qualityScores quality scores corresponding to each pair of matched
726      *                      points.
727      * @return an instance of affine 2D transformation estimator
728      * @throws IllegalArgumentException if provided lists of lines don't have
729      *                                  the same size or their size is smaller than MINIMUM_SIZE
730      */
731     public static AffineTransformation2DRobustEstimator createFromLines(
732             final List<Line2D> inputLines, final List<Line2D> outputLines, final double[] qualityScores) {
733         return LineCorrespondenceAffineTransformation2DRobustEstimator.create(inputLines, outputLines, qualityScores);
734     }
735 
736     /**
737      * Creates an affine 2D transformation estimator based on 2D line
738      * correspondences and using default robust estimator method
739      *
740      * @param listener      listener to be notified of events such as when estimation
741      *                      starts, ends or its progress significantly changes
742      * @param inputLines    list of input lines to be used to estimate an affine
743      *                      2D transformation
744      * @param outputLines   list of output lines to be used to estimate an affine
745      *                      2D transformation
746      * @param qualityScores quality scores corresponding to each pair of matched
747      *                      lines.
748      * @return an instance of affine 2D transformation estimator
749      * @throws IllegalArgumentException if provided lists of lines don't have
750      *                                  the same size or their size is smaller than MINIMUM_SIZE
751      */
752     public static AffineTransformation2DRobustEstimator createFromLines(
753             final AffineTransformation2DRobustEstimatorListener listener, final List<Line2D> inputLines,
754             final List<Line2D> outputLines, final double[] qualityScores) {
755         return LineCorrespondenceAffineTransformation2DRobustEstimator.create(listener, inputLines, outputLines,
756                 qualityScores);
757     }
758 
759     /**
760      * Gets standard deviation used for Levenberg-Marquardt fitting during
761      * refinement.
762      * Returned value gives an indication of how much variance each residual
763      * has.
764      * Typically, this value is related to the threshold used on each robust
765      * estimation, since residuals of found inliers are within the range of
766      * such threshold.
767      *
768      * @return standard deviation used for refinement.
769      */
770     protected abstract double getRefinementStandardDeviation();
771 }