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.ar.epipolar;
17
18 import com.irurueta.geometry.CoordinatesType;
19 import com.irurueta.geometry.Line2D;
20 import com.irurueta.geometry.Point2D;
21 import com.irurueta.geometry.estimators.LockedException;
22 import com.irurueta.geometry.estimators.NotReadyException;
23 import com.irurueta.statistics.UniformRandomizer;
24
25 /**
26 * Compares two fundamental matrices by estimating average epipolar distances.
27 * This class uses epipolar geometry to determine how similar fundamental
28 * matrices are. This is done by assuming a certain size on the retinal planes
29 * and generating random 2D points to obtain their associated epipolar lines and
30 * the distances of matched points to those epipolar lines
31 * This class simply computes the norm of the difference of both fundamental
32 * matrices. The smaller the value the more similar the fundamental matrices
33 * will be from a pure algebraic point of view.
34 */
35 public class EpipolarDistanceFundamentalMatrixComparator extends FundamentalMatrixComparator {
36
37 /**
38 * Defines default minimum horizontal coordinate when generating random
39 * samples.
40 */
41 public static final double DEFAULT_MIN_X = 0.0;
42
43 /**
44 * Defines default maximum horizontal coordinate when generating random
45 * samples.
46 */
47 public static final double DEFAULT_MAX_X = 640.0;
48
49 /**
50 * Defines default minimum vertical coordinate when generating random
51 * samples.
52 */
53 public static final double DEFAULT_MIN_Y = 0.0;
54
55 /**
56 * Defines default maximum vertical coordinate when generating random
57 * samples.
58 */
59 public static final double DEFAULT_MAX_Y = 480.0;
60
61 /**
62 * Default number of random samples to generate to compare fundamental
63 * matrices.
64 */
65 public static final int DEFAULT_N_SAMPLES = 100;
66
67 /**
68 * Minimum number of samples that must be generated to compare fundamental
69 * matrices.
70 */
71 public static final int MIN_N_SAMPLES = 1;
72
73 /**
74 * Minimum disparity factor respect to retinal plane size defined by
75 * minimum and maximum samples coordinates. When computing residuals,
76 * matched samples are created along the corresponding epipolar lines with a
77 * random disparity within provided range, and then the epipolar line for
78 * the randomly generated matched sample is generated on the original view
79 * to determine the distance to such line and the original sample.
80 */
81 public static final double DEFAULT_MIN_DISPARITY_FACTOR = -0.1;
82
83 /**
84 * Maximum disparity factor respect to retinal plane size defined by
85 * minimum and maximum samples coordinates. When computing residuals,
86 * matched samples are created along the corresponding epipolar lines with a
87 * random disparity within provided range, and then the epipolar line for
88 * the randomly generated matched sample is generated on the original view
89 * to determine the distance to such line and the original sample.
90 */
91 public static final double DEFAULT_MAX_DISPARITY_FACTOR = 0.1;
92
93 /**
94 * Default factor to determine maximum number of iterations respect to the
95 * number of samples to compute comparison.
96 */
97 public static final double DEFAULT_MAX_ITERATIONS_FACTOR = 10.0;
98
99 /**
100 * Minimum value for the factor to determine maximum number of iterations
101 * respect to the number of samples to compute comparison.
102 */
103 public static final double MIN_MAX_ITERATIONS_FACTOR = 1.0;
104
105 /**
106 * Default amount of progress variation before notifying a change in
107 * comparison progress. By default, this is set to 5%.
108 */
109 public static final float DEFAULT_PROGRESS_DELTA = 0.05f;
110
111 /**
112 * Minimum allowed value for progress delta.
113 */
114 public static final float MIN_PROGRESS_DELTA = 0.0f;
115
116 /**
117 * Maximum allowed value for progress delta.
118 */
119 public static final float MAX_PROGRESS_DELTA = 1.0f;
120
121 /**
122 * Minimum horizontal coordinate when generating random samples.
123 */
124 private double minX;
125
126 /**
127 * Maximum horizontal coordinate when generating random samples.
128 */
129 private double maxX;
130
131 /**
132 * Minimum vertical coordinate when generating random samples.
133 */
134 private double minY;
135
136 /**
137 * Maximum vertical coordinate when generating random samples.
138 */
139 private double maxY;
140
141 /**
142 * Number of random samples to generate to compare fundamental matrices.
143 */
144 private int nSamples;
145
146 /**
147 * Minimum horizontal disparity factor respect to retinal plane size defined
148 * by minimum and maximum samples coordinates. When computing residuals,
149 * matched samples are created along the corresponding epipolar lines with a
150 * random disparity within provided range of disparities, and then the
151 * epipolar line for the randomly generated matched sample is generated on
152 * the original view to determine the distance to such line and the original
153 * sample.
154 */
155 private double minHorizontalDisparityFactor;
156
157 /**
158 * Maximum horizontal disparity factor respect to retinal plane size defined
159 * by minimum and maximum samples coordinates. When computing residuals,
160 * matched samples are created along the corresponding epipolar lines with a
161 * random disparity within provided range of disparities, and then the
162 * epipolar line for the randomly generated matched sample is generated on
163 * the original view to determine the distance to such line and the original
164 * sample.
165 */
166 private double maxHorizontalDisparityFactor;
167
168 /**
169 * Minimum vertical disparity factor respect to retinal plane size defined
170 * by minimum and maximum samples coordinates. When computing residuals,
171 * matched samples are created along the corresponding epipolar lines with a
172 * random disparity within provided range of disparities, and then the
173 * epipolar line for the randomly generated matched sample is generated on
174 * the original view to determine the distance to such line and the original
175 * sample.
176 */
177 private double minVerticalDisparityFactor;
178
179 /**
180 * Maximum vertical disparity factor respect to retinal plane size defined
181 * by minimum and maximum samples coordinates. When computing residuals,
182 * matched samples are created along the corresponding epipolar lines with a
183 * random disparity within provided range of disparities, and then the
184 * epipolar line for the randomly generated matched sample is generated on
185 * the original view to determine the distance to such line and the original
186 * sample.
187 */
188 private double maxVerticalDisparityFactor;
189
190 /**
191 * Factor to determine maximum number of iterations respect to the
192 * number of samples to compute comparison.
193 */
194 private double maxIterationsFactor;
195
196 /**
197 * Amount of progress variation before notifying a progress change during
198 * comparison.
199 */
200 protected float progressDelta;
201
202 /**
203 * Constructor.
204 */
205 public EpipolarDistanceFundamentalMatrixComparator() {
206 super();
207 init();
208 }
209
210 /**
211 * Constructor.
212 *
213 * @param groundTruthFundamentalMatrix fundamental matrix to be considered
214 * as ground truth to compare against.
215 * @param otherFundamentalMatrix other fundamental matrix being compared.
216 */
217 public EpipolarDistanceFundamentalMatrixComparator(
218 final FundamentalMatrix groundTruthFundamentalMatrix, final FundamentalMatrix otherFundamentalMatrix) {
219 super(groundTruthFundamentalMatrix, otherFundamentalMatrix);
220 init();
221 }
222
223 /**
224 * Constructor.
225 *
226 * @param listener listener to handle events generated by this class.
227 */
228 public EpipolarDistanceFundamentalMatrixComparator(final FundamentalMatrixComparatorListener listener) {
229 super(listener);
230 init();
231 }
232
233 /**
234 * Constructor.
235 *
236 * @param groundTruthFundamentalMatrix fundamental matrix to be considered
237 * as ground truth to compare against.
238 * @param otherFundamentalMatrix other fundamental matrix being compared.
239 * @param listener listener to handle events generated by this class.
240 */
241 public EpipolarDistanceFundamentalMatrixComparator(
242 final FundamentalMatrix groundTruthFundamentalMatrix, final FundamentalMatrix otherFundamentalMatrix,
243 final FundamentalMatrixComparatorListener listener) {
244 super(groundTruthFundamentalMatrix, otherFundamentalMatrix, listener);
245 init();
246 }
247
248 /**
249 * Returns minimum horizontal coordinate when generating random samples.
250 *
251 * @return minimum horizontal coordinate when generating random samples.
252 */
253 public double getMinX() {
254 return minX;
255 }
256
257 /**
258 * Returns maximum horizontal coordinate when generating random samples.
259 *
260 * @return maximum horizontal coordinate when generating random samples.
261 */
262 public double getMaxX() {
263 return maxX;
264 }
265
266 /**
267 * Sets minimum and maximum horizontal coordinates when generating random
268 * samples.
269 *
270 * @param minX minimum horizontal coordinate when generating random samples.
271 * @param maxX maximum horizontal coordinate when generating random samples.
272 * @throws LockedException if this instance is locked.
273 * @throws IllegalArgumentException if minimum value is larger or equal
274 * than maximum one.
275 */
276 public void setMinMaxX(final double minX, final double maxX) throws LockedException {
277 if (isLocked()) {
278 throw new LockedException();
279 }
280 if (minX >= maxX) {
281 throw new IllegalArgumentException();
282 }
283
284 this.minX = minX;
285 this.maxX = maxX;
286 }
287
288 /**
289 * Returns minimum vertical coordinate when generating random samples.
290 *
291 * @return minimum vertical coordinate when generating random samples.
292 */
293 public double getMinY() {
294 return minY;
295 }
296
297 /**
298 * Returns maximum vertical coordinate when generating random samples.
299 *
300 * @return maximum vertical coordinate when generating random samples.
301 */
302 public double getMaxY() {
303 return maxY;
304 }
305
306 /**
307 * Sets minimum and maximum vertical coordinates when generating random
308 * samples.
309 *
310 * @param minY minimum vertical coordinate when generating random samples.
311 * @param maxY maximum vertical coordinate when generating random samples.
312 * @throws LockedException if this instance is locked.
313 * @throws IllegalArgumentException if minimum value is larger or equal
314 * than maximum one.
315 */
316 public void setMinMaxY(final double minY, final double maxY) throws LockedException {
317 if (isLocked()) {
318 throw new LockedException();
319 }
320 if (minY >= maxY) {
321 throw new IllegalArgumentException();
322 }
323
324 this.minY = minY;
325 this.maxY = maxY;
326 }
327
328 /**
329 * Returns number of random samples to generate to compare fundamental
330 * matrices.
331 *
332 * @return number of random samples to generate to compare fundamental
333 * matrices.
334 */
335 public int getNSamples() {
336 return nSamples;
337 }
338
339 /**
340 * Sets number of random samples to generate to compare fundamental matrices.
341 *
342 * @param nSamples number of random samples to generate to compare
343 * fundamental matrices.
344 * @throws LockedException if this instance is locked.
345 * @throws IllegalArgumentException if provided value is less than 1.
346 */
347 public void setNSamples(final int nSamples) throws LockedException {
348 if (isLocked()) {
349 throw new LockedException();
350 }
351 if (nSamples < MIN_N_SAMPLES) {
352 throw new IllegalArgumentException();
353 }
354
355 this.nSamples = nSamples;
356 }
357
358 /**
359 * Returns minimum horizontal disparity factor respect to retinal plane size
360 * defined by minimum and maximum samples coordinates. When computing
361 * residuals, matched samples are created along the corresponding epipolar
362 * lines with a random disparity within provided range of disparities, and
363 * then the epipolar line for the randomly generated matched sample is
364 * generated on the original view to determine the distance to such line and
365 * the original sample.
366 *
367 * @return minimum horizontal disparity factor.
368 */
369 public double getMinHorizontalDisparityFactor() {
370 return minHorizontalDisparityFactor;
371 }
372
373 /**
374 * Returns maximum horizontal disparity factor respect to retinal plane size
375 * defined by minimum and maximum samples coordinates. When computing
376 * residuals, matched samples are created along the corresponding epipolar
377 * lines with a random disparity within provided range of disparities, and
378 * then the epipolar line for the randomly generated matched sample is
379 * generated on the original view to determine the distance to such line and
380 * the original sample.
381 *
382 * @return maximum horizontal disparity factor.
383 */
384 public double getMaxHorizontalDisparityFactor() {
385 return maxHorizontalDisparityFactor;
386 }
387
388 /**
389 * Sets minimum and maximum horizontal disparity factor respect to retinal
390 * plane size defined by minimum and maximum samples coordinates. When
391 * computing residuals, matched samples are created along the corresponding
392 * epipolar lines with a random disparity within provided range of
393 * disparities, and then the epipolar line for the randomly generated matched
394 * sample is generated on the original view to determine the distance to
395 * such line and the original sample.
396 *
397 * @param minHorizontalDisparityFactor minimum horizontal disparity factor.
398 * @param maxHorizontalDisparityFactor maximum horizontal disparity factor.
399 * @throws LockedException if this instance is locked.
400 * @throws IllegalArgumentException if minimum value is larger or equal
401 * than maximum one.
402 */
403 public void setMinMaxHorizontalDisparityFactor(
404 final double minHorizontalDisparityFactor, final double maxHorizontalDisparityFactor)
405 throws LockedException {
406 if (isLocked()) {
407 throw new LockedException();
408 }
409 if (minHorizontalDisparityFactor >= maxHorizontalDisparityFactor) {
410 throw new IllegalArgumentException();
411 }
412
413 this.minHorizontalDisparityFactor = minHorizontalDisparityFactor;
414 this.maxHorizontalDisparityFactor = maxHorizontalDisparityFactor;
415 }
416
417 /**
418 * Returns minimum vertical disparity factor respect to retinal plane size
419 * defined by minimum and maximum samples coordinates. When computing
420 * residuals, matched samples are created along the corresponding epipolar
421 * lines with a random disparity within provided range of disparities, and
422 * then the epipolar line for the randomly generated matched sample is
423 * generated on the original view to determine the distance to such line and
424 * the original sample.
425 *
426 * @return minimum vertical disparity factor.
427 */
428 public double getMinVerticalDisparityFactor() {
429 return minVerticalDisparityFactor;
430 }
431
432 /**
433 * Returns maximum vertical disparity factor respect to retinal plane size
434 * defined by minimum and maximum samples coordinates. When computing
435 * residuals, matched samples are created along the corresponding epipolar
436 * lines with a random disparity within provided range of disparities, and
437 * then the epipolar line for the randomly generated matched sample is
438 * generated on the original view to determine the distance to such line and
439 * the original sample.
440 *
441 * @return maximum vertical disparity factor.
442 */
443 public double getMaxVerticalDisparityFactor() {
444 return maxVerticalDisparityFactor;
445 }
446
447 /**
448 * Sets minimum and maximum vertical disparity factor respect to retinal
449 * plane size defined by minimum and maximum samples coordinates. When
450 * computing residuals, matched samples are created along the corresponding
451 * epipolar lines with a random disparity within provided range of
452 * disparities, and then the epipolar line for the randomly generated matched
453 * sample is generated on the original view to determine the distance to
454 * such line and the original sample.
455 *
456 * @param minVerticalDisparityFactor minimum vertical disparity factor.
457 * @param maxVerticalDisparityFactor maximum vertical disparity factor.
458 * @throws LockedException if this instance is locked.
459 * @throws IllegalArgumentException if minimum value is larger or equal
460 * than maximum one.
461 */
462 public void setMinMaxVerticalDisparityFactor(
463 final double minVerticalDisparityFactor, final double maxVerticalDisparityFactor) throws LockedException {
464 if (isLocked()) {
465 throw new LockedException();
466 }
467 if (minVerticalDisparityFactor >= maxVerticalDisparityFactor) {
468 throw new IllegalArgumentException();
469 }
470
471 this.minVerticalDisparityFactor = minVerticalDisparityFactor;
472 this.maxVerticalDisparityFactor = maxVerticalDisparityFactor;
473 }
474
475 /**
476 * Returns factor to determine maximum number of iterations respect to the
477 * number of samples to compute comparison.
478 *
479 * @return factor to determine maximum number of iterations respect to the
480 * number of samples to compute comparison.
481 */
482 public double getMaxIterationsFactor() {
483 return maxIterationsFactor;
484 }
485
486 /**
487 * Sets factor to determine maximum number of iterations respect to the
488 * number of samples to compute comparison.
489 *
490 * @param maxIterationsFactor maximum number of iterations respect to the
491 * number of samples to compute comparison.
492 * @throws LockedException if this instance is locked.
493 * @throws IllegalArgumentException if provided value is less than 1.0.
494 */
495 public void setMaxIterationsFactor(final double maxIterationsFactor) throws LockedException {
496 if (isLocked()) {
497 throw new LockedException();
498 }
499 if (maxIterationsFactor < MIN_MAX_ITERATIONS_FACTOR) {
500 throw new IllegalArgumentException();
501 }
502
503 this.maxIterationsFactor = maxIterationsFactor;
504 }
505
506 /**
507 * Returns amount of progress variation before notifying a progress change
508 * during comparison computation.
509 *
510 * @return amount of progress variation before notifying a progress change
511 * during comparison computation.
512 */
513 public float getProgressDelta() {
514 return progressDelta;
515 }
516
517 /**
518 * Sets amount of progress variation before notifying a progress change
519 * during comparison computation.
520 *
521 * @param progressDelta amount of progress variation before notifying a
522 * progress change during comparison computation.
523 * @throws IllegalArgumentException if progress delta is less than zero or
524 * greater than 1.
525 * @throws LockedException if this estimator is locked.
526 */
527 public void setProgressDelta(final float progressDelta) throws LockedException {
528 if (isLocked()) {
529 throw new LockedException();
530 }
531 if (progressDelta < MIN_PROGRESS_DELTA || progressDelta > MAX_PROGRESS_DELTA) {
532 throw new IllegalArgumentException();
533 }
534 this.progressDelta = progressDelta;
535 }
536
537 /**
538 * Compares two fundamental matrices and returns the comparison value.
539 * Comparison value will depend on the method implemented to compare both
540 * fundamental matrices.
541 *
542 * @return comparison value. Typically, the smaller the absolute value the
543 * more similar the fundamental matrices are.
544 * @throws NotReadyException if this comparator is not yet ready to start
545 * the comparison.
546 * @throws LockedException if this instance is locked.
547 * @throws FundamentalMatrixComparatorException if comparison fails due to
548 * some other reason.
549 */
550 @SuppressWarnings("DuplicatedCode")
551 @Override
552 public double compare() throws NotReadyException, LockedException, FundamentalMatrixComparatorException {
553 if (isLocked()) {
554 throw new LockedException();
555 }
556 if (!isReady()) {
557 throw new NotReadyException();
558 }
559
560 try {
561 locked = true;
562
563 if (listener != null) {
564 listener.onCompareStart(this);
565 }
566
567 final var minHorizontalDisparity = minHorizontalDisparityFactor * (maxX - minX);
568 final var maxHorizontalDisparity = maxHorizontalDisparityFactor * (maxX - minX);
569 final var minVerticalDisparity = minVerticalDisparityFactor * (maxY - minY);
570 final var maxVerticalDisparity = maxVerticalDisparityFactor * (maxY - minY);
571
572 double d1;
573 double d1prime;
574 double d2;
575 double d2prime;
576 double inhomX;
577 double inhomY;
578 boolean repeat;
579 int counter;
580 final var m1 = Point2D.create(CoordinatesType.HOMOGENEOUS_COORDINATES);
581 final var m2 = Point2D.create(CoordinatesType.HOMOGENEOUS_COORDINATES);
582 final var l1real = new Line2D();
583 final var l1est = new Line2D();
584 final var l2real = new Line2D();
585 final var l2est = new Line2D();
586 final var randomizer = new UniformRandomizer();
587 var avgDist = 0.0;
588 final var maxIterations = (int) (nSamples * maxIterationsFactor);
589 var currentIter = 0;
590 float progress;
591 var previousProgress = 0.0f;
592 for (var i = 0; i < nSamples; i++) {
593 repeat = true;
594 counter = 0;
595 while (repeat && (counter < nSamples)) {
596 // set x value
597 inhomX = randomizer.nextDouble(minX, maxX);
598
599 // set y value
600 inhomY = randomizer.nextDouble(minY, maxY);
601 m1.setInhomogeneousCoordinates(inhomX, inhomY);
602 m1.normalize();
603
604 // real epipolar line for random point m1
605 groundTruthFundamentalMatrix.rightEpipolarLine(m1, l2real);
606 l2real.normalize();
607
608 // check that epipolar line lies within retinal plane size
609 // taking into account the following equation
610 // x*l2.getA() + y*l2.getB() + l2.getC() = 0
611 double yMinX;
612 double yMaxX;
613 if (Math.abs(l2real.getB()) > Double.MIN_VALUE) {
614 // for x = mMinX
615 yMinX = -(minX * l2real.getA() + l2real.getC()) / l2real.getB();
616
617 // for x = mMaxX
618 yMaxX = -(maxX * l2real.getA() + l2real.getC()) / l2real.getB();
619 } else {
620 yMinX = l2real.getA() >= 0.0 ? -Double.MAX_VALUE : Double.MAX_VALUE;
621 yMaxX = -yMinX;
622 }
623
624 // for y = mMinY
625 final var xMinY = -(minY * l2real.getB() + l2real.getC()) / l2real.getA();
626
627 // for y = mMaxY
628 final var xMaxY = -(maxY * l2real.getB() + l2real.getC()) / l2real.getA();
629
630 // if epipolar line does not intersect second image, we need
631 // to repeat with a different sample
632 repeat = (((yMinX < minY) && (yMaxX < minY)) || ((yMinX > maxY)
633 && (yMaxX > maxY)) || ((xMinY < minX) && (xMaxY < minX))
634 || ((xMinY > maxX) && (xMaxY > maxX)));
635 counter++;
636 currentIter++;
637 }
638
639 if (counter >= nSamples) {
640 continue;
641 }
642
643 // choose point lying on epipolar line l2real :
644 // m2.getX() * l2real.getA() + m2.getY() * l2real.getB() +
645 // l2real.getC() = 0
646 // choose random horizontal component within provided disparity:
647 inhomX = m1.getInhomX() + randomizer.nextDouble(minHorizontalDisparity, maxHorizontalDisparity);
648 if (Math.abs(l2real.getB()) > Double.MIN_VALUE) {
649 inhomY = -(inhomX * l2real.getA() + l2real.getC()) / l2real.getB();
650 } else {
651 inhomY = Double.MAX_VALUE;
652 }
653
654 // if point lies outside retinal plane limits, try setting random
655 // vertical component within provided disparity
656 if ((inhomY < minY) || (inhomY > maxY)) {
657 inhomY = m1.getInhomY() + randomizer.nextDouble(minVerticalDisparity, maxVerticalDisparity);
658 inhomX = -(inhomY * l2real.getB() + l2real.getC()) / l2real.getA();
659 }
660
661 m2.setInhomogeneousCoordinates(inhomX, inhomY);
662 m2.normalize();
663
664 // estimated epipolar line for some random point m1
665 otherFundamentalMatrix.rightEpipolarLine(m1, l2est);
666 l2est.normalize();
667
668 // compute distance from l2est to m2 (distance from estimated to
669 // real)
670 d1prime = Math.abs(l2est.signedDistance(m2));
671
672 otherFundamentalMatrix.leftEpipolarLine(m2, l1est);
673 l1est.normalize();
674 d1 = Math.abs(l1est.signedDistance(m1));
675
676 // repeat reversing roles of ground truth and other fundamental
677 // matrix
678 repeat = true;
679 counter = 0;
680 while (repeat && (counter < nSamples)) {
681 // set x value
682 inhomX = randomizer.nextDouble(minX, maxX);
683
684 // set y value
685 inhomY = randomizer.nextDouble(minY, maxY);
686 m1.setInhomogeneousCoordinates(inhomX, inhomY);
687 m1.normalize();
688
689 // real epipolar line for random point m1
690 otherFundamentalMatrix.rightEpipolarLine(m1, l2est);
691 l2est.normalize();
692
693 // check that epipolar line lies within retinal plane size
694 // taking into account the following equation
695 // x*l2.getA() + y*l2.getB() + l2.getC() = 0
696 double yMinX;
697 double yMaxX;
698 if (Math.abs(l2est.getB()) > Double.MIN_VALUE) {
699 // for x = mMinX
700 yMinX = -(minX * l2est.getA() + l2est.getC()) / l2est.getB();
701
702 // for x = mMaxX
703 yMaxX = -(maxX * l2est.getA() + l2est.getC()) / l2est.getB();
704 } else {
705 yMinX = l2est.getA() >= 0.0 ? -Double.MAX_VALUE : Double.MAX_VALUE;
706 yMaxX = -yMinX;
707 }
708
709 // for y = mMinY
710 final var xMinY = -(minY * l2est.getB() + l2est.getC()) / l2est.getA();
711
712 // for y = mMaxY
713 final var xMaxY = -(maxY * l2est.getB() + l2est.getC()) / l2est.getA();
714
715 // if epipolar line does not intersect second image, we need
716 // to repeat with a different sample
717 repeat = (((yMinX < minY) && (yMaxX < minY)) || ((yMinX > maxY)
718 && (yMaxX > maxY)) || ((xMinY < minX) && (xMaxY < minX))
719 || ((xMinY > maxX) && (xMaxY > maxX)));
720 counter++;
721 currentIter++;
722 }
723
724 if (counter >= nSamples) {
725 continue;
726 }
727
728 // choose point lying on epipolar line l2est :
729 // m2.getX() * l2est.getA() + m2.getY() * l2est.getB() +
730 // l2est.getC() = 0
731 // choose random horizontal component within provided disparity:
732 inhomX = m1.getInhomX() + randomizer.nextDouble(minHorizontalDisparity, maxHorizontalDisparity);
733 if (Math.abs(l2real.getB()) > Double.MIN_VALUE) {
734 inhomY = -(inhomX * l2est.getA() + l2est.getC()) / l2est.getB();
735 } else {
736 inhomY = Double.MAX_VALUE;
737 }
738
739 // if point lies outside retinal plane limits, try setting random
740 // Vertical component within provided disparity
741 if ((inhomY < minY) || (inhomY > maxY)) {
742 inhomY = m1.getInhomY() + randomizer.nextDouble(minVerticalDisparity, maxVerticalDisparity);
743 inhomX = -(inhomY * l2est.getB() + l2est.getC()) / l2est.getA();
744 }
745
746 m2.setInhomogeneousCoordinates(inhomX, inhomY);
747 m2.normalize();
748
749 // estimated epipolar line for some random point m1
750 otherFundamentalMatrix.rightEpipolarLine(m1, l2real);
751 l2real.normalize();
752
753 // compute distance from l2real to m2 (distance from estimated to
754 // real)
755 d2prime = Math.abs(l2real.signedDistance(m2));
756
757 otherFundamentalMatrix.leftEpipolarLine(m2, l1real);
758 l1real.normalize();
759 d2 = Math.abs(l1real.signedDistance(m1));
760
761 avgDist += (d1 + d1prime + d2 + d2prime) / 4.0;
762
763 if (currentIter > maxIterations) {
764 throw new FundamentalMatrixComparatorException();
765 }
766
767 progress = (float) currentIter / (float) maxIterations;
768
769 if (listener != null && progress - previousProgress > progressDelta) {
770 previousProgress = progress;
771 listener.onCompareProgressChange(this, progress);
772 }
773 }
774
775
776 if (listener != null) {
777 listener.onCompareEnd(this);
778 }
779
780 return avgDist / nSamples;
781
782 } finally {
783 locked = false;
784 }
785 }
786
787 /**
788 * Returns type of comparator.
789 *
790 * @return type of comparator.
791 */
792 @Override
793 public FundamentalMatrixComparatorType getType() {
794 return FundamentalMatrixComparatorType.EPIPOLAR_DISTANCE_COMPARATOR;
795 }
796
797 /**
798 * Initializes default settings.
799 */
800 private void init() {
801 minX = DEFAULT_MIN_X;
802 maxX = DEFAULT_MAX_X;
803 minY = DEFAULT_MIN_Y;
804 maxY = DEFAULT_MAX_Y;
805 nSamples = DEFAULT_N_SAMPLES;
806 minHorizontalDisparityFactor = minVerticalDisparityFactor = DEFAULT_MIN_DISPARITY_FACTOR;
807 maxHorizontalDisparityFactor = maxVerticalDisparityFactor = DEFAULT_MAX_DISPARITY_FACTOR;
808 maxIterationsFactor = DEFAULT_MAX_ITERATIONS_FACTOR;
809 progressDelta = DEFAULT_PROGRESS_DELTA;
810 }
811 }