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.Point3D;
19 import com.irurueta.geometry.ProjectiveTransformation3D;
20 import com.irurueta.geometry.refiners.PointCorrespondenceProjectiveTransformation3DRefiner;
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 * 3D transformation for collection of matching 3D 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 PointCorrespondenceProjectiveTransformation3DRobustEstimator
32 extends ProjectiveTransformation3DRobustEstimator {
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 3D 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<Point3D> inputPoints;
47
48 /**
49 * List of points to be used to estimate a projective 3D 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<Point3D> outputPoints;
56
57 /**
58 * Constructor.
59 */
60 protected PointCorrespondenceProjectiveTransformation3DRobustEstimator() {
61 super();
62 }
63
64 /**
65 * Constructor with lists of points to be used to estimate a projective 3D
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 3D transformation.
73 * @param outputPoints list of output points to be used to estimate a
74 * projective 3D 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 PointCorrespondenceProjectiveTransformation3DRobustEstimator(
79 final List<Point3D> inputPoints, final List<Point3D> 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 PointCorrespondenceProjectiveTransformation3DRobustEstimator(
91 final ProjectiveTransformation3DRobustEstimatorListener listener) {
92 super(listener);
93 }
94
95 /**
96 * Constructor with listener and lists of points to be used to estimate a
97 * projective 3D 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 3D transformation.
106 * @param outputPoints list of output points to be used to estimate a
107 * projective 3D 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 PointCorrespondenceProjectiveTransformation3DRobustEstimator(
112 final ProjectiveTransformation3DRobustEstimatorListener listener,
113 final List<Point3D> inputPoints, final List<Point3D> outputPoints) {
114 super(listener);
115 internalSetPoints(inputPoints, outputPoints);
116 }
117
118 /**
119 * Returns list of input points to be used to estimate a projective 3D
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 3D
127 * transformation.
128 */
129 public List<Point3D> getInputPoints() {
130 return inputPoints;
131 }
132
133 /**
134 * Returns list of output points to be used to estimate a projective 3D
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 an affine 2D
142 * transformation.
143 */
144 public List<Point3D> getOutputPoints() {
145 return outputPoints;
146 }
147
148 /**
149 * Sets lists of points to be used to estimate a projective 3D
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 3D transformation.
157 * @param outputPoints list of output points to be used to estimate a
158 * projective 3D 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<Point3D> inputPoints, final List<Point3D> 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 3D 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 3D 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 3D transformation.
219 * @return an instance of projective 3D transformation estimator.
220 */
221 public static PointCorrespondenceProjectiveTransformation3DRobustEstimator create(
222 final RobustEstimatorMethod method) {
223 return switch (method) {
224 case LMEDS -> new LMedSPointCorrespondenceProjectiveTransformation3DRobustEstimator();
225 case MSAC -> new MSACPointCorrespondenceProjectiveTransformation3DRobustEstimator();
226 case PROSAC -> new PROSACPointCorrespondenceProjectiveTransformation3DRobustEstimator();
227 case PROMEDS -> new PROMedSPointCorrespondenceProjectiveTransformation3DRobustEstimator();
228 default -> new RANSACPointCorrespondenceProjectiveTransformation3DRobustEstimator();
229 };
230 }
231
232 /**
233 * Creates a projective 3D transformation estimator based on 3D 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 3D transformation.
238 * @param outputPoints list of output points to be used to estimate a
239 * projective 3D transformation.
240 * @param method method of a robust estimator algorithm to estimate
241 * best projective 3D transformation.
242 * @return an instance of projective 3D 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 PointCorrespondenceProjectiveTransformation3DRobustEstimator create(
247 final List<Point3D> inputPoints, final List<Point3D> outputPoints, final RobustEstimatorMethod method) {
248 return switch (method) {
249 case LMEDS -> new LMedSPointCorrespondenceProjectiveTransformation3DRobustEstimator(
250 inputPoints, outputPoints);
251 case MSAC -> new MSACPointCorrespondenceProjectiveTransformation3DRobustEstimator(
252 inputPoints, outputPoints);
253 case PROSAC -> new PROSACPointCorrespondenceProjectiveTransformation3DRobustEstimator(
254 inputPoints, outputPoints);
255 case PROMEDS -> new PROMedSPointCorrespondenceProjectiveTransformation3DRobustEstimator(
256 inputPoints, outputPoints);
257 default -> new RANSACPointCorrespondenceProjectiveTransformation3DRobustEstimator(
258 inputPoints, outputPoints);
259 };
260 }
261
262 /**
263 * Creates a projective 3D transformation estimator based on 3D 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 3D transformation.
270 * @return an instance of projective 3D transformation estimator.
271 */
272 public static PointCorrespondenceProjectiveTransformation3DRobustEstimator create(
273 final ProjectiveTransformation3DRobustEstimatorListener listener, final RobustEstimatorMethod method) {
274 return switch (method) {
275 case LMEDS -> new LMedSPointCorrespondenceProjectiveTransformation3DRobustEstimator(listener);
276 case MSAC -> new MSACPointCorrespondenceProjectiveTransformation3DRobustEstimator(listener);
277 case PROSAC -> new PROSACPointCorrespondenceProjectiveTransformation3DRobustEstimator(listener);
278 case PROMEDS -> new PROMedSPointCorrespondenceProjectiveTransformation3DRobustEstimator(listener);
279 default -> new RANSACPointCorrespondenceProjectiveTransformation3DRobustEstimator(listener);
280 };
281 }
282
283 /**
284 * Creates a projective 3D transformation estimator based on 3D 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 3D transformation.
291 * @param outputPoints list of output points to be used to estimate a
292 * projective 3D transformation.
293 * @param method method of a robust estimator algorithm to estimate
294 * the best affine 3D transformation.
295 * @return an instance of projective 3D 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 PointCorrespondenceProjectiveTransformation3DRobustEstimator create(
300 final ProjectiveTransformation3DRobustEstimatorListener listener, final List<Point3D> inputPoints,
301 final List<Point3D> outputPoints, final RobustEstimatorMethod method) {
302 return switch (method) {
303 case LMEDS -> new LMedSPointCorrespondenceProjectiveTransformation3DRobustEstimator(
304 listener, inputPoints, outputPoints);
305 case MSAC -> new MSACPointCorrespondenceProjectiveTransformation3DRobustEstimator(
306 listener, inputPoints, outputPoints);
307 case PROSAC -> new PROSACPointCorrespondenceProjectiveTransformation3DRobustEstimator(
308 listener, inputPoints, outputPoints);
309 case PROMEDS -> new PROMedSPointCorrespondenceProjectiveTransformation3DRobustEstimator(
310 listener, inputPoints, outputPoints);
311 default -> new RANSACPointCorrespondenceProjectiveTransformation3DRobustEstimator(
312 listener, inputPoints, outputPoints);
313 };
314 }
315
316 /**
317 * Creates a projective 3D transformation estimator based on 3D 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 * best projective 3D transformation.
324 * @return an instance of affine 3D transformation estimator.
325 */
326 public static PointCorrespondenceProjectiveTransformation3DRobustEstimator create(
327 final double[] qualityScores, final RobustEstimatorMethod method) {
328 return switch (method) {
329 case LMEDS -> new LMedSPointCorrespondenceProjectiveTransformation3DRobustEstimator();
330 case MSAC -> new MSACPointCorrespondenceProjectiveTransformation3DRobustEstimator();
331 case PROSAC -> new PROSACPointCorrespondenceProjectiveTransformation3DRobustEstimator(qualityScores);
332 case PROMEDS -> new PROMedSPointCorrespondenceProjectiveTransformation3DRobustEstimator(qualityScores);
333 default -> new RANSACPointCorrespondenceProjectiveTransformation3DRobustEstimator();
334 };
335 }
336
337 /**
338 * Creates a projective 3D transformation estimator based on 3D point
339 * correspondences and using provided robust estimator method.
340 *
341 * @param inputPoints list of input points to be used to estimate a
342 * projective 3D transformation.
343 * @param outputPoints list of output points to be used to estimate a
344 * projective 3D transformation.
345 * @param qualityScores quality scores corresponding to each pair of matched
346 * points.
347 * @param method method of a robust estimator algorithm to estimate
348 * best projective 3D transformation.
349 * @return an instance of projective 3D transformation estimator.
350 * @throws IllegalArgumentException if provided lists of points don't have
351 * the same size or their size is smaller than MINIMUM_SIZE.
352 */
353 public static PointCorrespondenceProjectiveTransformation3DRobustEstimator create(
354 final List<Point3D> inputPoints, final List<Point3D> outputPoints, final double[] qualityScores,
355 final RobustEstimatorMethod method) {
356 return switch (method) {
357 case LMEDS -> new LMedSPointCorrespondenceProjectiveTransformation3DRobustEstimator(
358 inputPoints, outputPoints);
359 case MSAC -> new MSACPointCorrespondenceProjectiveTransformation3DRobustEstimator(
360 inputPoints, outputPoints);
361 case PROSAC -> new PROSACPointCorrespondenceProjectiveTransformation3DRobustEstimator(
362 inputPoints, outputPoints, qualityScores);
363 case PROMEDS -> new PROMedSPointCorrespondenceProjectiveTransformation3DRobustEstimator(
364 inputPoints, outputPoints, qualityScores);
365 default -> new RANSACPointCorrespondenceProjectiveTransformation3DRobustEstimator(
366 inputPoints, outputPoints);
367 };
368 }
369
370 /**
371 * Creates a projective 3D transformation estimator based on 3D point
372 * correspondences and using provided robust estimator method.
373 *
374 * @param listener listener to be notified of events such as when estimation
375 * starts, ends or its progress significantly changes.
376 * @param qualityScores quality scores corresponding to each pair of matched
377 * points.
378 * @param method method of a robust estimator algorithm to estimate
379 * best projective 3D transformation.
380 * @return an instance of projective 3D transformation estimator.
381 */
382 public static PointCorrespondenceProjectiveTransformation3DRobustEstimator create(
383 final ProjectiveTransformation3DRobustEstimatorListener listener, final double[] qualityScores,
384 final RobustEstimatorMethod method) {
385 return switch (method) {
386 case LMEDS -> new LMedSPointCorrespondenceProjectiveTransformation3DRobustEstimator(listener);
387 case MSAC -> new MSACPointCorrespondenceProjectiveTransformation3DRobustEstimator(listener);
388 case PROSAC -> new PROSACPointCorrespondenceProjectiveTransformation3DRobustEstimator(
389 listener, qualityScores);
390 case PROMEDS -> new PROMedSPointCorrespondenceProjectiveTransformation3DRobustEstimator(
391 listener, qualityScores);
392 default -> new RANSACPointCorrespondenceProjectiveTransformation3DRobustEstimator(listener);
393 };
394 }
395
396 /**
397 * Creates a projective 3D transformation estimator based on 3D point
398 * correspondences and using provided robust estimator method.
399 *
400 * @param listener listener to be notified of events such as when estimation
401 * starts, ends or its progress significantly changes.
402 * @param inputPoints list of input points to be used to estimate a
403 * projective 3D transformation.
404 * @param outputPoints list of output points to be used to estimate a
405 * projective 3D transformation.
406 * @param qualityScores quality scores corresponding to each pair of matched
407 * points.
408 * @param method method of a robust estimator algorithm to estimate
409 * best projective 3D transformation.
410 * @return an instance of projective 3D transformation estimator.
411 * @throws IllegalArgumentException if provided lists of points don't have
412 * the same size or their size is smaller than MINIMUM_SIZE.
413 */
414 public static PointCorrespondenceProjectiveTransformation3DRobustEstimator create(
415 final ProjectiveTransformation3DRobustEstimatorListener listener, final List<Point3D> inputPoints,
416 final List<Point3D> outputPoints, final double[] qualityScores, final RobustEstimatorMethod method) {
417 return switch (method) {
418 case LMEDS -> new LMedSPointCorrespondenceProjectiveTransformation3DRobustEstimator(
419 listener, inputPoints, outputPoints);
420 case MSAC -> new MSACPointCorrespondenceProjectiveTransformation3DRobustEstimator(
421 listener, inputPoints, outputPoints);
422 case PROSAC -> new PROSACPointCorrespondenceProjectiveTransformation3DRobustEstimator(
423 listener, inputPoints, outputPoints, qualityScores);
424 case PROMEDS -> new PROMedSPointCorrespondenceProjectiveTransformation3DRobustEstimator(
425 listener, inputPoints, outputPoints, qualityScores);
426 default -> new RANSACPointCorrespondenceProjectiveTransformation3DRobustEstimator(
427 listener, inputPoints, outputPoints);
428 };
429 }
430
431 /**
432 * Creates a projective 3D transformation estimator based on 3D point
433 * correspondences and using default robust estimator method.
434 *
435 * @return an instance of projective 3D transformation estimator.
436 */
437 public static PointCorrespondenceProjectiveTransformation3DRobustEstimator create() {
438 return create(DEFAULT_ROBUST_METHOD);
439 }
440
441 /**
442 * Creates a projective 3D transformation estimator based on 3D point
443 * correspondences and using default robust estimator method.
444 *
445 * @param inputPoints list of input points to be used to estimate a
446 * projective 3D transformation.
447 * @param outputPoints list of output points to be used to estimate a
448 * projective 3D transformation.
449 * @return an instance of projective 3D transformation estimator.
450 * @throws IllegalArgumentException if provided lists of points don't have
451 * the same size or their size is smaller than MINIMUM_SIZE.
452 */
453 public static PointCorrespondenceProjectiveTransformation3DRobustEstimator create(
454 final List<Point3D> inputPoints, final List<Point3D> outputPoints) {
455 return create(inputPoints, outputPoints, DEFAULT_ROBUST_METHOD);
456 }
457
458 /**
459 * Creates a projective 3D transformation estimator based on 3D point
460 * correspondences and using default robust estimator method.
461 *
462 * @param listener listener to be notified of events such as when estimation
463 * starts, ends or its progress significantly changes.
464 * @return an instance of projective 3D transformation estimator.
465 */
466 public static PointCorrespondenceProjectiveTransformation3DRobustEstimator create(
467 final ProjectiveTransformation3DRobustEstimatorListener listener) {
468 return create(listener, DEFAULT_ROBUST_METHOD);
469 }
470
471 /**
472 * Creates a projective 3D transformation estimator based on 3D point
473 * correspondences and using default robust estimator method.
474 *
475 * @param listener listener to be notified of events such as when estimation
476 * starts, ends or its progress significantly changes.
477 * @param inputPoints list of input points to be used to estimate a
478 * projective 3D transformation.
479 * @param outputPoints list of output points to be used to estimate a
480 * projective 3D transformation.
481 * @return an instance of projective 3D transformation estimator.
482 * @throws IllegalArgumentException if provided lists of points don't have
483 * the same size or their size is smaller than MINIMUM_SIZE.
484 */
485 public static PointCorrespondenceProjectiveTransformation3DRobustEstimator create(
486 final ProjectiveTransformation3DRobustEstimatorListener listener,
487 final List<Point3D> inputPoints, final List<Point3D> outputPoints) {
488 return create(listener, inputPoints, outputPoints, DEFAULT_ROBUST_METHOD);
489 }
490
491 /**
492 * Creates a projective 3D transformation estimator based on 3D point
493 * correspondences and using default robust estimator method.
494 *
495 * @param qualityScores quality scores corresponding to each pair of matched
496 * points.
497 * @return an instance of projective 3D transformation estimator.
498 */
499 public static PointCorrespondenceProjectiveTransformation3DRobustEstimator create(final double[] qualityScores) {
500 return create(qualityScores, DEFAULT_ROBUST_METHOD);
501 }
502
503 /**
504 * Creates a projective 3D transformation estimator based on 3D point
505 * correspondences and using default robust estimator method.
506 *
507 * @param inputPoints list of input points to be used to estimate a
508 * projective 3D transformation.
509 * @param outputPoints list of output points to be used to estimate a
510 * projective 3D transformation.
511 * @param qualityScores quality scores corresponding to each pair of matched
512 * points.
513 * @return an instance of projective 3D transformation estimator.
514 * @throws IllegalArgumentException if provided lists of points don't have
515 * the same size or their size is smaller than MINIMUM_SIZE.
516 */
517 public static PointCorrespondenceProjectiveTransformation3DRobustEstimator create(
518 final List<Point3D> inputPoints, final List<Point3D> outputPoints, final double[] qualityScores) {
519 return create(inputPoints, outputPoints, qualityScores, DEFAULT_ROBUST_METHOD);
520 }
521
522 /**
523 * Creates a projective 3D transformation estimator based on 3D point
524 * correspondences and using default robust estimator method.
525 *
526 * @param listener listener to be notified of events such as when estimation
527 * starts, ends or its progress significantly changes.
528 * @param qualityScores quality scores corresponding to each pair of matched
529 * points.
530 * @return an instance of projective 3D transformation estimator.
531 */
532 public static PointCorrespondenceProjectiveTransformation3DRobustEstimator create(
533 final ProjectiveTransformation3DRobustEstimatorListener listener, final double[] qualityScores) {
534 return create(listener, qualityScores, DEFAULT_ROBUST_METHOD);
535 }
536
537 /**
538 * Creates a projective 3D transformation estimator based on 3D point
539 * correspondences and using default robust estimator method.
540 *
541 * @param listener listener to be notified of events such as when estimation
542 * starts, ends or its progress significantly changes.
543 * @param inputPoints list of input points to be used to estimate a
544 * projective 3D transformation.
545 * @param outputPoints list of output points to be used to estimate a
546 * projective 3D transformation.
547 * @param qualityScores quality scores corresponding to each pair of matched
548 * points.
549 * @return an instance of projective 3D transformation estimator.
550 * @throws IllegalArgumentException if provided lists of points don't have
551 * the same size or their size is smaller than MINIMUM_SIZE.
552 */
553 public static PointCorrespondenceProjectiveTransformation3DRobustEstimator create(
554 final ProjectiveTransformation3DRobustEstimatorListener listener,
555 final List<Point3D> inputPoints, final List<Point3D> outputPoints, final double[] qualityScores) {
556 return create(listener, inputPoints, outputPoints, qualityScores, DEFAULT_ROBUST_METHOD);
557 }
558
559 /**
560 * Attempts to refine provided solution if refinement is requested.
561 * This method returns a refined solution of the same provided solution
562 * if refinement is not requested or has failed.
563 * If refinement is enabled, and it is requested to keep covariance, this
564 * method will also keep covariance of refined transformation.
565 *
566 * @param transformation transformation estimated by a robust estimator
567 * without refinement.
568 * @return solution after refinement (if requested) or the provided
569 * non-refined solution if not requested or refinement failed.
570 */
571 @SuppressWarnings("DuplicatedCode")
572 protected ProjectiveTransformation3D attemptRefine(final ProjectiveTransformation3D transformation) {
573 if (refineResult) {
574 final var refiner = new PointCorrespondenceProjectiveTransformation3DRefiner(transformation, keepCovariance,
575 getInliersData(), inputPoints, outputPoints, getRefinementStandardDeviation());
576
577 try {
578 final var result = new ProjectiveTransformation3D();
579 final var improved = refiner.refine(result);
580
581 if (keepCovariance) {
582 // keep covariance
583 covariance = refiner.getCovariance();
584 }
585
586 return improved ? result : transformation;
587 } catch (final Exception e) {
588 // refinement failed, so we return input value
589 return transformation;
590 }
591 } else {
592 return transformation;
593 }
594 }
595
596 /**
597 * Internal method to set lists of points to be used to estimate a
598 * projective 3D transformation.
599 * This method does not check whether estimator is locked or not.
600 *
601 * @param inputPoints list of input points to be used to estimate a
602 * projective 3D transformation.
603 * @param outputPoints list of output points to be used to estimate a
604 * projective 3D transformation.
605 * @throws IllegalArgumentException if provided lists of points don't have
606 * the same size or their size is smaller than MINIMUM_SIZE.
607 */
608 private void internalSetPoints(final List<Point3D> inputPoints, final List<Point3D> outputPoints) {
609 if (inputPoints.size() < MINIMUM_SIZE) {
610 throw new IllegalArgumentException();
611 }
612 if (inputPoints.size() != outputPoints.size()) {
613 throw new IllegalArgumentException();
614 }
615 this.inputPoints = inputPoints;
616 this.outputPoints = outputPoints;
617 }
618 }