1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package com.irurueta.geometry.estimators;
17
18 import com.irurueta.geometry.CoordinatesType;
19 import com.irurueta.geometry.PinholeCamera;
20 import com.irurueta.geometry.Point2D;
21 import com.irurueta.geometry.Point3D;
22 import com.irurueta.numerical.robust.MSACRobustEstimator;
23 import com.irurueta.numerical.robust.MSACRobustEstimatorListener;
24 import com.irurueta.numerical.robust.RobustEstimator;
25 import com.irurueta.numerical.robust.RobustEstimatorException;
26 import com.irurueta.numerical.robust.RobustEstimatorMethod;
27
28 import java.util.ArrayList;
29 import java.util.List;
30
31
32
33
34
35 @SuppressWarnings("DuplicatedCode")
36 public class MSACDLTPointCorrespondencePinholeCameraRobustEstimator extends
37 DLTPointCorrespondencePinholeCameraRobustEstimator {
38
39
40
41
42
43
44
45 public static final double DEFAULT_THRESHOLD = 1.0;
46
47
48
49
50
51 public static final double MIN_THRESHOLD = 0.0;
52
53
54
55
56
57
58
59 private double threshold;
60
61
62
63
64 public MSACDLTPointCorrespondencePinholeCameraRobustEstimator() {
65 super();
66 threshold = DEFAULT_THRESHOLD;
67 }
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82 public MSACDLTPointCorrespondencePinholeCameraRobustEstimator(
83 final List<Point3D> points3D, final List<Point2D> points2D) {
84 super(points3D, points2D);
85 threshold = DEFAULT_THRESHOLD;
86 }
87
88
89
90
91
92
93
94 public MSACDLTPointCorrespondencePinholeCameraRobustEstimator(final PinholeCameraRobustEstimatorListener listener) {
95 super(listener);
96 threshold = DEFAULT_THRESHOLD;
97 }
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115 public MSACDLTPointCorrespondencePinholeCameraRobustEstimator(
116 final PinholeCameraRobustEstimatorListener listener,
117 final List<Point3D> points3D, final List<Point2D> points2D) {
118 super(listener, points3D, points2D);
119 threshold = DEFAULT_THRESHOLD;
120 }
121
122
123
124
125
126
127
128
129
130
131 public double getThreshold() {
132 return threshold;
133 }
134
135
136
137
138
139
140
141
142
143
144
145
146
147 public void setThreshold(final double threshold) throws LockedException {
148 if (isLocked()) {
149 throw new LockedException();
150 }
151 if (threshold <= MIN_THRESHOLD) {
152 throw new IllegalArgumentException();
153 }
154 this.threshold = threshold;
155 }
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170 @Override
171 public PinholeCamera estimate() throws LockedException, NotReadyException, RobustEstimatorException {
172 if (isLocked()) {
173 throw new LockedException();
174 }
175 if (!isReady()) {
176 throw new NotReadyException();
177 }
178
179
180 final var nonRobustEstimator = new DLTPointCorrespondencePinholeCameraEstimator();
181
182 nonRobustEstimator.setLMSESolutionAllowed(false);
183 nonRobustEstimator.setPointCorrespondencesNormalized(normalizeSubsetPointCorrespondences);
184
185
186 nonRobustEstimator.setSuggestSkewnessValueEnabled(isSuggestSkewnessValueEnabled());
187 nonRobustEstimator.setSuggestedSkewnessValue(getSuggestedSkewnessValue());
188 nonRobustEstimator.setSuggestHorizontalFocalLengthEnabled(isSuggestHorizontalFocalLengthEnabled());
189 nonRobustEstimator.setSuggestedHorizontalFocalLengthValue(getSuggestedHorizontalFocalLengthValue());
190 nonRobustEstimator.setSuggestVerticalFocalLengthEnabled(isSuggestVerticalFocalLengthEnabled());
191 nonRobustEstimator.setSuggestedVerticalFocalLengthValue(getSuggestedVerticalFocalLengthValue());
192 nonRobustEstimator.setSuggestAspectRatioEnabled(isSuggestAspectRatioEnabled());
193 nonRobustEstimator.setSuggestedAspectRatioValue(getSuggestedAspectRatioValue());
194 nonRobustEstimator.setSuggestPrincipalPointEnabled(isSuggestPrincipalPointEnabled());
195 nonRobustEstimator.setSuggestedPrincipalPointValue(getSuggestedPrincipalPointValue());
196 nonRobustEstimator.setSuggestRotationEnabled(isSuggestRotationEnabled());
197 nonRobustEstimator.setSuggestedRotationValue(getSuggestedRotationValue());
198 nonRobustEstimator.setSuggestCenterEnabled(isSuggestCenterEnabled());
199 nonRobustEstimator.setSuggestedCenterValue(getSuggestedCenterValue());
200
201
202 final var innerEstimator = new MSACRobustEstimator<>(new MSACRobustEstimatorListener<PinholeCamera>() {
203
204
205 private final Point2D testPoint = Point2D.create(CoordinatesType.HOMOGENEOUS_COORDINATES);
206
207
208 private final List<Point3D> subset3D = new ArrayList<>();
209
210
211 private final List<Point2D> subset2D = new ArrayList<>();
212
213 @Override
214 public double getThreshold() {
215 return threshold;
216 }
217
218 @Override
219 public int getTotalSamples() {
220 return points3D.size();
221 }
222
223 @Override
224 public int getSubsetSize() {
225 return PointCorrespondencePinholeCameraRobustEstimator.MIN_NUMBER_OF_POINT_CORRESPONDENCES;
226 }
227
228 @Override
229 public void estimatePreliminarSolutions(final int[] samplesIndices, final List<PinholeCamera> solutions) {
230 subset3D.clear();
231 subset3D.add(points3D.get(samplesIndices[0]));
232 subset3D.add(points3D.get(samplesIndices[1]));
233 subset3D.add(points3D.get(samplesIndices[2]));
234 subset3D.add(points3D.get(samplesIndices[3]));
235 subset3D.add(points3D.get(samplesIndices[4]));
236 subset3D.add(points3D.get(samplesIndices[5]));
237
238 subset2D.clear();
239 subset2D.add(points2D.get(samplesIndices[0]));
240 subset2D.add(points2D.get(samplesIndices[1]));
241 subset2D.add(points2D.get(samplesIndices[2]));
242 subset2D.add(points2D.get(samplesIndices[3]));
243 subset2D.add(points2D.get(samplesIndices[4]));
244 subset2D.add(points2D.get(samplesIndices[5]));
245
246 try {
247 nonRobustEstimator.setLists(subset3D, subset2D);
248
249 final var cam = nonRobustEstimator.estimate();
250 solutions.add(cam);
251 } catch (final Exception e) {
252
253
254 }
255 }
256
257 @Override
258 public double computeResidual(final PinholeCamera currentEstimation, final int i) {
259
260 final var point3D = points3D.get(i);
261 final var point2D = points2D.get(i);
262
263
264 currentEstimation.project(point3D, testPoint);
265
266
267 return testPoint.distanceTo(point2D);
268 }
269
270 @Override
271 public boolean isReady() {
272 return MSACDLTPointCorrespondencePinholeCameraRobustEstimator.this.isReady();
273 }
274
275 @Override
276 public void onEstimateStart(final RobustEstimator<PinholeCamera> estimator) {
277 if (listener != null) {
278 listener.onEstimateStart(MSACDLTPointCorrespondencePinholeCameraRobustEstimator.this);
279 }
280 }
281
282 @Override
283 public void onEstimateEnd(final RobustEstimator<PinholeCamera> estimator) {
284 if (listener != null) {
285 listener.onEstimateEnd(MSACDLTPointCorrespondencePinholeCameraRobustEstimator.this);
286 }
287 }
288
289 @Override
290 public void onEstimateNextIteration(final RobustEstimator<PinholeCamera> estimator, final int iteration) {
291 if (listener != null) {
292 listener.onEstimateNextIteration(
293 MSACDLTPointCorrespondencePinholeCameraRobustEstimator.this, iteration);
294 }
295 }
296
297 @Override
298 public void onEstimateProgressChange(final RobustEstimator<PinholeCamera> estimator, final float progress) {
299 if (listener != null) {
300 listener.onEstimateProgressChange(
301 MSACDLTPointCorrespondencePinholeCameraRobustEstimator.this, progress);
302 }
303 }
304 });
305
306 try {
307 locked = true;
308 inliersData = null;
309 innerEstimator.setConfidence(confidence);
310 innerEstimator.setMaxIterations(maxIterations);
311 innerEstimator.setProgressDelta(progressDelta);
312 final var result = innerEstimator.estimate();
313 inliersData = innerEstimator.getInliersData();
314 return attemptRefine(result, nonRobustEstimator.getMaxSuggestionWeight());
315 } catch (final com.irurueta.numerical.LockedException e) {
316 throw new LockedException(e);
317 } catch (final com.irurueta.numerical.NotReadyException e) {
318 throw new NotReadyException(e);
319 } finally {
320 locked = false;
321 }
322 }
323
324
325
326
327
328
329 @Override
330 public RobustEstimatorMethod getMethod() {
331 return RobustEstimatorMethod.MSAC;
332 }
333
334
335
336
337
338
339
340
341
342
343
344
345 @Override
346 protected double getRefinementStandardDeviation() {
347 return threshold;
348 }
349 }