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.Plane;
19 import com.irurueta.geometry.ProjectiveTransformation3D;
20 import com.irurueta.geometry.refiners.PlaneCorrespondenceProjectiveTransformation3DRefiner;
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 collections of matching planes.
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 PlaneCorrespondenceProjectiveTransformation3DRobustEstimator
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 planes to be used to estimate a projective 3D transformation.
41 * Each line in the list of input lines must be matched with the
42 * corresponding line in the list of output lines located at the same
43 * position. Hence, both input lines and output lines must have the
44 * same size, and their size must be greater or equal than MINIMUM_SIZE.
45 */
46 protected List<Plane> inputPlanes;
47
48 /**
49 * List of planes to be used to estimate a projective 3D transformation.
50 * Each point in the list of output lines must be matched with the
51 * corresponding line in the list of input lines located at the same
52 * position. Hence, both input lines and output lines must have the
53 * same size, and their size must be greater or equal than MINIMUM_SIZE.
54 */
55 protected List<Plane> outputPlanes;
56
57 /**
58 * Constructor.
59 */
60 protected PlaneCorrespondenceProjectiveTransformation3DRobustEstimator() {
61 super();
62 }
63
64 /**
65 * Constructor with lists of planes to be used to estimate a projective 3D
66 * transformation.
67 * Planes 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 inputPlanes list of input planes to be used to estimate a
72 * projective 3D transformation.
73 * @param outputPlanes list of output planes ot be used to estimate a
74 * projective 3D transformation.
75 * @throws IllegalArgumentException if provided lists of planes don't have
76 * the same size or their size is smaller than MINIMUM_SIZE.
77 */
78 protected PlaneCorrespondenceProjectiveTransformation3DRobustEstimator(
79 final List<Plane> inputPlanes, final List<Plane> outputPlanes) {
80 super();
81 internalSetPlanes(inputPlanes, outputPlanes);
82 }
83
84 /**
85 * Constructor.
86 *
87 * @param listener listener to be notified of events such as when estimation
88 * starts, ends or its progress significantly changes.
89 */
90 protected PlaneCorrespondenceProjectiveTransformation3DRobustEstimator(
91 final ProjectiveTransformation3DRobustEstimatorListener listener) {
92 super(listener);
93 }
94
95 /**
96 * Constructor with listener and lists of planes to be used to estimate
97 * projective 3D transformation.
98 * Planes 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 inputPlanes list of input planes to be used to estimate a
105 * projective 3D transformation.
106 * @param outputPlanes list of output planes to be used to estimate a
107 * projective 3D transformation.
108 * @throws IllegalArgumentException if provided lists of planes don't have
109 * the same size or their size is smaller than MINIMUM_SIZE.
110 */
111 protected PlaneCorrespondenceProjectiveTransformation3DRobustEstimator(
112 final ProjectiveTransformation3DRobustEstimatorListener listener,
113 final List<Plane> inputPlanes, final List<Plane> outputPlanes) {
114 super(listener);
115 internalSetPlanes(inputPlanes, outputPlanes);
116 }
117
118 /**
119 * Returns list of input planes to be used to estimate a projective 3D
120 * transformation.
121 * Each plane in the list of input planes must be matched with the
122 * corresponding planes in the list of output planes located at the same
123 * position. Hence, both input planes and output planes must have the same
124 * size, and their size must be greater or equal than MINIMUM_SIZE
125 *
126 * @return list of input planes to be used to estimate an affine 3D
127 * transformation.
128 */
129 public List<Plane> getInputPlanes() {
130 return inputPlanes;
131 }
132
133 /**
134 * Returns list of output planes to be used to estimate a projective 3D
135 * transformation.
136 * Each plane in the list of output planes must be matched with the
137 * corresponding plane in the list of input planes located at the same
138 * position. Hence, both input planes and output planes must have the same
139 * size, and their size must be greater or equal than MINIMUM_SIZE.
140 *
141 * @return list of output planes to be used to estimate a projective 3D
142 * transformation.
143 */
144 public List<Plane> getOutputPlanes() {
145 return outputPlanes;
146 }
147
148 /**
149 * Sets lists of planes to be used to estimate a projective 3D
150 * transformation.
151 * Planes 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 inputPlanes list of input planes to be used to estimate a
156 * projective 3D transformation.
157 * @param outputPlanes list of output planes to be used to estimate a
158 * projective 3D transformation.
159 * @throws IllegalArgumentException if provided lists of planes 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 protected final void setPlanes(final List<Plane> inputPlanes, final List<Plane> outputPlanes)
165 throws LockedException {
166 if (isLocked()) {
167 throw new LockedException();
168 }
169 internalSetPlanes(inputPlanes, outputPlanes);
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 planes) are provided
176 * and a minimum of MINIMUM_SIZE lines are available.
177 *
178 * @return true if estimator is ready, false otherwise.
179 */
180 public boolean isReady() {
181 return inputPlanes != null && outputPlanes != null && inputPlanes.size() == outputPlanes.size()
182 && inputPlanes.size() >= MINIMUM_SIZE;
183 }
184
185 /**
186 * Returns quality scores corresponding to each pair of matched planes.
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 planes.
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 3D plane
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 PlaneCorrespondenceProjectiveTransformation3DRobustEstimator create(
222 final RobustEstimatorMethod method) {
223 return switch (method) {
224 case LMEDS -> new LMedSPlaneCorrespondenceProjectiveTransformation3DRobustEstimator();
225 case MSAC -> new MSACPlaneCorrespondenceProjectiveTransformation3DRobustEstimator();
226 case PROSAC -> new PROSACPlaneCorrespondenceProjectiveTransformation3DRobustEstimator();
227 case PROMEDS -> new PROMedSPlaneCorrespondenceProjectiveTransformation3DRobustEstimator();
228 default -> new RANSACPlaneCorrespondenceProjectiveTransformation3DRobustEstimator();
229 };
230 }
231
232 /**
233 * Creates a projective 3D transformation estimator based on 3D plane
234 * correspondences and using provided robust estimator method.
235 *
236 * @param inputPlanes list of input planes to be used to estimate a
237 * projective 3D transformation.
238 * @param outputPlanes list of output planes 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 lines don't have
244 * the same size or their size is smaller than MINIMUM_SIZE.
245 */
246 public static PlaneCorrespondenceProjectiveTransformation3DRobustEstimator create(
247 final List<Plane> inputPlanes, final List<Plane> outputPlanes, final RobustEstimatorMethod method) {
248 return switch (method) {
249 case LMEDS -> new LMedSPlaneCorrespondenceProjectiveTransformation3DRobustEstimator(
250 inputPlanes, outputPlanes);
251 case MSAC -> new MSACPlaneCorrespondenceProjectiveTransformation3DRobustEstimator(
252 inputPlanes, outputPlanes);
253 case PROSAC -> new PROSACPlaneCorrespondenceProjectiveTransformation3DRobustEstimator(
254 inputPlanes, outputPlanes);
255 case PROMEDS -> new PROMedSPlaneCorrespondenceProjectiveTransformation3DRobustEstimator(
256 inputPlanes, outputPlanes);
257 default -> new RANSACPlaneCorrespondenceProjectiveTransformation3DRobustEstimator(
258 inputPlanes, outputPlanes);
259 };
260 }
261
262 /**
263 * Creates a projective 3D transformation estimator based on 3D plane
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 best
269 * projective 3D transformation.
270 * @return an instance of projective 3D transformation estimator.
271 */
272 public static PlaneCorrespondenceProjectiveTransformation3DRobustEstimator create(
273 final ProjectiveTransformation3DRobustEstimatorListener listener, final RobustEstimatorMethod method) {
274 return switch (method) {
275 case LMEDS -> new LMedSPlaneCorrespondenceProjectiveTransformation3DRobustEstimator(listener);
276 case MSAC -> new MSACPlaneCorrespondenceProjectiveTransformation3DRobustEstimator(listener);
277 case PROSAC -> new PROSACPlaneCorrespondenceProjectiveTransformation3DRobustEstimator(listener);
278 case PROMEDS -> new PROMedSPlaneCorrespondenceProjectiveTransformation3DRobustEstimator(listener);
279 default -> new RANSACPlaneCorrespondenceProjectiveTransformation3DRobustEstimator(listener);
280 };
281 }
282
283 /**
284 * Creates a projective 3D transformation estimator based on 3D line
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 inputPlanes list of input lines to be used to estimate a
290 * projective 3D transformation.
291 * @param outputPlanes list of output lines to be used to estimate a
292 * projective 3D transformation.
293 * @param method method of a robust estimator algorithm to estimate best
294 * projective 3D transformation.
295 * @return an instance of projective 3D transformation estimator.
296 * @throws IllegalArgumentException if provided lists of lines don't have
297 * the same size or their size is smaller than MINIMUM_SIZE.
298 */
299 public static PlaneCorrespondenceProjectiveTransformation3DRobustEstimator create(
300 final ProjectiveTransformation3DRobustEstimatorListener listener,
301 final List<Plane> inputPlanes, List<Plane> outputPlanes, final RobustEstimatorMethod method) {
302 return switch (method) {
303 case LMEDS -> new LMedSPlaneCorrespondenceProjectiveTransformation3DRobustEstimator(
304 listener, inputPlanes, outputPlanes);
305 case MSAC -> new MSACPlaneCorrespondenceProjectiveTransformation3DRobustEstimator(
306 listener, inputPlanes, outputPlanes);
307 case PROSAC -> new PROSACPlaneCorrespondenceProjectiveTransformation3DRobustEstimator(
308 listener, inputPlanes, outputPlanes);
309 case PROMEDS -> new PROMedSPlaneCorrespondenceProjectiveTransformation3DRobustEstimator(
310 listener, inputPlanes, outputPlanes);
311 default -> new RANSACPlaneCorrespondenceProjectiveTransformation3DRobustEstimator(
312 listener, inputPlanes, outputPlanes);
313 };
314 }
315
316 /**
317 * Creates a projective 3D transformation estimator based on 3D plane
318 * correspondences and using provided robust estimator method.
319 *
320 * @param qualityScores quality scores corresponding to each pair of matched
321 * planes.
322 * @param method method of a robust estimator algorithm to estimate best
323 * projective 3D transformation.
324 * @return an instance of projective 3D transformation estimator.
325 */
326 public static PlaneCorrespondenceProjectiveTransformation3DRobustEstimator create(
327 final double[] qualityScores, final RobustEstimatorMethod method) {
328 return switch (method) {
329 case LMEDS -> new LMedSPlaneCorrespondenceProjectiveTransformation3DRobustEstimator();
330 case MSAC -> new MSACPlaneCorrespondenceProjectiveTransformation3DRobustEstimator();
331 case PROSAC -> new PROSACPlaneCorrespondenceProjectiveTransformation3DRobustEstimator(qualityScores);
332 case PROMEDS -> new PROMedSPlaneCorrespondenceProjectiveTransformation3DRobustEstimator(qualityScores);
333 default -> new RANSACPlaneCorrespondenceProjectiveTransformation3DRobustEstimator();
334 };
335 }
336
337 /**
338 * Creates a projective 3D transformation estimator based on plane
339 * correspondences and using provided robust estimator method.
340 *
341 * @param inputPlanes list of input planes to be used to estimate a
342 * projective 3D transformation.
343 * @param outputPlanes list of output planes to be used to estimate a
344 * projective 3D transformation.
345 * @param qualityScores quality scores corresponding to each pair of matched
346 * planes.
347 * @param method method of a robust estimator algorithm to estimate best
348 * projective 3D transformation.
349 * @return an instance of projective 3D transformation estimator.
350 * @throws IllegalArgumentException if provided lists of lines don't have
351 * the same size or their size is smaller than MINIMUM_SIZE.
352 */
353 public static PlaneCorrespondenceProjectiveTransformation3DRobustEstimator create(
354 final List<Plane> inputPlanes, final List<Plane> outputPlanes, final double[] qualityScores,
355 final RobustEstimatorMethod method) {
356 return switch (method) {
357 case LMEDS -> new LMedSPlaneCorrespondenceProjectiveTransformation3DRobustEstimator(
358 inputPlanes, outputPlanes);
359 case MSAC -> new MSACPlaneCorrespondenceProjectiveTransformation3DRobustEstimator(
360 inputPlanes, outputPlanes);
361 case PROSAC -> new PROSACPlaneCorrespondenceProjectiveTransformation3DRobustEstimator(
362 inputPlanes, outputPlanes, qualityScores);
363 case PROMEDS -> new PROMedSPlaneCorrespondenceProjectiveTransformation3DRobustEstimator(
364 inputPlanes, outputPlanes, qualityScores);
365 default -> new RANSACPlaneCorrespondenceProjectiveTransformation3DRobustEstimator(
366 inputPlanes, outputPlanes);
367 };
368 }
369
370 /**
371 * Creates a projective 3D transformation estimator based on plane
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 * lines.
378 * @param method method of a robust estimator algorithm to estimate best
379 * projective 3D transformation.
380 * @return an instance of projective 3D transformation estimator.
381 */
382 public static PlaneCorrespondenceProjectiveTransformation3DRobustEstimator create(
383 final ProjectiveTransformation3DRobustEstimatorListener listener, final double[] qualityScores,
384 final RobustEstimatorMethod method) {
385 return switch (method) {
386 case LMEDS -> new LMedSPlaneCorrespondenceProjectiveTransformation3DRobustEstimator(listener);
387 case MSAC -> new MSACPlaneCorrespondenceProjectiveTransformation3DRobustEstimator(listener);
388 case PROSAC -> new PROSACPlaneCorrespondenceProjectiveTransformation3DRobustEstimator(
389 listener, qualityScores);
390 case PROMEDS -> new PROMedSPlaneCorrespondenceProjectiveTransformation3DRobustEstimator(
391 listener, qualityScores);
392 default -> new RANSACPlaneCorrespondenceProjectiveTransformation3DRobustEstimator(listener);
393 };
394 }
395
396 /**
397 * Creates a projective 3D transformation estimator based on plane
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 inputPlanes list of input planes to be used to estimate a
403 * projective 3D transformation.
404 * @param outputPlanes list of output planes to be used to estimate a
405 * projective 3D transformation.
406 * @param qualityScores quality scores corresponding to each pair of matched
407 * planes.
408 * @param method method of a robust estimator algorithm to estimate best
409 * projective 3D transformation.
410 * @return an instance of projective 3D transformation estimator.
411 * @throws IllegalArgumentException if provided lists of lines don't have
412 * the same size or their size is smaller than MINIMUM_SIZE.
413 */
414 public static PlaneCorrespondenceProjectiveTransformation3DRobustEstimator create(
415 final ProjectiveTransformation3DRobustEstimatorListener listener,
416 final List<Plane> inputPlanes, final List<Plane> outputPlanes, final double[] qualityScores,
417 final RobustEstimatorMethod method) {
418 return switch (method) {
419 case LMEDS -> new LMedSPlaneCorrespondenceProjectiveTransformation3DRobustEstimator(
420 listener, inputPlanes, outputPlanes);
421 case MSAC -> new MSACPlaneCorrespondenceProjectiveTransformation3DRobustEstimator(
422 listener, inputPlanes, outputPlanes);
423 case PROSAC -> new PROSACPlaneCorrespondenceProjectiveTransformation3DRobustEstimator(
424 listener, inputPlanes, outputPlanes, qualityScores);
425 case PROMEDS -> new PROMedSPlaneCorrespondenceProjectiveTransformation3DRobustEstimator(
426 listener, inputPlanes, outputPlanes, qualityScores);
427 default -> new RANSACPlaneCorrespondenceProjectiveTransformation3DRobustEstimator(
428 listener, inputPlanes, outputPlanes);
429 };
430 }
431
432 /**
433 * Creates a projective 3D transformation estimator based on plane
434 * correspondences and using default robust estimator method.
435 *
436 * @return an instance of projective 3D transformation estimator.
437 */
438 public static PlaneCorrespondenceProjectiveTransformation3DRobustEstimator create() {
439 return create(DEFAULT_ROBUST_METHOD);
440 }
441
442 /**
443 * Creates a projective 3D transformation estimator based on plane
444 * correspondences and using default robust estimator method.
445 *
446 * @param inputPlanes list of input planes to be used to estimate a
447 * projective 3D transformation.
448 * @param outputPlanes list of output planes to be used to estimate a
449 * projective 3D transformation.
450 * @return an instance of projective 3D transformation estimator.
451 * @throws IllegalArgumentException if provided lists of planes don't have
452 * the same size or their size is smaller than MINIMUM_SIZE.
453 */
454 public static PlaneCorrespondenceProjectiveTransformation3DRobustEstimator create(
455 final List<Plane> inputPlanes, final List<Plane> outputPlanes) {
456 return create(inputPlanes, outputPlanes, DEFAULT_ROBUST_METHOD);
457 }
458
459 /**
460 * Creates a projective 3D transformation estimator based on plane
461 * correspondences and using default robust estimator method.
462 *
463 * @param listener listener to be notified of events such as when estimation
464 * starts, ends or its progress significantly changes.
465 * @return an instance of projective 3D transformation estimator.
466 */
467 public static PlaneCorrespondenceProjectiveTransformation3DRobustEstimator create(
468 final ProjectiveTransformation3DRobustEstimatorListener listener) {
469 return create(listener, DEFAULT_ROBUST_METHOD);
470 }
471
472 /**
473 * Creates a projective 3D transformation estimator based on plane
474 * correspondences and using default robust estimator method.
475 *
476 * @param listener listener to be notified of events such as when estimation
477 * starts, ends or its progress significantly changes.
478 * @param inputPlanes list of input planes to be used to estimate a
479 * projective 3D transformation.
480 * @param outputPlanes list of output planes to be used to estimate a
481 * projective 3D transformation.
482 * @return an instance of projective 3D transformation estimator.
483 * @throws IllegalArgumentException if provided lists of lines don't have
484 * the same size or their size is smaller than MINIMUM_SIZE.
485 */
486 public static PlaneCorrespondenceProjectiveTransformation3DRobustEstimator create(
487 final ProjectiveTransformation3DRobustEstimatorListener listener,
488 final List<Plane> inputPlanes, final List<Plane> outputPlanes) {
489 return create(listener, inputPlanes, outputPlanes, DEFAULT_ROBUST_METHOD);
490 }
491
492 /**
493 * Creates a projective 3D transformation estimator based on plane
494 * correspondences and using default robust estimator method.
495 *
496 * @param qualityScores quality scores corresponding to each pair of matched
497 * planes.
498 * @return an instance of projective 3D transformation estimator.
499 */
500 public static PlaneCorrespondenceProjectiveTransformation3DRobustEstimator create(final double[] qualityScores) {
501 return create(qualityScores, DEFAULT_ROBUST_METHOD);
502 }
503
504 /**
505 * Creates a projective 3D transformation estimator based on 3D line
506 * correspondences and using default robust estimator method.
507 *
508 * @param inputPlanes list of input planes to be used to estimate a
509 * projective 3D transformation.
510 * @param outputPlanes list of output planes to be used to estimate a
511 * projective 3D transformation.
512 * @param qualityScores quality scores corresponding to each pair of matched
513 * planes.
514 * @return an instance of projective 3D transformation estimator.
515 * @throws IllegalArgumentException if provided lists of lines don't have
516 * the same size or their size is smaller than MINIMUM_SIZE.
517 */
518 public static PlaneCorrespondenceProjectiveTransformation3DRobustEstimator create(
519 final List<Plane> inputPlanes, final List<Plane> outputPlanes, final double[] qualityScores) {
520 return create(inputPlanes, outputPlanes, qualityScores, DEFAULT_ROBUST_METHOD);
521 }
522
523 /**
524 * Creates a projective 3D transformation estimator based on 3D line
525 * correspondences and using default robust estimator method.
526 *
527 * @param listener listener to be notified of events such as when estimation
528 * starts, ends or its progress significantly changes.
529 * @param qualityScores quality scores corresponding to each pair of matched
530 * points.
531 * @return an instance of projective 3D transformation estimator.
532 */
533 public static PlaneCorrespondenceProjectiveTransformation3DRobustEstimator create(
534 final ProjectiveTransformation3DRobustEstimatorListener listener, final double[] qualityScores) {
535 return create(listener, qualityScores, DEFAULT_ROBUST_METHOD);
536 }
537
538 /**
539 * Creates a projective 3D transformation estimator based on plane
540 * correspondences and using default robust estimator method.
541 *
542 * @param listener listener to be notified of events such as when estimation
543 * starts, ends or its progress significantly changes.
544 * @param inputPlanes list of input planes to be used to estimate a
545 * projective 3D transformation.
546 * @param outputPlanes list of output planes to be used to estimate a
547 * projective 3D transformation.
548 * @param qualityScores quality scores corresponding to each pair of matched
549 * lines.
550 * @return an instance of projective 3D transformation estimator.
551 * @throws IllegalArgumentException if provided lists of lines don't have
552 * the same size or their size is smaller than MINIMUM_SIZE.
553 */
554 public static PlaneCorrespondenceProjectiveTransformation3DRobustEstimator create(
555 final ProjectiveTransformation3DRobustEstimatorListener listener,
556 final List<Plane> inputPlanes, final List<Plane> outputPlanes, final double[] qualityScores) {
557 return create(listener, inputPlanes, outputPlanes, qualityScores, DEFAULT_ROBUST_METHOD);
558 }
559
560 /**
561 * Internal method to set lists of planes to be used to estimate a
562 * projective 3D transformation.
563 * This method does not check whether estimator is locked or not
564 *
565 * @param inputPlanes list of input planes to be used to estimate a
566 * projective 3D transformation.
567 * @param outputPlanes list of output planes to be used to estimate a
568 * projective 3D transformation.
569 * @throws IllegalArgumentException if provided lists of lines don't have
570 * the same size or their size is smaller than MINIMUM_SIZE.
571 */
572 private void internalSetPlanes(final List<Plane> inputPlanes, final List<Plane> outputPlanes) {
573 if (inputPlanes.size() < MINIMUM_SIZE) {
574 throw new IllegalArgumentException();
575 }
576 if (inputPlanes.size() != outputPlanes.size()) {
577 throw new IllegalArgumentException();
578 }
579 this.inputPlanes = inputPlanes;
580 this.outputPlanes = outputPlanes;
581 }
582
583 /**
584 * Computes residual by comparing two lines algebraically by doing the
585 * dot product of their parameters.
586 * A residual of 0 indicates that dot product was 1 or -1 and lines were
587 * equal.
588 * A residual of 1 indicates that dot product was 0 and lines were
589 * orthogonal.
590 * If dot product was -1, then although their director vectors are opposed,
591 * lines are considered equal, since sign changes are not taken into account.
592 *
593 * @param plane originally sampled output plane.
594 * @param transformedPlane estimated output plane obtained after using
595 * estimated transformation.
596 * @return computed residual.
597 */
598 @SuppressWarnings("DuplicatedCode")
599 protected static double getResidual(final Plane plane, final Plane transformedPlane) {
600 return PlaneCorrespondenceAffineTransformation3DRobustEstimator.getResidual(plane, transformedPlane);
601 }
602
603 /**
604 * Attempts to refine provided solution if refinement is requested.
605 * This method returns a refined solution of the same provided solution
606 * if refinement is not requested or has failed.
607 * If refinement is enabled, and it is requested to keep covariance, this
608 * method will also keep covariance of refined transformation.
609 *
610 * @param transformation transformation estimated by a robust estimator
611 * without refinement.
612 * @return solution after refinement (if requested) or the provided
613 * non-refined solution if not requested or refinement failed.
614 */
615 @SuppressWarnings("DuplicatedCode")
616 protected ProjectiveTransformation3D attemptRefine(final ProjectiveTransformation3D transformation) {
617 if (refineResult) {
618 final var refiner = new PlaneCorrespondenceProjectiveTransformation3DRefiner(transformation,
619 keepCovariance, getInliersData(), inputPlanes, outputPlanes, getRefinementStandardDeviation());
620
621 try {
622 final var result = new ProjectiveTransformation3D();
623 final var improved = refiner.refine(result);
624
625 if (keepCovariance) {
626 // keep covariance
627 covariance = refiner.getCovariance();
628 }
629
630 return improved ? result : transformation;
631 } catch (final Exception e) {
632 // refinement failed, so we return input value
633 return transformation;
634 }
635 } else {
636 return transformation;
637 }
638 }
639 }