1 /*
2 * Copyright (C) 2017 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.ar.sfm;
17
18 import com.irurueta.ar.calibration.estimators.KruppaDualImageOfAbsoluteConicEstimator;
19 import com.irurueta.ar.epipolar.Corrector;
20 import com.irurueta.ar.epipolar.CorrectorType;
21 import com.irurueta.ar.epipolar.FundamentalMatrix;
22 import com.irurueta.geometry.PinholeCamera;
23 import com.irurueta.geometry.Point2D;
24 import com.irurueta.geometry.Point3D;
25 import com.irurueta.geometry.estimators.LockedException;
26 import com.irurueta.geometry.estimators.NotReadyException;
27
28 import java.util.ArrayList;
29 import java.util.BitSet;
30 import java.util.List;
31
32 /**
33 * Estimates an initial pair of cameras in the metric stratum (up to an
34 * arbitrary scale) using a given fundamental matrix to obtain the Dual Image
35 * of Absolute Conic by solving Kruppa equations to obtain the Essential matrix,
36 * so that once it is computed it can be used to determine best pair of camera
37 * poses and translations by triangulating a set of matched points and checking
38 * that their triangulation lies in front of cameras.
39 */
40 public class DualImageOfAbsoluteConicInitialCamerasEstimator extends InitialCamerasEstimator {
41
42 /**
43 * Indicates whether matched 2D points must be triangulated by default.
44 */
45 public static final boolean DEFAULT_TRIANGULATE_POINTS = false;
46
47 /**
48 * Indicates whether triangulated points must be marked as valid (i.e. when
49 * they lie in front of both of the estimated cameras) or not.
50 */
51 public static final boolean DEFAULT_MARK_VALID_TRIANGULATED_POINTS = false;
52
53 /**
54 * Aspect ratio of intrinsic parameters of cameras.
55 * Typically, this value is 1.0 if vertical coordinates increase upwards,
56 * or -1.0 if it is the opposite.
57 */
58 private double aspectRatio = KruppaDualImageOfAbsoluteConicEstimator.DEFAULT_FOCAL_DISTANCE_ASPECT_RATIO;
59
60 /**
61 * Horizontal coordinate of principal point. This value should be the
62 * coordinates of the center of an image assuming that the coordinates start
63 * on the top-left or bottom-left corner. Using a value close to zero
64 * will produce inaccurate results.
65 */
66 private double principalPointX;
67
68 /**
69 * Vertical coordinate of principal point. This value should be the
70 * coordinates of the center of an image assuming that the coordinates start
71 * on the top-left or bottom-left corner. Using a value close to zero will
72 * produce inaccurate results.
73 */
74 private double principalPointY;
75
76 /**
77 * Matched 2D points on left view.
78 */
79 private List<Point2D> leftPoints;
80
81 /**
82 * Matched 2D points on right view.
83 */
84 private List<Point2D> rightPoints;
85
86 /**
87 * Type of corrector to use to triangulate matched points or null if no
88 * corrector needs to be used.
89 */
90 private CorrectorType correctorType = Corrector.DEFAULT_TYPE;
91
92 /**
93 * Indicates whether matched 2D points need to be triangulated.
94 */
95 private boolean triangulatePoints = DEFAULT_TRIANGULATE_POINTS;
96
97 /**
98 * Marks which of the triangulated points are marked as valid (lie in front
99 * of both of the estimated cameras) and which ones aren't.
100 */
101 private boolean markValidTriangulatedPoints = DEFAULT_MARK_VALID_TRIANGULATED_POINTS;
102
103 /**
104 * Contains triangulated points.
105 */
106 private List<Point3D> triangulatedPoints;
107
108 /**
109 * Contains booleans indicating whether triangulated points are valid (i.e.
110 * lie in front of both estimated cameras) or not.
111 */
112 private BitSet validTriangulatedPoints;
113
114 /**
115 * Constructor.
116 */
117 public DualImageOfAbsoluteConicInitialCamerasEstimator() {
118 super();
119 }
120
121 /**
122 * Constructor.
123 *
124 * @param fundamentalMatrix fundamental matrix relating two views.
125 */
126 public DualImageOfAbsoluteConicInitialCamerasEstimator(final FundamentalMatrix fundamentalMatrix) {
127 super(fundamentalMatrix);
128 }
129
130 /**
131 * Constructor.
132 *
133 * @param leftPoints matched 2D points on left view.
134 * @param rightPoints matched 2D points on right view.
135 * @throws IllegalArgumentException if provided lists don't have the same
136 * size.
137 */
138 public DualImageOfAbsoluteConicInitialCamerasEstimator(
139 final List<Point2D> leftPoints, final List<Point2D> rightPoints) {
140 super();
141 internalSetLeftAndRightPoints(leftPoints, rightPoints);
142 }
143
144 /**
145 * Constructor.
146 *
147 * @param fundamentalMatrix fundamental matrix relating two views.
148 * @param leftPoints matched 2D points on left view.
149 * @param rightPoints matched 2D points on right view.
150 * @throws IllegalArgumentException if provided lists don't have the same
151 * size.
152 */
153 public DualImageOfAbsoluteConicInitialCamerasEstimator(
154 final FundamentalMatrix fundamentalMatrix, final List<Point2D> leftPoints,
155 final List<Point2D> rightPoints) {
156 super(fundamentalMatrix);
157 internalSetLeftAndRightPoints(leftPoints, rightPoints);
158 }
159
160 /**
161 * Constructor.
162 *
163 * @param listener listener to handle events raised by this instance.
164 */
165 public DualImageOfAbsoluteConicInitialCamerasEstimator(final InitialCamerasEstimatorListener listener) {
166 super(listener);
167 }
168
169 /**
170 * Constructor.
171 *
172 * @param fundamentalMatrix fundamental matrix relating two views.
173 * @param listener listener to handle events raised by this instance.
174 */
175 public DualImageOfAbsoluteConicInitialCamerasEstimator(
176 final FundamentalMatrix fundamentalMatrix, final InitialCamerasEstimatorListener listener) {
177 super(fundamentalMatrix, listener);
178 }
179
180 /**
181 * Constructor.
182 *
183 * @param leftPoints matched 2D points on left view.
184 * @param rightPoints matched 2D points on right view.
185 * @param listener listener to handle events raised by this instance.
186 * @throws IllegalArgumentException if provided lists don't have the same
187 * size.
188 */
189 public DualImageOfAbsoluteConicInitialCamerasEstimator(
190 final List<Point2D> leftPoints, final List<Point2D> rightPoints,
191 final InitialCamerasEstimatorListener listener) {
192 super(listener);
193 internalSetLeftAndRightPoints(leftPoints, rightPoints);
194 }
195
196 /**
197 * Constructor.
198 *
199 * @param fundamentalMatrix fundamental matrix relating two views.
200 * @param leftPoints matched 2D points on left view.
201 * @param rightPoints matched 2D points on right view.
202 * @param listener listener to handle events raised by this instance.
203 * @throws IllegalArgumentException if provided lists don't have the same
204 * size.
205 */
206 public DualImageOfAbsoluteConicInitialCamerasEstimator(
207 final FundamentalMatrix fundamentalMatrix,
208 final List<Point2D> leftPoints,
209 final List<Point2D> rightPoints,
210 final InitialCamerasEstimatorListener listener) {
211 super(fundamentalMatrix, listener);
212 internalSetLeftAndRightPoints(leftPoints, rightPoints);
213 }
214
215 /**
216 * Returns method used by this estimator.
217 *
218 * @return method used by this estimator.
219 */
220 @Override
221 public InitialCamerasEstimatorMethod getMethod() {
222 return InitialCamerasEstimatorMethod.DUAL_IMAGE_OF_ABSOLUTE_CONIC;
223 }
224
225 /**
226 * Indicates if estimator is ready.
227 *
228 * @return true if estimator is ready, false otherwise.
229 */
230 @Override
231 public boolean isReady() {
232 return fundamentalMatrix != null && leftPoints != null && rightPoints != null
233 && leftPoints.size() == rightPoints.size();
234 }
235
236 /**
237 * Estimates cameras.
238 *
239 * @throws LockedException if estimator is locked.
240 * @throws NotReadyException if estimator is not ready.
241 * @throws InitialCamerasEstimationFailedException if estimation of cameras
242 * fails for some reason, typically due to numerical
243 * instabilities.
244 */
245 @SuppressWarnings("DuplicatedCode")
246 @Override
247 public void estimate() throws LockedException, NotReadyException, InitialCamerasEstimationFailedException {
248 if (isLocked()) {
249 throw new LockedException();
250 }
251
252 if (!isReady()) {
253 throw new NotReadyException();
254 }
255
256 try {
257 locked = true;
258
259 if (listener != null) {
260 listener.onStart(this);
261 }
262
263 if (triangulatePoints) {
264 triangulatedPoints = new ArrayList<>();
265 } else {
266 triangulatedPoints = null;
267 }
268
269 final var nPoints = leftPoints.size();
270 if (markValidTriangulatedPoints) {
271 validTriangulatedPoints = new BitSet(nPoints);
272 } else {
273 validTriangulatedPoints = null;
274 }
275
276 if (estimatedLeftCamera == null) {
277 estimatedLeftCamera = new PinholeCamera();
278 }
279 if (estimatedRightCamera == null) {
280 estimatedRightCamera = new PinholeCamera();
281 }
282
283 generateInitialMetricCamerasUsingDIAC(fundamentalMatrix, principalPointX, principalPointY, aspectRatio,
284 leftPoints, rightPoints, correctorType, estimatedLeftCamera, estimatedRightCamera,
285 triangulatedPoints, validTriangulatedPoints);
286
287 if (listener != null) {
288 listener.onFinish(this, estimatedLeftCamera, estimatedRightCamera);
289 }
290 } catch (final InitialCamerasEstimationFailedException e) {
291 if (listener != null) {
292 listener.onFail(this, e);
293 }
294 throw e;
295 } finally {
296 locked = false;
297 }
298 }
299
300 /**
301 * Gets aspect ratio of intrinsic parameters of cameras.
302 * Typically, this value is 1.0 if vertical coordinates increase upwards,
303 * or -1.0 if it is the opposite.
304 *
305 * @return aspect ratio of intrinsic parameters of cameras.
306 */
307 public double getAspectRatio() {
308 return aspectRatio;
309 }
310
311 /**
312 * Sets aspect ratio of intrinsic parameters of cameras.
313 * Typically, this value is 1.0 if vertical coordinates increase upwards,
314 * or -1.0 if it is the opposite.
315 *
316 * @param aspectRatio aspect ratio of intrinsic parameters of cameras.
317 * @throws LockedException if estimator is locked.
318 */
319 public void setAspectRatio(final double aspectRatio) throws LockedException {
320 if (isLocked()) {
321 throw new LockedException();
322 }
323 this.aspectRatio = aspectRatio;
324 }
325
326 /**
327 * Gets horizontal coordinate of principal point. This value should be the
328 * coordinates of the center of an image assuming that the coordinates start
329 * on the top-left or bottom-left corner. Using a value close to zero
330 * will produce inaccurate results.
331 *
332 * @return horizontal coordinate of principal point.
333 */
334 public double getPrincipalPointX() {
335 return principalPointX;
336 }
337
338 /**
339 * Sets horizontal coordinate of principal point. This value should be the
340 * coordinates of the center of an image assuming that the coordinates start
341 * on the top-left or bottom-left corner. Using a value close to zero
342 * will produce inaccurate results.
343 *
344 * @param principalPointX horizontal coordinate of principal point.
345 * @throws LockedException if estimator is locked.
346 */
347 public void setPrincipalPointX(final double principalPointX) throws LockedException {
348 if (isLocked()) {
349 throw new LockedException();
350 }
351 this.principalPointX = principalPointX;
352 }
353
354 /**
355 * Gets vertical coordinate of principal point. This value should be the
356 * coordinates of the center of an image assuming that the coordinates start
357 * on the top-left or bottom-left corner. Using a value close to zero will
358 * produce inaccurate results.
359 *
360 * @return vertical coordinate of principal point.
361 */
362 public double getPrincipalPointY() {
363 return principalPointY;
364 }
365
366 /**
367 * Sets vertical coordinate of principal point. This value should be the
368 * coordinates of the center of an image assuming that the coordinates start
369 * on the top-left or bottom-left corner. Using a value close to zero will
370 * produce inaccurate results.
371 *
372 * @param principalPointY vertical coordinate of principal point.
373 * @throws LockedException if estimator is locked.
374 */
375 public void setPrincipalPointY(final double principalPointY) throws LockedException {
376 if (isLocked()) {
377 throw new LockedException();
378 }
379 this.principalPointY = principalPointY;
380 }
381
382 /**
383 * Sets horizontal and vertical coordinates of principal point. This value
384 * should be the coordinates of the center of an image assuming that the
385 * coordinates start on the top-left or bottom-left corner. Using a value
386 * close to zero will produce inaccurate results.
387 *
388 * @param principalPointX horizontal coordinate of principal point.
389 * @param principalPointY vertical coordinate of principal point.
390 * @throws LockedException if estimator is locked.
391 */
392 public void setPrincipalPoint(final double principalPointX, final double principalPointY) throws LockedException {
393 if (isLocked()) {
394 throw new LockedException();
395 }
396 this.principalPointX = principalPointX;
397 this.principalPointY = principalPointY;
398 }
399
400 /**
401 * Gets matched 2D points on left view.
402 *
403 * @return matched 2D points on left view.
404 */
405 public List<Point2D> getLeftPoints() {
406 return leftPoints;
407 }
408
409 /**
410 * Sets matched 2D points on left view.
411 *
412 * @param leftPoints matched 2D points on left view.
413 * @throws LockedException if estimator is locked.
414 */
415 public void setLeftPoints(final List<Point2D> leftPoints) throws LockedException {
416 if (isLocked()) {
417 throw new LockedException();
418 }
419 this.leftPoints = leftPoints;
420 }
421
422 /**
423 * Gets matched 2D points on right view.
424 *
425 * @return matched 2D points on right view.
426 */
427 public List<Point2D> getRightPoints() {
428 return rightPoints;
429 }
430
431 /**
432 * Sets matched 2D points on right view.
433 *
434 * @param rightPoints matched 2D points on right view.
435 * @throws LockedException if estimator is locked.
436 */
437 public void setRightPoints(final List<Point2D> rightPoints) throws LockedException {
438 if (isLocked()) {
439 throw new LockedException();
440 }
441 this.rightPoints = rightPoints;
442 }
443
444 /**
445 * Sets matched 2D points on left and right views.
446 *
447 * @param leftPoints matched 2D points on left view.
448 * @param rightPoints matched 2D points on right view.
449 * @throws LockedException if estimator is locked.
450 * @throws IllegalArgumentException if provided lists don't have the same
451 * size.
452 */
453 public void setLeftAndRightPoints(final List<Point2D> leftPoints, final List<Point2D> rightPoints)
454 throws LockedException {
455 if (isLocked()) {
456 throw new LockedException();
457 }
458 internalSetLeftAndRightPoints(leftPoints, rightPoints);
459 }
460
461 /**
462 * Gets type of corrector to use to triangulate matched points or null if
463 * no corrector needs to be used.
464 *
465 * @return type of corrector to use.
466 */
467 public CorrectorType getCorrectorType() {
468 return correctorType;
469 }
470
471 /**
472 * Sets type of corrector to use to triangulate matched points or null if
473 * no corrector needs to be used.
474 *
475 * @param correctorType type of corrector to use.
476 * @throws LockedException if estimator is locked.
477 */
478 public void setCorrectorType(final CorrectorType correctorType) throws LockedException {
479 if (isLocked()) {
480 throw new LockedException();
481 }
482 this.correctorType = correctorType;
483 }
484
485 /**
486 * Indicates whether matched 2D points need to be triangulated or not.
487 *
488 * @return true if 2D points need to be triangulated, false otherwise.
489 */
490 public boolean arePointsTriangulated() {
491 return triangulatePoints;
492 }
493
494 /**
495 * Specifies whether matched 2D points need to be triangulated or not.
496 *
497 * @param triangulatePoints true if 2D points need to be triangulated, false
498 * otherwise.
499 * @throws LockedException if estimator is locked.
500 */
501 public void setPointsTriangulated(final boolean triangulatePoints) throws LockedException {
502 if (isLocked()) {
503 throw new LockedException();
504 }
505 this.triangulatePoints = triangulatePoints;
506 }
507
508 /**
509 * Indicates which triangulated points are marked as valid (lie in front
510 * of both of the estimated cameras) and which ones aren't.
511 *
512 * @return true to mark valid and invalid triangulated points, false
513 * otherwise.
514 */
515 public boolean areValidTriangulatedPointsMarked() {
516 return markValidTriangulatedPoints;
517 }
518
519 /**
520 * Specifies whether triangulated points are marked as valid (lie in front
521 * of both of the estimated cameras) and which ones aren't.
522 *
523 * @param markValidTriangulatedPoints true to mark valid and invalid
524 * triangulated points, false otherwise.
525 * @throws LockedException if estimator is locked.
526 */
527 public void setValidTriangulatedPointsMarked(final boolean markValidTriangulatedPoints) throws LockedException {
528 if (isLocked()) {
529 throw new LockedException();
530 }
531 this.markValidTriangulatedPoints = markValidTriangulatedPoints;
532 }
533
534 /**
535 * Gets triangulated points, if available.
536 *
537 * @return triangulated points or null.
538 */
539 public List<Point3D> getTriangulatedPoints() {
540 return triangulatedPoints;
541 }
542
543 /**
544 * Gets bitset indicating which of the triangulated points are valid and
545 * which ones aren't.
546 *
547 * @return bitset indicating validity of triangulated points or null if not
548 * available.
549 */
550 public BitSet getValidTriangulatedPoints() {
551 return validTriangulatedPoints;
552 }
553
554 /**
555 * Generates a pair of metric cameras (up to an arbitrary space) by
556 * estimating the intrinsic parameters of the views by solving the Kruppa
557 * equations to obtain the Dual Image of Absolute Conic (DIAC).
558 * The estimated intrinsic parameters can later be used to find the
559 * essential matrix (assuming that both views have the same intrinsic
560 * parameters), and the essential matrix along with provided matched 2D
561 * points can be used to determine the best pair of camera pose and
562 * translation that yields the largest number of triangulated points laying
563 * in front of both of the estimated cameras.
564 * This method uses default corrector type, does not keep triangulated
565 * points or valid triangulated points, and uses default aspect ratio (1.0).
566 *
567 * @param fundamentalMatrix fundamental matrix relating both left and right
568 * views.
569 * @param principalPointX horizontal coordinate of principal point. This
570 * value should be the coordinates of the center of an image assuming that
571 * the coordinates start on the top-left or bottom-left corner. Using a
572 * value close to zero will produce inaccurate results.
573 * @param principalPointY vertical coordinate of principal point. This
574 * value should be the coordinates of the center of an image assuming that
575 * the coordinates start on the top-left or bottom-left corner. Using a
576 * value close to zero will produce inaccurate results.
577 * @param leftPoints points on left view matched with points on right view,
578 * so they can be triangulated using estimated cameras. Both lists of points
579 * must have the same size.
580 * @param rightPoints points on right view matched with points on left view,
581 * so they can be triangulated using estimated cameras. Both lists of points
582 * must have the same size.
583 * @param leftCamera instance where estimated left camera will be stored.
584 * @param rightCamera instance where estimated right camera will be stored.
585 * @return number of valid triangulated points which lie in front of the two
586 * estimated cameras.
587 * @throws InitialCamerasEstimationFailedException if estimation of cameras
588 * fails for some reason, typically due to numerical
589 * instabilities.
590 * @throws IllegalArgumentException if provided lists of left and right
591 * points don't have the same size.
592 */
593 public static int generateInitialMetricCamerasUsingDIAC(
594 final FundamentalMatrix fundamentalMatrix, final double principalPointX,
595 final double principalPointY, final List<Point2D> leftPoints,
596 final List<Point2D> rightPoints, final PinholeCamera leftCamera,
597 final PinholeCamera rightCamera) throws InitialCamerasEstimationFailedException {
598
599 return generateInitialMetricCamerasUsingDIAC(fundamentalMatrix, principalPointX, principalPointY,
600 leftPoints, rightPoints, Corrector.DEFAULT_TYPE, leftCamera, rightCamera);
601 }
602
603 /**
604 * Generates a pair of metric cameras (up to an arbitrary space) by
605 * estimating the intrinsic parameters of the views by solving the Kruppa
606 * equations to obtain the Dual Image of Absolute Conic (DIAC).
607 * The estimated intrinsic parameters can later be used to find the
608 * essential matrix (assuming that both views have the same intrinsic
609 * parameters), and the essential matrix along with provided matched 2D
610 * points can be used to determine the best pair of camera pose and
611 * translation that yields the largest number of triangulated points laying
612 * in front of both of the estimated cameras.
613 * This method does not keep triangulated points or valid triangulated
614 * points and uses default aspect ratio (1.0).
615 *
616 * @param fundamentalMatrix fundamental matrix relating both left and right
617 * views.
618 * @param principalPointX horizontal coordinate of principal point. This
619 * value should be the coordinates of the center of an image assuming that
620 * the coordinates start on the top-left or bottom-left corner. Using a
621 * value close to zero will produce inaccurate results.
622 * @param principalPointY vertical coordinate of principal point. This
623 * value should be the coordinates of the center of an image assuming that
624 * the coordinates start on the top-left or bottom-left corner. Using a
625 * value close to zero will produce inaccurate results.
626 * @param leftPoints points on left view matched with points on right view,
627 * so they can be triangulated using estimated cameras. Both lists of points
628 * must have the same size.
629 * @param rightPoints points on right view matched with points on left view,
630 * so they can be triangulated using estimated cameras. Both lists of points
631 * must have the same size.
632 * @param correctorType corrector type to be used to correct 2D points, so
633 * they follow the epipolar geometry defined by provided fundamental matrix
634 * so that error on triangulated points is reduced. If null, no corrector
635 * will be used.
636 * @param leftCamera instance where estimated left camera will be stored.
637 * @param rightCamera instance where estimated right camera will be stored.
638 * @return number of valid triangulated points which lie in front of the two
639 * estimated cameras.
640 * @throws InitialCamerasEstimationFailedException if estimation of
641 * cameras fails for some reason, typically due to
642 * numerical instabilities.
643 * @throws IllegalArgumentException if provided lists of left and right
644 * points don't have the same size.
645 */
646 public static int generateInitialMetricCamerasUsingDIAC(
647 final FundamentalMatrix fundamentalMatrix, final double principalPointX,
648 final double principalPointY, final List<Point2D> leftPoints,
649 final List<Point2D> rightPoints, final CorrectorType correctorType,
650 final PinholeCamera leftCamera, final PinholeCamera rightCamera)
651 throws InitialCamerasEstimationFailedException {
652
653 return generateInitialMetricCamerasUsingDIAC(fundamentalMatrix, principalPointX, principalPointY,
654 leftPoints, rightPoints, correctorType, leftCamera, rightCamera, null,
655 null);
656 }
657
658 /**
659 * Generates a pair of metric cameras (up to an arbitrary space) by
660 * estimating the intrinsic parameters of the views by solving the Kruppa
661 * equations to obtain the Dual Image of Absolute Conic (DIAC).
662 * The estimated intrinsic parameters can later be used to find the
663 * essential matrix (assuming that both views have the same intrinsic
664 * parameters), and the essential matrix along with provided matched 2D
665 * points can be used to determine the best pair of camera pose and
666 * translation that yields the largest number of triangulated points laying
667 * in front of both of the estimated cameras.
668 * This method uses default corrector type and default aspect ratio (1.0).
669 *
670 * @param fundamentalMatrix fundamental matrix relating both left and right
671 * views.
672 * @param principalPointX horizontal coordinate of principal point. This
673 * value should be the coordinates of the center of an image assuming
674 * that the coordinates start on the top-left or bottom-left corner.
675 * Using a value close to zero will produce inaccurate results.
676 * @param principalPointY vertical coordinate of principal point. This
677 * value should be the coordinates of the center of an image assuming
678 * that the coordinates start on the top-left or bottom-left corner.
679 * Using a value close to zero will produce inaccurate results.
680 * @param leftPoints points on left view matched with points on right view,
681 * so they can be triangulated using estimated cameras. Both lists of
682 * points must have the same size.
683 * @param rightPoints points on right view matched with points on left view,
684 * so they can be triangulated using estimated cameras. Both lists of
685 * points must have the same size.
686 * @param leftCamera instance where estimated left camera will be stored.
687 * @param rightCamera instance where estimated right camera will be stored.
688 * @param triangulatedPoints instance where triangulated 3D points will be
689 * stored or null if triangulated points don't need to be kept.
690 * @param validTriangulatedPoints instance which indicates which
691 * triangulated 3D points are considered valid because they lie in
692 * front of both cameras or null if such data doesn't need to be kept.
693 * @return number of valid triangulated points which lie in front of the two
694 * estimated cameras.
695 * @throws InitialCamerasEstimationFailedException if estimation of cameras
696 * fails for some reason, typically due to numerical
697 * instabilities.
698 * @throws IllegalArgumentException if provided lists of left and right
699 * points don't have the same size.
700 */
701 public static int generateInitialMetricCamerasUsingDIAC(
702 final FundamentalMatrix fundamentalMatrix, final double principalPointX,
703 final double principalPointY, final List<Point2D> leftPoints,
704 final List<Point2D> rightPoints, final PinholeCamera leftCamera,
705 final PinholeCamera rightCamera, final List<Point3D> triangulatedPoints,
706 final BitSet validTriangulatedPoints)
707 throws InitialCamerasEstimationFailedException {
708
709 return generateInitialMetricCamerasUsingDIAC(fundamentalMatrix, principalPointX, principalPointY,
710 leftPoints, rightPoints, Corrector.DEFAULT_TYPE, leftCamera, rightCamera, triangulatedPoints,
711 validTriangulatedPoints);
712 }
713
714 /**
715 * Generates a pair of metric cameras (up to an arbitrary space) by
716 * estimating the intrinsic parameters of the views by solving the Kruppa
717 * equations to obtain the Dual Image of Absolute Conic (DIAC).
718 * The estimated intrinsic parameters can later be used to find the
719 * essential matrix (assuming that both views have the same intrinsic
720 * parameters), and the essential matrix along with provided matched 2D
721 * points can be used to determine the best pair of camera pose and
722 * translation that yields the largest number of triangulated points laying
723 * in front of both of the estimated cameras.
724 * This method uses default aspect ratio (1.0).
725 *
726 * @param fundamentalMatrix fundamental matrix relating both left and right
727 * views.
728 * @param principalPointX horizontal coordinate of principal point. This
729 * value should be the coordinates of the center of an image assuming
730 * that the coordinates start on the top-left or bottom-left corner.
731 * Using a value close to zero will produce inaccurate results.
732 * @param principalPointY vertical coordinate of principal point. This
733 * value should be the coordinates of the center of an image assuming
734 * that the coordinates start on the top-left or bottom-left corner.
735 * Using a value close to zero will produce inaccurate results.
736 * @param leftPoints points on left view matched with points on right view,
737 * so they can be triangulated using estimated cameras. Both lists of
738 * points must have the same size.
739 * @param rightPoints points on right view matched with points on left view,
740 * so they can be triangulated using estimated cameras. Both lists of
741 * points must have the same size.
742 * @param correctorType corrector type to be used to correct 2D points, so
743 * they follow the epipolar geometry defined by provided fundamental
744 * matrix so that error on triangulated points is reduced. If null, no
745 * corrector will be used.
746 * @param leftCamera instance where estimated left camera will be stored.
747 * @param rightCamera instance where estimated right camera will be stored.
748 * @param triangulatedPoints instance where triangulated 3D points will be
749 * stored or null if triangulated points don't need to be kept.
750 * @param validTriangulatedPoints instance which indicates which
751 * triangulated 3D points are considered valid because they lie in
752 * front of both cameras or null if such data doesn't need to be kept.
753 * @return number of valid triangulated points which lie in front of the two
754 * estimated cameras.
755 * @throws InitialCamerasEstimationFailedException if estimation of cameras
756 * fails for some reason, typically due to numerical
757 * instabilities.
758 * @throws IllegalArgumentException if provided lists of left and right
759 * points don't have the same size.
760 */
761 public static int generateInitialMetricCamerasUsingDIAC(
762 final FundamentalMatrix fundamentalMatrix, final double principalPointX,
763 final double principalPointY, final List<Point2D> leftPoints,
764 final List<Point2D> rightPoints, final CorrectorType correctorType,
765 final PinholeCamera leftCamera, final PinholeCamera rightCamera,
766 final List<Point3D> triangulatedPoints, final BitSet validTriangulatedPoints)
767 throws InitialCamerasEstimationFailedException {
768
769 return generateInitialMetricCamerasUsingDIAC(fundamentalMatrix,
770 principalPointX, principalPointY,
771 KruppaDualImageOfAbsoluteConicEstimator.DEFAULT_FOCAL_DISTANCE_ASPECT_RATIO, leftPoints, rightPoints,
772 correctorType, leftCamera, rightCamera, triangulatedPoints, validTriangulatedPoints);
773 }
774
775 /**
776 * Generates a pair of metric cameras (up to an arbitrary space) by
777 * estimating the intrinsic parameters of the views by solving the Kruppa
778 * equations to obtain the Dual Image of Absolute Conic (DIAC).
779 * The estimated intrinsic parameters can later be used to find the
780 * essential matrix (assuming that both views have the same intrinsic
781 * parameters), and the essential matrix along with provided matched 2D
782 * points can be used to determine the best pair of camera pose and
783 * translation that yields the largest number of triangulated points laying
784 * in front of both of the estimated cameras.
785 * This method uses default corrector type and does not keep triangulated
786 * points or valid triangulated points.
787 *
788 * @param fundamentalMatrix fundamental matrix relating both left and right
789 * views.
790 * @param principalPointX horizontal coordinate of principal point. This
791 * value should be the coordinates of the center of an image assuming that
792 * the coordinates start on the top-left or bottom-left corner. Using a
793 * value close to zero will produce inaccurate results.
794 * @param principalPointY vertical coordinate of principal point. This
795 * value should be the coordinates of the center of an image assuming that
796 * the coordinates start on the top-left or bottom-left corner. Using a
797 * value close to zero will produce inaccurate results.
798 * @param aspectRatio aspect ratio for estimated intrinsic parameters. This
799 * is typically 1.0 if vertical coordinates increase upwards or -1.0 if it
800 * is the opposite.
801 * @param leftPoints points on left view matched with points on right view,
802 * so they can be triangulated using estimated cameras. Both lists of points
803 * must have the same size.
804 * @param rightPoints points on right view matched with points on left view,
805 * so they can be triangulated using estimated cameras. Both lists of points
806 * must have the same size.
807 * @param leftCamera instance where estimated left camera will be stored.
808 * @param rightCamera instance where estimated right camera will be stored.
809 * @return number of valid triangulated points which lie in front of the two
810 * estimated cameras.
811 * @throws InitialCamerasEstimationFailedException if estimation of cameras
812 * fails for some reason, typically due to numerical
813 * instabilities.
814 * @throws IllegalArgumentException if provided lists of left and right
815 * points don't have the same size.
816 */
817 public static int generateInitialMetricCamerasUsingDIAC(
818 final FundamentalMatrix fundamentalMatrix, final double principalPointX,
819 final double principalPointY, final double aspectRatio,
820 final List<Point2D> leftPoints, final List<Point2D> rightPoints,
821 final PinholeCamera leftCamera, final PinholeCamera rightCamera)
822 throws InitialCamerasEstimationFailedException {
823
824 return generateInitialMetricCamerasUsingDIAC(fundamentalMatrix, principalPointX, principalPointY, aspectRatio,
825 leftPoints, rightPoints, Corrector.DEFAULT_TYPE, leftCamera, rightCamera);
826 }
827
828 /**
829 * Generates a pair of metric cameras (up to an arbitrary space) by
830 * estimating the intrinsic parameters of the views by solving the Kruppa
831 * equations to obtain the Dual Image of Absolute Conic (DIAC).
832 * The estimated intrinsic parameters can later be used to find the
833 * essential matrix (assuming that both views have the same intrinsic
834 * parameters), and the essential matrix along with provided matched 2D
835 * points can be used to determine the best pair of camera pose and
836 * translation that yields the largest number of triangulated points laying
837 * in front of both of the estimated cameras.
838 * This method does not keep triangulated points or valid triangulated
839 * points.
840 *
841 * @param fundamentalMatrix fundamental matrix relating both left and right
842 * views.
843 * @param principalPointX horizontal coordinate of principal point. This
844 * value should be the coordinates of the center of an image assuming that
845 * the coordinates start on the top-left or bottom-left corner. Using a
846 * value close to zero will produce inaccurate results.
847 * @param principalPointY vertical coordinate of principal point. This
848 * value should be the coordinates of the center of an image assuming that
849 * the coordinates start on the top-left or bottom-left corner. Using a
850 * value close to zero will produce inaccurate results.
851 * @param aspectRatio aspect ratio for estimated intrinsic parameters. This
852 * is typically 1.0 if vertical coordinates increase upwards or -1.0 if it
853 * is the opposite.
854 * @param leftPoints points on left view matched with points on right view,
855 * so they can be triangulated using estimated cameras. Both lists of points
856 * must have the same size.
857 * @param rightPoints points on right view matched with points on left view,
858 * so they can be triangulated using estimated cameras. Both lists of points
859 * must have the same size.
860 * @param correctorType corrector type to be used to correct 2D points, so
861 * they follow the epipolar geometry defined by provided fundamental matrix
862 * so that error on triangulated points is reduced. If null, no corrector
863 * will be used.
864 * @param leftCamera instance where estimated left camera will be stored.
865 * @param rightCamera instance where estimated right camera will be stored.
866 * @return number of valid triangulated points which lie in front of the two
867 * estimated cameras.
868 * @throws InitialCamerasEstimationFailedException if estimation of
869 * cameras fails for some reason, typically due to
870 * numerical instabilities.
871 * @throws IllegalArgumentException if provided lists of left and right
872 * points don't have the same size.
873 */
874 public static int generateInitialMetricCamerasUsingDIAC(
875 final FundamentalMatrix fundamentalMatrix, final double principalPointX,
876 final double principalPointY, final double aspectRatio,
877 final List<Point2D> leftPoints, final List<Point2D> rightPoints,
878 final CorrectorType correctorType, final PinholeCamera leftCamera,
879 final PinholeCamera rightCamera) throws InitialCamerasEstimationFailedException {
880
881 return generateInitialMetricCamerasUsingDIAC(fundamentalMatrix, principalPointX, principalPointY, aspectRatio,
882 leftPoints, rightPoints, correctorType, leftCamera, rightCamera, null,
883 null);
884 }
885
886 /**
887 * Generates a pair of metric cameras (up to an arbitrary space) by
888 * estimating the intrinsic parameters of the views by solving the Kruppa
889 * equations to obtain the Dual Image of Absolute Conic (DIAC).
890 * The estimated intrinsic parameters can later be used to find the
891 * essential matrix (assuming that both views have the same intrinsic
892 * parameters), and the essential matrix along with provided matched 2D
893 * points can be used to determine the best pair of camera pose and
894 * translation that yields the largest number of triangulated points laying
895 * in front of both of the estimated cameras.
896 * This method uses default corrector type.
897 *
898 * @param fundamentalMatrix fundamental matrix relating both left and right
899 * views.
900 * @param principalPointX horizontal coordinate of principal point. This
901 * value should be the coordinates of the center of an image assuming
902 * that the coordinates start on the top-left or bottom-left corner.
903 * Using a value close to zero will produce inaccurate results.
904 * @param principalPointY vertical coordinate of principal point. This
905 * value should be the coordinates of the center of an image assuming
906 * that the coordinates start on the top-left or bottom-left corner.
907 * Using a value close to zero will produce inaccurate results.
908 * @param aspectRatio aspect ratio for estimated intrinsic parameters. This
909 * is typically 1.0 if vertical coordinates increase upwards or -1.0 if
910 * it is the opposite.
911 * @param leftPoints points on left view matched with points on right view,
912 * so they can be triangulated using estimated cameras. Both lists of
913 * points must have the same size.
914 * @param rightPoints points on right view matched with points on left view,
915 * so they can be triangulated using estimated cameras. Both lists of
916 * points must have the same size.
917 * @param leftCamera instance where estimated left camera will be stored.
918 * @param rightCamera instance where estimated right camera will be stored.
919 * @param triangulatedPoints instance where triangulated 3D points will be
920 * stored or null if triangulated points don't need to be kept.
921 * @param validTriangulatedPoints instance which indicates which
922 * triangulated 3D points are considered valid because they lie in
923 * front of both cameras or null if such data doesn't need to be kept.
924 * @return number of valid triangulated points which lie in front of the two
925 * estimated cameras.
926 * @throws InitialCamerasEstimationFailedException if estimation of cameras
927 * fails for some reason, typically due to numerical
928 * instabilities.
929 * @throws IllegalArgumentException if provided lists of left and right
930 * points don't have the same size.
931 */
932 public static int generateInitialMetricCamerasUsingDIAC(
933 final FundamentalMatrix fundamentalMatrix, final double principalPointX,
934 final double principalPointY, final double aspectRatio,
935 final List<Point2D> leftPoints, final List<Point2D> rightPoints,
936 final PinholeCamera leftCamera, final PinholeCamera rightCamera,
937 final List<Point3D> triangulatedPoints, final BitSet validTriangulatedPoints)
938 throws InitialCamerasEstimationFailedException {
939
940 return generateInitialMetricCamerasUsingDIAC(fundamentalMatrix, principalPointX, principalPointY, aspectRatio,
941 leftPoints, rightPoints, Corrector.DEFAULT_TYPE, leftCamera, rightCamera, triangulatedPoints,
942 validTriangulatedPoints);
943 }
944
945 /**
946 * Generates a pair of metric cameras (up to an arbitrary space) by
947 * estimating the intrinsic parameters of the views by solving the Kruppa
948 * equations to obtain the Dual Image of Absolute Conic (DIAC).
949 * The estimated intrinsic parameters can later be used to find the
950 * essential matrix (assuming that both views have the same intrinsic
951 * parameters), and the essential matrix along with provided matched 2D
952 * points can be used to determine the best pair of camera pose and
953 * translation that yields the largest number of triangulated points laying
954 * in front of both of the estimated cameras.
955 *
956 * @param fundamentalMatrix fundamental matrix relating both left and right
957 * views.
958 * @param principalPointX horizontal coordinate of principal point. This
959 * value should be the coordinates of the center of an image assuming
960 * that the coordinates start on the top-left or bottom-left corner.
961 * Using a value close to zero will produce inaccurate results.
962 * @param principalPointY vertical coordinate of principal point. This
963 * value should be the coordinates of the center of an image assuming
964 * that the coordinates start on the top-left or bottom-left corner.
965 * Using a value close to zero will produce inaccurate results.
966 * @param aspectRatio aspect ratio for estimated intrinsic parameters. This
967 * is typically 1.0 if vertical coordinates increase upwards or -1.0 if
968 * it is the opposite.
969 * @param leftPoints points on left view matched with points on right view,
970 * so they can be triangulated using estimated cameras. Both lists of
971 * points must have the same size.
972 * @param rightPoints points on right view matched with points on left view,
973 * so they can be triangulated using estimated cameras. Both lists of
974 * points must have the same size.
975 * @param correctorType corrector type to be used to correct 2D points, so
976 * they follow the epipolar geometry defined by provided fundamental
977 * matrix so that error on triangulated points is reduced. If null, no
978 * corrector will be used.
979 * @param leftCamera instance where estimated left camera will be stored.
980 * @param rightCamera instance where estimated right camera will be stored.
981 * @param triangulatedPoints instance where triangulated 3D points will be
982 * stored or null if triangulated points don't need to be kept.
983 * @param validTriangulatedPoints instance which indicates which
984 * triangulated 3D points are considered valid because they lie in
985 * front of both cameras or null if such data doesn't need to be kept.
986 * @return number of valid triangulated points which lie in front of the two
987 * estimated cameras.
988 * @throws InitialCamerasEstimationFailedException if estimation of cameras
989 * fails for some reason, typically due to numerical
990 * instabilities.
991 * @throws IllegalArgumentException if provided lists of left and right
992 * points don't have the same size.
993 */
994 public static int generateInitialMetricCamerasUsingDIAC(
995 final FundamentalMatrix fundamentalMatrix, final double principalPointX,
996 final double principalPointY, final double aspectRatio,
997 final List<Point2D> leftPoints, final List<Point2D> rightPoints,
998 final CorrectorType correctorType, final PinholeCamera leftCamera,
999 final PinholeCamera rightCamera, final List<Point3D> triangulatedPoints,
1000 final BitSet validTriangulatedPoints) throws InitialCamerasEstimationFailedException {
1001
1002 try {
1003 final KruppaDualImageOfAbsoluteConicEstimator diacEstimator = new KruppaDualImageOfAbsoluteConicEstimator(
1004 fundamentalMatrix);
1005 diacEstimator.setPrincipalPointX(principalPointX);
1006 diacEstimator.setPrincipalPointY(principalPointY);
1007 diacEstimator.setFocalDistanceAspectRatioKnown(true);
1008 diacEstimator.setFocalDistanceAspectRatio(aspectRatio);
1009
1010 final var diac = diacEstimator.estimate();
1011
1012 final var intrinsic = diac.getIntrinsicParameters();
1013
1014 return EssentialMatrixInitialCamerasEstimator.generateInitialMetricCamerasFromEssentialMatrix(
1015 fundamentalMatrix, intrinsic, intrinsic, leftPoints, rightPoints, correctorType, leftCamera,
1016 rightCamera, triangulatedPoints, validTriangulatedPoints);
1017
1018 } catch (final InitialCamerasEstimationFailedException e) {
1019 throw e;
1020 } catch (final Exception e) {
1021 throw new InitialCamerasEstimationFailedException(e);
1022 }
1023 }
1024
1025 /**
1026 * Internal method to set matched 2D points on left and right views.
1027 * This method does not check whether the estimator is locked or not, only
1028 * ensures that provided lists have the same size.
1029 *
1030 * @param leftPoints matched 2D points on left view.
1031 * @param rightPoints matched 2D points on right view.
1032 * @throws IllegalArgumentException if provided lists don't have the same
1033 * size.
1034 */
1035 private void internalSetLeftAndRightPoints(final List<Point2D> leftPoints, final List<Point2D> rightPoints) {
1036 if (leftPoints == null || rightPoints == null || leftPoints.size() != rightPoints.size()) {
1037 throw new IllegalArgumentException();
1038 }
1039 this.leftPoints = leftPoints;
1040 this.rightPoints = rightPoints;
1041 }
1042 }