HELLO·Android
系统源代码
IT资讯
技术文章
我的收藏
注册
登录
-
我收藏的文章
创建代码块
我的代码块
我的账号
Nougat 7.0
|
7.0.0_r31
下载
查看原文件
收藏
根目录
external
opencv3
modules
calib3d
src
dls.cpp
#include "precomp.hpp" #include "dls.h" #include
#ifdef HAVE_EIGEN # if defined __GNUC__ && defined __APPLE__ # pragma GCC diagnostic ignored "-Wshadow" # endif # include
# include
# include "opencv2/core/eigen.hpp" #endif using namespace std; dls::dls(const cv::Mat& opoints, const cv::Mat& ipoints) { N = std::max(opoints.checkVector(3, CV_32F), opoints.checkVector(3, CV_64F)); p = cv::Mat(3, N, CV_64F); z = cv::Mat(3, N, CV_64F); mn = cv::Mat::zeros(3, 1, CV_64F); cost__ = 9999; f1coeff.resize(21); f2coeff.resize(21); f3coeff.resize(21); if (opoints.depth() == ipoints.depth()) { if (opoints.depth() == CV_32F) init_points
(opoints, ipoints); else init_points
(opoints, ipoints); } else if (opoints.depth() == CV_32F) init_points
(opoints, ipoints); else init_points
(opoints, ipoints); } dls::~dls() { // TODO Auto-generated destructor stub } bool dls::compute_pose(cv::Mat& R, cv::Mat& t) { std::vector
R_; R_.push_back(rotx(CV_PI/2)); R_.push_back(roty(CV_PI/2)); R_.push_back(rotz(CV_PI/2)); // version that calls dls 3 times, to avoid Cayley singularity for (int i = 0; i < 3; ++i) { // Make a random rotation cv::Mat pp = R_[i] * ( p - cv::repeat(mn, 1, p.cols) ); // clear for new data C_est_.clear(); t_est_.clear(); cost_.clear(); this->run_kernel(pp); // run dls_pnp() // find global minimum for (unsigned int j = 0; j < cost_.size(); ++j) { if( cost_[j] < cost__ ) { t_est__ = t_est_[j] - C_est_[j] * R_[i] * mn; C_est__ = C_est_[j] * R_[i]; cost__ = cost_[j]; } } } if(C_est__.cols > 0 && C_est__.rows > 0) { C_est__.copyTo(R); t_est__.copyTo(t); return true; } return false; } void dls::run_kernel(const cv::Mat& pp) { cv::Mat Mtilde(27, 27, CV_64F); cv::Mat D = cv::Mat::zeros(9, 9, CV_64F); build_coeff_matrix(pp, Mtilde, D); cv::Mat eigenval_r, eigenval_i, eigenvec_r, eigenvec_i; compute_eigenvec(Mtilde, eigenval_r, eigenval_i, eigenvec_r, eigenvec_i); /* * Now check the solutions */ // extract the optimal solutions from the eigen decomposition of the // Multiplication matrix cv::Mat sols = cv::Mat::zeros(3, 27, CV_64F); std::vector
cost; int count = 0; for (int k = 0; k < 27; ++k) { // V(:,k) = V(:,k)/V(1,k); cv::Mat V_kA = eigenvec_r.col(k); // 27x1 cv::Mat V_kB = cv::Mat(1, 1, z.depth(), V_kA.at
(0)); // 1x1 cv::Mat V_k; cv::solve(V_kB.t(), V_kA.t(), V_k); // A/B = B'\A' cv::Mat( V_k.t()).copyTo( eigenvec_r.col(k) ); //if (imag(V(2,k)) == 0) #ifdef HAVE_EIGEN const double epsilon = 1e-4; if( eigenval_i.at
(k,0) >= -epsilon && eigenval_i.at
(k,0) <= epsilon ) #endif { double stmp[3]; stmp[0] = eigenvec_r.at
(9, k); stmp[1] = eigenvec_r.at
(3, k); stmp[2] = eigenvec_r.at
(1, k); cv::Mat H = Hessian(stmp); cv::Mat eigenvalues, eigenvectors; cv::eigen(H, eigenvalues, eigenvectors); if(positive_eigenvalues(&eigenvalues)) { // sols(:,i) = stmp; cv::Mat stmp_mat(3, 1, CV_64F, &stmp); stmp_mat.copyTo( sols.col(count) ); cv::Mat Cbar = cayley2rotbar(stmp_mat); cv::Mat Cbarvec = Cbar.reshape(1,1).t(); // cost(i) = CbarVec' * D * CbarVec; cv::Mat cost_mat = Cbarvec.t() * D * Cbarvec; cost.push_back( cost_mat.at
(0) ); count++; } } } // extract solutions sols = sols.clone().colRange(0, count); std::vector
C_est, t_est; for (int j = 0; j < sols.cols; ++j) { // recover the optimal orientation // C_est(:,:,j) = 1/(1 + sols(:,j)' * sols(:,j)) * cayley2rotbar(sols(:,j)); cv::Mat sols_j = sols.col(j); double sols_mult = 1./(1.+cv::Mat( sols_j.t() * sols_j ).at
(0)); cv::Mat C_est_j = cayley2rotbar(sols_j).mul(sols_mult); C_est.push_back( C_est_j ); cv::Mat A2 = cv::Mat::zeros(3, 3, CV_64F); cv::Mat b2 = cv::Mat::zeros(3, 1, CV_64F); for (int i = 0; i < N; ++i) { cv::Mat eye = cv::Mat::eye(3, 3, CV_64F); cv::Mat z_mul = z.col(i)*z.col(i).t(); A2 += eye - z_mul; b2 += (z_mul - eye) * C_est_j * pp.col(i); } // recover the optimal translation cv::Mat X2; cv::solve(A2, b2, X2); // A\B t_est.push_back(X2); } // check that the points are infront of the center of perspectivity for (int k = 0; k < sols.cols; ++k) { cv::Mat cam_points = C_est[k] * pp + cv::repeat(t_est[k], 1, pp.cols); cv::Mat cam_points_k = cam_points.row(2); if(is_empty(&cam_points_k)) { cv::Mat C_valid = C_est[k], t_valid = t_est[k]; double cost_valid = cost[k]; C_est_.push_back(C_valid); t_est_.push_back(t_valid); cost_.push_back(cost_valid); } } } void dls::build_coeff_matrix(const cv::Mat& pp, cv::Mat& Mtilde, cv::Mat& D) { cv::Mat eye = cv::Mat::eye(3, 3, CV_64F); // build coeff matrix // An intermediate matrix, the inverse of what is called "H" in the paper // (see eq. 25) cv::Mat H = cv::Mat::zeros(3, 3, CV_64F); cv::Mat A = cv::Mat::zeros(3, 9, CV_64F); cv::Mat pp_i(3, 1, CV_64F); cv::Mat z_i(3, 1, CV_64F); for (int i = 0; i < N; ++i) { z.col(i).copyTo(z_i); A += ( z_i*z_i.t() - eye ) * LeftMultVec(pp.col(i)); } H = eye.mul(N) - z * z.t(); // A\B cv::solve(H, A, A, cv::DECOMP_NORMAL); H.release(); cv::Mat ppi_A(3, 1, CV_64F); for (int i = 0; i < N; ++i) { z.col(i).copyTo(z_i); ppi_A = LeftMultVec(pp.col(i)) + A; D += ppi_A.t() * ( eye - z_i*z_i.t() ) * ppi_A; } A.release(); // fill the coefficients fill_coeff(&D); // generate random samples std::vector
u(5); cv::randn(u, 0, 200); cv::Mat M2 = cayley_LS_M(f1coeff, f2coeff, f3coeff, u); cv::Mat M2_1 = M2(cv::Range(0,27), cv::Range(0,27)); cv::Mat M2_2 = M2(cv::Range(0,27), cv::Range(27,120)); cv::Mat M2_3 = M2(cv::Range(27,120), cv::Range(27,120)); cv::Mat M2_4 = M2(cv::Range(27,120), cv::Range(0,27)); M2.release(); // A/B = B'\A' cv::Mat M2_5; cv::solve(M2_3.t(), M2_2.t(), M2_5); M2_2.release(); M2_3.release(); // construct the multiplication matrix via schur compliment of the Macaulay // matrix Mtilde = M2_1 - M2_5.t()*M2_4; } void dls::compute_eigenvec(const cv::Mat& Mtilde, cv::Mat& eigenval_real, cv::Mat& eigenval_imag, cv::Mat& eigenvec_real, cv::Mat& eigenvec_imag) { #ifdef HAVE_EIGEN Eigen::MatrixXd Mtilde_eig, zeros_eig; cv::cv2eigen(Mtilde, Mtilde_eig); cv::cv2eigen(cv::Mat::zeros(27, 27, CV_64F), zeros_eig); Eigen::MatrixXcd Mtilde_eig_cmplx(27, 27); Mtilde_eig_cmplx.real() = Mtilde_eig; Mtilde_eig_cmplx.imag() = zeros_eig; Eigen::ComplexEigenSolver
ces; ces.compute(Mtilde_eig_cmplx); Eigen::MatrixXd eigval_real = ces.eigenvalues().real(); Eigen::MatrixXd eigval_imag = ces.eigenvalues().imag(); Eigen::MatrixXd eigvec_real = ces.eigenvectors().real(); Eigen::MatrixXd eigvec_imag = ces.eigenvectors().imag(); cv::eigen2cv(eigval_real, eigenval_real); cv::eigen2cv(eigval_imag, eigenval_imag); cv::eigen2cv(eigvec_real, eigenvec_real); cv::eigen2cv(eigvec_imag, eigenvec_imag); #else EigenvalueDecomposition es(Mtilde); eigenval_real = es.eigenvalues(); eigenvec_real = es.eigenvectors(); eigenval_imag = eigenvec_imag = cv::Mat(); #endif } void dls::fill_coeff(const cv::Mat * D_mat) { // TODO: shift D and coefficients one position to left double D[10][10]; // put D_mat into array for (int i = 0; i < D_mat->rows; ++i) { const double* Di = D_mat->ptr
(i); for (int j = 0; j < D_mat->cols; ++j) { D[i+1][j+1] = Di[j]; } } // F1 COEFFICIENT f1coeff[1] = 2*D[1][6] - 2*D[1][8] + 2*D[5][6] - 2*D[5][8] + 2*D[6][1] + 2*D[6][5] + 2*D[6][9] - 2*D[8][1] - 2*D[8][5] - 2*D[8][9] + 2*D[9][6] - 2*D[9][8]; // constant term f1coeff[2] = 6*D[1][2] + 6*D[1][4] + 6*D[2][1] - 6*D[2][5] - 6*D[2][9] + 6*D[4][1] - 6*D[4][5] - 6*D[4][9] - 6*D[5][2] - 6*D[5][4] - 6*D[9][2] - 6*D[9][4]; // s1^2 * s2 f1coeff[3] = 4*D[1][7] - 4*D[1][3] + 8*D[2][6] - 8*D[2][8] - 4*D[3][1] + 4*D[3][5] + 4*D[3][9] + 8*D[4][6] - 8*D[4][8] + 4*D[5][3] - 4*D[5][7] + 8*D[6][2] + 8*D[6][4] + 4*D[7][1] - 4*D[7][5] - 4*D[7][9] - 8*D[8][2] - 8*D[8][4] + 4*D[9][3] - 4*D[9][7]; // s1 * s2 f1coeff[4] = 4*D[1][2] - 4*D[1][4] + 4*D[2][1] - 4*D[2][5] - 4*D[2][9] + 8*D[3][6] - 8*D[3][8] - 4*D[4][1] + 4*D[4][5] + 4*D[4][9] - 4*D[5][2] + 4*D[5][4] + 8*D[6][3] + 8*D[6][7] + 8*D[7][6] - 8*D[7][8] - 8*D[8][3] - 8*D[8][7] - 4*D[9][2] + 4*D[9][4]; //s1 * s3 f1coeff[5] = 8*D[2][2] - 8*D[3][3] - 8*D[4][4] + 8*D[6][6] + 8*D[7][7] - 8*D[8][8]; // s2 * s3 f1coeff[6] = 4*D[2][6] - 2*D[1][7] - 2*D[1][3] + 4*D[2][8] - 2*D[3][1] + 2*D[3][5] - 2*D[3][9] + 4*D[4][6] + 4*D[4][8] + 2*D[5][3] + 2*D[5][7] + 4*D[6][2] + 4*D[6][4] - 2*D[7][1] + 2*D[7][5] - 2*D[7][9] + 4*D[8][2] + 4*D[8][4] - 2*D[9][3] - 2*D[9][7]; // s2^2 * s3 f1coeff[7] = 2*D[2][5] - 2*D[1][4] - 2*D[2][1] - 2*D[1][2] - 2*D[2][9] - 2*D[4][1] + 2*D[4][5] - 2*D[4][9] + 2*D[5][2] + 2*D[5][4] - 2*D[9][2] - 2*D[9][4]; //s2^3 f1coeff[8] = 4*D[1][9] - 4*D[1][1] + 8*D[3][3] + 8*D[3][7] + 4*D[5][5] + 8*D[7][3] + 8*D[7][7] + 4*D[9][1] - 4*D[9][9]; // s1 * s3^2 f1coeff[9] = 4*D[1][1] - 4*D[5][5] - 4*D[5][9] + 8*D[6][6] - 8*D[6][8] - 8*D[8][6] + 8*D[8][8] - 4*D[9][5] - 4*D[9][9]; // s1 f1coeff[10] = 2*D[1][3] + 2*D[1][7] + 4*D[2][6] - 4*D[2][8] + 2*D[3][1] + 2*D[3][5] + 2*D[3][9] - 4*D[4][6] + 4*D[4][8] + 2*D[5][3] + 2*D[5][7] + 4*D[6][2] - 4*D[6][4] + 2*D[7][1] + 2*D[7][5] + 2*D[7][9] - 4*D[8][2] + 4*D[8][4] + 2*D[9][3] + 2*D[9][7]; // s3 f1coeff[11] = 2*D[1][2] + 2*D[1][4] + 2*D[2][1] + 2*D[2][5] + 2*D[2][9] - 4*D[3][6] + 4*D[3][8] + 2*D[4][1] + 2*D[4][5] + 2*D[4][9] + 2*D[5][2] + 2*D[5][4] - 4*D[6][3] + 4*D[6][7] + 4*D[7][6] - 4*D[7][8] + 4*D[8][3] - 4*D[8][7] + 2*D[9][2] + 2*D[9][4]; // s2 f1coeff[12] = 2*D[2][9] - 2*D[1][4] - 2*D[2][1] - 2*D[2][5] - 2*D[1][2] + 4*D[3][6] + 4*D[3][8] - 2*D[4][1] - 2*D[4][5] + 2*D[4][9] - 2*D[5][2] - 2*D[5][4] + 4*D[6][3] + 4*D[6][7] + 4*D[7][6] + 4*D[7][8] + 4*D[8][3] + 4*D[8][7] + 2*D[9][2] + 2*D[9][4]; // s2 * s3^2 f1coeff[13] = 6*D[1][6] - 6*D[1][8] - 6*D[5][6] + 6*D[5][8] + 6*D[6][1] - 6*D[6][5] - 6*D[6][9] - 6*D[8][1] + 6*D[8][5] + 6*D[8][9] - 6*D[9][6] + 6*D[9][8]; // s1^2 f1coeff[14] = 2*D[1][8] - 2*D[1][6] + 4*D[2][3] + 4*D[2][7] + 4*D[3][2] - 4*D[3][4] - 4*D[4][3] - 4*D[4][7] - 2*D[5][6] + 2*D[5][8] - 2*D[6][1] - 2*D[6][5] + 2*D[6][9] + 4*D[7][2] - 4*D[7][4] + 2*D[8][1] + 2*D[8][5] - 2*D[8][9] + 2*D[9][6] - 2*D[9][8]; // s3^2 f1coeff[15] = 2*D[1][8] - 2*D[1][6] - 4*D[2][3] + 4*D[2][7] - 4*D[3][2] - 4*D[3][4] - 4*D[4][3] + 4*D[4][7] + 2*D[5][6] - 2*D[5][8] - 2*D[6][1] + 2*D[6][5] - 2*D[6][9] + 4*D[7][2] + 4*D[7][4] + 2*D[8][1] - 2*D[8][5] + 2*D[8][9] - 2*D[9][6] + 2*D[9][8]; // s2^2 f1coeff[16] = 2*D[3][9] - 2*D[1][7] - 2*D[3][1] - 2*D[3][5] - 2*D[1][3] - 2*D[5][3] - 2*D[5][7] - 2*D[7][1] - 2*D[7][5] + 2*D[7][9] + 2*D[9][3] + 2*D[9][7]; // s3^3 f1coeff[17] = 4*D[1][6] + 4*D[1][8] + 8*D[2][3] + 8*D[2][7] + 8*D[3][2] + 8*D[3][4] + 8*D[4][3] + 8*D[4][7] - 4*D[5][6] - 4*D[5][8] + 4*D[6][1] - 4*D[6][5] - 4*D[6][9] + 8*D[7][2] + 8*D[7][4] + 4*D[8][1] - 4*D[8][5] - 4*D[8][9] - 4*D[9][6] - 4*D[9][8]; // s1 * s2 * s3 f1coeff[18] = 4*D[1][5] - 4*D[1][1] + 8*D[2][2] + 8*D[2][4] + 8*D[4][2] + 8*D[4][4] + 4*D[5][1] - 4*D[5][5] + 4*D[9][9]; // s1 * s2^2 f1coeff[19] = 6*D[1][3] + 6*D[1][7] + 6*D[3][1] - 6*D[3][5] - 6*D[3][9] - 6*D[5][3] - 6*D[5][7] + 6*D[7][1] - 6*D[7][5] - 6*D[7][9] - 6*D[9][3] - 6*D[9][7]; // s1^2 * s3 f1coeff[20] = 4*D[1][1] - 4*D[1][5] - 4*D[1][9] - 4*D[5][1] + 4*D[5][5] + 4*D[5][9] - 4*D[9][1] + 4*D[9][5] + 4*D[9][9]; // s1^3 // F2 COEFFICIENT f2coeff[1] = - 2*D[1][3] + 2*D[1][7] - 2*D[3][1] - 2*D[3][5] - 2*D[3][9] - 2*D[5][3] + 2*D[5][7] + 2*D[7][1] + 2*D[7][5] + 2*D[7][9] - 2*D[9][3] + 2*D[9][7]; // constant term f2coeff[2] = 4*D[1][5] - 4*D[1][1] + 8*D[2][2] + 8*D[2][4] + 8*D[4][2] + 8*D[4][4] + 4*D[5][1] - 4*D[5][5] + 4*D[9][9]; // s1^2 * s2 f2coeff[3] = 4*D[1][8] - 4*D[1][6] - 8*D[2][3] + 8*D[2][7] - 8*D[3][2] - 8*D[3][4] - 8*D[4][3] + 8*D[4][7] + 4*D[5][6] - 4*D[5][8] - 4*D[6][1] + 4*D[6][5] - 4*D[6][9] + 8*D[7][2] + 8*D[7][4] + 4*D[8][1] - 4*D[8][5] + 4*D[8][9] - 4*D[9][6] + 4*D[9][8]; // s1 * s2 f2coeff[4] = 8*D[2][2] - 8*D[3][3] - 8*D[4][4] + 8*D[6][6] + 8*D[7][7] - 8*D[8][8]; // s1 * s3 f2coeff[5] = 4*D[1][4] - 4*D[1][2] - 4*D[2][1] + 4*D[2][5] - 4*D[2][9] - 8*D[3][6] - 8*D[3][8] + 4*D[4][1] - 4*D[4][5] + 4*D[4][9] + 4*D[5][2] - 4*D[5][4] - 8*D[6][3] + 8*D[6][7] + 8*D[7][6] + 8*D[7][8] - 8*D[8][3] + 8*D[8][7] - 4*D[9][2] + 4*D[9][4]; // s2 * s3 f2coeff[6] = 6*D[5][6] - 6*D[1][8] - 6*D[1][6] + 6*D[5][8] - 6*D[6][1] + 6*D[6][5] - 6*D[6][9] - 6*D[8][1] + 6*D[8][5] - 6*D[8][9] - 6*D[9][6] - 6*D[9][8]; // s2^2 * s3 f2coeff[7] = 4*D[1][1] - 4*D[1][5] + 4*D[1][9] - 4*D[5][1] + 4*D[5][5] - 4*D[5][9] + 4*D[9][1] - 4*D[9][5] + 4*D[9][9]; // s2^3 f2coeff[8] = 2*D[2][9] - 2*D[1][4] - 2*D[2][1] - 2*D[2][5] - 2*D[1][2] + 4*D[3][6] + 4*D[3][8] - 2*D[4][1] - 2*D[4][5] + 2*D[4][9] - 2*D[5][2] - 2*D[5][4] + 4*D[6][3] + 4*D[6][7] + 4*D[7][6] + 4*D[7][8] + 4*D[8][3] + 4*D[8][7] + 2*D[9][2] + 2*D[9][4]; // s1 * s3^2 f2coeff[9] = 2*D[1][2] + 2*D[1][4] + 2*D[2][1] + 2*D[2][5] + 2*D[2][9] - 4*D[3][6] + 4*D[3][8] + 2*D[4][1] + 2*D[4][5] + 2*D[4][9] + 2*D[5][2] + 2*D[5][4] - 4*D[6][3] + 4*D[6][7] + 4*D[7][6] - 4*D[7][8] + 4*D[8][3] - 4*D[8][7] + 2*D[9][2] + 2*D[9][4]; // s1 f2coeff[10] = 2*D[1][6] + 2*D[1][8] - 4*D[2][3] + 4*D[2][7] - 4*D[3][2] + 4*D[3][4] + 4*D[4][3] - 4*D[4][7] + 2*D[5][6] + 2*D[5][8] + 2*D[6][1] + 2*D[6][5] + 2*D[6][9] + 4*D[7][2] - 4*D[7][4] + 2*D[8][1] + 2*D[8][5] + 2*D[8][9] + 2*D[9][6] + 2*D[9][8]; // s3 f2coeff[11] = 8*D[3][3] - 4*D[1][9] - 4*D[1][1] - 8*D[3][7] + 4*D[5][5] - 8*D[7][3] + 8*D[7][7] - 4*D[9][1] - 4*D[9][9]; // s2 f2coeff[12] = 4*D[1][1] - 4*D[5][5] + 4*D[5][9] + 8*D[6][6] + 8*D[6][8] + 8*D[8][6] + 8*D[8][8] + 4*D[9][5] - 4*D[9][9]; // s2 * s3^2 f2coeff[13] = 2*D[1][7] - 2*D[1][3] + 4*D[2][6] - 4*D[2][8] - 2*D[3][1] + 2*D[3][5] + 2*D[3][9] + 4*D[4][6] - 4*D[4][8] + 2*D[5][3] - 2*D[5][7] + 4*D[6][2] + 4*D[6][4] + 2*D[7][1] - 2*D[7][5] - 2*D[7][9] - 4*D[8][2] - 4*D[8][4] + 2*D[9][3] - 2*D[9][7]; // s1^2 f2coeff[14] = 2*D[1][3] - 2*D[1][7] + 4*D[2][6] + 4*D[2][8] + 2*D[3][1] + 2*D[3][5] - 2*D[3][9] - 4*D[4][6] - 4*D[4][8] + 2*D[5][3] - 2*D[5][7] + 4*D[6][2] - 4*D[6][4] - 2*D[7][1] - 2*D[7][5] + 2*D[7][9] + 4*D[8][2] - 4*D[8][4] - 2*D[9][3] + 2*D[9][7]; // s3^2 f2coeff[15] = 6*D[1][3] - 6*D[1][7] + 6*D[3][1] - 6*D[3][5] + 6*D[3][9] - 6*D[5][3] + 6*D[5][7] - 6*D[7][1] + 6*D[7][5] - 6*D[7][9] + 6*D[9][3] - 6*D[9][7]; // s2^2 f2coeff[16] = 2*D[6][9] - 2*D[1][8] - 2*D[5][6] - 2*D[5][8] - 2*D[6][1] - 2*D[6][5] - 2*D[1][6] - 2*D[8][1] - 2*D[8][5] + 2*D[8][9] + 2*D[9][6] + 2*D[9][8]; // s3^3 f2coeff[17] = 8*D[2][6] - 4*D[1][7] - 4*D[1][3] + 8*D[2][8] - 4*D[3][1] + 4*D[3][5] - 4*D[3][9] + 8*D[4][6] + 8*D[4][8] + 4*D[5][3] + 4*D[5][7] + 8*D[6][2] + 8*D[6][4] - 4*D[7][1] + 4*D[7][5] - 4*D[7][9] + 8*D[8][2] + 8*D[8][4] - 4*D[9][3] - 4*D[9][7]; // s1 * s2 * s3 f2coeff[18] = 6*D[2][5] - 6*D[1][4] - 6*D[2][1] - 6*D[1][2] - 6*D[2][9] - 6*D[4][1] + 6*D[4][5] - 6*D[4][9] + 6*D[5][2] + 6*D[5][4] - 6*D[9][2] - 6*D[9][4]; // s1 * s2^2 f2coeff[19] = 2*D[1][6] + 2*D[1][8] + 4*D[2][3] + 4*D[2][7] + 4*D[3][2] + 4*D[3][4] + 4*D[4][3] + 4*D[4][7] - 2*D[5][6] - 2*D[5][8] + 2*D[6][1] - 2*D[6][5] - 2*D[6][9] + 4*D[7][2] + 4*D[7][4] + 2*D[8][1] - 2*D[8][5] - 2*D[8][9] - 2*D[9][6] - 2*D[9][8]; // s1^2 * s3 f2coeff[20] = 2*D[1][2] + 2*D[1][4] + 2*D[2][1] - 2*D[2][5] - 2*D[2][9] + 2*D[4][1] - 2*D[4][5] - 2*D[4][9] - 2*D[5][2] - 2*D[5][4] - 2*D[9][2] - 2*D[9][4]; // s1^3 // F3 COEFFICIENT f3coeff[1] = 2*D[1][2] - 2*D[1][4] + 2*D[2][1] + 2*D[2][5] + 2*D[2][9] - 2*D[4][1] - 2*D[4][5] - 2*D[4][9] + 2*D[5][2] - 2*D[5][4] + 2*D[9][2] - 2*D[9][4]; // constant term f3coeff[2] = 2*D[1][6] + 2*D[1][8] + 4*D[2][3] + 4*D[2][7] + 4*D[3][2] + 4*D[3][4] + 4*D[4][3] + 4*D[4][7] - 2*D[5][6] - 2*D[5][8] + 2*D[6][1] - 2*D[6][5] - 2*D[6][9] + 4*D[7][2] + 4*D[7][4] + 2*D[8][1] - 2*D[8][5] - 2*D[8][9] - 2*D[9][6] - 2*D[9][8]; // s1^2 * s2 f3coeff[3] = 8*D[2][2] - 8*D[3][3] - 8*D[4][4] + 8*D[6][6] + 8*D[7][7] - 8*D[8][8]; // s1 * s2 f3coeff[4] = 4*D[1][8] - 4*D[1][6] + 8*D[2][3] + 8*D[2][7] + 8*D[3][2] - 8*D[3][4] - 8*D[4][3] - 8*D[4][7] - 4*D[5][6] + 4*D[5][8] - 4*D[6][1] - 4*D[6][5] + 4*D[6][9] + 8*D[7][2] - 8*D[7][4] + 4*D[8][1] + 4*D[8][5] - 4*D[8][9] + 4*D[9][6] - 4*D[9][8]; // s1 * s3 f3coeff[5] = 4*D[1][3] - 4*D[1][7] + 8*D[2][6] + 8*D[2][8] + 4*D[3][1] + 4*D[3][5] - 4*D[3][9] - 8*D[4][6] - 8*D[4][8] + 4*D[5][3] - 4*D[5][7] + 8*D[6][2] - 8*D[6][4] - 4*D[7][1] - 4*D[7][5] + 4*D[7][9] + 8*D[8][2] - 8*D[8][4] - 4*D[9][3] + 4*D[9][7]; // s2 * s3 f3coeff[6] = 4*D[1][1] - 4*D[5][5] + 4*D[5][9] + 8*D[6][6] + 8*D[6][8] + 8*D[8][6] + 8*D[8][8] + 4*D[9][5] - 4*D[9][9]; // s2^2 * s3 f3coeff[7] = 2*D[5][6] - 2*D[1][8] - 2*D[1][6] + 2*D[5][8] - 2*D[6][1] + 2*D[6][5] - 2*D[6][9] - 2*D[8][1] + 2*D[8][5] - 2*D[8][9] - 2*D[9][6] - 2*D[9][8]; // s2^3 f3coeff[8] = 6*D[3][9] - 6*D[1][7] - 6*D[3][1] - 6*D[3][5] - 6*D[1][3] - 6*D[5][3] - 6*D[5][7] - 6*D[7][1] - 6*D[7][5] + 6*D[7][9] + 6*D[9][3] + 6*D[9][7]; // s1 * s3^2 f3coeff[9] = 2*D[1][3] + 2*D[1][7] + 4*D[2][6] - 4*D[2][8] + 2*D[3][1] + 2*D[3][5] + 2*D[3][9] - 4*D[4][6] + 4*D[4][8] + 2*D[5][3] + 2*D[5][7] + 4*D[6][2] - 4*D[6][4] + 2*D[7][1] + 2*D[7][5] + 2*D[7][9] - 4*D[8][2] + 4*D[8][4] + 2*D[9][3] + 2*D[9][7]; // s1 f3coeff[10] = 8*D[2][2] - 4*D[1][5] - 4*D[1][1] - 8*D[2][4] - 8*D[4][2] + 8*D[4][4] - 4*D[5][1] - 4*D[5][5] + 4*D[9][9]; // s3 f3coeff[11] = 2*D[1][6] + 2*D[1][8] - 4*D[2][3] + 4*D[2][7] - 4*D[3][2] + 4*D[3][4] + 4*D[4][3] - 4*D[4][7] + 2*D[5][6] + 2*D[5][8] + 2*D[6][1] + 2*D[6][5] + 2*D[6][9] + 4*D[7][2] - 4*D[7][4] + 2*D[8][1] + 2*D[8][5] + 2*D[8][9] + 2*D[9][6] + 2*D[9][8]; // s2 f3coeff[12] = 6*D[6][9] - 6*D[1][8] - 6*D[5][6] - 6*D[5][8] - 6*D[6][1] - 6*D[6][5] - 6*D[1][6] - 6*D[8][1] - 6*D[8][5] + 6*D[8][9] + 6*D[9][6] + 6*D[9][8]; // s2 * s3^2 f3coeff[13] = 2*D[1][2] - 2*D[1][4] + 2*D[2][1] - 2*D[2][5] - 2*D[2][9] + 4*D[3][6] - 4*D[3][8] - 2*D[4][1] + 2*D[4][5] + 2*D[4][9] - 2*D[5][2] + 2*D[5][4] + 4*D[6][3] + 4*D[6][7] + 4*D[7][6] - 4*D[7][8] - 4*D[8][3] - 4*D[8][7] - 2*D[9][2] + 2*D[9][4]; // s1^2 f3coeff[14] = 6*D[1][4] - 6*D[1][2] - 6*D[2][1] - 6*D[2][5] + 6*D[2][9] + 6*D[4][1] + 6*D[4][5] - 6*D[4][9] - 6*D[5][2] + 6*D[5][4] + 6*D[9][2] - 6*D[9][4]; // s3^2 f3coeff[15] = 2*D[1][4] - 2*D[1][2] - 2*D[2][1] + 2*D[2][5] - 2*D[2][9] - 4*D[3][6] - 4*D[3][8] + 2*D[4][1] - 2*D[4][5] + 2*D[4][9] + 2*D[5][2] - 2*D[5][4] - 4*D[6][3] + 4*D[6][7] + 4*D[7][6] + 4*D[7][8] - 4*D[8][3] + 4*D[8][7] - 2*D[9][2] + 2*D[9][4]; // s2^2 f3coeff[16] = 4*D[1][1] + 4*D[1][5] - 4*D[1][9] + 4*D[5][1] + 4*D[5][5] - 4*D[5][9] - 4*D[9][1] - 4*D[9][5] + 4*D[9][9]; // s3^3 f3coeff[17] = 4*D[2][9] - 4*D[1][4] - 4*D[2][1] - 4*D[2][5] - 4*D[1][2] + 8*D[3][6] + 8*D[3][8] - 4*D[4][1] - 4*D[4][5] + 4*D[4][9] - 4*D[5][2] - 4*D[5][4] + 8*D[6][3] + 8*D[6][7] + 8*D[7][6] + 8*D[7][8] + 8*D[8][3] + 8*D[8][7] + 4*D[9][2] + 4*D[9][4]; // s1 * s2 * s3 f3coeff[18] = 4*D[2][6] - 2*D[1][7] - 2*D[1][3] + 4*D[2][8] - 2*D[3][1] + 2*D[3][5] - 2*D[3][9] + 4*D[4][6] + 4*D[4][8] + 2*D[5][3] + 2*D[5][7] + 4*D[6][2] + 4*D[6][4] - 2*D[7][1] + 2*D[7][5] - 2*D[7][9] + 4*D[8][2] + 4*D[8][4] - 2*D[9][3] - 2*D[9][7]; // s1 * s2^2 f3coeff[19] = 4*D[1][9] - 4*D[1][1] + 8*D[3][3] + 8*D[3][7] + 4*D[5][5] + 8*D[7][3] + 8*D[7][7] + 4*D[9][1] - 4*D[9][9]; // s1^2 * s3 f3coeff[20] = 2*D[1][3] + 2*D[1][7] + 2*D[3][1] - 2*D[3][5] - 2*D[3][9] - 2*D[5][3] - 2*D[5][7] + 2*D[7][1] - 2*D[7][5] - 2*D[7][9] - 2*D[9][3] - 2*D[9][7]; // s1^3 } cv::Mat dls::LeftMultVec(const cv::Mat& v) { cv::Mat mat_ = cv::Mat::zeros(3, 9, CV_64F); for (int i = 0; i < 3; ++i) { mat_.at
(i, 3*i + 0) = v.at
(0); mat_.at
(i, 3*i + 1) = v.at
(1); mat_.at
(i, 3*i + 2) = v.at
(2); } return mat_; } cv::Mat dls::cayley_LS_M(const std::vector
& a, const std::vector
& b, const std::vector
& c, const std::vector
& u) { // TODO: input matrix pointer // TODO: shift coefficients one position to left cv::Mat M = cv::Mat::zeros(120, 120, CV_64F); M.at
(0,0)=u[1]; M.at
(0,35)=a[1]; M.at
(0,83)=b[1]; M.at
(0,118)=c[1]; M.at
(1,0)=u[4]; M.at
(1,1)=u[1]; M.at
(1,34)=a[1]; M.at
(1,35)=a[10]; M.at
(1,54)=b[1]; M.at
(1,83)=b[10]; M.at
(1,99)=c[1]; M.at
(1,118)=c[10]; M.at
(2,1)=u[4]; M.at
(2,2)=u[1]; M.at
(2,34)=a[10]; M.at
(2,35)=a[14]; M.at
(2,51)=a[1]; M.at
(2,54)=b[10]; M.at
(2,65)=b[1]; M.at
(2,83)=b[14]; M.at
(2,89)=c[1]; M.at
(2,99)=c[10]; M.at
(2,118)=c[14]; M.at
(3,0)=u[3]; M.at
(3,3)=u[1]; M.at
(3,35)=a[11]; M.at
(3,49)=a[1]; M.at
(3,76)=b[1]; M.at
(3,83)=b[11]; M.at
(3,118)=c[11]; M.at
(3,119)=c[1]; M.at
(4,1)=u[3]; M.at
(4,3)=u[4]; M.at
(4,4)=u[1]; M.at
(4,34)=a[11]; M.at
(4,35)=a[5]; M.at
(4,43)=a[1]; M.at
(4,49)=a[10]; M.at
(4,54)=b[11]; M.at
(4,71)=b[1]; M.at
(4,76)=b[10]; M.at
(4,83)=b[5]; M.at
(4,99)=c[11]; M.at
(4,100)=c[1]; M.at
(4,118)=c[5]; M.at
(4,119)=c[10]; M.at
(5,2)=u[3]; M.at
(5,4)=u[4]; M.at
(5,5)=u[1]; M.at
(5,34)=a[5]; M.at
(5,35)=a[12]; M.at
(5,41)=a[1]; M.at
(5,43)=a[10]; M.at
(5,49)=a[14]; M.at
(5,51)=a[11]; M.at
(5,54)=b[5]; M.at
(5,62)=b[1]; M.at
(5,65)=b[11]; M.at
(5,71)=b[10]; M.at
(5,76)=b[14]; M.at
(5,83)=b[12]; M.at
(5,89)=c[11]; M.at
(5,99)=c[5]; M.at
(5,100)=c[10]; M.at
(5,111)=c[1]; M.at
(5,118)=c[12]; M.at
(5,119)=c[14]; M.at
(6,3)=u[3]; M.at
(6,6)=u[1]; M.at
(6,30)=a[1]; M.at
(6,35)=a[15]; M.at
(6,49)=a[11]; M.at
(6,75)=b[1]; M.at
(6,76)=b[11]; M.at
(6,83)=b[15]; M.at
(6,107)=c[1]; M.at
(6,118)=c[15]; M.at
(6,119)=c[11]; M.at
(7,4)=u[3]; M.at
(7,6)=u[4]; M.at
(7,7)=u[1]; M.at
(7,30)=a[10]; M.at
(7,34)=a[15]; M.at
(7,35)=a[6]; M.at
(7,43)=a[11]; M.at
(7,45)=a[1]; M.at
(7,49)=a[5]; M.at
(7,54)=b[15]; M.at
(7,63)=b[1]; M.at
(7,71)=b[11]; M.at
(7,75)=b[10]; M.at
(7,76)=b[5]; M.at
(7,83)=b[6]; M.at
(7,99)=c[15]; M.at
(7,100)=c[11]; M.at
(7,107)=c[10]; M.at
(7,112)=c[1]; M.at
(7,118)=c[6]; M.at
(7,119)=c[5]; M.at
(8,5)=u[3]; M.at
(8,7)=u[4]; M.at
(8,8)=u[1]; M.at
(8,30)=a[14]; M.at
(8,34)=a[6]; M.at
(8,41)=a[11]; M.at
(8,43)=a[5]; M.at
(8,45)=a[10]; M.at
(8,46)=a[1]; M.at
(8,49)=a[12]; M.at
(8,51)=a[15]; M.at
(8,54)=b[6]; M.at
(8,62)=b[11]; M.at
(8,63)=b[10]; M.at
(8,65)=b[15]; M.at
(8,66)=b[1]; M.at
(8,71)=b[5]; M.at
(8,75)=b[14]; M.at
(8,76)=b[12]; M.at
(8,89)=c[15]; M.at
(8,99)=c[6]; M.at
(8,100)=c[5]; M.at
(8,102)=c[1]; M.at
(8,107)=c[14]; M.at
(8,111)=c[11]; M.at
(8,112)=c[10]; M.at
(8,119)=c[12]; M.at
(9,0)=u[2]; M.at
(9,9)=u[1]; M.at
(9,35)=a[9]; M.at
(9,36)=a[1]; M.at
(9,83)=b[9]; M.at
(9,84)=b[1]; M.at
(9,88)=c[1]; M.at
(9,118)=c[9]; M.at
(10,1)=u[2]; M.at
(10,9)=u[4]; M.at
(10,10)=u[1]; M.at
(10,33)=a[1]; M.at
(10,34)=a[9]; M.at
(10,35)=a[4]; M.at
(10,36)=a[10]; M.at
(10,54)=b[9]; M.at
(10,59)=b[1]; M.at
(10,83)=b[4]; M.at
(10,84)=b[10]; M.at
(10,88)=c[10]; M.at
(10,99)=c[9]; M.at
(10,117)=c[1]; M.at
(10,118)=c[4]; M.at
(11,2)=u[2]; M.at
(11,10)=u[4]; M.at
(11,11)=u[1]; M.at
(11,28)=a[1]; M.at
(11,33)=a[10]; M.at
(11,34)=a[4]; M.at
(11,35)=a[8]; M.at
(11,36)=a[14]; M.at
(11,51)=a[9]; M.at
(11,54)=b[4]; M.at
(11,57)=b[1]; M.at
(11,59)=b[10]; M.at
(11,65)=b[9]; M.at
(11,83)=b[8]; M.at
(11,84)=b[14]; M.at
(11,88)=c[14]; M.at
(11,89)=c[9]; M.at
(11,99)=c[4]; M.at
(11,114)=c[1]; M.at
(11,117)=c[10]; M.at
(11,118)=c[8]; M.at
(12,3)=u[2]; M.at
(12,9)=u[3]; M.at
(12,12)=u[1]; M.at
(12,35)=a[3]; M.at
(12,36)=a[11]; M.at
(12,39)=a[1]; M.at
(12,49)=a[9]; M.at
(12,76)=b[9]; M.at
(12,79)=b[1]; M.at
(12,83)=b[3]; M.at
(12,84)=b[11]; M.at
(12,88)=c[11]; M.at
(12,96)=c[1]; M.at
(12,118)=c[3]; M.at
(12,119)=c[9]; M.at
(13,4)=u[2]; M.at
(13,10)=u[3]; M.at
(13,12)=u[4]; M.at
(13,13)=u[1]; M.at
(13,33)=a[11]; M.at
(13,34)=a[3]; M.at
(13,35)=a[17]; M.at
(13,36)=a[5]; M.at
(13,39)=a[10]; M.at
(13,43)=a[9]; M.at
(13,47)=a[1]; M.at
(13,49)=a[4]; M.at
(13,54)=b[3]; M.at
(13,59)=b[11]; M.at
(13,60)=b[1]; M.at
(13,71)=b[9]; M.at
(13,76)=b[4]; M.at
(13,79)=b[10]; M.at
(13,83)=b[17]; M.at
(13,84)=b[5]; M.at
(13,88)=c[5]; M.at
(13,90)=c[1]; M.at
(13,96)=c[10]; M.at
(13,99)=c[3]; M.at
(13,100)=c[9]; M.at
(13,117)=c[11]; M.at
(13,118)=c[17]; M.at
(13,119)=c[4]; M.at
(14,5)=u[2]; M.at
(14,11)=u[3]; M.at
(14,13)=u[4]; M.at
(14,14)=u[1]; M.at
(14,28)=a[11]; M.at
(14,33)=a[5]; M.at
(14,34)=a[17]; M.at
(14,36)=a[12]; M.at
(14,39)=a[14]; M.at