Updating for N=2
authoredgarriba <edgar.riba@gmail.com>
Mon, 6 Oct 2014 08:28:04 +0000 (10:28 +0200)
committeredgarriba <edgar.riba@gmail.com>
Mon, 6 Oct 2014 08:28:04 +0000 (10:28 +0200)
modules/calib3d/src/upnp.cpp
modules/calib3d/src/upnp.h

index 440471a..66081e0 100644 (file)
@@ -2,21 +2,10 @@
 #include "upnp.h"
 #include <limits>
 
-void printMat(cv::Mat &mat)
-{
-       cout << mat.rows << "x" << mat.cols << endl;
-       for (int i = 0; i < mat.rows; ++i) {
-               cout << "[";
-               for (int j = 0; j < mat.cols; ++j) {
-                       cout << mat.at<double>(i,j) << ",";
-               }
-               cout << "];" << endl;
-       }
-}
 upnp::upnp(const cv::Mat& cameraMatrix, const cv::Mat& opoints, const cv::Mat& ipoints)
 {
   if (cameraMatrix.depth() == CV_32F)
-      init_camera_parameters<float>(cameraMatrix);
+    init_camera_parameters<float>(cameraMatrix);
   else
     init_camera_parameters<double>(cameraMatrix);
 
@@ -47,67 +36,67 @@ upnp::upnp(const cv::Mat& cameraMatrix, const cv::Mat& opoints, const cv::Mat& i
 
 upnp::~upnp()
 {
-    if (A1)
-        delete[] A1;
-    if (A2)
-        delete[] A2;
+  if (A1)
+    delete[] A1;
+  if (A2)
+    delete[] A2;
 }
 
 double upnp::compute_pose(cv::Mat& R, cv::Mat& t)
 {
-       choose_control_points();
-       compute_alphas();
+  choose_control_points();
+  compute_alphas();
 
-       CvMat * M = cvCreateMat(2 * number_of_correspondences, 12, CV_64F);
+  CvMat * M = cvCreateMat(2 * number_of_correspondences, 12, CV_64F);
 
-       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]);
-       }
+  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]);
+  }
 
-       double mtm[12 * 12], d[12], ut[12 * 12];
-       CvMat MtM = cvMat(12, 12, CV_64F, mtm);
-       CvMat D   = cvMat(12,  1, CV_64F, d);
-       CvMat Ut  = cvMat(12, 12, CV_64F, ut);
+  double mtm[12 * 12], d[12], ut[12 * 12];
+  CvMat MtM = cvMat(12, 12, CV_64F, mtm);
+  CvMat D   = cvMat(12,  1, CV_64F, d);
+  CvMat Ut  = cvMat(12, 12, CV_64F, ut);
 
-       cvMulTransposed(M, &MtM, 1);
-       cvSVD(&MtM, &D, &Ut, 0, CV_SVD_MODIFY_A | CV_SVD_U_T);
-       cvReleaseMat(&M);
+  cvMulTransposed(M, &MtM, 1);
+  cvSVD(&MtM, &D, &Ut, 0, CV_SVD_MODIFY_A | CV_SVD_U_T);
+  cvReleaseMat(&M);
 
-    double l_6x12[6 * 12], rho[6];
-    CvMat L_6x12 = cvMat(6, 12, CV_64F, l_6x12);
-    CvMat Rho    = cvMat(6,  1, CV_64F, rho);
+  double l_6x12[6 * 12], rho[6];
+  CvMat L_6x12 = cvMat(6, 12, CV_64F, l_6x12);
+  CvMat Rho    = cvMat(6,  1, CV_64F, rho);
 
-       compute_L_6x12(ut, l_6x12);
-       compute_rho(rho);
+  compute_L_6x12(ut, l_6x12);
+  compute_rho(rho);
 
-       double Betas[4][4], Efs[4][1], rep_errors[4];
-       double Rs[4][3][3], ts[4][3];
+  double Betas[3][4], Efs[3][1], rep_errors[3];
+  double Rs[3][3][3], ts[3][3];
 
-       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], Efs[1], Rs[1], ts[1]);
+  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]);
 
-    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], Efs[2], Rs[2], ts[2]);
+  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]);
 
-       int N = 1;
-       //if (rep_errors[2] < rep_errors[1]) N = 2;
-       //if (rep_errors[3] < rep_errors[N]) N = 3;
+  int N = 1;
+  if (rep_errors[2] < rep_errors[1]) N = 2;
 
-       cv::Mat(3, 1, CV_64F, ts[N]).copyTo(t);
-       cv::Mat(3, 3, CV_64F, Rs[N]).copyTo(R);
+  cv::Mat(3, 1, CV_64F, ts[N]).copyTo(t);
+  cv::Mat(3, 3, CV_64F, Rs[N]).copyTo(R);
+  fu = fv = Efs[N][0];
 
-       return Efs[N][0];
+  return fu;
 }
 
 void upnp::copy_R_and_t(const double R_src[3][3], const double t_src[3],
-      double R_dst[3][3], double t_dst[3])
+     double R_dst[3][3], double t_dst[3])
 {
   for(int i = 0; i < 3; i++) {
     for(int j = 0; j < 3; j++)
-      R_dst[i][j] = R_src[i][j];
+     R_dst[i][j] = R_src[i][j];
     t_dst[i] = t_src[i];
   }
 }
@@ -177,7 +166,7 @@ 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++)
-  ccs[i][j] = -ccs[i][j];
+        ccs[i][j] = -ccs[i][j];
 
     for(int i = 0; i < number_of_correspondences; i++) {
       pcs[3 * i    ] = -pcs[3 * i];
@@ -187,10 +176,10 @@ void upnp::solve_for_sign(void)
   }
 }
 
-double upnp::compute_R_and_t(const double * ut, const double * betas, const double * efs,
-           double R[3][3], double t[3])
+double upnp::compute_R_and_t(const double * ut, const double * betas,
+         double R[3][3], double t[3])
 {
-  compute_ccs(betas, efs, ut);
+  compute_ccs(betas, ut);
   compute_pcs();
 
   solve_for_sign();
@@ -221,27 +210,27 @@ double upnp::reprojection_error(const double R[3][3], const double t[3])
 
 void upnp::choose_control_points()
 {
-       for (int i = 0; i < 4; ++i)
-        cws[i][0] = cws[i][1] = cws[i][2] = 0;
+    for (int i = 0; i < 4; ++i)
+      cws[i][0] = cws[i][1] = cws[i][2] = 0;
     cws[0][0] = cws[1][1] = cws[2][2] = 1.;
 }
 
 void upnp::compute_alphas()
 {
-       cv::Mat CC = cv::Mat(4, 3, CV_64F, &cws);
-       cv::Mat PC = cv::Mat(number_of_correspondences, 3, CV_64F, &pws.front());
-       cv::Mat ALPHAS = cv::Mat(number_of_correspondences, 4, CV_64F, &alphas.front());
+    cv::Mat CC = cv::Mat(4, 3, CV_64F, &cws);
+    cv::Mat PC = cv::Mat(number_of_correspondences, 3, CV_64F, &pws[0]);
+    cv::Mat ALPHAS = cv::Mat(number_of_correspondences, 4, CV_64F, &alphas[0]);
 
-       cv::Mat CC_ = CC.clone().t();
-       cv::Mat PC_ = PC.clone().t();
+    cv::Mat CC_ = CC.clone().t();
+    cv::Mat PC_ = PC.clone().t();
 
-       cv::Mat row14 = cv::Mat::ones(1, 4, CV_64F);
-       cv::Mat row1n = cv::Mat::ones(1, number_of_correspondences, CV_64F);
+    cv::Mat row14 = cv::Mat::ones(1, 4, CV_64F);
+    cv::Mat row1n = cv::Mat::ones(1, number_of_correspondences, CV_64F);
 
-       CC_.push_back(row14);
-       PC_.push_back(row1n);
+    CC_.push_back(row14);
+    PC_.push_back(row1n);
 
-       ALPHAS = cv::Mat( CC_.inv() * PC_ ).t();
+    ALPHAS = cv::Mat( CC_.inv() * PC_ ).t();
 }
 
 void upnp::fill_M(CvMat * M, const int row, const double * as, const double u, const double v)
@@ -260,20 +249,20 @@ void upnp::fill_M(CvMat * M, const int row, const double * as, const double u, c
   }
 }
 
-void upnp::compute_ccs(const double * betas, const double * f, const double * ut)
+void upnp::compute_ccs(const double * betas, const double * ut)
 {
-       for(int i = 0; i < 4; ++i)
-               ccs[i][0] = ccs[i][1] = ccs[i][2] = 0.0f;
-
-       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]; // be careful with that
-       }
-
-       for (int i = 0; i < 4; ++i) ccs[i][2] *= f[0];
+    for(int i = 0; i < 4; ++i)
+      ccs[i][0] = ccs[i][1] = ccs[i][2] = 0.0f;
+
+    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;
 }
 
 void upnp::compute_pcs(void)
@@ -289,177 +278,245 @@ void upnp::compute_pcs(void)
 
 void upnp::find_betas_and_focal_approx_1(const CvMat * Ut, const CvMat * Rho, double * betas, double * efs)
 {
-       cv::Mat Kmf1 = cv::Mat(12, 1, CV_64F, Ut->data.db + 11 * 12);
-       cv::Mat dsq = cv::Mat(6, 1, CV_64F, Rho->data.db);
+    cv::Mat Kmf1 = cv::Mat(12, 1, CV_64F, Ut->data.db + 11 * 12);
+    cv::Mat dsq = cv::Mat(6, 1, CV_64F, Rho->data.db);
 
-       cv::Mat D = compute_constraint_distance_2param_6eq_2unk_f_unk( Kmf1 );
-       cv::Mat Dt = D.t();
+    cv::Mat D = compute_constraint_distance_2param_6eq_2unk_f_unk( Kmf1 );
+    cv::Mat Dt = D.t();
 
-       cv::Mat A = Dt * D;
-       cv::Mat b = Dt * dsq;
+    cv::Mat A = Dt * D;
+    cv::Mat b = Dt * dsq;
 
-       cv::Mat x = cv::Mat(2, 1, CV_64F);
-       cv::solve(A, b, x);
+    cv::Mat x = cv::Mat(2, 1, CV_64F);
+    cv::solve(A, b, x);
 
-       betas[0] = std::sqrt( std::abs( x.at<double>(0) ) );
-       betas[1] = betas[2] = betas[3] = 0;
+    betas[0] = std::sqrt( std::abs( x.at<double>(0) ) );
+    betas[1] = betas[2] = betas[3] = 0;
 
-       efs[0] = std::sqrt( std::abs( x.at<double>(1) ) ) / betas[0];
+    efs[0] = std::sqrt( std::abs( x.at<double>(1) ) ) / betas[0];
 }
 
 void upnp::find_betas_and_focal_approx_2(const CvMat * Ut, const CvMat * Rho, double * betas, double * efs)
 {
 
-       cv::Mat Kmf1 = cv::Mat(12, 1, CV_64F, Ut->data.db + 10 * 12);
-       cv::Mat Kmf2 = cv::Mat(12, 1, CV_64F, Ut->data.db + 11 * 12);
-       cv::Mat dsq = cv::Mat(6, 1, CV_64F, Rho->data.db);
+  cv::Mat Kmf1 = cv::Mat(12, 1, CV_64F, Ut->data.db + 10 * 12);
+  cv::Mat Kmf2 = cv::Mat(12, 1, CV_64F, Ut->data.db + 11 * 12);
+  cv::Mat dsq = cv::Mat(6, 1, CV_64F, Rho->data.db);
+
+  cv::Mat D = compute_constraint_distance_3param_6eq_6unk_f_unk( Kmf1, Kmf2 );
+
+  cv::Mat A = D;
+  cv::Mat b = dsq;
 
-       cv::Mat D = compute_constraint_distance_3param_6eq_6unk_f_unk( Kmf1, Kmf2 );  // OKAY
+  double x[6];
+  cv::Mat X = cv::Mat(6, 1, CV_64F, x);
 
-       cv::Mat A = D;
-       cv::Mat b = dsq;
+  cv::solve(A, b, X, cv::DECOMP_QR);
 
-       cv::Mat x = cv::Mat(6, 1, CV_64F);
+  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];
+    betas[1] = betas[0] = 0;
+    fu = fv = solutions[i][2];
+
+    double Rs[3][3], ts[3];
+    double error_i = compute_R_and_t( Ut->data.db, betas, Rs, ts);
+
+    if( error_i < min_error)
+    {
+      min_error = error_i;
+      min_sol = i;
+    }
+}
 
-       cv::solve(A, b, x, cv::DECOMP_QR);
+  betas[0] = solutions[min_sol][0];
+  betas[1] = solutions[min_sol][1];
+  betas[2] = betas[3] = 0;
 
-       betas[0] = std::sqrt( std::abs( x.at<double>(0) ) );
-    betas[1] = std::sqrt( std::abs( x.at<double>(2) ) * ( x.at<double>(2) < 0 ) ? -1 : ( x.at<double>(2) > 0 ) ? 1 : 0 );
-    betas[2] = betas[3] = 0;
+  efs[0] = solutions[min_sol][2];
 }
 
 cv::Mat upnp::compute_constraint_distance_2param_6eq_2unk_f_unk(const cv::Mat& M1)
 {
-       cv::Mat P = cv::Mat(6, 2, CV_64F);
-
-       double m[13];
-       for (int i = 1; i < 13; ++i) m[i] = M1.at<double>(i-1);
-
-       double t1 = std::pow( m[4], 2 );
-       double t4 = std::pow( m[1], 2 );
-       double t5 = std::pow( m[5], 2 );
-       double t8 = std::pow( m[2], 2 );
-       double t10 = std::pow( m[6], 2 );
-       double t13 = std::pow( m[3], 2 );
-       double t15 = std::pow( m[7], 2 );
-       double t18 = std::pow( m[8], 2 );
-       double t22 = std::pow( m[9], 2 );
-       double t26 = std::pow( m[10], 2 );
-       double t29 = std::pow( m[11], 2 );
-       double t33 = std::pow( m[12], 2 );
-
-       P.at<double>(0,0) = t1 - 2 * m[4] * m[1] + t4 + t5 - 2 * m[5] * m[2] + t8;
-       P.at<double>(0,1) = t10 - 2 * m[6] * m[3] + t13;
-       P.at<double>(1,0) = t15 - 2 * m[7] * m[1] + t4 + t18 - 2 * m[8] * m[2] + t8;
-       P.at<double>(1,1) = t22 - 2 * m[9] * m[3] + t13;
-       P.at<double>(2,0) = t26 - 2 * m[10] * m[1] + t4 + t29 - 2 * m[11] * m[2] + t8;
-       P.at<double>(2,1) = t33 - 2 * m[12] * m[3] + t13;
-       P.at<double>(3,0) = t15 - 2 * m[7] * m[4] + t1 + t18 - 2 * m[8] * m[5] + t5;
-       P.at<double>(3,1) = t22 - 2 * m[9] * m[6] + t10;
-       P.at<double>(4,0) = t26 - 2 * m[10] * m[4] + t1 + t29 - 2 * m[11] * m[5] + t5;
-       P.at<double>(4,1) = t33 - 2 * m[12] * m[6] + t10;
-       P.at<double>(5,0) = t26 - 2 * m[10] * m[7] + t15 + t29 - 2 * m[11] * m[8] + t18;
-       P.at<double>(5,1) = t33 - 2 * m[12] * m[9] + t22;
-
-       return P;
+  cv::Mat P = cv::Mat(6, 2, CV_64F);
+
+  double m[13];
+  for (int i = 1; i < 13; ++i) m[i] = M1.at<double>(i-1);
+
+  double t1 = std::pow( m[4], 2 );
+  double t4 = std::pow( m[1], 2 );
+  double t5 = std::pow( m[5], 2 );
+  double t8 = std::pow( m[2], 2 );
+  double t10 = std::pow( m[6], 2 );
+  double t13 = std::pow( m[3], 2 );
+  double t15 = std::pow( m[7], 2 );
+  double t18 = std::pow( m[8], 2 );
+  double t22 = std::pow( m[9], 2 );
+  double t26 = std::pow( m[10], 2 );
+  double t29 = std::pow( m[11], 2 );
+  double t33 = std::pow( m[12], 2 );
+
+  P.at<double>(0,0) = t1 - 2 * m[4] * m[1] + t4 + t5 - 2 * m[5] * m[2] + t8;
+  P.at<double>(0,1) = t10 - 2 * m[6] * m[3] + t13;
+  P.at<double>(1,0) = t15 - 2 * m[7] * m[1] + t4 + t18 - 2 * m[8] * m[2] + t8;
+  P.at<double>(1,1) = t22 - 2 * m[9] * m[3] + t13;
+  P.at<double>(2,0) = t26 - 2 * m[10] * m[1] + t4 + t29 - 2 * m[11] * m[2] + t8;
+  P.at<double>(2,1) = t33 - 2 * m[12] * m[3] + t13;
+  P.at<double>(3,0) = t15 - 2 * m[7] * m[4] + t1 + t18 - 2 * m[8] * m[5] + t5;
+  P.at<double>(3,1) = t22 - 2 * m[9] * m[6] + t10;
+  P.at<double>(4,0) = t26 - 2 * m[10] * m[4] + t1 + t29 - 2 * m[11] * m[5] + t5;
+  P.at<double>(4,1) = t33 - 2 * m[12] * m[6] + t10;
+  P.at<double>(5,0) = t26 - 2 * m[10] * m[7] + t15 + t29 - 2 * m[11] * m[8] + t18;
+  P.at<double>(5,1) = t33 - 2 * m[12] * m[9] + t22;
+
+  return P;
 }
 
 cv::Mat upnp::compute_constraint_distance_3param_6eq_6unk_f_unk(const cv::Mat& M1, const cv::Mat& M2)
 {
-       cv::Mat P = cv::Mat(6, 6, CV_64F);
-
-       double m[3][13];
-       for (int i = 1; i < 13; ++i)
-       {
-               m[1][i] = M1.at<double>(i-1);
-               m[2][i] = M2.at<double>(i-1);
-       }
-
-       double t1 = std::pow( m[1][4], 2 );
-       double t2 = std::pow( m[1][1], 2 );
-       double t7 = std::pow( m[1][5], 2 );
-       double t8 = std::pow( m[1][2], 2 );
-       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];
-       double t19 = std::pow( m[2][4], 2 );
-       double t22 = std::pow( m[2][2], 2 );
-       double t23 = std::pow( m[2][1], 2 );
-       double t24 = std::pow( m[2][5], 2 );
-       double t28 = std::pow( m[1][6], 2 );
-       double t29 = std::pow( m[1][3], 2 );
-       double t34 = std::pow( m[1][3], 2 );
-       double t36 = m[1][6] * m[2][6];
-       double t40 = std::pow( m[2][6], 2 );
-       double t41 = std::pow( m[2][3], 2 );
-       double t47 = std::pow( m[1][7], 2 );
-       double t48 = std::pow( m[1][8], 2 );
-       double t52 = m[1][7] * m[2][7];
-       double t55 = m[1][8] * m[2][8];
-       double t59 = std::pow( m[2][8], 2 );
-       double t62 = std::pow( m[2][7], 2 );
-       double t64 = std::pow( m[1][9], 2 );
-       double t68 = m[1][9] * m[2][9];
-       double t74 = std::pow( m[2][9], 2 );
-       double t78 = std::pow( m[1][10], 2 );
-       double t79 = std::pow( m[1][11], 2 );
-       double t84 = m[1][10] * m[2][10];
-       double t87 = m[1][11] * m[2][11];
-       double t90 = std::pow( m[2][10], 2 );
-       double t95 = std::pow( m[2][11], 2 );
-       double t99 = std::pow( m[1][12], 2 );
-       double t101 = m[1][12] * m[2][12];
-       double t105 = std::pow( m[2][12], 2 );
-
-       P.at<double>(0,0) = t1 + t2 - 2 * m[1][4] * m[1][1] - 2 * m[1][5] * m[1][2] + t7 + t8;
-       P.at<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.at<double>(0,2) = t19 - 2 * m[2][4] * m[2][1] + t22 + t23 + t24 - 2 * m[2][5] * m[2][2];
-       P.at<double>(0,3) = t28 + t29 - 2 * m[1][6] * m[1][3];
-       P.at<double>(0,4) = -2 * m[2][6] * m[1][3] + 2 * t34 - 2 * m[1][6] * m[2][3] + 2 * t36;
-       P.at<double>(0,5) = -2 * m[2][6] * m[2][3] + t40 + t41;
-
-       P.at<double>(1,0) = t8 - 2 * m[1][8] * m[1][2] - 2 * m[1][7] * m[1][1] + t47 + t48 + t2;
-       P.at<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.at<double>(1,2) = -2 * m[2][8] * m[2][2] + t22 + t23 + t59 - 2 * m[2][7] * m[2][1] + t62;
-       P.at<double>(1,3) = t29 + t64 - 2 * m[1][9] * m[1][3];
-       P.at<double>(1,4) = 2 * t34 + 2 * t68 - 2 * m[2][9] * m[1][3] - 2 * m[1][9] * m[2][3];
-       P.at<double>(1,5) = -2 * m[2][9] * m[2][3] + t74 + t41;
-
-       P.at<double>(2,0) = -2 * m[1][11] * m[1][2] + t2 + t8 + t78 + t79 - 2 * m[1][10] * m[1][1];
-       P.at<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.at<double>(2,2) = t90 + t22 - 2 * m[2][10] * m[2][1] + t23 - 2 * m[2][11] * m[2][2] + t95;
-       P.at<double>(2,3) = -2 * m[1][12] * m[1][3] + t99 + t29;
-       P.at<double>(2,4) = 2 * t34 + 2 * t101 - 2 * m[2][12] * m[1][3] - 2 * m[1][12] * m[2][3];
-       P.at<double>(2,5) = t41 + t105 - 2 * m[2][12] * m[2][3];
-
-       P.at<double>(3,0) = t48 + t1 - 2 * m[1][8] * m[1][5] + t7 - 2 * m[1][7] * m[1][4] + t47;
-       P.at<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.at<double>(3,2) = t24 - 2 * m[2][8] * m[2][5] + t19 - 2 * m[2][7] * m[2][4] + t62 + t59;
-       P.at<double>(3,3) = -2 * m[1][9] * m[1][6] + t64 + t28;
-       P.at<double>(3,4) = 2 * t68 + 2 * t36 - 2 * m[2][9] * m[1][6] - 2 * m[1][9] * m[2][6];
-       P.at<double>(3,5) = t40 + t74 - 2 * m[2][9] * m[2][6];
-
-       P.at<double>(4,0) = t1 - 2 * m[1][10] * m[1][4] + t7 + t78 + t79 - 2 * m[1][11] * m[1][5];
-       P.at<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.at<double>(4,2) = t19 + t24 - 2 * m[2][10] * m[2][4] - 2 * m[2][11] * m[2][5] + t95 + t90;
-       P.at<double>(4,3) = t28 - 2 * m[1][12] * m[1][6] + t99;
-       P.at<double>(4,4) = 2 * t101 + 2 * t36 - 2 * m[2][12] * m[1][6] - 2 * m[1][12] * m[2][6];
-       P.at<double>(4,5) = t105 - 2 * m[2][12] * m[2][6] + t40;
-
-       P.at<double>(5,0) = -2 * m[1][10] * m[1][7] + t47 + t48 + t78 + t79 - 2 * m[1][11] * m[1][8];
-       P.at<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.at<double>(5,2) = -2 * m[2][10] * m[2][7] - 2 * m[2][11] * m[2][8] + t62 + t59 + t90 + t95;
-       P.at<double>(5,3) = t64 - 2 * m[1][12] * m[1][9] + t99;
-       P.at<double>(5,4) = 2 * t68 - 2 * m[2][12] * m[1][9] - 2 * m[1][12] * m[2][9] + 2 * t101;
-       P.at<double>(5,5) = t105 - 2 * m[2][12] * m[2][9] + t74;
-
-       return P;
+  cv::Mat P = cv::Mat(6, 6, CV_64F);
+
+  double m[3][13];
+  for (int i = 1; i < 13; ++i)
+  {
+    m[1][i] = M1.at<double>(i-1);
+    m[2][i] = M2.at<double>(i-1);
+  }
+
+  double t1 = std::pow( m[1][4], 2 );
+  double t2 = std::pow( m[1][1], 2 );
+  double t7 = std::pow( m[1][5], 2 );
+  double t8 = std::pow( m[1][2], 2 );
+  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];
+  double t19 = std::pow( m[2][4], 2 );
+  double t22 = std::pow( m[2][2], 2 );
+  double t23 = std::pow( m[2][1], 2 );
+  double t24 = std::pow( m[2][5], 2 );
+  double t28 = std::pow( m[1][6], 2 );
+  double t29 = std::pow( m[1][3], 2 );
+  double t34 = std::pow( m[1][3], 2 );
+  double t36 = m[1][6] * m[2][6];
+  double t40 = std::pow( m[2][6], 2 );
+  double t41 = std::pow( m[2][3], 2 );
+  double t47 = std::pow( m[1][7], 2 );
+  double t48 = std::pow( m[1][8], 2 );
+  double t52 = m[1][7] * m[2][7];
+  double t55 = m[1][8] * m[2][8];
+  double t59 = std::pow( m[2][8], 2 );
+  double t62 = std::pow( m[2][7], 2 );
+  double t64 = std::pow( m[1][9], 2 );
+  double t68 = m[1][9] * m[2][9];
+  double t74 = std::pow( m[2][9], 2 );
+  double t78 = std::pow( m[1][10], 2 );
+  double t79 = std::pow( m[1][11], 2 );
+  double t84 = m[1][10] * m[2][10];
+  double t87 = m[1][11] * m[2][11];
+  double t90 = std::pow( m[2][10], 2 );
+  double t95 = std::pow( m[2][11], 2 );
+  double t99 = std::pow( m[1][12], 2 );
+  double t101 = m[1][12] * m[2][12];
+  double t105 = std::pow( m[2][12], 2 );
+
+  P.at<double>(0,0) = t1 + t2 - 2 * m[1][4] * m[1][1] - 2 * m[1][5] * m[1][2] + t7 + t8;
+  P.at<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.at<double>(0,2) = t19 - 2 * m[2][4] * m[2][1] + t22 + t23 + t24 - 2 * m[2][5] * m[2][2];
+  P.at<double>(0,3) = t28 + t29 - 2 * m[1][6] * m[1][3];
+  P.at<double>(0,4) = -2 * m[2][6] * m[1][3] + 2 * t34 - 2 * m[1][6] * m[2][3] + 2 * t36;
+  P.at<double>(0,5) = -2 * m[2][6] * m[2][3] + t40 + t41;
+
+  P.at<double>(1,0) = t8 - 2 * m[1][8] * m[1][2] - 2 * m[1][7] * m[1][1] + t47 + t48 + t2;
+  P.at<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.at<double>(1,2) = -2 * m[2][8] * m[2][2] + t22 + t23 + t59 - 2 * m[2][7] * m[2][1] + t62;
+  P.at<double>(1,3) = t29 + t64 - 2 * m[1][9] * m[1][3];
+  P.at<double>(1,4) = 2 * t34 + 2 * t68 - 2 * m[2][9] * m[1][3] - 2 * m[1][9] * m[2][3];
+  P.at<double>(1,5) = -2 * m[2][9] * m[2][3] + t74 + t41;
+
+  P.at<double>(2,0) = -2 * m[1][11] * m[1][2] + t2 + t8 + t78 + t79 - 2 * m[1][10] * m[1][1];
+  P.at<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.at<double>(2,2) = t90 + t22 - 2 * m[2][10] * m[2][1] + t23 - 2 * m[2][11] * m[2][2] + t95;
+  P.at<double>(2,3) = -2 * m[1][12] * m[1][3] + t99 + t29;
+  P.at<double>(2,4) = 2 * t34 + 2 * t101 - 2 * m[2][12] * m[1][3] - 2 * m[1][12] * m[2][3];
+  P.at<double>(2,5) = t41 + t105 - 2 * m[2][12] * m[2][3];
+
+  P.at<double>(3,0) = t48 + t1 - 2 * m[1][8] * m[1][5] + t7 - 2 * m[1][7] * m[1][4] + t47;
+  P.at<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.at<double>(3,2) = t24 - 2 * m[2][8] * m[2][5] + t19 - 2 * m[2][7] * m[2][4] + t62 + t59;
+  P.at<double>(3,3) = -2 * m[1][9] * m[1][6] + t64 + t28;
+  P.at<double>(3,4) = 2 * t68 + 2 * t36 - 2 * m[2][9] * m[1][6] - 2 * m[1][9] * m[2][6];
+  P.at<double>(3,5) = t40 + t74 - 2 * m[2][9] * m[2][6];
+
+  P.at<double>(4,0) = t1 - 2 * m[1][10] * m[1][4] + t7 + t78 + t79 - 2 * m[1][11] * m[1][5];
+  P.at<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.at<double>(4,2) = t19 + t24 - 2 * m[2][10] * m[2][4] - 2 * m[2][11] * m[2][5] + t95 + t90;
+  P.at<double>(4,3) = t28 - 2 * m[1][12] * m[1][6] + t99;
+  P.at<double>(4,4) = 2 * t101 + 2 * t36 - 2 * m[2][12] * m[1][6] - 2 * m[1][12] * m[2][6];
+  P.at<double>(4,5) = t105 - 2 * m[2][12] * m[2][6] + t40;
+
+  P.at<double>(5,0) = -2 * m[1][10] * m[1][7] + t47 + t48 + t78 + t79 - 2 * m[1][11] * m[1][8];
+  P.at<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.at<double>(5,2) = -2 * m[2][10] * m[2][7] - 2 * m[2][11] * m[2][8] + t62 + t59 + t90 + t95;
+  P.at<double>(5,3) = t64 - 2 * m[1][12] * m[1][9] + t99;
+  P.at<double>(5,4) = 2 * t68 - 2 * m[2][12] * m[1][9] - 2 * m[1][12] * m[2][9] + 2 * t101;
+  P.at<double>(5,5) = t105 - 2 * m[2][12] * m[2][9] + t74;
+
+  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];
+    cv::Mat M = cv::Mat(3, 3, CV_64F, matrix);
+    cv::Mat I = cv::Mat(3, 1, CV_64F, independent_term);
+    cv::Mat S = cv::Mat(1, 3, CV_64F);
+
+    for (int j = 0; j < 9; ++j) matrix[j] = (double)matrix_to_resolve[i][j];
+
+    independent_term[0] = std::log( std::abs( betas[ combination[i][0]-1 ] ) );
+    independent_term[1] = std::log( std::abs( betas[ combination[i][1]-1 ] ) );
+    independent_term[2] = std::log( std::abs( betas[ combination[i][2]-1 ] ) );
+
+    cv::exp( cv::Mat(M.inv() * I), S);
+
+    solutions[i][0] = S.at<double>(0);
+    solutions[i][1] = S.at<double>(1) * sign( betas[1] );
+    solutions[i][2] = std::abs( S.at<double>(2) );
+  }
 }
 
 void upnp::gauss_newton(const CvMat * L_6x12, const CvMat * Rho, double betas[4], double * f)
 {
-  const int iterations_number = 100;
+  const int iterations_number = 50;
 
   double a[6*4], b[6], x[4];
   CvMat A = cvMat(6, 4, CV_64F, a);
@@ -471,41 +528,43 @@ void upnp::gauss_newton(const CvMat * L_6x12, const CvMat * Rho, double betas[4]
     compute_A_and_b_gauss_newton(L_6x12->data.db, Rho->data.db, betas, &A, &B, f[0]);
     qr_solve(&A, &B, &X);
     for(int i = 0; i < 3; i++)
-        betas[i] += x[i];
+      betas[i] += x[i];
     f[0] += x[3];
   }
 
   if (f[0] < 0) f[0] = -f[0];
+    fu = fv = f[0];
+
 }
 
 void upnp::compute_A_and_b_gauss_newton(const double * l_6x12, const double * rho,
-          const double betas[4], CvMat * A, CvMat * b, double const f)
+        const double betas[4], CvMat * A, CvMat * b, double const f)
 {
 
   for(int i = 0; i < 6; i++) {
     const double * rowL = l_6x12 + i * 12;
     double * rowA = A->data.db + i * 4;
 
-    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] );
+    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] );
     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] ) ;
 
     cvmSet(b, i, 0, rho[i] -
-     (
-               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]
-      ));
+    (
+      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]
+     ));
   }
 }
 
@@ -529,8 +588,8 @@ void upnp::compute_L_6x12(const double * ut, double * l_6x12)
 
       b++;
       if (b > 3) {
-          a++;
-          b = a + 1;
+        a++;
+        b = a + 1;
       }
     }
   }
@@ -539,29 +598,29 @@ void upnp::compute_L_6x12(const double * ut, double * l_6x12)
     double * row = l_6x12 + 12 * i;
 
     row[0] =         dotXY(dv[0][i], dv[0][i]);
-       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]);
+    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]);
   }
 }
 
 void upnp::compute_rho(double * rho)
 {
-       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]);
+  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]);
 }
 
 double upnp::dist2(const double * p1, const double * p2)
@@ -587,6 +646,11 @@ double upnp::dotZ(const double * v1, const double * v2)
   return v1[2] * v2[2];
 }
 
+double upnp::sign(const double v)
+{
+  return ( v < 0 ) ? -1. : ( v > 0 ) ? 1. : 0.;
+}
+
 void upnp::qr_solve(CvMat * A, CvMat * b, CvMat * X)
 {
   const int nr = A->rows;
@@ -622,35 +686,35 @@ void upnp::qr_solve(CvMat * A, CvMat * b, CvMat * X)
     }
     else
     {
-      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;
-        }
-      }
+     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;
+       }
+     }
     }
     ppAkk += nc + 1;
   }
@@ -662,15 +726,15 @@ void upnp::qr_solve(CvMat * A, CvMat * b, CvMat * X)
     double * ppAij = ppAjj, tau = 0;
     for(int i = j; i < nr; i++)
     {
-      tau += *ppAij * pb[i];
-      ppAij += nc;
+     tau += *ppAij * pb[i];
+     ppAij += nc;
     }
     tau /= A1[j];
     ppAij = ppAjj;
     for(int i = j; i < nr; i++)
     {
-      pb[i] -= tau * *ppAij;
-      ppAij += nc;
+     pb[i] -= tau * *ppAij;
+     ppAij += nc;
     }
     ppAjj += nc + 1;
   }
@@ -684,8 +748,8 @@ void upnp::qr_solve(CvMat * A, CvMat * b, CvMat * X)
 
     for(int j = i + 1; j < nc; j++)
     {
-      sum += *ppAij * pX[j];
-      ppAij++;
+     sum += *ppAij * pX[j];
+     ppAij++;
     }
     pX[i] = (pb[i] - sum) / A2[i];
   }
index 39d21bf..9a061bd 100644 (file)
@@ -28,12 +28,12 @@ private:
       {
           for(int i = 0; i < number_of_correspondences; i++)
           {
-               pws[3 * i    ] = opoints.at<OpointType>(0,i).x;
-                       pws[3 * i + 1] = opoints.at<OpointType>(0,i).y;
-                       pws[3 * i + 2] = opoints.at<OpointType>(0,i).z;
+            pws[3 * i    ] = opoints.at<OpointType>(0,i).x;
+            pws[3 * i + 1] = opoints.at<OpointType>(0,i).y;
+            pws[3 * i + 2] = opoints.at<OpointType>(0,i).z;
 
-                       us[2 * i    ] = ipoints.at<IpointType>(0,i).x;
-                       us[2 * i + 1] = ipoints.at<IpointType>(0,i).y;
+            us[2 * i    ] = ipoints.at<IpointType>(0,i).x;
+            us[2 * i + 1] = ipoints.at<IpointType>(0,i).y;
           }
       }
 
@@ -41,7 +41,7 @@ private:
       void choose_control_points();
       void compute_alphas();
       void fill_M(CvMat * M, const int row, const double * alphas, const double u, const double v);
-      void compute_ccs(const double * betas, const double * f, const double * ut);
+      void compute_ccs(const double * betas, const double * ut);
       void compute_pcs(void);
 
       void solve_for_sign(void);
@@ -52,7 +52,9 @@ private:
 
       cv::Mat compute_constraint_distance_2param_6eq_2unk_f_unk(const cv::Mat& M1);
       cv::Mat compute_constraint_distance_3param_6eq_6unk_f_unk(const cv::Mat& M1, const cv::Mat& M2);
+      void generate_all_possible_solutions_for_f_unk(const double betas_[5], double solutions[18][3]);
 
+      double sign(const double v);
       double dot(const double * v1, const double * v2);
       double dotXY(const double * v1, const double * v2);
       double dotZ(const double * v1, const double * v2);
@@ -65,7 +67,7 @@ private:
       void compute_A_and_b_gauss_newton(const double * l_6x12, const double * rho,
                           const double cb[4], CvMat * A, CvMat * b, double const f);
 
-      double compute_R_and_t(const double * ut, const double * betas, const double * efs,
+      double compute_R_and_t(const double * ut, const double * betas,
                    double R[3][3], double t[3]);
 
       void estimate_R_and_t(double R[3][3], double t[3]);