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 }