Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
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
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
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
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
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
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
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
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
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
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
00206
00207 TooN::Vector<4> realRoots;
00208
00209 this->solveQuartic( factors, realRoots );
00210
00211
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 }