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.geometry.Point2D;
19 import com.irurueta.geometry.ProjectiveTransformation2D;
20 import com.irurueta.geometry.refiners.PointCorrespondenceProjectiveTransformation2DRefiner;
21 import com.irurueta.numerical.robust.RobustEstimatorMethod;
22
23 import java.util.List;
24
25 /**
26 * This is an abstract class for algorithms to robustly find the best projective
27 * 2D transformation for collections of matching 2D points.
28 * Implementations of this class should be able to detect and discard outliers
29 * in order to find the best solution.
30 */
31 public abstract class PointCorrespondenceProjectiveTransformation2DRobustEstimator
32 extends ProjectiveTransformation2DRobustEstimator {
33
34 /**
35 * Default robust estimator method when none is provided.
36 */
37 public static final RobustEstimatorMethod DEFAULT_ROBUST_METHOD = RobustEstimatorMethod.PROMEDS;
38
39 /**
40 * List of points to be used to estimate a projective 2D transformation.
41 * Each point in the list of input points must be matched with the
42 * corresponding point in the list of output points located at the same
43 * position. Hence, both input points and output points must have the same
44 * size, and their size must be greater or equal than MINIMUM_SIZE.
45 */
46 protected List<Point2D> inputPoints;
47
48 /**
49 * List of points to be used to estimate a projective 2D transformation.
50 * Each point in the list of output points must be matched with the
51 * corresponding point in the list of input points located at the same
52 * position. Hence, both input points and output points must have the same
53 * size, and their size must be greater or equal than MINIMUM_SIZE.
54 */
55 protected List<Point2D> outputPoints;
56
57 /**
58 * Constructor.
59 */
60 protected PointCorrespondenceProjectiveTransformation2DRobustEstimator() {
61 super();
62 }
63
64 /**
65 * Constructor with lists of points to be used to estimate a projective 2D
66 * transformation.
67 * Points in the list located at the same position are considered to be
68 * matched. Hence, both lists must have the same size, and their size must
69 * be greater or equal than MINIMUM_SIZE.
70 *
71 * @param inputPoints list of input points to be used to estimate a
72 * projective 2D transformation.
73 * @param outputPoints list of output points to be used to estimate a
74 * projective 2D transformation.
75 * @throws IllegalArgumentException if provided lists of points don't have
76 * the same size or their size is smaller than MINIMUM_SIZE.
77 */
78 protected PointCorrespondenceProjectiveTransformation2DRobustEstimator(
79 final List<Point2D> inputPoints, final List<Point2D> outputPoints) {
80 super();
81 internalSetPoints(inputPoints, outputPoints);
82 }
83
84 /**
85 * Constructor.
86 *
87 * @param listener listener to be notified of events such as when estimation
88 * stars, ends or its progress significantly changes.
89 */
90 protected PointCorrespondenceProjectiveTransformation2DRobustEstimator(
91 final ProjectiveTransformation2DRobustEstimatorListener listener) {
92 super(listener);
93 }
94
95 /**
96 * Constructor with listener and lists of points to be used to estimate a
97 * projection 2D transformation.
98 * Points in the list located at the same position are considered to be
99 * matched. Hence, both lists must have the same size, and their size must
100 * be greater or equal than MINIMUM_SIZE.
101 *
102 * @param listener listener to be notified of events such as when estimation
103 * starts, ends or its progress significantly changes.
104 * @param inputPoints list of input points to be used to estimate a
105 * projective 2D transformation.
106 * @param outputPoints list of output points to be used to estimate a
107 * projective 2D transformation.
108 * @throws IllegalArgumentException if provided lists of points don't have
109 * the same size or their size is smaller than MINIMUM_SIZE.
110 */
111 protected PointCorrespondenceProjectiveTransformation2DRobustEstimator(
112 final ProjectiveTransformation2DRobustEstimatorListener listener,
113 final List<Point2D> inputPoints, final List<Point2D> outputPoints) {
114 super(listener);
115 internalSetPoints(inputPoints, outputPoints);
116 }
117
118 /**
119 * Returns list of input points to be used to estimate a projective 2D
120 * transformation.
121 * Each point in the list of input points must be matched with the
122 * corresponding point in the list of output points located at the same
123 * position. Hence, both input points and output points must have the same
124 * size, and their size must be greater or equal than MINIMUM_SIZE.
125 *
126 * @return list of input points to be used to estimate a projective 2D
127 * transformation.
128 */
129 public List<Point2D> getInputPoints() {
130 return inputPoints;
131 }
132
133 /**
134 * Returns list of output points to be used to estimate a projective 2D
135 * transformation.
136 * Each point in the list of output points must be matched with the
137 * corresponding point in the list of input points located at the same
138 * position. Hence, both input points and output points must have the same
139 * size, and their size must be greater or equal than MINIMUM_SIZE.
140 *
141 * @return list of output points to be used to estimate a projective 2D
142 * transformation.
143 */
144 public List<Point2D> getOutputPoints() {
145 return outputPoints;
146 }
147
148 /**
149 * Sets lists of points to be used to estimate a projective 2D
150 * transformation.
151 * Points in the list located at the same position are considered to be
152 * matched. Hence, both lists must have the same size, and their size must
153 * be greater or equal than MINIMUM_SIZE.
154 *
155 * @param inputPoints list of input points to be used to estimate a
156 * projective 2D transformation.
157 * @param outputPoints list of output points to be used to estimate a
158 * projective 2D transformation.
159 * @throws IllegalArgumentException if provided lists of points don't have
160 * the same size or their size is smaller than MINIMUM_SIZE.
161 * @throws LockedException if estimator is locked because a computation is
162 * already in progress.
163 */
164 public final void setPoints(final List<Point2D> inputPoints, final List<Point2D> outputPoints)
165 throws LockedException {
166 if (isLocked()) {
167 throw new LockedException();
168 }
169 internalSetPoints(inputPoints, outputPoints);
170 }
171
172 /**
173 * Indicates if estimator is ready to start the projective 2D transformation
174 * estimation.
175 * This is true when input data (i.e. lists of matched points) are provided
176 * and a minimum of MINIMUM_SIZE points are available.
177 *
178 * @return true if estimator is ready, false otherwise.
179 */
180 public boolean isReady() {
181 return inputPoints != null && outputPoints != null && inputPoints.size() == outputPoints.size()
182 && inputPoints.size() >= MINIMUM_SIZE;
183 }
184
185 /**
186 * Returns quality scores corresponding to each pair of matched points.
187 * The larger the score value the better the quality of the matching.
188 * This implementation always returns null.
189 * Subclasses using quality scores must implement proper behaviour.
190 *
191 * @return quality scores corresponding to each pair of matched points.
192 */
193 public double[] getQualityScores() {
194 return null;
195 }
196
197 /**
198 * Sets quality scores corresponding to each pair of matched points.
199 * The larger the score value the better the quality of the matching.
200 * This implementation makes no action.
201 * Subclasses using quality scores must implement proper behaviour.
202 *
203 * @param qualityScores quality scores corresponding to each pair of matched
204 * points.
205 * @throws LockedException if robust estimator is locked because an
206 * estimation is already in progress.
207 * @throws IllegalArgumentException if provided quality scores length is
208 * smaller than MINIMUM_SIZE (i.e. 3 samples).
209 */
210 public void setQualityScores(final double[] qualityScores) throws LockedException {
211 }
212
213 /**
214 * Creates a projective 2D transformation estimator based on 2D point
215 * correspondences and using provided robust estimator method.
216 *
217 * @param method method of a robust estimator algorithm to estimate
218 * best projective 2D transformation.
219 * @return an instance of projective 2D transformation estimator.
220 */
221 public static PointCorrespondenceProjectiveTransformation2DRobustEstimator create(
222 final RobustEstimatorMethod method) {
223 return switch (method) {
224 case LMEDS -> new LMedSPointCorrespondenceProjectiveTransformation2DRobustEstimator();
225 case MSAC -> new MSACPointCorrespondenceProjectiveTransformation2DRobustEstimator();
226 case PROSAC -> new PROSACPointCorrespondenceProjectiveTransformation2DRobustEstimator();
227 case PROMEDS -> new PROMedSPointCorrespondenceProjectiveTransformation2DRobustEstimator();
228 default -> new RANSACPointCorrespondenceProjectiveTransformation2DRobustEstimator();
229 };
230 }
231
232 /**
233 * Creates a projective 2D transformation estimator based on 2D point
234 * correspondences and using provided robust estimator method.
235 *
236 * @param inputPoints list of input points to be used to estimate a
237 * projective 2D transformation.
238 * @param outputPoints list of output points to be used to estimate a
239 * projective 2D transformation.
240 * @param method method of a robust estimator algorithm to estimate
241 * best projective 2D transformation.
242 * @return an instance of projective 2D transformation estimator.
243 * @throws IllegalArgumentException if provided lists of points don't have
244 * the same size or their size is smaller than MINIMUM_SIZE.
245 */
246 public static PointCorrespondenceProjectiveTransformation2DRobustEstimator create(
247 final List<Point2D> inputPoints, final List<Point2D> outputPoints, final RobustEstimatorMethod method) {
248 return switch (method) {
249 case LMEDS -> new LMedSPointCorrespondenceProjectiveTransformation2DRobustEstimator(
250 inputPoints, outputPoints);
251 case MSAC -> new MSACPointCorrespondenceProjectiveTransformation2DRobustEstimator(
252 inputPoints, outputPoints);
253 case PROSAC -> new PROSACPointCorrespondenceProjectiveTransformation2DRobustEstimator(
254 inputPoints, outputPoints);
255 case PROMEDS -> new PROMedSPointCorrespondenceProjectiveTransformation2DRobustEstimator(
256 inputPoints, outputPoints);
257 default -> new RANSACPointCorrespondenceProjectiveTransformation2DRobustEstimator(
258 inputPoints, outputPoints);
259 };
260 }
261
262 /**
263 * Creates a projective 2D transformation estimator based on 2D point
264 * correspondences and using provided robust estimator method.
265 *
266 * @param listener listener to be notified of events such as when estimation
267 * starts, ends or its progress significantly changes.
268 * @param method method of a robust estimator algorithm to estimate
269 * best projective 2D transformation.
270 * @return an instance of projective 2D transformation estimator.
271 */
272 public static PointCorrespondenceProjectiveTransformation2DRobustEstimator create(
273 final ProjectiveTransformation2DRobustEstimatorListener listener, final RobustEstimatorMethod method) {
274 return switch (method) {
275 case LMEDS -> new LMedSPointCorrespondenceProjectiveTransformation2DRobustEstimator(listener);
276 case MSAC -> new MSACPointCorrespondenceProjectiveTransformation2DRobustEstimator(listener);
277 case PROSAC -> new PROSACPointCorrespondenceProjectiveTransformation2DRobustEstimator(listener);
278 case PROMEDS -> new PROMedSPointCorrespondenceProjectiveTransformation2DRobustEstimator(listener);
279 default -> new RANSACPointCorrespondenceProjectiveTransformation2DRobustEstimator(listener);
280 };
281 }
282
283 /**
284 * Creates a projective 2D transformation estimator based on 2D point
285 * correspondences and using provided robust estimator method.
286 *
287 * @param listener listener to be notified of events such as when estimation
288 * starts, ends or its progress significantly changes.
289 * @param inputPoints list of input points to be used to estimate a
290 * projective 2D transformation.
291 * @param outputPoints list of output points to be used to estimate a
292 * projective 2D transformation.
293 * @param method method of a robust estimator algorithm to estimate
294 * best projective 2D transformation.
295 * @return an instance of projective 2D transformation estimator.
296 * @throws IllegalArgumentException if provided lists of points don't have
297 * the same size or their size is smaller than MINIMUM_SIZE.
298 */
299 public static PointCorrespondenceProjectiveTransformation2DRobustEstimator create(
300 final ProjectiveTransformation2DRobustEstimatorListener listener, final List<Point2D> inputPoints,
301 final List<Point2D> outputPoints, final RobustEstimatorMethod method) {
302 return switch (method) {
303 case LMEDS -> new LMedSPointCorrespondenceProjectiveTransformation2DRobustEstimator(
304 listener, inputPoints, outputPoints);
305 case MSAC -> new MSACPointCorrespondenceProjectiveTransformation2DRobustEstimator(
306 listener, inputPoints, outputPoints);
307 case PROSAC -> new PROSACPointCorrespondenceProjectiveTransformation2DRobustEstimator(
308 listener, inputPoints, outputPoints);
309 case PROMEDS -> new PROMedSPointCorrespondenceProjectiveTransformation2DRobustEstimator(
310 listener, inputPoints, outputPoints);
311 default -> new RANSACPointCorrespondenceProjectiveTransformation2DRobustEstimator(
312 listener, inputPoints, outputPoints);
313 };
314 }
315
316 /**
317 * Creates a projective 2D transformation estimator based on 2D point
318 * correspondences and using provided robust estimator method.
319 *
320 * @param qualityScores quality scores corresponding to each pair of matched
321 * points.
322 * @param method method of a robust estimator algorithm to estimate
323 * the best affine 2D transformation.
324 * @return an instance of projective 2D transformation estimator.
325 * @throws IllegalArgumentException if provided quality scores length is
326 * smaller than MINIMUM_SIZE (i.e. 3 matched points).
327 */
328 public static PointCorrespondenceProjectiveTransformation2DRobustEstimator create(
329 final double[] qualityScores, final RobustEstimatorMethod method) {
330 return switch (method) {
331 case LMEDS -> new LMedSPointCorrespondenceProjectiveTransformation2DRobustEstimator();
332 case MSAC -> new MSACPointCorrespondenceProjectiveTransformation2DRobustEstimator();
333 case PROSAC -> new PROSACPointCorrespondenceProjectiveTransformation2DRobustEstimator(qualityScores);
334 case PROMEDS -> new PROMedSPointCorrespondenceProjectiveTransformation2DRobustEstimator(qualityScores);
335 default -> new RANSACPointCorrespondenceProjectiveTransformation2DRobustEstimator();
336 };
337 }
338
339 /**
340 * Creates a projective 2D transformation estimator based on 2D point
341 * correspondences and using provided robust estimator method.
342 *
343 * @param inputPoints list of input points to be used to estimate a
344 * projective 2D transformation.
345 * @param outputPoints list of output points to be used to estimate a
346 * projective 2D transformation.
347 * @param qualityScores quality scores corresponding to each pair of matched
348 * points.
349 * @param method method of a robust estimator algorithm to estimate
350 * best projective 2D transformation.
351 * @return an instance of projective 2D transformation estimator.
352 * @throws IllegalArgumentException if provided lists of points or quality
353 * scores don't have the same size or their size is smaller than
354 * MINIMUM_SIZE.
355 */
356 public static PointCorrespondenceProjectiveTransformation2DRobustEstimator create(
357 final List<Point2D> inputPoints, final List<Point2D> outputPoints,
358 final double[] qualityScores, final RobustEstimatorMethod method) {
359 return switch (method) {
360 case LMEDS -> new LMedSPointCorrespondenceProjectiveTransformation2DRobustEstimator(
361 inputPoints, outputPoints);
362 case MSAC -> new MSACPointCorrespondenceProjectiveTransformation2DRobustEstimator(
363 inputPoints, outputPoints);
364 case PROSAC -> new PROSACPointCorrespondenceProjectiveTransformation2DRobustEstimator(
365 inputPoints, outputPoints, qualityScores);
366 case PROMEDS -> new PROMedSPointCorrespondenceProjectiveTransformation2DRobustEstimator(
367 inputPoints, outputPoints, qualityScores);
368 default -> new RANSACPointCorrespondenceProjectiveTransformation2DRobustEstimator(
369 inputPoints, outputPoints);
370 };
371 }
372
373 /**
374 * Creates a projective 2D transformation estimator based on 2D point
375 * correspondences and using provided robust estimator method.
376 *
377 * @param listener listener to be notified of events such as when estimation
378 * starts, ends or its progress significantly changes.
379 * @param qualityScores quality scores corresponding to each pair of matched
380 * points.
381 * @param method method of a robust estimator algorithm to estimate
382 * best projective 2D transformation.
383 * @return an instance of projective 2D transformation estimator.
384 */
385 public static PointCorrespondenceProjectiveTransformation2DRobustEstimator create(
386 final ProjectiveTransformation2DRobustEstimatorListener listener, final double[] qualityScores,
387 final RobustEstimatorMethod method) {
388 return switch (method) {
389 case LMEDS -> new LMedSPointCorrespondenceProjectiveTransformation2DRobustEstimator(listener);
390 case MSAC -> new MSACPointCorrespondenceProjectiveTransformation2DRobustEstimator(listener);
391 case PROSAC -> new PROSACPointCorrespondenceProjectiveTransformation2DRobustEstimator(
392 listener, qualityScores);
393 case PROMEDS -> new PROMedSPointCorrespondenceProjectiveTransformation2DRobustEstimator(
394 listener, qualityScores);
395 default -> new RANSACPointCorrespondenceProjectiveTransformation2DRobustEstimator(listener);
396 };
397 }
398
399 /**
400 * Creates a projective 2D transformation estimator based on 2D point
401 * correspondences and using provided robust estimator method.
402 *
403 * @param listener listener to be notified of events such as when estimation
404 * starts, ends or its progress significantly changes.
405 * @param inputPoints list of input points to be used to estimate a
406 * projective 2D transformation.
407 * @param outputPoints list of output points to be used to estimate a
408 * projective 2D transformation.
409 * @param qualityScores quality scores corresponding to each pair of matched
410 * points.
411 * @param method method of a robust estimator algorithm to estimate
412 * best projective 2D transformation.
413 * @return an instance of projective 2D transformation estimator.
414 * @throws IllegalArgumentException if provided lists of points don't have
415 * the same size or their size is smaller than MINIMUM_SIZE.
416 */
417 public static PointCorrespondenceProjectiveTransformation2DRobustEstimator create(
418 final ProjectiveTransformation2DRobustEstimatorListener listener, final List<Point2D> inputPoints,
419 final List<Point2D> outputPoints, final double[] qualityScores, final RobustEstimatorMethod method) {
420 return switch (method) {
421 case LMEDS -> new LMedSPointCorrespondenceProjectiveTransformation2DRobustEstimator(
422 listener, inputPoints, outputPoints);
423 case MSAC -> new MSACPointCorrespondenceProjectiveTransformation2DRobustEstimator(
424 listener, inputPoints, outputPoints);
425 case PROSAC -> new PROSACPointCorrespondenceProjectiveTransformation2DRobustEstimator(
426 listener, inputPoints, outputPoints, qualityScores);
427 case PROMEDS -> new PROMedSPointCorrespondenceProjectiveTransformation2DRobustEstimator(
428 listener, inputPoints, outputPoints, qualityScores);
429 default -> new RANSACPointCorrespondenceProjectiveTransformation2DRobustEstimator(
430 listener, inputPoints, outputPoints);
431 };
432 }
433
434 /**
435 * Creates a projective 2D transformation estimator based on 2D point
436 * correspondences and using default robust estimator method.
437 *
438 * @return an instance of projective 2D transformation estimator.
439 */
440 public static PointCorrespondenceProjectiveTransformation2DRobustEstimator create() {
441 return create(DEFAULT_ROBUST_METHOD);
442 }
443
444 /**
445 * Creates a projective 2D transformation estimator based on 2D point
446 * correspondences and using default robust estimator method.
447 *
448 * @param inputPoints list of input points to be used to estimate a
449 * projective 2D transformation.
450 * @param outputPoints list of output points to be used to estimate a
451 * projective 2D transformation.
452 * @return an instance of projective 2D transformation estimator.
453 * @throws IllegalArgumentException if provided lists of points don't have
454 * the same size or their size is smaller than MINIMUM_SIZE.
455 */
456 public static PointCorrespondenceProjectiveTransformation2DRobustEstimator create(
457 final List<Point2D> inputPoints, final List<Point2D> outputPoints) {
458 return create(inputPoints, outputPoints, DEFAULT_ROBUST_METHOD);
459 }
460
461 /**
462 * Creates a projective 2D transformation estimator based on 2D point
463 * correspondences and using default robust estimator method.
464 *
465 * @param listener listener to be notified of events such as when estimation
466 * starts, ends or its progress significantly changes.
467 * @return an instance of projective 2D transformation estimator.
468 */
469 public static PointCorrespondenceProjectiveTransformation2DRobustEstimator create(
470 final ProjectiveTransformation2DRobustEstimatorListener listener) {
471 return create(listener, DEFAULT_ROBUST_METHOD);
472 }
473
474 /**
475 * Creates a projective 2D transformation estimator based on 2D point
476 * correspondences and using default robust estimator method.
477 *
478 * @param listener listener to be notified of events such as when estimation
479 * starts, ends or its progress significantly changes.
480 * @param inputPoints list of input points to be used to estimate a
481 * projective 2D transformation.
482 * @param outputPoints list of output points to be used to estimate a
483 * projective 2D transformation.
484 * @return an instance of projective 2D transformation estimator.
485 * @throws IllegalArgumentException if provided lists of points don't have
486 * the same size or their size is smaller than MINIMUM_SIZE.
487 */
488 public static PointCorrespondenceProjectiveTransformation2DRobustEstimator create(
489 final ProjectiveTransformation2DRobustEstimatorListener listener,
490 final List<Point2D> inputPoints, final List<Point2D> outputPoints) {
491 return create(listener, inputPoints, outputPoints, DEFAULT_ROBUST_METHOD);
492 }
493
494 /**
495 * Creates a projective 2D transformation estimator based on 2D point
496 * correspondences and using default robust estimator method.
497 *
498 * @param qualityScores quality scores corresponding to each pair of matched
499 * points.
500 * @return an instance of projective 2D transformation estimator.
501 */
502 public static PointCorrespondenceProjectiveTransformation2DRobustEstimator create(final double[] qualityScores) {
503 return create(qualityScores, DEFAULT_ROBUST_METHOD);
504 }
505
506 /**
507 * Creates a projective 2D transformation estimator based on 2D point
508 * correspondences and using default robust estimator method.
509 *
510 * @param inputPoints list of input points to be used to estimate a
511 * projective 2D transformation.
512 * @param outputPoints list of output points to be used to estimate a
513 * projective 2D transformation.
514 * @param qualityScores quality scores corresponding to each pair of matched
515 * points.
516 * @return an instance of affine 2D transformation estimator.
517 * @throws IllegalArgumentException if provided lists of points don't have
518 * the same size or their size is smaller than MINIMUM_SIZE.
519 */
520 public static PointCorrespondenceProjectiveTransformation2DRobustEstimator create(
521 final List<Point2D> inputPoints, final List<Point2D> outputPoints, final double[] qualityScores) {
522 return create(inputPoints, outputPoints, qualityScores, DEFAULT_ROBUST_METHOD);
523 }
524
525 /**
526 * Creates a projective 2D transformation estimator based on 2D point
527 * correspondences and using default robust estimator method.
528 *
529 * @param listener listener to be notified of events such as when estimation
530 * starts, ends or its progress significantly changes.
531 * @param qualityScores quality scores corresponding to each pair of matched
532 * points.
533 * @return an instance of affine 2D transformation estimator.
534 */
535 public static PointCorrespondenceProjectiveTransformation2DRobustEstimator create(
536 final ProjectiveTransformation2DRobustEstimatorListener listener, final double[] qualityScores) {
537 return create(listener, qualityScores, DEFAULT_ROBUST_METHOD);
538 }
539
540 /**
541 * Creates a projective 2D transformation estimator based on 2D point
542 * correspondences and using default robust estimator method.
543 *
544 * @param listener listener to be notified of events such as when estimation
545 * starts, ends or its progress significantly changes.
546 * @param inputPoints list of input points to be used to estimate a
547 * projective 2D transformation.
548 * @param outputPoints list of output points to be used to estimate a
549 * projective 2D transformation.
550 * @param qualityScores quality scores corresponding to each pair of matched
551 * points.
552 * @return an instance of projective 2D transformation estimator.
553 * @throws IllegalArgumentException if provided lists of points don't have
554 * the same size or their size is smaller than MINIMUM_SIZE.
555 */
556 public static PointCorrespondenceProjectiveTransformation2DRobustEstimator create(
557 final ProjectiveTransformation2DRobustEstimatorListener listener,
558 final List<Point2D> inputPoints, final List<Point2D> outputPoints, final double[] qualityScores) {
559 return create(listener, inputPoints, outputPoints, qualityScores, DEFAULT_ROBUST_METHOD);
560 }
561
562 /**
563 * Attempts to refine provided solution if refinement is requested.
564 * This method returns a refined solution of the same provided solution
565 * if refinement is not requested or has failed.
566 * If refinement is enabled, and it is requested to keep covariance, this
567 * method will also keep covariance of refined transformation.
568 *
569 * @param transformation transformation estimated by a robust estimator
570 * without refinement.
571 * @return solution after refinement (if requested) or the provided
572 * non-refined solution if not requested or refinement failed.
573 */
574 @SuppressWarnings("DuplicatedCode")
575 protected ProjectiveTransformation2D attemptRefine(final ProjectiveTransformation2D transformation) {
576 if (refineResult) {
577 final var refiner = new PointCorrespondenceProjectiveTransformation2DRefiner(transformation, keepCovariance,
578 getInliersData(), inputPoints, outputPoints, getRefinementStandardDeviation());
579
580 try {
581 final var result = new ProjectiveTransformation2D();
582 final var improved = refiner.refine(result);
583
584 if (keepCovariance) {
585 // keep covariance
586 covariance = refiner.getCovariance();
587 }
588
589 return improved ? result : transformation;
590 } catch (final Exception e) {
591 // refinement failed, so we return input value
592 return transformation;
593 }
594 } else {
595 return transformation;
596 }
597 }
598
599 /**
600 * Internal method to set lists of points to be used to estimate a
601 * projective 2D transformation.
602 * This method does not check whether estimator is locked or not.
603 *
604 * @param inputPoints list of input points to be used to estimate an
605 * affine 2D transformation.
606 * @param outputPoints list of output points to be used to estimate an
607 * affine 2D transformation.
608 * @throws IllegalArgumentException if provided lists of points don't have
609 * the same size or their size is smaller than MINIMUM_SIZE.
610 */
611 private void internalSetPoints(final List<Point2D> inputPoints, final List<Point2D> outputPoints) {
612 if (inputPoints.size() < MINIMUM_SIZE) {
613 throw new IllegalArgumentException();
614 }
615 if (inputPoints.size() != outputPoints.size()) {
616 throw new IllegalArgumentException();
617 }
618 this.inputPoints = inputPoints;
619 this.outputPoints = outputPoints;
620 }
621 }