Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add calibrate with jacobians for Cal3Bundler #539

Merged
merged 9 commits into from
Sep 29, 2020
37 changes: 28 additions & 9 deletions gtsam/geometry/Cal3Bundler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,13 @@ namespace gtsam {

/* ************************************************************************* */
Cal3Bundler::Cal3Bundler() :
f_(1), k1_(0), k2_(0), u0_(0), v0_(0) {
f_(1), k1_(0), k2_(0), u0_(0), v0_(0), tol_(1e-5) {
}

/* ************************************************************************* */
Cal3Bundler::Cal3Bundler(double f, double k1, double k2, double u0, double v0) :
f_(f), k1_(k1), k2_(k2), u0_(u0), v0_(v0) {
}
Cal3Bundler::Cal3Bundler(double f, double k1, double k2, double u0, double v0,
double tol)
varunagrawal marked this conversation as resolved.
Show resolved Hide resolved
: f_(f), k1_(k1), k2_(k2), u0_(u0), v0_(v0), tol_(tol) {}

/* ************************************************************************* */
Matrix3 Cal3Bundler::K() const {
Expand Down Expand Up @@ -94,21 +94,24 @@ Point2 Cal3Bundler::uncalibrate(const Point2& p, //
}

/* ************************************************************************* */
Point2 Cal3Bundler::calibrate(const Point2& pi, const double tol) const {
Point2 Cal3Bundler::calibrate(const Point2& pi,
OptionalJacobian<2, 3> Dcal,
OptionalJacobian<2, 2> Dp) const {
// Copied from Cal3DS2 :-(
// but specialized with k1,k2 non-zero only and fx=fy and s=0
const Point2 invKPi((pi.x() - u0_)/f_, (pi.y() - v0_)/f_);
double x = (pi.x() - u0_)/f_, y = (pi.y() - v0_)/f_;
const Point2 invKPi(x, y);
varunagrawal marked this conversation as resolved.
Show resolved Hide resolved

// initialize by ignoring the distortion at all, might be problematic for pixels around boundary
Point2 pn = invKPi;
Point2 pn(x, y);

// iterate until the uncalibrate is close to the actual pixel coordinate
const int maxIterations = 10;
int iteration;
for (iteration = 0; iteration < maxIterations; ++iteration) {
if (distance2(uncalibrate(pn), pi) <= tol)
if (distance2(uncalibrate(pn), pi) <= tol_)
break;
const double x = pn.x(), y = pn.y(), xx = x * x, yy = y * y;
const double px = pn.x(), py = pn.y(), xx = px * px, yy = py * py;
const double rr = xx + yy;
const double g = (1 + k1_ * rr + k2_ * rr * rr);
pn = invKPi / g;
Expand All @@ -118,6 +121,22 @@ Point2 Cal3Bundler::calibrate(const Point2& pi, const double tol) const {
throw std::runtime_error(
"Cal3Bundler::calibrate fails to converge. need a better initialization");

// We make use of the Implicit Function Theorem to compute the Jacobians from uncalibrate
// Given f(pi, pn) = uncalibrate(pn) - pi, and g(pi) = calibrate, we can easily compute the Jacobians
// df/pi = -I (pn and pi are independent args)
// Dcal = -inv(H_uncal_pn) * df/pi = -inv(H_uncal_pn) * (-I) = inv(H_uncal_pn)
// Dp = -inv(H_uncal_pn) * df/K = -inv(H_uncal_pn) * H_uncal_K
Matrix23 H_uncal_K;
Matrix22 H_uncal_pn;

if (Dcal || Dp) {
// Compute uncalibrate Jacobians
uncalibrate(pn, Dcal ? &H_uncal_K : nullptr, H_uncal_pn);

if (Dp) *Dp = H_uncal_pn.inverse();
if (Dcal) *Dcal = -H_uncal_pn.inverse() * H_uncal_K;

}
return pn;
}

Expand Down
19 changes: 16 additions & 3 deletions gtsam/geometry/Cal3Bundler.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ class GTSAM_EXPORT Cal3Bundler {
double f_; ///< focal length
double k1_, k2_; ///< radial distortion
double u0_, v0_; ///< image center, not a parameter to be optimized but a constant
double tol_; ///< tolerance value when calibrating

public:

Expand All @@ -51,8 +52,10 @@ class GTSAM_EXPORT Cal3Bundler {
* @param k2 second radial distortion coefficient (quartic)
* @param u0 optional image center (default 0), considered a constant
* @param v0 optional image center (default 0), considered a constant
* @param tol optional calibration tolerance value
*/
Cal3Bundler(double f, double k1, double k2, double u0 = 0, double v0 = 0);
Cal3Bundler(double f, double k1, double k2, double u0 = 0, double v0 = 0,
double tol = 1e-5);

virtual ~Cal3Bundler() {}

Expand Down Expand Up @@ -117,8 +120,17 @@ class GTSAM_EXPORT Cal3Bundler {
Point2 uncalibrate(const Point2& p, OptionalJacobian<2, 3> Dcal = boost::none,
OptionalJacobian<2, 2> Dp = boost::none) const;

/// Convert a pixel coordinate to ideal coordinate
Point2 calibrate(const Point2& pi, const double tol = 1e-5) const;
/**
* Convert a pixel coordinate to ideal coordinate xy
* @param p point in image coordinates
* @param tol optional tolerance threshold value for iterative minimization
* @param Dcal optional 2*3 Jacobian wrpt Cal3Bundler parameters
* @param Dp optional 2*2 Jacobian wrpt intrinsic coordinates
* @return point in intrinsic coordinates
*/
Point2 calibrate(const Point2& pi,
OptionalJacobian<2, 3> Dcal = boost::none,
OptionalJacobian<2, 2> Dp = boost::none) const;

/// @deprecated might be removed in next release, use uncalibrate
Matrix2 D2d_intrinsic(const Point2& p) const;
Expand Down Expand Up @@ -164,6 +176,7 @@ class GTSAM_EXPORT Cal3Bundler {
ar & BOOST_SERIALIZATION_NVP(k2_);
ar & BOOST_SERIALIZATION_NVP(u0_);
ar & BOOST_SERIALIZATION_NVP(v0_);
ar & BOOST_SERIALIZATION_NVP(tol_);
}

/// @}
Expand Down
23 changes: 17 additions & 6 deletions gtsam/geometry/tests/testCal3Bundler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,14 @@ TEST( Cal3Bundler, calibrate )
Point2 pn(0.5, 0.5);
Point2 pi = K.uncalibrate(pn);
Point2 pn_hat = K.calibrate(pi);
CHECK( traits<Point2>::Equals(pn, pn_hat, 1e-5));
CHECK(traits<Point2>::Equals(pn, pn_hat, 1e-5));
}

/* ************************************************************************* */
Point2 uncalibrate_(const Cal3Bundler& k, const Point2& pt) { return k.uncalibrate(pt); }

Point2 calibrate_(const Cal3Bundler& k, const Point2& pt) { return k.calibrate(pt); }

/* ************************************************************************* */
TEST( Cal3Bundler, Duncalibrate)
{
Expand All @@ -69,11 +71,20 @@ TEST( Cal3Bundler, Duncalibrate)
Matrix numerical2 = numericalDerivative22(uncalibrate_, K, p);
CHECK(assert_equal(numerical1,Dcal,1e-7));
CHECK(assert_equal(numerical2,Dp,1e-7));
CHECK(assert_equal(numerical1,K.D2d_calibration(p),1e-7));
CHECK(assert_equal(numerical2,K.D2d_intrinsic(p),1e-7));
Matrix Dcombined(2,5);
Dcombined << Dp, Dcal;
CHECK(assert_equal(Dcombined,K.D2d_intrinsic_calibration(p),1e-7));
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These methods are deprecated, which is why I removed these tests.

}

/* ************************************************************************* */
TEST( Cal3Bundler, Dcalibrate)
{
Matrix Dcal, Dp;
Point2 pn(0.5, 0.5);
Point2 pi = K.uncalibrate(pn);
Point2 actual = K.calibrate(pi, Dcal, Dp);
CHECK(assert_equal(pn, actual, 1e-7));
Matrix numerical1 = numericalDerivative21(calibrate_, K, pi);
Matrix numerical2 = numericalDerivative22(calibrate_, K, pi);
CHECK(assert_equal(numerical1,Dcal,1e-5));
CHECK(assert_equal(numerical2,Dp,1e-5));
}

/* ************************************************************************* */
Expand Down
9 changes: 9 additions & 0 deletions gtsam/geometry/tests/testPinholeCamera.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,15 @@ TEST( PinholeCamera, range3) {
EXPECT(assert_equal(Hexpected2, D2, 1e-7));
}

/* ************************************************************************* */
TEST( PinholeCamera, Cal3Bundler) {
Cal3Bundler calibration;
Pose3 wTc;
PinholeCamera<Cal3Bundler> camera(wTc, calibration);
Point2 p(50, 100);
camera.backproject(p, 10);
}

/* ************************************************************************* */
int main() { TestResult tr; return TestRegistry::runAllTests(tr); }
/* ************************************************************************* */
Expand Down
3 changes: 2 additions & 1 deletion gtsam/gtsam.i
Original file line number Diff line number Diff line change
Expand Up @@ -1054,6 +1054,7 @@ class Cal3Bundler {
// Standard Constructors
Cal3Bundler();
Cal3Bundler(double fx, double k1, double k2, double u0, double v0);
Cal3Bundler(double fx, double k1, double k2, double u0, double v0, double tol);
varunagrawal marked this conversation as resolved.
Show resolved Hide resolved

// Testable
void print(string s) const;
Expand All @@ -1066,7 +1067,7 @@ class Cal3Bundler {
Vector localCoordinates(const gtsam::Cal3Bundler& c) const;

// Action on Point2
gtsam::Point2 calibrate(const gtsam::Point2& p, double tol) const;
gtsam::Point2 calibrate(const gtsam::Point2& p) const;
gtsam::Point2 uncalibrate(const gtsam::Point2& p) const;

// Standard Interface
Expand Down