Skip to content

Commit 2b944e2

Browse files
authored
Merge pull request #1801 from alicevision/dev/equirectangular
Add Equirectangular camera support for SFM
2 parents f0cd5d4 + cab0dc5 commit 2b944e2

21 files changed

+452
-833
lines changed

src/aliceVision/aliceVision.i

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include <aliceVision/camera/IntrinsicBase.hpp>
2626
#include <aliceVision/camera/Pinhole.hpp>
2727
#include <aliceVision/camera/Equidistant.hpp>
28+
#include <aliceVision/camera/Equirectangular.hpp>
2829

2930
using namespace aliceVision;
3031

src/aliceVision/calibration/distortionEstimationGeometry.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include "distortionEstimationGeometry.hpp"
88

99
#include <aliceVision/system/Logger.hpp>
10+
#include <aliceVision/numeric/algebra.hpp>
1011
#include <aliceVision/sfm/bundle/manifolds/so3.hpp>
1112
#include <ceres/ceres.h>
1213
#include <cmath>

src/aliceVision/camera/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ set(camera_files_headers
1414
Undistortion3DEClassicLD.hpp
1515
UndistortionRadial.hpp
1616
Equidistant.hpp
17+
Equirectangular.hpp
1718
IntrinsicBase.hpp
1819
IntrinsicInitMode.hpp
1920
IntrinsicScaleOffset.hpp
@@ -28,6 +29,7 @@ set(camera_files_sources
2829
DistortionRadial.cpp
2930
UndistortionRadial.cpp
3031
Equidistant.cpp
32+
Equirectangular.cpp
3133
IntrinsicBase.cpp
3234
IntrinsicScaleOffset.cpp
3335
IntrinsicScaleOffsetDisto.cpp

src/aliceVision/camera/Camera.i

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,5 @@ using namespace aliceVision::camera;
2929

3030
%include <aliceVision/camera/IntrinsicInitMode.i>
3131
%include <aliceVision/camera/Equidistant.i>
32+
%include <aliceVision/camera/Equirectangular.i>
3233
%include <aliceVision/camera/Pinhole.i>

src/aliceVision/camera/Equidistant.cpp

Lines changed: 0 additions & 197 deletions
Original file line numberDiff line numberDiff line change
@@ -67,203 +67,6 @@ Vec2 Equidistant::project(const Vec4& pt, bool applyDistortion) const
6767
return pt_ima;
6868
}
6969

70-
Eigen::Matrix<double, 2, 9> Equidistant::getDerivativeTransformProjectWrtRotation(const Eigen::Matrix4d& pose, const Vec4& pt) const
71-
{
72-
Eigen::Matrix4d T = pose;
73-
const Vec4 X = T * pt; // apply pose
74-
75-
const Eigen::Matrix<double, 3, 9> d_X_d_R = getJacobian_AB_wrt_A<3, 3, 1>(pose.block<3, 3>(0, 0), pt.head(3));
76-
77-
/* Compute angle with optical center */
78-
double len2d = sqrt(X(0) * X(0) + X(1) * X(1));
79-
Eigen::Matrix<double, 2, 2> d_len2d_d_X;
80-
d_len2d_d_X(0) = X(0) / len2d;
81-
d_len2d_d_X(1) = X(1) / len2d;
82-
83-
const double angle_Z = std::atan2(len2d, X(2));
84-
const double d_angle_Z_d_len2d = X(2) / (len2d * len2d + X(2) * X(2));
85-
86-
/* Ignore depth component and compute radial angle */
87-
const double angle_radial = std::atan2(X(1), X(0));
88-
89-
Eigen::Matrix<double, 2, 3> d_angles_d_X;
90-
d_angles_d_X(0, 0) = -X(1) / (X(0) * X(0) + X(1) * X(1));
91-
d_angles_d_X(0, 1) = X(0) / (X(0) * X(0) + X(1) * X(1));
92-
d_angles_d_X(0, 2) = 0.0;
93-
94-
d_angles_d_X(1, 0) = d_angle_Z_d_len2d * d_len2d_d_X(0);
95-
d_angles_d_X(1, 1) = d_angle_Z_d_len2d * d_len2d_d_X(1);
96-
d_angles_d_X(1, 2) = -len2d / (len2d * len2d + X(2) * X(2));
97-
98-
const double rsensor = std::min(sensorWidth(), sensorHeight());
99-
const double rscale = sensorWidth() / std::max(w(), h());
100-
const double fmm = _scale(0) * rscale;
101-
const double fov = rsensor / fmm;
102-
103-
const double radius = angle_Z / (0.5 * fov);
104-
105-
const double d_radius_d_angle_Z = 1.0 / (0.5 * fov);
106-
107-
/* radius = focal * angle_Z */
108-
const Vec2 P{cos(angle_radial) * radius, sin(angle_radial) * radius};
109-
110-
Eigen::Matrix<double, 2, 2> d_P_d_angles;
111-
d_P_d_angles(0, 0) = -sin(angle_radial) * radius;
112-
d_P_d_angles(0, 1) = cos(angle_radial) * d_radius_d_angle_Z;
113-
d_P_d_angles(1, 0) = cos(angle_radial) * radius;
114-
d_P_d_angles(1, 1) = sin(angle_radial) * d_radius_d_angle_Z;
115-
116-
return getDerivativeCam2ImaWrtPoint() * getDerivativeAddDistoWrtPt(P) * d_P_d_angles * d_angles_d_X * d_X_d_R;
117-
}
118-
119-
Eigen::Matrix<double, 2, 16> Equidistant::getDerivativeTransformProjectWrtPose(const Eigen::Matrix4d& pose, const Vec4& pt) const
120-
{
121-
Eigen::Matrix4d T = pose;
122-
const Vec4 X = T * pt; // apply pose
123-
124-
const Eigen::Matrix<double, 4, 16> d_X_d_T = getJacobian_AB_wrt_A<4, 4, 1>(T, pt);
125-
126-
/* Compute angle with optical center */
127-
double len2d = sqrt(X(0) * X(0) + X(1) * X(1));
128-
Eigen::Matrix<double, 2, 2> d_len2d_d_X;
129-
d_len2d_d_X(0) = X(0) / len2d;
130-
d_len2d_d_X(1) = X(1) / len2d;
131-
132-
const double angle_Z = std::atan2(len2d, X(2));
133-
const double d_angle_Z_d_len2d = X(2) / (len2d * len2d + X(2) * X(2));
134-
135-
/* Ignore depth component and compute radial angle */
136-
const double angle_radial = std::atan2(X(1), X(0));
137-
138-
Eigen::Matrix<double, 2, 3> d_angles_d_X;
139-
d_angles_d_X(0, 0) = -X(1) / (X(0) * X(0) + X(1) * X(1));
140-
d_angles_d_X(0, 1) = X(0) / (X(0) * X(0) + X(1) * X(1));
141-
d_angles_d_X(0, 2) = 0.0;
142-
143-
d_angles_d_X(1, 0) = d_angle_Z_d_len2d * d_len2d_d_X(0);
144-
d_angles_d_X(1, 1) = d_angle_Z_d_len2d * d_len2d_d_X(1);
145-
d_angles_d_X(1, 2) = -len2d / (len2d * len2d + X(2) * X(2));
146-
147-
const double rsensor = std::min(sensorWidth(), sensorHeight());
148-
const double rscale = sensorWidth() / std::max(w(), h());
149-
const double fmm = _scale(0) * rscale;
150-
const double fov = rsensor / fmm;
151-
152-
const double radius = angle_Z / (0.5 * fov);
153-
154-
const double d_radius_d_angle_Z = 1.0 / (0.5 * fov);
155-
156-
/* radius = focal * angle_Z */
157-
const Vec2 P{cos(angle_radial) * radius, sin(angle_radial) * radius};
158-
159-
Eigen::Matrix<double, 2, 2> d_P_d_angles;
160-
d_P_d_angles(0, 0) = -sin(angle_radial) * radius;
161-
d_P_d_angles(0, 1) = cos(angle_radial) * d_radius_d_angle_Z;
162-
d_P_d_angles(1, 0) = cos(angle_radial) * radius;
163-
d_P_d_angles(1, 1) = sin(angle_radial) * d_radius_d_angle_Z;
164-
165-
return getDerivativeCam2ImaWrtPoint() * getDerivativeAddDistoWrtPt(P) * d_P_d_angles * d_angles_d_X * d_X_d_T.block<3, 16>(0, 0);
166-
}
167-
168-
Eigen::Matrix<double, 2, 16> Equidistant::getDerivativeTransformProjectWrtPoseLeft(const Eigen::Matrix4d& pose, const Vec4& pt) const
169-
{
170-
Eigen::Matrix4d T = pose;
171-
const Vec4 X = T * pt; // apply pose
172-
173-
const Eigen::Matrix<double, 4, 16> d_X_d_T = getJacobian_AB_wrt_A<4, 4, 1>(Eigen::Matrix4d::Identity(), X);
174-
175-
/* Compute angle with optical center */
176-
double len2d = sqrt(X(0) * X(0) + X(1) * X(1));
177-
Eigen::Matrix<double, 2, 2> d_len2d_d_X;
178-
d_len2d_d_X(0) = X(0) / len2d;
179-
d_len2d_d_X(1) = X(1) / len2d;
180-
181-
const double angle_Z = std::atan2(len2d, X(2));
182-
const double d_angle_Z_d_len2d = X(2) / (len2d * len2d + X(2) * X(2));
183-
184-
/* Ignore depth component and compute radial angle */
185-
const double angle_radial = std::atan2(X(1), X(0));
186-
187-
Eigen::Matrix<double, 2, 3> d_angles_d_X;
188-
d_angles_d_X(0, 0) = -X(1) / (X(0) * X(0) + X(1) * X(1));
189-
d_angles_d_X(0, 1) = X(0) / (X(0) * X(0) + X(1) * X(1));
190-
d_angles_d_X(0, 2) = 0.0;
191-
192-
d_angles_d_X(1, 0) = d_angle_Z_d_len2d * d_len2d_d_X(0);
193-
d_angles_d_X(1, 1) = d_angle_Z_d_len2d * d_len2d_d_X(1);
194-
d_angles_d_X(1, 2) = -len2d / (len2d * len2d + X(2) * X(2));
195-
196-
const double rsensor = std::min(sensorWidth(), sensorHeight());
197-
const double rscale = sensorWidth() / std::max(w(), h());
198-
const double fmm = _scale(0) * rscale;
199-
const double fov = rsensor / fmm;
200-
201-
const double radius = angle_Z / (0.5 * fov);
202-
203-
const double d_radius_d_angle_Z = 1.0 / (0.5 * fov);
204-
205-
/* radius = focal * angle_Z */
206-
const Vec2 P{cos(angle_radial) * radius, sin(angle_radial) * radius};
207-
208-
Eigen::Matrix<double, 2, 2> d_P_d_angles;
209-
d_P_d_angles(0, 0) = -sin(angle_radial) * radius;
210-
d_P_d_angles(0, 1) = cos(angle_radial) * d_radius_d_angle_Z;
211-
d_P_d_angles(1, 0) = cos(angle_radial) * radius;
212-
d_P_d_angles(1, 1) = sin(angle_radial) * d_radius_d_angle_Z;
213-
214-
return getDerivativeCam2ImaWrtPoint() * getDerivativeAddDistoWrtPt(P) * d_P_d_angles * d_angles_d_X * d_X_d_T.block<3, 16>(0, 0);
215-
}
216-
217-
Eigen::Matrix<double, 2, 4> Equidistant::getDerivativeTransformProjectWrtPoint(const Eigen::Matrix4d& pose, const Vec4& pt) const
218-
{
219-
Eigen::Matrix4d T = pose;
220-
const Vec4 X = T * pt; // apply pose
221-
222-
const Eigen::Matrix4d& d_X_d_pt = T;
223-
224-
/* Compute angle with optical center */
225-
const double len2d = sqrt(X(0) * X(0) + X(1) * X(1));
226-
Eigen::Matrix<double, 2, 2> d_len2d_d_X;
227-
d_len2d_d_X(0) = X(0) / len2d;
228-
d_len2d_d_X(1) = X(1) / len2d;
229-
230-
const double angle_Z = std::atan2(len2d, X(2));
231-
const double d_angle_Z_d_len2d = X(2) / (len2d * len2d + X(2) * X(2));
232-
233-
/* Ignore depth component and compute radial angle */
234-
const double angle_radial = std::atan2(X(1), X(0));
235-
236-
Eigen::Matrix<double, 2, 4> d_angles_d_X;
237-
d_angles_d_X(0, 0) = -X(1) / (X(0) * X(0) + X(1) * X(1));
238-
d_angles_d_X(0, 1) = X(0) / (X(0) * X(0) + X(1) * X(1));
239-
d_angles_d_X(0, 2) = 0.0;
240-
d_angles_d_X(0, 3) = 0.0;
241-
242-
d_angles_d_X(1, 0) = d_angle_Z_d_len2d * d_len2d_d_X(0);
243-
d_angles_d_X(1, 1) = d_angle_Z_d_len2d * d_len2d_d_X(1);
244-
d_angles_d_X(1, 2) = -len2d / (len2d * len2d + X(2) * X(2));
245-
d_angles_d_X(1, 3) = 0.0;
246-
247-
const double rsensor = std::min(sensorWidth(), sensorHeight());
248-
const double rscale = sensorWidth() / std::max(w(), h());
249-
const double fmm = _scale(0) * rscale;
250-
const double fov = rsensor / fmm;
251-
const double radius = angle_Z / (0.5 * fov);
252-
253-
double d_radius_d_angle_Z = 1.0 / (0.5 * fov);
254-
255-
/* radius = focal * angle_Z */
256-
const Vec2 P{cos(angle_radial) * radius, sin(angle_radial) * radius};
257-
258-
Eigen::Matrix<double, 2, 2> d_P_d_angles;
259-
d_P_d_angles(0, 0) = -sin(angle_radial) * radius;
260-
d_P_d_angles(0, 1) = cos(angle_radial) * d_radius_d_angle_Z;
261-
d_P_d_angles(1, 0) = cos(angle_radial) * radius;
262-
d_P_d_angles(1, 1) = sin(angle_radial) * d_radius_d_angle_Z;
263-
264-
return getDerivativeCam2ImaWrtPoint() * getDerivativeAddDistoWrtPt(P) * d_P_d_angles * d_angles_d_X * d_X_d_pt;
265-
}
266-
26770
Eigen::Matrix<double, 2, 3> Equidistant::getDerivativeTransformProjectWrtPoint3(const Eigen::Matrix4d& T, const Vec4& pt) const
26871
{
26972
const Vec4 X = T * pt; // apply pose

src/aliceVision/camera/Equidistant.hpp

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -76,14 +76,6 @@ class Equidistant : public IntrinsicScaleOffsetDisto
7676

7777
Vec2 project(const Vec4& pt, bool applyDistortion = true) const override;
7878

79-
Eigen::Matrix<double, 2, 9> getDerivativeTransformProjectWrtRotation(const Eigen::Matrix4d& pose, const Vec4& pt) const override;
80-
81-
Eigen::Matrix<double, 2, 16> getDerivativeTransformProjectWrtPose(const Eigen::Matrix4d& pose, const Vec4& pt) const override;
82-
83-
Eigen::Matrix<double, 2, 16> getDerivativeTransformProjectWrtPoseLeft(const Eigen::Matrix4d& pose, const Vec4& pt) const override;
84-
85-
Eigen::Matrix<double, 2, 4> getDerivativeTransformProjectWrtPoint(const Eigen::Matrix4d& pose, const Vec4& pt) const override;
86-
8779
Eigen::Matrix<double, 2, 3> getDerivativeTransformProjectWrtPoint3(const Eigen::Matrix4d& pose, const Vec4& pt) const override;
8880

8981
Eigen::Matrix<double, 2, 3> getDerivativeTransformProjectWrtDisto(const Eigen::Matrix4d& pose, const Vec4& pt) const;

0 commit comments

Comments
 (0)