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
24 import java.util.ArrayList;
25 import java.util.List;
26
27 /**
28 * Fixes matched pairs of points so that they perfectly follow a given epipolar
29 * geometry.
30 * When matching points typically the matching precision is about 1 pixel,
31 * however this makes that matched points under a given epipolar geometry (i.e.
32 * fundamental or essential matrix), do not lie perfectly on the corresponding
33 * epipolar plane or epipolar lines.
34 * The consequence is that triangularization of these matches will fail or
35 * produce inaccurate results.
36 * By fixing matched points using a corrector following a given epipolar
37 * geometry, this effect is alleviated.
38 * This corrector uses the Sampson approximation which is capable to remove
39 * small errors when matches are close to their real epipolar lines. This method
40 * is faster than the Gold Standard method, but can only correct small errors
41 * (1 or 2 pixels).
42 */
43 public class SampsonCorrector extends Corrector {
44
45 /**
46 * Constructor.
47 */
48 public SampsonCorrector() {
49 super();
50 }
51
52 /**
53 * Constructor.
54 *
55 * @param fundamentalMatrix fundamental matrix to be set.
56 */
57 public SampsonCorrector(final FundamentalMatrix fundamentalMatrix) {
58 super(fundamentalMatrix);
59 }
60
61 /**
62 * Constructor.
63 *
64 * @param leftPoints points to be corrected on left view.
65 * @param rightPoints points to be corrected on right view.
66 * @throws IllegalArgumentException if provided lists of points don't have
67 * the same size.
68 */
69 public SampsonCorrector(final List<Point2D> leftPoints, final List<Point2D> rightPoints) {
70 super(leftPoints, rightPoints);
71 }
72
73 /**
74 * Constructor.
75 *
76 * @param leftPoints points to be corrected on left view.
77 * @param rightPoints points to be corrected on right view.
78 * @param fundamentalMatrix fundamental matrix to be set.
79 * @throws IllegalArgumentException if provided lists of points don't have
80 * the same size.
81 */
82 public SampsonCorrector(final List<Point2D> leftPoints, final List<Point2D> rightPoints,
83 final FundamentalMatrix fundamentalMatrix) {
84 super(leftPoints, rightPoints, fundamentalMatrix);
85 }
86
87 /**
88 * Constructor.
89 *
90 * @param listener listener to handle events generated by this class.
91 */
92 public SampsonCorrector(final CorrectorListener listener) {
93 super(listener);
94 }
95
96 /**
97 * Constructor.
98 *
99 * @param fundamentalMatrix fundamental matrix to be set.
100 * @param listener listener to handle events generated by this class.
101 */
102 public SampsonCorrector(final FundamentalMatrix fundamentalMatrix, final CorrectorListener listener) {
103 super(fundamentalMatrix, listener);
104 }
105
106 /**
107 * Constructor.
108 *
109 * @param leftPoints points to be corrected on left view.
110 * @param rightPoints points to be corrected on right view.
111 * @param listener listener to handle events generated by this class.
112 * @throws IllegalArgumentException if provided lists of points don't have
113 * the same size.
114 */
115 public SampsonCorrector(final List<Point2D> leftPoints, final List<Point2D> rightPoints,
116 final CorrectorListener listener) {
117 super(leftPoints, rightPoints, listener);
118 }
119
120 /**
121 * Constructor.
122 *
123 * @param leftPoints points to be corrected on left view.
124 * @param rightPoints points to be corrected on right view.
125 * @param fundamentalMatrix fundamental matrix to be set.
126 * @param listener listener to handle events generated by this class.
127 * @throws IllegalArgumentException if provided lists of points don't have
128 * the same size.
129 */
130 public SampsonCorrector(final List<Point2D> leftPoints, final List<Point2D> rightPoints,
131 final FundamentalMatrix fundamentalMatrix, final CorrectorListener listener) {
132 super(leftPoints, rightPoints, fundamentalMatrix, listener);
133 }
134
135 /**
136 * Corrects the lists of provided matched points to be corrected.
137 *
138 * @throws NotReadyException if this instance is not ready (either points or
139 * fundamental matrix has not been provided yet).
140 * @throws LockedException if this instance is locked doing computations.
141 */
142 @SuppressWarnings("DuplicatedCode")
143 @Override
144 public void correct() throws NotReadyException, LockedException {
145 if (isLocked()) {
146 throw new LockedException();
147 }
148 if (!isReady()) {
149 throw new NotReadyException();
150 }
151
152 locked = true;
153
154 if (listener != null) {
155 listener.onCorrectStart(this);
156 }
157
158 // epipolar lines to be reused for memory efficiency
159 final var leftEpipolarLine = new Line2D();
160 final var rightEpipolarLine = new Line2D();
161
162 leftCorrectedPoints = new ArrayList<>();
163 rightCorrectedPoints = new ArrayList<>();
164
165 final var size = leftPoints.size();
166 float progress;
167 var previousProgress = 0.0f;
168 for (var i = 0; i < size; i++) {
169 final var leftPoint = leftPoints.get(i);
170 final var rightPoint = rightPoints.get(i);
171
172 final var leftCorrectedPoint = Point2D.create(CoordinatesType.HOMOGENEOUS_COORDINATES);
173 final var rightCorrectedPoint = Point2D.create(CoordinatesType.HOMOGENEOUS_COORDINATES);
174
175 // correct single pair
176 SampsonSingleCorrector.correct(leftPoint, rightPoint, fundamentalMatrix, leftCorrectedPoint,
177 rightCorrectedPoint, leftEpipolarLine, rightEpipolarLine);
178
179 leftCorrectedPoints.add(leftCorrectedPoint);
180 rightCorrectedPoints.add(rightCorrectedPoint);
181
182 if (listener != null) {
183 progress = i / (float) size;
184 if (progress - previousProgress > progressDelta) {
185 // progress has changed significantly
186 previousProgress = progress;
187 listener.onCorrectProgressChange(this, progress);
188 }
189 }
190 }
191
192 if (listener != null) {
193 listener.onCorrectEnd(this);
194 }
195
196 locked = false;
197 }
198
199 /**
200 * Gets type of correction being used.
201 *
202 * @return type of correction.
203 */
204 @Override
205 public CorrectorType getType() {
206 return CorrectorType.SAMPSON_CORRECTOR;
207 }
208 }