upnp.cpp 24.9 KB
Newer Older
edgarriba's avatar
edgarriba committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
//M*//////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000, Intel Corporation, all rights reserved.
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/

/****************************************************************************************\
* Exhaustive Linearization for Robust Camera Pose and Focal Length Estimation.
* Contributed by Edgar Riba
\****************************************************************************************/

edgarriba's avatar
edgarriba committed
48 49 50 51
#include "precomp.hpp"
#include "upnp.h"
#include <limits>

edgarriba's avatar
edgarriba committed
52 53 54 55
using namespace std;
using namespace cv;

upnp::upnp(const Mat& cameraMatrix, const Mat& opoints, const Mat& ipoints)
edgarriba's avatar
edgarriba committed
56 57
{
  if (cameraMatrix.depth() == CV_32F)
edgarriba's avatar
edgarriba committed
58
    init_camera_parameters<float>(cameraMatrix);
edgarriba's avatar
edgarriba committed
59 60 61 62 63 64 65 66 67 68 69
  else
    init_camera_parameters<double>(cameraMatrix);

  number_of_correspondences = std::max(opoints.checkVector(3, CV_32F), opoints.checkVector(3, CV_64F));

  pws.resize(3 * number_of_correspondences);
  us.resize(2 * number_of_correspondences);

  if (opoints.depth() == ipoints.depth())
  {
    if (opoints.depth() == CV_32F)
edgarriba's avatar
edgarriba committed
70
      init_points<Point3f,Point2f>(opoints, ipoints);
edgarriba's avatar
edgarriba committed
71
    else
edgarriba's avatar
edgarriba committed
72
      init_points<Point3d,Point2d>(opoints, ipoints);
edgarriba's avatar
edgarriba committed
73 74
  }
  else if (opoints.depth() == CV_32F)
edgarriba's avatar
edgarriba committed
75
    init_points<Point3f,Point2d>(opoints, ipoints);
edgarriba's avatar
edgarriba committed
76
  else
edgarriba's avatar
edgarriba committed
77
    init_points<Point3d,Point2f>(opoints, ipoints);
edgarriba's avatar
edgarriba committed
78 79 80 81 82 83 84 85 86 87 88

  alphas.resize(4 * number_of_correspondences);
  pcs.resize(3 * number_of_correspondences);

  max_nr = 0;
  A1 = NULL;
  A2 = NULL;
}

upnp::~upnp()
{
edgarriba's avatar
edgarriba committed
89 90 91 92
  if (A1)
    delete[] A1;
  if (A2)
    delete[] A2;
edgarriba's avatar
edgarriba committed
93 94
}

edgarriba's avatar
edgarriba committed
95
double upnp::compute_pose(Mat& R, Mat& t)
edgarriba's avatar
edgarriba committed
96
{
edgarriba's avatar
edgarriba committed
97 98
  choose_control_points();
  compute_alphas();
edgarriba's avatar
edgarriba committed
99

edgarriba's avatar
edgarriba committed
100
  Mat * M = new Mat(2 * number_of_correspondences, 12, CV_64F);
edgarriba's avatar
edgarriba committed
101

edgarriba's avatar
edgarriba committed
102 103 104 105
  for(int i = 0; i < number_of_correspondences; i++)
  {
    fill_M(M, 2 * i, &alphas[0] + 4 * i, us[2 * i], us[2 * i + 1]);
  }
edgarriba's avatar
edgarriba committed
106

edgarriba's avatar
edgarriba committed
107 108 109 110 111
  double mtm[12 * 12], d[12], ut[12 * 12], vt[12 * 12];
  Mat MtM = Mat(12, 12, CV_64F, mtm);
  Mat D   = Mat(12,  1, CV_64F, d);
  Mat Ut  = Mat(12, 12, CV_64F, ut);
  Mat Vt  = Mat(12, 12, CV_64F, vt);
edgarriba's avatar
edgarriba committed
112

edgarriba's avatar
edgarriba committed
113 114 115 116
  MtM = M->t() * (*M);
  SVD::compute(MtM, D, Ut, Vt, SVD::MODIFY_A | SVD::FULL_UV);
  Mat(Ut.t()).copyTo(Ut);
  M->release();
edgarriba's avatar
edgarriba committed
117

edgarriba's avatar
edgarriba committed
118
  double l_6x12[6 * 12], rho[6];
edgarriba's avatar
edgarriba committed
119 120
  Mat L_6x12 = Mat(6, 12, CV_64F, l_6x12);
  Mat Rho    = Mat(6,  1, CV_64F, rho);
edgarriba's avatar
edgarriba committed
121

edgarriba's avatar
edgarriba committed
122 123
  compute_L_6x12(ut, l_6x12);
  compute_rho(rho);
edgarriba's avatar
edgarriba committed
124

edgarriba's avatar
edgarriba committed
125 126
  double Betas[3][4], Efs[3][1], rep_errors[3];
  double Rs[3][3][3], ts[3][3];
edgarriba's avatar
edgarriba committed
127

edgarriba's avatar
edgarriba committed
128 129 130
  find_betas_and_focal_approx_1(&Ut, &Rho, Betas[1], Efs[1]);
  gauss_newton(&L_6x12, &Rho, Betas[1], Efs[1]);
  rep_errors[1] = compute_R_and_t(ut, Betas[1], Rs[1], ts[1]);
edgarriba's avatar
edgarriba committed
131

edgarriba's avatar
edgarriba committed
132 133 134
  find_betas_and_focal_approx_2(&Ut, &Rho, Betas[2], Efs[2]);
  gauss_newton(&L_6x12, &Rho, Betas[2], Efs[2]);
  rep_errors[2] = compute_R_and_t(ut, Betas[2], Rs[2], ts[2]);
edgarriba's avatar
edgarriba committed
135

edgarriba's avatar
edgarriba committed
136 137
  int N = 1;
  if (rep_errors[2] < rep_errors[1]) N = 2;
edgarriba's avatar
edgarriba committed
138

edgarriba's avatar
edgarriba committed
139 140
  Mat(3, 1, CV_64F, ts[N]).copyTo(t);
  Mat(3, 3, CV_64F, Rs[N]).copyTo(R);
edgarriba's avatar
edgarriba committed
141
  fu = fv = Efs[N][0];
142

edgarriba's avatar
edgarriba committed
143
  return fu;
edgarriba's avatar
edgarriba committed
144 145 146
}

void upnp::copy_R_and_t(const double R_src[3][3], const double t_src[3],
edgarriba's avatar
edgarriba committed
147
     double R_dst[3][3], double t_dst[3])
edgarriba's avatar
edgarriba committed
148 149 150
{
  for(int i = 0; i < 3; i++) {
    for(int j = 0; j < 3; j++)
edgarriba's avatar
edgarriba committed
151
      R_dst[i][j] = R_src[i][j];
edgarriba's avatar
edgarriba committed
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177
    t_dst[i] = t_src[i];
  }
}

void upnp::estimate_R_and_t(double R[3][3], double t[3])
{
  double pc0[3], pw0[3];

  pc0[0] = pc0[1] = pc0[2] = 0.0;
  pw0[0] = pw0[1] = pw0[2] = 0.0;

  for(int i = 0; i < number_of_correspondences; i++) {
    const double * pc = &pcs[3 * i];
    const double * pw = &pws[3 * i];

    for(int j = 0; j < 3; j++) {
      pc0[j] += pc[j];
      pw0[j] += pw[j];
    }
  }
  for(int j = 0; j < 3; j++) {
    pc0[j] /= number_of_correspondences;
    pw0[j] /= number_of_correspondences;
  }

  double abt[3 * 3], abt_d[3], abt_u[3 * 3], abt_v[3 * 3];
edgarriba's avatar
edgarriba committed
178 179 180 181
  Mat ABt   = Mat(3, 3, CV_64F, abt);
  Mat ABt_D = Mat(3, 1, CV_64F, abt_d);
  Mat ABt_U = Mat(3, 3, CV_64F, abt_u);
  Mat ABt_V = Mat(3, 3, CV_64F, abt_v);
edgarriba's avatar
edgarriba committed
182

edgarriba's avatar
edgarriba committed
183
  ABt.setTo(0.0);
edgarriba's avatar
edgarriba committed
184 185 186 187 188 189 190 191 192 193 194
  for(int i = 0; i < number_of_correspondences; i++) {
    double * pc = &pcs[3 * i];
    double * pw = &pws[3 * i];

    for(int j = 0; j < 3; j++) {
      abt[3 * j    ] += (pc[j] - pc0[j]) * (pw[0] - pw0[0]);
      abt[3 * j + 1] += (pc[j] - pc0[j]) * (pw[1] - pw0[1]);
      abt[3 * j + 2] += (pc[j] - pc0[j]) * (pw[2] - pw0[2]);
    }
  }

edgarriba's avatar
edgarriba committed
195 196
  SVD::compute(ABt, ABt_D, ABt_U, ABt_V, SVD::MODIFY_A);
  Mat(ABt_V.t()).copyTo(ABt_V);
edgarriba's avatar
edgarriba committed
197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221

  for(int i = 0; i < 3; i++)
    for(int j = 0; j < 3; j++)
      R[i][j] = dot(abt_u + 3 * i, abt_v + 3 * j);

  const double det =
    R[0][0] * R[1][1] * R[2][2] + R[0][1] * R[1][2] * R[2][0] + R[0][2] * R[1][0] * R[2][1] -
    R[0][2] * R[1][1] * R[2][0] - R[0][1] * R[1][0] * R[2][2] - R[0][0] * R[1][2] * R[2][1];

  if (det < 0) {
    R[2][0] = -R[2][0];
    R[2][1] = -R[2][1];
    R[2][2] = -R[2][2];
  }

  t[0] = pc0[0] - dot(R[0], pw0);
  t[1] = pc0[1] - dot(R[1], pw0);
  t[2] = pc0[2] - dot(R[2], pw0);
}

void upnp::solve_for_sign(void)
{
  if (pcs[2] < 0.0) {
    for(int i = 0; i < 4; i++)
      for(int j = 0; j < 3; j++)
edgarriba's avatar
edgarriba committed
222
        ccs[i][j] = -ccs[i][j];
edgarriba's avatar
edgarriba committed
223 224 225 226 227 228 229 230 231

    for(int i = 0; i < number_of_correspondences; i++) {
      pcs[3 * i    ] = -pcs[3 * i];
      pcs[3 * i + 1] = -pcs[3 * i + 1];
      pcs[3 * i + 2] = -pcs[3 * i + 2];
    }
  }
}

edgarriba's avatar
edgarriba committed
232 233
double upnp::compute_R_and_t(const double * ut, const double * betas,
         double R[3][3], double t[3])
edgarriba's avatar
edgarriba committed
234
{
edgarriba's avatar
edgarriba committed
235
  compute_ccs(betas, ut);
edgarriba's avatar
edgarriba committed
236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265
  compute_pcs();

  solve_for_sign();

  estimate_R_and_t(R, t);

  return reprojection_error(R, t);
}

double upnp::reprojection_error(const double R[3][3], const double t[3])
{
  double sum2 = 0.0;

  for(int i = 0; i < number_of_correspondences; i++) {
    double * pw = &pws[3 * i];
    double Xc = dot(R[0], pw) + t[0];
    double Yc = dot(R[1], pw) + t[1];
    double inv_Zc = 1.0 / (dot(R[2], pw) + t[2]);
    double ue = uc + fu * Xc * inv_Zc;
    double ve = vc + fv * Yc * inv_Zc;
    double u = us[2 * i], v = us[2 * i + 1];

    sum2 += sqrt( (u - ue) * (u - ue) + (v - ve) * (v - ve) );
  }

  return sum2 / number_of_correspondences;
}

void upnp::choose_control_points()
{
edgarriba's avatar
edgarriba committed
266
    for (int i = 0; i < 4; ++i)
edgarriba's avatar
edgarriba committed
267 268
      cws[i][0] = cws[i][1] = cws[i][2] = 0.0;
    cws[0][0] = cws[1][1] = cws[2][2] = 1.0;
edgarriba's avatar
edgarriba committed
269 270 271 272
}

void upnp::compute_alphas()
{
edgarriba's avatar
edgarriba committed
273 274 275
    Mat CC = Mat(4, 3, CV_64F, &cws);
    Mat PC = Mat(number_of_correspondences, 3, CV_64F, &pws[0]);
    Mat ALPHAS = Mat(number_of_correspondences, 4, CV_64F, &alphas[0]);
edgarriba's avatar
edgarriba committed
276

edgarriba's avatar
edgarriba committed
277 278
    Mat CC_ = CC.clone().t();
    Mat PC_ = PC.clone().t();
edgarriba's avatar
edgarriba committed
279

edgarriba's avatar
edgarriba committed
280 281
    Mat row14 = Mat::ones(1, 4, CV_64F);
    Mat row1n = Mat::ones(1, number_of_correspondences, CV_64F);
edgarriba's avatar
edgarriba committed
282

edgarriba's avatar
edgarriba committed
283 284
    CC_.push_back(row14);
    PC_.push_back(row1n);
edgarriba's avatar
edgarriba committed
285

edgarriba's avatar
edgarriba committed
286
    ALPHAS = Mat( CC_.inv() * PC_ ).t();
edgarriba's avatar
edgarriba committed
287 288
}

edgarriba's avatar
edgarriba committed
289
void upnp::fill_M(Mat * M, const int row, const double * as, const double u, const double v)
edgarriba's avatar
edgarriba committed
290
{
edgarriba's avatar
edgarriba committed
291
  double * M1 = M->ptr<double>(row);
edgarriba's avatar
edgarriba committed
292 293 294 295 296 297 298 299 300 301 302 303 304
  double * M2 = M1 + 12;

  for(int i = 0; i < 4; i++) {
    M1[3 * i    ] = as[i] * fu;
    M1[3 * i + 1] = 0.0;
    M1[3 * i + 2] = as[i] * (uc - u);

    M2[3 * i    ] = 0.0;
    M2[3 * i + 1] = as[i] * fv;
    M2[3 * i + 2] = as[i] * (vc - v);
  }
}

edgarriba's avatar
edgarriba committed
305
void upnp::compute_ccs(const double * betas, const double * ut)
edgarriba's avatar
edgarriba committed
306
{
edgarriba's avatar
edgarriba committed
307
    for(int i = 0; i < 4; ++i)
edgarriba's avatar
edgarriba committed
308
      ccs[i][0] = ccs[i][1] = ccs[i][2] = 0.0;
edgarriba's avatar
edgarriba committed
309 310 311 312 313 314 315 316 317 318

    int N = 4;
    for(int i = 0; i < N; ++i) {
      const double * v = ut + 12 * (9 + i);
      for(int j = 0; j < 4; ++j)
        for(int k = 0; k < 3; ++k)
          ccs[j][k] += betas[i] * v[3 * j + k];
    }

    for (int i = 0; i < 4; ++i) ccs[i][2] *= fu;
edgarriba's avatar
edgarriba committed
319 320 321 322 323 324 325 326 327 328 329 330 331
}

void upnp::compute_pcs(void)
{
  for(int i = 0; i < number_of_correspondences; i++) {
    double * a = &alphas[0] + 4 * i;
    double * pc = &pcs[0] + 3 * i;

    for(int j = 0; j < 3; j++)
      pc[j] = a[0] * ccs[0][j] + a[1] * ccs[1][j] + a[2] * ccs[2][j] + a[3] * ccs[3][j];
  }
}

edgarriba's avatar
edgarriba committed
332
void upnp::find_betas_and_focal_approx_1(Mat * Ut, Mat * Rho, double * betas, double * efs)
edgarriba's avatar
edgarriba committed
333
{
edgarriba's avatar
edgarriba committed
334 335
  Mat Kmf1 = Mat(12, 1, CV_64F, Ut->ptr<double>(11));
  Mat dsq = Mat(6, 1, CV_64F, Rho->ptr<double>(0));
edgarriba's avatar
edgarriba committed
336

edgarriba's avatar
edgarriba committed
337 338
  Mat D = compute_constraint_distance_2param_6eq_2unk_f_unk( Kmf1 );
  Mat Dt = D.t();
edgarriba's avatar
edgarriba committed
339

edgarriba's avatar
edgarriba committed
340 341
  Mat A = Dt * D;
  Mat b = Dt * dsq;
edgarriba's avatar
edgarriba committed
342

edgarriba's avatar
edgarriba committed
343 344
  Mat x = Mat(2, 1, CV_64F);
  solve(A, b, x);
edgarriba's avatar
edgarriba committed
345

edgarriba's avatar
edgarriba committed
346 347
  betas[0] = sqrt( abs( x.at<double>(0) ) );
  betas[1] = betas[2] = betas[3] = 0.0;
edgarriba's avatar
edgarriba committed
348

edgarriba's avatar
edgarriba committed
349
  efs[0] = sqrt( abs( x.at<double>(1) ) ) / betas[0];
edgarriba's avatar
edgarriba committed
350 351
}

edgarriba's avatar
edgarriba committed
352
void upnp::find_betas_and_focal_approx_2(Mat * Ut, Mat * Rho, double * betas, double * efs)
edgarriba's avatar
edgarriba committed
353
{
edgarriba's avatar
edgarriba committed
354 355 356
  double u[12*12];
  Mat U = Mat(12, 12, CV_64F, u);
  Ut->copyTo(U);
edgarriba's avatar
edgarriba committed
357

edgarriba's avatar
edgarriba committed
358 359 360
  Mat Kmf1 = Mat(12, 1, CV_64F, Ut->ptr<double>(10));
  Mat Kmf2 = Mat(12, 1, CV_64F, Ut->ptr<double>(11));
  Mat dsq = Mat(6, 1, CV_64F, Rho->ptr<double>(0));
edgarriba's avatar
edgarriba committed
361

edgarriba's avatar
edgarriba committed
362
  Mat D = compute_constraint_distance_3param_6eq_6unk_f_unk( Kmf1, Kmf2 );
edgarriba's avatar
edgarriba committed
363

edgarriba's avatar
edgarriba committed
364 365
  Mat A = D;
  Mat b = dsq;
edgarriba's avatar
edgarriba committed
366

edgarriba's avatar
edgarriba committed
367
  double x[6];
edgarriba's avatar
edgarriba committed
368
  Mat X = Mat(6, 1, CV_64F, x);
edgarriba's avatar
edgarriba committed
369

edgarriba's avatar
edgarriba committed
370
  solve(A, b, X, DECOMP_QR);
edgarriba's avatar
edgarriba committed
371

edgarriba's avatar
edgarriba committed
372 373 374 375 376 377 378 379 380 381
  double solutions[18][3];
  generate_all_possible_solutions_for_f_unk(x, solutions);

  // find solution with minimum reprojection error
  double min_error = std::numeric_limits<double>::max();
  int min_sol = 0;
  for (int i = 0; i < 18; ++i) {

    betas[3] = solutions[i][0];
    betas[2] = solutions[i][1];
edgarriba's avatar
edgarriba committed
382
    betas[1] = betas[0] = 0.0;
edgarriba's avatar
edgarriba committed
383 384 385
    fu = fv = solutions[i][2];

    double Rs[3][3], ts[3];
edgarriba's avatar
edgarriba committed
386
    double error_i = compute_R_and_t( u, betas, Rs, ts);
edgarriba's avatar
edgarriba committed
387 388 389 390 391 392 393

    if( error_i < min_error)
    {
      min_error = error_i;
      min_sol = i;
    }
}
edgarriba's avatar
edgarriba committed
394

edgarriba's avatar
edgarriba committed
395 396
  betas[0] = solutions[min_sol][0];
  betas[1] = solutions[min_sol][1];
edgarriba's avatar
edgarriba committed
397
  betas[2] = betas[3] = 0.0;
edgarriba's avatar
edgarriba committed
398

edgarriba's avatar
edgarriba committed
399
  efs[0] = solutions[min_sol][2];
edgarriba's avatar
edgarriba committed
400 401
}

edgarriba's avatar
edgarriba committed
402
Mat upnp::compute_constraint_distance_2param_6eq_2unk_f_unk(const Mat& M1)
edgarriba's avatar
edgarriba committed
403
{
edgarriba's avatar
edgarriba committed
404
  Mat P = Mat(6, 2, CV_64F);
edgarriba's avatar
edgarriba committed
405 406

  double m[13];
edgarriba's avatar
edgarriba committed
407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433
  for (int i = 1; i < 13; ++i) m[i] = *M1.ptr<double>(i-1);

  double t1 = pow( m[4], 2 );
  double t4 = pow( m[1], 2 );
  double t5 = pow( m[5], 2 );
  double t8 = pow( m[2], 2 );
  double t10 = pow( m[6], 2 );
  double t13 = pow( m[3], 2 );
  double t15 = pow( m[7], 2 );
  double t18 = pow( m[8], 2 );
  double t22 = pow( m[9], 2 );
  double t26 = pow( m[10], 2 );
  double t29 = pow( m[11], 2 );
  double t33 = pow( m[12], 2 );

  *P.ptr<double>(0,0) = t1 - 2 * m[4] * m[1] + t4 + t5 - 2 * m[5] * m[2] + t8;
  *P.ptr<double>(0,1) = t10 - 2 * m[6] * m[3] + t13;
  *P.ptr<double>(1,0) = t15 - 2 * m[7] * m[1] + t4 + t18 - 2 * m[8] * m[2] + t8;
  *P.ptr<double>(1,1) = t22 - 2 * m[9] * m[3] + t13;
  *P.ptr<double>(2,0) = t26 - 2 * m[10] * m[1] + t4 + t29 - 2 * m[11] * m[2] + t8;
  *P.ptr<double>(2,1) = t33 - 2 * m[12] * m[3] + t13;
  *P.ptr<double>(3,0) = t15 - 2 * m[7] * m[4] + t1 + t18 - 2 * m[8] * m[5] + t5;
  *P.ptr<double>(3,1) = t22 - 2 * m[9] * m[6] + t10;
  *P.ptr<double>(4,0) = t26 - 2 * m[10] * m[4] + t1 + t29 - 2 * m[11] * m[5] + t5;
  *P.ptr<double>(4,1) = t33 - 2 * m[12] * m[6] + t10;
  *P.ptr<double>(5,0) = t26 - 2 * m[10] * m[7] + t15 + t29 - 2 * m[11] * m[8] + t18;
  *P.ptr<double>(5,1) = t33 - 2 * m[12] * m[9] + t22;
edgarriba's avatar
edgarriba committed
434 435

  return P;
edgarriba's avatar
edgarriba committed
436 437
}

edgarriba's avatar
edgarriba committed
438
Mat upnp::compute_constraint_distance_3param_6eq_6unk_f_unk(const Mat& M1, const Mat& M2)
edgarriba's avatar
edgarriba committed
439
{
edgarriba's avatar
edgarriba committed
440
  Mat P = Mat(6, 6, CV_64F);
edgarriba's avatar
edgarriba committed
441 442 443 444

  double m[3][13];
  for (int i = 1; i < 13; ++i)
  {
edgarriba's avatar
edgarriba committed
445 446
    m[1][i] = *M1.ptr<double>(i-1);
    m[2][i] = *M2.ptr<double>(i-1);
edgarriba's avatar
edgarriba committed
447 448
  }

edgarriba's avatar
edgarriba committed
449 450 451 452
  double t1 = pow( m[1][4], 2 );
  double t2 = pow( m[1][1], 2 );
  double t7 = pow( m[1][5], 2 );
  double t8 = pow( m[1][2], 2 );
edgarriba's avatar
edgarriba committed
453 454 455 456
  double t11 = m[1][1] * m[2][1];
  double t12 = m[1][5] * m[2][5];
  double t15 = m[1][2] * m[2][2];
  double t16 = m[1][4] * m[2][4];
edgarriba's avatar
edgarriba committed
457 458 459 460 461 462 463
  double t19 = pow( m[2][4], 2 );
  double t22 = pow( m[2][2], 2 );
  double t23 = pow( m[2][1], 2 );
  double t24 = pow( m[2][5], 2 );
  double t28 = pow( m[1][6], 2 );
  double t29 = pow( m[1][3], 2 );
  double t34 = pow( m[1][3], 2 );
edgarriba's avatar
edgarriba committed
464
  double t36 = m[1][6] * m[2][6];
edgarriba's avatar
edgarriba committed
465 466 467 468
  double t40 = pow( m[2][6], 2 );
  double t41 = pow( m[2][3], 2 );
  double t47 = pow( m[1][7], 2 );
  double t48 = pow( m[1][8], 2 );
edgarriba's avatar
edgarriba committed
469 470
  double t52 = m[1][7] * m[2][7];
  double t55 = m[1][8] * m[2][8];
edgarriba's avatar
edgarriba committed
471 472 473
  double t59 = pow( m[2][8], 2 );
  double t62 = pow( m[2][7], 2 );
  double t64 = pow( m[1][9], 2 );
edgarriba's avatar
edgarriba committed
474
  double t68 = m[1][9] * m[2][9];
edgarriba's avatar
edgarriba committed
475 476 477
  double t74 = pow( m[2][9], 2 );
  double t78 = pow( m[1][10], 2 );
  double t79 = pow( m[1][11], 2 );
edgarriba's avatar
edgarriba committed
478 479
  double t84 = m[1][10] * m[2][10];
  double t87 = m[1][11] * m[2][11];
edgarriba's avatar
edgarriba committed
480 481 482
  double t90 = pow( m[2][10], 2 );
  double t95 = pow( m[2][11], 2 );
  double t99 = pow( m[1][12], 2 );
edgarriba's avatar
edgarriba committed
483
  double t101 = m[1][12] * m[2][12];
edgarriba's avatar
edgarriba committed
484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526
  double t105 = pow( m[2][12], 2 );

  *P.ptr<double>(0,0) = t1 + t2 - 2 * m[1][4] * m[1][1] - 2 * m[1][5] * m[1][2] + t7 + t8;
  *P.ptr<double>(0,1) = -2 * m[2][4] * m[1][1] + 2 * t11 + 2 * t12 - 2 * m[1][4] * m[2][1] - 2 * m[2][5] * m[1][2] + 2 * t15 + 2 * t16 - 2 * m[1][5] * m[2][2];
  *P.ptr<double>(0,2) = t19 - 2 * m[2][4] * m[2][1] + t22 + t23 + t24 - 2 * m[2][5] * m[2][2];
  *P.ptr<double>(0,3) = t28 + t29 - 2 * m[1][6] * m[1][3];
  *P.ptr<double>(0,4) = -2 * m[2][6] * m[1][3] + 2 * t34 - 2 * m[1][6] * m[2][3] + 2 * t36;
  *P.ptr<double>(0,5) = -2 * m[2][6] * m[2][3] + t40 + t41;

  *P.ptr<double>(1,0) = t8 - 2 * m[1][8] * m[1][2] - 2 * m[1][7] * m[1][1] + t47 + t48 + t2;
  *P.ptr<double>(1,1) = 2 * t15 - 2 * m[1][8] * m[2][2] - 2 * m[2][8] * m[1][2] + 2 * t52 - 2 * m[1][7] * m[2][1] - 2 * m[2][7] * m[1][1] + 2 * t55 + 2 * t11;
  *P.ptr<double>(1,2) = -2 * m[2][8] * m[2][2] + t22 + t23 + t59 - 2 * m[2][7] * m[2][1] + t62;
  *P.ptr<double>(1,3) = t29 + t64 - 2 * m[1][9] * m[1][3];
  *P.ptr<double>(1,4) = 2 * t34 + 2 * t68 - 2 * m[2][9] * m[1][3] - 2 * m[1][9] * m[2][3];
  *P.ptr<double>(1,5) = -2 * m[2][9] * m[2][3] + t74 + t41;

  *P.ptr<double>(2,0) = -2 * m[1][11] * m[1][2] + t2 + t8 + t78 + t79 - 2 * m[1][10] * m[1][1];
  *P.ptr<double>(2,1) = 2 * t15 - 2 * m[1][11] * m[2][2] + 2 * t84 - 2 * m[1][10] * m[2][1] - 2 * m[2][10] * m[1][1] + 2 * t87 - 2 * m[2][11] * m[1][2]+ 2 * t11;
  *P.ptr<double>(2,2) = t90 + t22 - 2 * m[2][10] * m[2][1] + t23 - 2 * m[2][11] * m[2][2] + t95;
  *P.ptr<double>(2,3) = -2 * m[1][12] * m[1][3] + t99 + t29;
  *P.ptr<double>(2,4) = 2 * t34 + 2 * t101 - 2 * m[2][12] * m[1][3] - 2 * m[1][12] * m[2][3];
  *P.ptr<double>(2,5) = t41 + t105 - 2 * m[2][12] * m[2][3];

  *P.ptr<double>(3,0) = t48 + t1 - 2 * m[1][8] * m[1][5] + t7 - 2 * m[1][7] * m[1][4] + t47;
  *P.ptr<double>(3,1) = 2 * t16 - 2 * m[1][7] * m[2][4] + 2 * t55 + 2 * t52 - 2 * m[1][8] * m[2][5] - 2 * m[2][8] * m[1][5] - 2 * m[2][7] * m[1][4] + 2 * t12;
  *P.ptr<double>(3,2) = t24 - 2 * m[2][8] * m[2][5] + t19 - 2 * m[2][7] * m[2][4] + t62 + t59;
  *P.ptr<double>(3,3) = -2 * m[1][9] * m[1][6] + t64 + t28;
  *P.ptr<double>(3,4) = 2 * t68 + 2 * t36 - 2 * m[2][9] * m[1][6] - 2 * m[1][9] * m[2][6];
  *P.ptr<double>(3,5) = t40 + t74 - 2 * m[2][9] * m[2][6];

  *P.ptr<double>(4,0) = t1 - 2 * m[1][10] * m[1][4] + t7 + t78 + t79 - 2 * m[1][11] * m[1][5];
  *P.ptr<double>(4,1) = 2 * t84 - 2 * m[1][11] * m[2][5] - 2 * m[1][10] * m[2][4] + 2 * t16 - 2 * m[2][11] * m[1][5] + 2 * t87 - 2 * m[2][10] * m[1][4] + 2 * t12;
  *P.ptr<double>(4,2) = t19 + t24 - 2 * m[2][10] * m[2][4] - 2 * m[2][11] * m[2][5] + t95 + t90;
  *P.ptr<double>(4,3) = t28 - 2 * m[1][12] * m[1][6] + t99;
  *P.ptr<double>(4,4) = 2 * t101 + 2 * t36 - 2 * m[2][12] * m[1][6] - 2 * m[1][12] * m[2][6];
  *P.ptr<double>(4,5) = t105 - 2 * m[2][12] * m[2][6] + t40;

  *P.ptr<double>(5,0) = -2 * m[1][10] * m[1][7] + t47 + t48 + t78 + t79 - 2 * m[1][11] * m[1][8];
  *P.ptr<double>(5,1) = 2 * t84 + 2 * t87 - 2 * m[2][11] * m[1][8] - 2 * m[1][10] * m[2][7] - 2 * m[2][10] * m[1][7] + 2 * t55 + 2 * t52 - 2 * m[1][11] * m[2][8];
  *P.ptr<double>(5,2) = -2 * m[2][10] * m[2][7] - 2 * m[2][11] * m[2][8] + t62 + t59 + t90 + t95;
  *P.ptr<double>(5,3) = t64 - 2 * m[1][12] * m[1][9] + t99;
  *P.ptr<double>(5,4) = 2 * t68 - 2 * m[2][12] * m[1][9] - 2 * m[1][12] * m[2][9] + 2 * t101;
  *P.ptr<double>(5,5) = t105 - 2 * m[2][12] * m[2][9] + t74;
edgarriba's avatar
edgarriba committed
527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554

  return P;
}

void upnp::generate_all_possible_solutions_for_f_unk(const double betas[5], double solutions[18][3])
{
  int matrix_to_resolve[18][9] = {
    { 2, 0, 0, 1, 1, 0, 2, 0, 2 }, { 2, 0, 0, 1, 1, 0, 1, 1, 2 },
    { 2, 0, 0, 1, 1, 0, 0, 2, 2 }, { 2, 0, 0, 0, 2, 0, 2, 0, 2 },
    { 2, 0, 0, 0, 2, 0, 1, 1, 2 }, { 2, 0, 0, 0, 2, 0, 0, 2, 2 },
    { 2, 0, 0, 2, 0, 2, 1, 1, 2 }, { 2, 0, 0, 2, 0, 2, 0, 2, 2 },
    { 2, 0, 0, 1, 1, 2, 0, 2, 2 }, { 1, 1, 0, 0, 2, 0, 2, 0, 2 },
    { 1, 1, 0, 0, 2, 0, 1, 1, 2 }, { 1, 1, 0, 2, 0, 2, 0, 2, 2 },
    { 1, 1, 0, 2, 0, 2, 1, 1, 2 }, { 1, 1, 0, 2, 0, 2, 0, 2, 2 },
    { 1, 1, 0, 1, 1, 2, 0, 2, 2 }, { 0, 2, 0, 2, 0, 2, 1, 1, 2 },
    { 0, 2, 0, 2, 0, 2, 0, 2, 2 }, { 0, 2, 0, 1, 1, 2, 0, 2, 2 }
  };

  int combination[18][3] = {
    { 1, 2, 4 }, { 1, 2, 5 }, { 1, 2, 6 }, { 1, 3, 4 },
    { 1, 3, 5 }, { 1, 3, 6 }, { 1, 4, 5 }, { 1, 4, 6 },
    { 1, 5, 6 }, { 2, 3, 4 }, { 2, 3, 5 }, { 2, 3, 6 },
    { 2, 4, 5 }, { 2, 4, 6 }, { 2, 5, 6 }, { 3, 4, 5 },
    { 3, 4, 6 }, { 3, 5, 6 }
  };

  for (int i = 0; i < 18; ++i) {
    double matrix[9], independent_term[3];
edgarriba's avatar
edgarriba committed
555 556 557
    Mat M = Mat(3, 3, CV_64F, matrix);
    Mat I = Mat(3, 1, CV_64F, independent_term);
    Mat S = Mat(1, 3, CV_64F);
edgarriba's avatar
edgarriba committed
558 559 560

    for (int j = 0; j < 9; ++j) matrix[j] = (double)matrix_to_resolve[i][j];

edgarriba's avatar
edgarriba committed
561 562 563
    independent_term[0] = log( abs( betas[ combination[i][0]-1 ] ) );
    independent_term[1] = log( abs( betas[ combination[i][1]-1 ] ) );
    independent_term[2] = log( abs( betas[ combination[i][2]-1 ] ) );
edgarriba's avatar
edgarriba committed
564

edgarriba's avatar
edgarriba committed
565
    exp( Mat(M.inv() * I), S);
edgarriba's avatar
edgarriba committed
566 567 568

    solutions[i][0] = S.at<double>(0);
    solutions[i][1] = S.at<double>(1) * sign( betas[1] );
edgarriba's avatar
edgarriba committed
569
    solutions[i][2] = abs( S.at<double>(2) );
edgarriba's avatar
edgarriba committed
570
  }
edgarriba's avatar
edgarriba committed
571 572
}

edgarriba's avatar
edgarriba committed
573
void upnp::gauss_newton(const Mat * L_6x12, const Mat * Rho, double betas[4], double * f)
edgarriba's avatar
edgarriba committed
574
{
edgarriba's avatar
edgarriba committed
575
  const int iterations_number = 50;
edgarriba's avatar
edgarriba committed
576 577

  double a[6*4], b[6], x[4];
edgarriba's avatar
edgarriba committed
578 579 580
  Mat * A = new Mat(6, 4, CV_64F, a);
  Mat * B = new Mat(6, 1, CV_64F, b);
  Mat * X = new Mat(4, 1, CV_64F, x);
edgarriba's avatar
edgarriba committed
581 582 583

  for(int k = 0; k < iterations_number; k++)
  {
edgarriba's avatar
edgarriba committed
584 585
    compute_A_and_b_gauss_newton(L_6x12->ptr<double>(0), Rho->ptr<double>(0), betas, A, B, f[0]);
    qr_solve(A, B, X);
edgarriba's avatar
edgarriba committed
586
    for(int i = 0; i < 3; i++)
edgarriba's avatar
edgarriba committed
587
      betas[i] += x[i];
edgarriba's avatar
edgarriba committed
588 589 590 591
    f[0] += x[3];
  }

  if (f[0] < 0) f[0] = -f[0];
edgarriba's avatar
edgarriba committed
592 593
    fu = fv = f[0];

edgarriba's avatar
edgarriba committed
594 595 596
}

void upnp::compute_A_and_b_gauss_newton(const double * l_6x12, const double * rho,
edgarriba's avatar
edgarriba committed
597
        const double betas[4], Mat * A, Mat * b, double const f)
edgarriba's avatar
edgarriba committed
598 599 600 601
{

  for(int i = 0; i < 6; i++) {
    const double * rowL = l_6x12 + i * 12;
edgarriba's avatar
edgarriba committed
602
    double * rowA = A->ptr<double>(i);
edgarriba's avatar
edgarriba committed
603

edgarriba's avatar
edgarriba committed
604 605 606
    rowA[0] = 2 * rowL[0] * betas[0] +    rowL[1] * betas[1] +    rowL[2] * betas[2] + f*f * ( 2 * rowL[6]*betas[0] +    rowL[7]*betas[1]  +    rowL[8]*betas[2] );
    rowA[1] =    rowL[1] * betas[0] + 2 * rowL[3] * betas[1] +    rowL[4] * betas[2] + f*f * (    rowL[7]*betas[0] + 2 * rowL[9]*betas[1]  +    rowL[10]*betas[2] );
    rowA[2] =    rowL[2] * betas[0] +    rowL[4] * betas[1] + 2 * rowL[5] * betas[2] + f*f * (    rowL[8]*betas[0] +    rowL[10]*betas[1] + 2 * rowL[11]*betas[2] );
edgarriba's avatar
edgarriba committed
607 608
    rowA[3] = 2*f * ( rowL[6]*betas[0]*betas[0] + rowL[7]*betas[0]*betas[1] + rowL[8]*betas[0]*betas[2] + rowL[9]*betas[1]*betas[1] + rowL[10]*betas[1]*betas[2] + rowL[11]*betas[2]*betas[2] ) ;

edgarriba's avatar
edgarriba committed
609
    *b->ptr<double>(i) = rho[i] -
edgarriba's avatar
edgarriba committed
610 611 612 613 614 615 616 617 618 619 620 621 622
    (
      rowL[0] * betas[0] * betas[0] +
      rowL[1] * betas[0] * betas[1] +
      rowL[2] * betas[0] * betas[2] +
      rowL[3] * betas[1] * betas[1] +
      rowL[4] * betas[1] * betas[2] +
      rowL[5] * betas[2] * betas[2] +
      f*f * rowL[6] * betas[0] * betas[0] +
      f*f * rowL[7] * betas[0] * betas[1] +
      f*f * rowL[8] * betas[0] * betas[2] +
      f*f * rowL[9] * betas[1] * betas[1] +
      f*f * rowL[10] * betas[1] * betas[2] +
      f*f * rowL[11] * betas[2] * betas[2]
edgarriba's avatar
edgarriba committed
623
     );
edgarriba's avatar
edgarriba committed
624 625 626 627 628
  }
}

void upnp::compute_L_6x12(const double * ut, double * l_6x12)
{
629
  const double * v[3];
edgarriba's avatar
edgarriba committed
630 631 632 633 634

  v[0] = ut + 12 * 9;
  v[1] = ut + 12 * 10;
  v[2] = ut + 12 * 11;

635
  double dv[3][6][3];
edgarriba's avatar
edgarriba committed
636

637
  for(int i = 0; i < 3; i++) {
edgarriba's avatar
edgarriba committed
638 639 640 641 642 643 644 645
    int a = 0, b = 1;
    for(int j = 0; j < 6; j++) {
      dv[i][j][0] = v[i][3 * a    ] - v[i][3 * b];
      dv[i][j][1] = v[i][3 * a + 1] - v[i][3 * b + 1];
      dv[i][j][2] = v[i][3 * a + 2] - v[i][3 * b + 2];

      b++;
      if (b > 3) {
edgarriba's avatar
edgarriba committed
646 647
        a++;
        b = a + 1;
edgarriba's avatar
edgarriba committed
648 649 650 651 652 653 654 655
      }
    }
  }

  for(int i = 0; i < 6; i++) {
    double * row = l_6x12 + 12 * i;

    row[0] =         dotXY(dv[0][i], dv[0][i]);
edgarriba's avatar
edgarriba committed
656 657 658 659 660 661 662 663 664 665 666 667
    row[1] =  2.0f * dotXY(dv[0][i], dv[1][i]);
    row[2] =         dotXY(dv[1][i], dv[1][i]);
    row[3] =  2.0f * dotXY(dv[0][i], dv[2][i]);
    row[4] =  2.0f * dotXY(dv[1][i], dv[2][i]);
    row[5] =         dotXY(dv[2][i], dv[2][i]);

    row[6] =         dotZ(dv[0][i], dv[0][i]);
    row[7] =  2.0f * dotZ(dv[0][i], dv[1][i]);
    row[8] =  2.0f * dotZ(dv[0][i], dv[2][i]);
    row[9] =         dotZ(dv[1][i], dv[1][i]);
    row[10] = 2.0f * dotZ(dv[1][i], dv[2][i]);
    row[11] =        dotZ(dv[2][i], dv[2][i]);
edgarriba's avatar
edgarriba committed
668 669 670 671 672
  }
}

void upnp::compute_rho(double * rho)
{
edgarriba's avatar
edgarriba committed
673 674 675 676 677 678
  rho[0] = dist2(cws[0], cws[1]);
  rho[1] = dist2(cws[0], cws[2]);
  rho[2] = dist2(cws[0], cws[3]);
  rho[3] = dist2(cws[1], cws[2]);
  rho[4] = dist2(cws[1], cws[3]);
  rho[5] = dist2(cws[2], cws[3]);
edgarriba's avatar
edgarriba committed
679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703
}

double upnp::dist2(const double * p1, const double * p2)
{
  return
    (p1[0] - p2[0]) * (p1[0] - p2[0]) +
    (p1[1] - p2[1]) * (p1[1] - p2[1]) +
    (p1[2] - p2[2]) * (p1[2] - p2[2]);
}

double upnp::dot(const double * v1, const double * v2)
{
  return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2];
}

double upnp::dotXY(const double * v1, const double * v2)
{
  return v1[0] * v2[0] + v1[1] * v2[1];
}

double upnp::dotZ(const double * v1, const double * v2)
{
  return v1[2] * v2[2];
}

edgarriba's avatar
edgarriba committed
704 705
double upnp::sign(const double v)
{
edgarriba's avatar
edgarriba committed
706
  return ( v < 0.0 ) ? -1.0 : ( v > 0.0 ) ? 1.0 : 0.0;
edgarriba's avatar
edgarriba committed
707 708
}

edgarriba's avatar
edgarriba committed
709
void upnp::qr_solve(Mat * A, Mat * b, Mat * X)
edgarriba's avatar
edgarriba committed
710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725
{
  const int nr = A->rows;
  const int nc = A->cols;

  if (max_nr != 0 && max_nr < nr)
  {
    delete [] A1;
    delete [] A2;
  }
  if (max_nr < nr)
  {
    max_nr = nr;
    A1 = new double[nr];
    A2 = new double[nr];
  }

edgarriba's avatar
edgarriba committed
726
  double * pA = A->ptr<double>(0), * ppAkk = pA;
edgarriba's avatar
edgarriba committed
727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743
  for(int k = 0; k < nc; k++)
  {
    double * ppAik1 = ppAkk, eta = fabs(*ppAik1);
    for(int i = k + 1; i < nr; i++)
    {
      double elt = fabs(*ppAik1);
      if (eta < elt) eta = elt;
      ppAik1 += nc;
    }
    if (eta == 0)
    {
      A1[k] = A2[k] = 0.0;
      //cerr << "God damnit, A is singular, this shouldn't happen." << endl;
      return;
    }
    else
    {
edgarriba's avatar
edgarriba committed
744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772
     double * ppAik2 = ppAkk, sum2 = 0.0, inv_eta = 1. / eta;
     for(int i = k; i < nr; i++)
     {
       *ppAik2 *= inv_eta;
       sum2 += *ppAik2 * *ppAik2;
       ppAik2 += nc;
     }
     double sigma = sqrt(sum2);
     if (*ppAkk < 0)
     sigma = -sigma;
     *ppAkk += sigma;
     A1[k] = sigma * *ppAkk;
     A2[k] = -eta * sigma;
     for(int j = k + 1; j < nc; j++)
     {
       double * ppAik = ppAkk, sum = 0;
       for(int i = k; i < nr; i++)
       {
        sum += *ppAik * ppAik[j - k];
        ppAik += nc;
       }
       double tau = sum / A1[k];
       ppAik = ppAkk;
       for(int i = k; i < nr; i++)
       {
        ppAik[j - k] -= tau * *ppAik;
        ppAik += nc;
       }
     }
edgarriba's avatar
edgarriba committed
773 774 775 776 777
    }
    ppAkk += nc + 1;
  }

  // b <- Qt b
edgarriba's avatar
edgarriba committed
778
  double * ppAjj = pA, * pb = b->ptr<double>(0);
edgarriba's avatar
edgarriba committed
779 780 781 782 783
  for(int j = 0; j < nc; j++)
  {
    double * ppAij = ppAjj, tau = 0;
    for(int i = j; i < nr; i++)
    {
edgarriba's avatar
edgarriba committed
784 785
     tau += *ppAij * pb[i];
     ppAij += nc;
edgarriba's avatar
edgarriba committed
786 787 788 789 790
    }
    tau /= A1[j];
    ppAij = ppAjj;
    for(int i = j; i < nr; i++)
    {
edgarriba's avatar
edgarriba committed
791 792
     pb[i] -= tau * *ppAij;
     ppAij += nc;
edgarriba's avatar
edgarriba committed
793 794 795 796 797
    }
    ppAjj += nc + 1;
  }

  // X = R-1 b
edgarriba's avatar
edgarriba committed
798
  double * pX = X->ptr<double>(0);
edgarriba's avatar
edgarriba committed
799 800 801 802 803 804 805
  pX[nc - 1] = pb[nc - 1] / A2[nc - 1];
  for(int i = nc - 2; i >= 0; i--)
  {
    double * ppAij = pA + i * nc + (i + 1), sum = 0;

    for(int j = i + 1; j < nc; j++)
    {
edgarriba's avatar
edgarriba committed
806 807
     sum += *ppAij * pX[j];
     ppAij++;
edgarriba's avatar
edgarriba committed
808 809 810 811
    }
    pX[i] = (pb[i] - sum) / A2[i];
  }
}