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.algebra.AlgebraException;
19 import com.irurueta.algebra.ArrayUtils;
20 import com.irurueta.algebra.Matrix;
21 import com.irurueta.algebra.SingularValueDecomposer;
22 import com.irurueta.algebra.Utils;
23 import com.irurueta.geometry.CoordinatesType;
24 import com.irurueta.geometry.GeometryException;
25 import com.irurueta.geometry.MatrixRotation3D;
26 import com.irurueta.geometry.PinholeCamera;
27 import com.irurueta.geometry.PinholeCameraIntrinsicParameters;
28 import com.irurueta.geometry.Point3D;
29 import com.irurueta.geometry.ProjectiveTransformation2D;
30 import com.irurueta.geometry.Rotation3D;
31 import com.irurueta.geometry.Transformation2D;
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46 public class CameraPoseEstimator {
47
48
49
50
51 private Rotation3D rotation;
52
53
54
55
56 private Point3D cameraCenter;
57
58
59
60
61 private PinholeCamera camera;
62
63
64
65
66
67
68
69
70
71
72 public void estimate(final PinholeCameraIntrinsicParameters intrinsic, final Transformation2D homography)
73 throws AlgebraException, GeometryException {
74 rotation = new MatrixRotation3D();
75 cameraCenter = Point3D.create(CoordinatesType.HOMOGENEOUS_COORDINATES);
76 camera = new PinholeCamera();
77 estimate(intrinsic, homography, rotation, cameraCenter, camera);
78 }
79
80
81
82
83
84
85 public Rotation3D getRotation() {
86 return rotation;
87 }
88
89
90
91
92
93
94 public Point3D getCameraCenter() {
95 return cameraCenter;
96 }
97
98
99
100
101
102
103 public PinholeCamera getCamera() {
104 return camera;
105 }
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120 public static void estimate(
121 final PinholeCameraIntrinsicParameters intrinsic,
122 final Transformation2D homography,
123 final Rotation3D estimatedRotation,
124 final Point3D estimatedCameraCenter,
125 final PinholeCamera estimatedCamera)
126 throws AlgebraException, GeometryException {
127
128
129
130
131 final var intrinsicInvMatrix = intrinsic.getInverseInternalMatrix();
132
133 if (homography instanceof ProjectiveTransformation2D projectiveTransformation2D) {
134 projectiveTransformation2D.normalize();
135 }
136 final var homographyMatrix = homography.asMatrix();
137
138 final var h1 = homographyMatrix.getSubmatrix(0, 0, 2, 0);
139 final var h2 = homographyMatrix.getSubmatrix(
140 0, 1, 2, 1);
141 final var h3 = homographyMatrix.getSubmatrix(0, 2, 2, 2);
142
143 final var matR1 = intrinsicInvMatrix.multiplyAndReturnNew(h1);
144 final var matR2 = intrinsicInvMatrix.multiplyAndReturnNew(h2);
145 final var matT = intrinsicInvMatrix.multiplyAndReturnNew(h3);
146
147
148
149
150
151
152 final var norm1 = Utils.normF(matR1);
153 final var norm2 = Utils.normF(matR2);
154 final var invNorm = 2.0 / (norm1 + norm2);
155 matR1.multiplyByScalar(invNorm);
156 matR2.multiplyByScalar(invNorm);
157
158
159
160 matT.multiplyByScalar(invNorm);
161
162 final var r1 = matR1.getBuffer();
163 final var r2 = matR2.getBuffer();
164
165
166
167 final var r3 = Utils.crossProduct(r1, r2);
168 ArrayUtils.normalize(r3);
169
170 final var rot = new Matrix(3, 3);
171 rot.setSubmatrix(0, 0, 2, 0, r1);
172 rot.setSubmatrix(0, 1, 2, 1, r2);
173 rot.setSubmatrix(0, 2, 2, 2, r3);
174
175
176
177
178
179
180
181 final var decomposer = new SingularValueDecomposer(rot);
182 decomposer.decompose();
183 final var u = decomposer.getU();
184 final var v = decomposer.getV();
185 v.transpose();
186
187
188
189 u.multiply(v, rot);
190
191
192
193 final var det = Utils.det(rot);
194 if (det < 0.0) {
195 rot.multiplyByScalar(-1.0);
196 }
197
198 estimatedRotation.fromMatrix(rot);
199
200
201
202
203
204 final var invRot = rot.transposeAndReturnNew();
205 invRot.multiply(matT);
206 invRot.multiplyByScalar(-1.0);
207
208 final var centerBuffer = invRot.getBuffer();
209 estimatedCameraCenter.setInhomogeneousCoordinates(centerBuffer[0], centerBuffer[1], centerBuffer[2]);
210
211
212
213
214 estimatedCamera.setIntrinsicAndExtrinsicParameters(intrinsic, estimatedRotation, estimatedCameraCenter);
215 }
216 }