View Javadoc
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 }