P3p.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2011, Laurent Kneip, ETH Zurich
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions are met:
00007  *     * Redistributions of source code must retain the above copyright
00008  *       notice, this list of conditions and the following disclaimer.
00009  *     * Redistributions in binary form must reproduce the above copyright
00010  *       notice, this list of conditions and the following disclaimer in the
00011  *       documentation and/or other materials provided with the distribution.
00012  *     * Neither the name of ETH Zurich nor the
00013  *       names of its contributors may be used to endorse or promote products
00014  *       derived from this software without specific prior written permission.
00015  *
00016  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
00017  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00018  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00019  * DISCLAIMED. IN NO EVENT SHALL ETH ZURICH BE LIABLE FOR ANY
00020  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00021  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00022  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00023  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00024  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00025  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00026  */
00027 
00028 /*
00029  * P3p.cpp
00030  *
00031  *  Created on: Nov 2, 2010
00032  *      Author: Laurent Kneip
00033  * Description: Compute the absolute pose of a camera using three 3D-to-2D correspondences
00034  *   Reference: A Novel Parametrization of the P3P-Problem for a Direct Computation of
00035  *              Absolute Camera Position and Orientation
00036  *
00037  *       Input: featureVectors: 3x3 matrix with UNITARY feature vectors (each column is a vector)
00038  *              worldPoints: 3x3 matrix with corresponding 3D world points (each column is a point)
00039  *              solutions: 3x16 matrix that will contain the solutions
00040  *                         form: [ 3x1 position(solution1) 3x3 orientation(solution1) 3x1 position(solution2) 3x3 orientation(solution2) ... ]
00041  *                         the obtained orientation matrices are defined as transforming points from the cam to the world frame
00042  *      Output: int: 0 if correct execution
00043  *                  -1 if world points aligned
00044  */
00045 
00046 #include "P3p.h"
00047 
00048 #include <stdlib.h>
00049 #include <stdint.h>
00050 #include <stdio.h>
00051 #include <math.h>
00052 #include <complex>
00053 #include <TooN/SVD.h>
00054 #include <TooN/determinant.h>
00055 
00056 P3p::P3p() {
00057 }
00058 
00059 P3p::~P3p() {
00060 }
00061 
00062 int P3p::computePoses( TooN::Matrix<3,3> featureVectors, TooN::Matrix<3,3> worldPoints, TooN::Matrix<3,16> & solutions )
00063 {
00064     // Extraction of world points
00065 
00066     TooN::Vector<3> P1 = worldPoints.T()[0];
00067     TooN::Vector<3> P2 = worldPoints.T()[1];
00068     TooN::Vector<3> P3 = worldPoints.T()[2];
00069 
00070     // Verification that world points are not colinear
00071 
00072     TooN::Vector<3> temp1 = P2 - P1;
00073     TooN::Vector<3> temp2 = P3 - P1;
00074 
00075     if(TooN::norm(temp1 ^ temp2) == 0)
00076         return -1;
00077 
00078     // Extraction of feature vectors
00079 
00080     TooN::Vector<3> f1 = featureVectors.T()[0];
00081     TooN::Vector<3> f2 = featureVectors.T()[1];
00082     TooN::Vector<3> f3 = featureVectors.T()[2];
00083 
00084     // Creation of intermediate camera frame
00085 
00086     TooN::Vector<3> e1 = f1;
00087     TooN::Vector<3> e3 = f1 ^ f2;
00088     e3 = e3 / TooN::norm(e3);
00089     TooN::Vector<3> e2 = e3 ^ e1;
00090 
00091     TooN::Matrix<3,3> T;
00092     T[0] = e1;
00093     T[1] = e2;
00094     T[2] = e3;
00095 
00096     f3 = T*f3;
00097 
00098     // Reinforce that f3[2] > 0 for having theta in [0;pi]
00099 
00100     if( f3[2] > 0 )
00101     {
00102         f1 = featureVectors.T()[1];
00103         f2 = featureVectors.T()[0];
00104         f3 = featureVectors.T()[2];
00105 
00106         e1 = f1;
00107         e3 = f1 ^ f2;
00108         e3 = e3 / TooN::norm(e3);
00109         e2 = e3 ^ e1;
00110 
00111         T[0] = e1;
00112         T[1] = e2;
00113         T[2] = e3;
00114 
00115         f3 = T*f3;
00116 
00117         P1 = worldPoints.T()[1];
00118         P2 = worldPoints.T()[0];
00119         P3 = worldPoints.T()[2];
00120     }
00121 
00122     // Creation of intermediate world frame
00123 
00124     TooN::Vector<3> n1 = P2-P1;
00125     n1 = n1 / TooN::norm(n1);
00126     TooN::Vector<3> n3 = n1 ^ (P3-P1);
00127     n3 = n3 / TooN::norm(n3);
00128     TooN::Vector<3> n2 = n3 ^ n1;
00129 
00130     TooN::Matrix<3,3> N;
00131     N[0] = n1;
00132     N[1] = n2;
00133     N[2] = n3;
00134 
00135     // Extraction of known parameters
00136 
00137     P3 = N*(P3-P1);
00138 
00139     double d_12 = TooN::norm(P2-P1);
00140     double f_1 = f3[0]/f3[2];
00141     double f_2 = f3[1]/f3[2];
00142     double p_1 = P3[0];
00143     double p_2 = P3[1];
00144 
00145     double cos_beta = f1 * f2;
00146     double b = 1/(1-pow(cos_beta,2)) - 1;
00147 
00148     if (cos_beta < 0)
00149         b = -sqrt(b);
00150     else
00151         b = sqrt(b);
00152 
00153     // Definition of temporary variables for avoiding multiple computation
00154 
00155     double f_1_pw2 = pow(f_1,2);
00156     double f_2_pw2 = pow(f_2,2);
00157     double p_1_pw2 = pow(p_1,2);
00158     double p_1_pw3 = p_1_pw2 * p_1;
00159     double p_1_pw4 = p_1_pw3 * p_1;
00160     double p_2_pw2 = pow(p_2,2);
00161     double p_2_pw3 = p_2_pw2 * p_2;
00162     double p_2_pw4 = p_2_pw3 * p_2;
00163     double d_12_pw2 = pow(d_12,2);
00164     double b_pw2 = pow(b,2);
00165 
00166     // Computation of factors of 4th degree polynomial
00167 
00168     TooN::Vector<5> factors;
00169 
00170     factors[0] = -f_2_pw2*p_2_pw4
00171         -p_2_pw4*f_1_pw2
00172         -p_2_pw4;
00173 
00174     factors[1] = 2*p_2_pw3*d_12*b
00175         +2*f_2_pw2*p_2_pw3*d_12*b
00176         -2*f_2*p_2_pw3*f_1*d_12;
00177 
00178     factors[2] = -f_2_pw2*p_2_pw2*p_1_pw2
00179         -f_2_pw2*p_2_pw2*d_12_pw2*b_pw2
00180         -f_2_pw2*p_2_pw2*d_12_pw2
00181         +f_2_pw2*p_2_pw4
00182         +p_2_pw4*f_1_pw2
00183         +2*p_1*p_2_pw2*d_12
00184         +2*f_1*f_2*p_1*p_2_pw2*d_12*b
00185         -p_2_pw2*p_1_pw2*f_1_pw2
00186         +2*p_1*p_2_pw2*f_2_pw2*d_12
00187         -p_2_pw2*d_12_pw2*b_pw2
00188         -2*p_1_pw2*p_2_pw2;
00189 
00190     factors[3] = 2*p_1_pw2*p_2*d_12*b
00191         +2*f_2*p_2_pw3*f_1*d_12
00192         -2*f_2_pw2*p_2_pw3*d_12*b
00193         -2*p_1*p_2*d_12_pw2*b;
00194 
00195     factors[4] = -2*f_2*p_2_pw2*f_1*p_1*d_12*b
00196         +f_2_pw2*p_2_pw2*d_12_pw2
00197         +2*p_1_pw3*d_12
00198         -p_1_pw2*d_12_pw2
00199         +f_2_pw2*p_2_pw2*p_1_pw2
00200         -p_1_pw4
00201         -2*f_2_pw2*p_2_pw2*p_1*d_12
00202         +p_2_pw2*f_1_pw2*p_1_pw2
00203         +f_2_pw2*p_2_pw2*d_12_pw2*b_pw2;
00204 
00205     // Computation of roots
00206 
00207     TooN::Vector<4> realRoots;
00208 
00209     this->solveQuartic( factors, realRoots );
00210 
00211     // Backsubstitution of each solution
00212 
00213     for(int i=0; i<4; i++)
00214     {
00215         double cot_alpha = (-f_1*p_1/f_2-realRoots[i]*p_2+d_12*b)/(-f_1*realRoots[i]*p_2/f_2+p_1-d_12);
00216 
00217         double cos_theta = realRoots[i];
00218         double sin_theta = sqrt(1-pow(realRoots[i],2));
00219         double sin_alpha = sqrt(1/(pow(cot_alpha,2)+1));
00220         double cos_alpha = sqrt(1-pow(sin_alpha,2));
00221 
00222         if (cot_alpha < 0)
00223             cos_alpha = -cos_alpha;
00224 
00225         TooN::Vector<3> C = TooN::makeVector(
00226                 d_12*cos_alpha*(sin_alpha*b+cos_alpha),
00227                 cos_theta*d_12*sin_alpha*(sin_alpha*b+cos_alpha),
00228                 sin_theta*d_12*sin_alpha*(sin_alpha*b+cos_alpha));
00229 
00230         C = P1 + N.T()*C;
00231 
00232         TooN::Matrix<3,3> R;
00233         R[0] = TooN::makeVector(        -cos_alpha,             -sin_alpha*cos_theta,   -sin_alpha*sin_theta );
00234         R[1] = TooN::makeVector(        sin_alpha,              -cos_alpha*cos_theta,   -cos_alpha*sin_theta );
00235         R[2] = TooN::makeVector(        0,                              -sin_theta,                             cos_theta );
00236 
00237         R = N.T()*R.T()*T;
00238 
00239         solutions.T()[i*4] = C;
00240         solutions.T()[i*4+1] = R.T()[0];
00241         solutions.T()[i*4+2] = R.T()[1];
00242         solutions.T()[i*4+3] = R.T()[2];
00243     }
00244 
00245     return 0;
00246 }
00247 
00248 int P3p::solveQuartic( TooN::Vector<5> factors, TooN::Vector<4> & realRoots  )
00249 {
00250     double A = factors[0];
00251     double B = factors[1];
00252     double C = factors[2];
00253     double D = factors[3];
00254     double E = factors[4];
00255 
00256     double A_pw2 = A*A;
00257     double B_pw2 = B*B;
00258     double A_pw3 = A_pw2*A;
00259     double B_pw3 = B_pw2*B;
00260     double A_pw4 = A_pw3*A;
00261     double B_pw4 = B_pw3*B;
00262 
00263     double alpha = -3*B_pw2/(8*A_pw2)+C/A;
00264     double beta = B_pw3/(8*A_pw3)-B*C/(2*A_pw2)+D/A;
00265     double gamma = -3*B_pw4/(256*A_pw4)+B_pw2*C/(16*A_pw3)-B*D/(4*A_pw2)+E/A;
00266 
00267     double alpha_pw2 = alpha*alpha;
00268     double alpha_pw3 = alpha_pw2*alpha;
00269 
00270     std::complex<double> P (-alpha_pw2/12-gamma,0);
00271     std::complex<double> Q (-alpha_pw3/108+alpha*gamma/3-pow(beta,2)/8,0);
00272     std::complex<double> R = -Q/2.0+sqrt(pow(Q,2.0)/4.0+pow(P,3.0)/27.0);
00273 
00274     std::complex<double> U = pow(R,(1.0/3.0));
00275     std::complex<double> y;
00276 
00277     if (U.real() == 0)
00278         y = -5.0*alpha/6.0-pow(Q,(1.0/3.0));
00279     else
00280         y = -5.0*alpha/6.0-P/(3.0*U)+U;
00281 
00282     std::complex<double> w = sqrt(alpha+2.0*y);
00283 
00284     std::complex<double> temp;
00285 
00286     temp = -B/(4.0*A) + 0.5*(w+sqrt(-(3.0*alpha+2.0*y+2.0*beta/w)));
00287     realRoots[0] = temp.real();
00288     temp = -B/(4.0*A) + 0.5*(w-sqrt(-(3.0*alpha+2.0*y+2.0*beta/w)));
00289     realRoots[1] = temp.real();
00290     temp = -B/(4.0*A) + 0.5*(-w+sqrt(-(3.0*alpha+2.0*y-2.0*beta/w)));
00291     realRoots[2] = temp.real();
00292     temp = -B/(4.0*A) + 0.5*(-w-sqrt(-(3.0*alpha+2.0*y-2.0*beta/w)));
00293     realRoots[3] = temp.real();
00294 
00295     return 0;
00296 }


dlut_libvo
Author(s): Zhuang Yan
autogenerated on Thu Jun 6 2019 20:03:29