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.estimators;
17
18 import com.irurueta.ar.epipolar.FundamentalMatrix;
19 import com.irurueta.geometry.Point2D;
20 import com.irurueta.geometry.estimators.LockedException;
21 import com.irurueta.geometry.estimators.NotReadyException;
22
23 import java.util.List;
24
25 /**
26 * Base class for a non-robust fundamental matrix estimator.
27 */
28 public abstract class FundamentalMatrixEstimator {
29
30 /**
31 * Default method for non-robust fundamental matrix estimation.
32 */
33 public static final FundamentalMatrixEstimatorMethod DEFAULT_METHOD =
34 FundamentalMatrixEstimatorMethod.SEVEN_POINTS_ALGORITHM;
35
36 /**
37 * Listener to be notified of events generated by this fundamental matrix
38 * estimator.
39 */
40 protected FundamentalMatrixEstimatorListener listener;
41
42 /**
43 * List of 2D points corresponding to left view.
44 */
45 protected List<Point2D> leftPoints;
46
47 /**
48 * List of 2D points corresponding to right view.
49 */
50 protected List<Point2D> rightPoints;
51
52 /**
53 * Indicates whether this instance is locked because estimation is being
54 * computed.
55 */
56 protected boolean locked;
57
58 /**
59 * Constructor.
60 */
61 protected FundamentalMatrixEstimator() {
62 }
63
64 /**
65 * Constructor with matched 2D points.
66 *
67 * @param leftPoints 2D points on left view.
68 * @param rightPoints 2D points on right view.
69 * @throws IllegalArgumentException if provided list of points do not
70 * have the same length.
71 */
72 protected FundamentalMatrixEstimator(final List<Point2D> leftPoints, final List<Point2D> rightPoints) {
73 internalSetPoints(leftPoints, rightPoints);
74 }
75
76 /**
77 * Returns matched 2D points on left view.
78 *
79 * @return 2D points on left view.
80 */
81 public List<Point2D> getLeftPoints() {
82 return leftPoints;
83 }
84
85 /**
86 * Returns matched 2D points on right view.
87 *
88 * @return 2D points on right view.
89 */
90 public List<Point2D> getRightPoints() {
91 return rightPoints;
92 }
93
94 /**
95 * Sets matched 2D points on both left and right views.
96 *
97 * @param leftPoints matched 2D points on left view.
98 * @param rightPoints matched 2D points on right view.
99 * @throws LockedException if this fundamental matrix estimator is locked.
100 * @throws IllegalArgumentException if provided matched points on left and
101 * right views do not have the same length.
102 */
103 public void setPoints(final List<Point2D> leftPoints, final List<Point2D> rightPoints) throws LockedException {
104 if (isLocked()) {
105 throw new LockedException();
106 }
107
108 internalSetPoints(leftPoints, rightPoints);
109 }
110
111 /**
112 * Returns listener to be notified of events generated by this fundamental
113 * matrix estimator.
114 *
115 * @return listener to be notified of events generated by this fundamental
116 * matrix estimator.
117 */
118 public FundamentalMatrixEstimatorListener getListener() {
119 return listener;
120 }
121
122 /**
123 * Sets listener to be notified of events generated by this fundamental
124 * matrix estimator.
125 *
126 * @param listener listener to be notified of events generated by this
127 * fundamental matrix estimator.
128 * @throws LockedException if this estimator is locked.
129 */
130 public void setListener(final FundamentalMatrixEstimatorListener listener) throws LockedException {
131 if (isLocked()) {
132 throw new LockedException();
133 }
134
135 this.listener = listener;
136 }
137
138 /**
139 * Returns boolean indicating if estimator is locked because estimation is
140 * under progress.
141 *
142 * @return true if estimator is locked, false otherwise.
143 */
144 public boolean isLocked() {
145 return locked;
146 }
147
148 /**
149 * Returns boolean indicating whether estimator is ready to start the
150 * fundamental matrix estimation.
151 * This is true when the required number of matched points is provided to
152 * obtain a solution.
153 *
154 * @return true if estimator is ready to start the fundamental matrix
155 * estimation, false otherwise.
156 */
157 public abstract boolean isReady();
158
159 /**
160 * Estimates a fundamental matrix using provided lists of matched points on
161 * left and right views.
162 *
163 * @return a fundamental matrix.
164 * @throws LockedException if estimator is locked doing an estimation.
165 * @throws NotReadyException if estimator is not ready because required
166 * input points have not already been provided.
167 * @throws FundamentalMatrixEstimatorException if configuration of provided
168 * 2D points is degenerate and fundamental matrix
169 * estimation fails.
170 */
171 public abstract FundamentalMatrix estimate() throws LockedException, NotReadyException,
172 FundamentalMatrixEstimatorException;
173
174 /**
175 * Returns method of non-robust fundamental matrix estimator.
176 *
177 * @return method of fundamental matrix estimator.
178 */
179 public abstract FundamentalMatrixEstimatorMethod getMethod();
180
181 /**
182 * Returns minimum number of matched pair of points required to start
183 * the estimation.
184 *
185 * @return minimum number of matched pair of points required to start
186 * the estimation.
187 */
188 public abstract int getMinRequiredPoints();
189
190 /**
191 * Creates an instance of a fundamental matrix estimator using provided
192 * method.
193 *
194 * @param method a fundamental matrix estimator method.
195 * @return an instance of a fundamental matrix estimator.
196 */
197 public static FundamentalMatrixEstimator create(final FundamentalMatrixEstimatorMethod method) {
198 return switch (method) {
199 case AFFINE_ALGORITHM -> new AffineFundamentalMatrixEstimator();
200 case EIGHT_POINTS_ALGORITHM -> new EightPointsFundamentalMatrixEstimator();
201 default -> new SevenPointsFundamentalMatrixEstimator();
202 };
203 }
204
205 /**
206 * Creates an instance of a fundamental matrix estimator using provided
207 * matched 2D points on left and right views and provided method.
208 *
209 * @param leftPoints matched 2D points on left view.
210 * @param rightPoints matched 2D points on right view.
211 * @param method a fundamental matrix estimator method.
212 * @return an instance of a fundamental matrix estimator.
213 * @throws IllegalArgumentException if provided list of points do not
214 * have the same length.
215 */
216 public static FundamentalMatrixEstimator create(
217 final List<Point2D> leftPoints, final List<Point2D> rightPoints,
218 final FundamentalMatrixEstimatorMethod method) {
219 return switch (method) {
220 case AFFINE_ALGORITHM -> new AffineFundamentalMatrixEstimator(leftPoints, rightPoints);
221 case EIGHT_POINTS_ALGORITHM -> new EightPointsFundamentalMatrixEstimator(leftPoints, rightPoints);
222 default -> new SevenPointsFundamentalMatrixEstimator(leftPoints, rightPoints);
223 };
224 }
225
226 /**
227 * Creates an instance of a fundamental matrix estimator using default
228 * method.
229 *
230 * @return an instance of a fundamental matrix estimator.
231 */
232 public static FundamentalMatrixEstimator create() {
233 return create(DEFAULT_METHOD);
234 }
235
236 /**
237 * Creates an instance of a fundamental matrix estimator using provided
238 * matched 2D points on left and right views and default method.
239 *
240 * @param leftPoints matched 2D points on left view.
241 * @param rightPoints matched 2D points on right view.
242 * @return an instance of a fundamental matrix estimator.
243 * @throws IllegalArgumentException if provided list of points do not
244 * have the same length.
245 */
246 public static FundamentalMatrixEstimator create(final List<Point2D> leftPoints, final List<Point2D> rightPoints) {
247 return create(leftPoints, rightPoints, DEFAULT_METHOD);
248 }
249
250 /**
251 * Sets matched 2D points on left and right views.
252 * This method does not check whether instance is locked or not.
253 *
254 * @param leftPoints matched 2D points on left view.
255 * @param rightPoints matched 2D points on right view.
256 * @throws IllegalArgumentException if provided lists of points don't have
257 * the same size.
258 */
259 private void internalSetPoints(final List<Point2D> leftPoints, final List<Point2D> rightPoints) {
260 if (leftPoints.size() != rightPoints.size()) {
261 throw new IllegalArgumentException();
262 }
263
264 this.leftPoints = leftPoints;
265 this.rightPoints = rightPoints;
266 }
267 }