1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package com.irurueta.ar.calibration.estimators;
17
18 import com.irurueta.ar.calibration.ImageOfAbsoluteConic;
19 import com.irurueta.geometry.HomogeneousPoint3D;
20 import com.irurueta.geometry.MatrixRotation3D;
21 import com.irurueta.geometry.PinholeCamera;
22 import com.irurueta.geometry.ProjectiveTransformation2D;
23 import com.irurueta.geometry.Transformation2D;
24 import com.irurueta.geometry.estimators.LockedException;
25 import com.irurueta.geometry.estimators.NotReadyException;
26
27 import java.util.ArrayList;
28
29
30
31
32
33
34
35
36
37 public class SingleHomographyPinholeCameraEstimator {
38
39
40
41
42 public static final double DEFAULT_ASPECT_RATIO = 1.0;
43
44
45
46
47 private double focalDistanceAspectRatio = DEFAULT_ASPECT_RATIO;
48
49
50
51
52 private Transformation2D homography;
53
54
55
56
57 private boolean locked = false;
58
59
60
61
62 private SingleHomographyPinholeCameraEstimatorListener listener;
63
64
65
66
67 public SingleHomographyPinholeCameraEstimator() {
68 }
69
70
71
72
73
74
75
76 public SingleHomographyPinholeCameraEstimator(final SingleHomographyPinholeCameraEstimatorListener listener) {
77 this.listener = listener;
78 }
79
80
81
82
83
84
85
86 public SingleHomographyPinholeCameraEstimator(final Transformation2D homography) {
87 internalSetHomography(homography);
88 }
89
90
91
92
93
94
95
96
97 public SingleHomographyPinholeCameraEstimator(
98 final Transformation2D homography, final SingleHomographyPinholeCameraEstimatorListener listener) {
99 internalSetHomography(homography);
100 this.listener = listener;
101 }
102
103
104
105
106
107
108 public double getFocalDistanceAspectRatio() {
109 return focalDistanceAspectRatio;
110 }
111
112
113
114
115
116
117
118 public void setFocalDistanceAspectRatio(final double focalDistanceAspectRatio) throws LockedException {
119 if (locked) {
120 throw new LockedException();
121 }
122 this.focalDistanceAspectRatio = focalDistanceAspectRatio;
123 }
124
125
126
127
128
129
130 public Transformation2D getHomography() {
131 return homography;
132 }
133
134
135
136
137
138
139
140 public void setHomography(final Transformation2D homography) throws LockedException {
141 if (locked) {
142 throw new LockedException();
143 }
144 this.homography = homography;
145 }
146
147
148
149
150
151
152
153 public boolean isReady() {
154 return homography != null;
155 }
156
157
158
159
160
161
162
163 public SingleHomographyPinholeCameraEstimatorListener getListener() {
164 return listener;
165 }
166
167
168
169
170
171
172
173
174 public void setListener(final SingleHomographyPinholeCameraEstimatorListener listener) throws LockedException {
175 if (locked) {
176 throw new LockedException();
177 }
178 this.listener = listener;
179 }
180
181
182
183
184
185
186 public boolean isLocked() {
187 return locked;
188 }
189
190
191
192
193
194
195
196
197
198
199 public PinholeCamera estimate() throws LockedException, NotReadyException,
200 SingleHomographyPinholeCameraEstimatorException {
201 final var result = new PinholeCamera();
202 estimate(result);
203 return result;
204 }
205
206
207
208
209
210
211
212
213
214
215 public void estimate(PinholeCamera result) throws LockedException, NotReadyException,
216 SingleHomographyPinholeCameraEstimatorException {
217 if (locked) {
218 throw new LockedException();
219 }
220
221 if (!isReady()) {
222 throw new NotReadyException();
223 }
224
225 try {
226 locked = true;
227
228 if (listener != null) {
229 listener.onEstimateStart(this);
230 }
231
232
233 final var homographies = new ArrayList<Transformation2D>();
234 homographies.add(homography);
235
236 homographies.add(((ProjectiveTransformation2D) homography).inverseAndReturnNew());
237 final var intrinsicEstimator = new LMSEImageOfAbsoluteConicEstimator(homographies);
238 intrinsicEstimator.setPrincipalPointAtOrigin(true);
239 intrinsicEstimator.setFocalDistanceAspectRatioKnown(true);
240 intrinsicEstimator.setFocalDistanceAspectRatio(focalDistanceAspectRatio);
241 ImageOfAbsoluteConic iac = intrinsicEstimator.estimate();
242 iac.normalize();
243
244 final var intrinsic = iac.getIntrinsicParameters();
245
246
247 final var rotation = new MatrixRotation3D();
248 final var center = new HomogeneousPoint3D();
249 CameraPoseEstimator.estimate(intrinsic, homography, rotation, center, result);
250
251 if (listener != null) {
252 listener.onEstimateEnd(this);
253 }
254
255 } catch (final Exception e) {
256 throw new SingleHomographyPinholeCameraEstimatorException(e);
257 } finally {
258 locked = false;
259 }
260 }
261
262
263
264
265
266
267
268 private void internalSetHomography(final Transformation2D homography) {
269 if (homography == null) {
270 throw new NullPointerException();
271 }
272 this.homography = homography;
273 }
274 }