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
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056 #include <new>
00057
00058 #include "ObjectPose.h"
00059
00060 #include "Math/Math2d.h"
00061 #include "Math/Math3d.h"
00062 #include "Math/DoubleMatrix.h"
00063 #include "Math/LinearAlgebra.h"
00064 #include "Calibration/Calibration.h"
00065
00066 #include <math.h>
00067 #include <stdio.h>
00068
00069
00070
00071
00072
00073
00074 #define TOL 1e-5
00075 #define EPSILON 1e-8
00076
00077
00078
00079
00080
00081
00082
00083
00084 CObjectPose::CObjectPose(const Vec3d *pObjectPoints, int nPoints)
00085 {
00086 int i;
00087
00088 m_nPoints = nPoints;
00089
00090
00091 m_pP = new Vec3d[m_nPoints];
00092
00093 m_tPbar = pObjectPoints[0];
00094 for (i = 1; i < m_nPoints; i++)
00095 Math3d::AddToVec(m_tPbar, pObjectPoints[i]);
00096
00097 Math3d::MulVecScalar(m_tPbar, 1.0f / m_nPoints, m_tPbar);
00098
00099 for (i = 0; i < m_nPoints; i++)
00100 Math3d::SubtractVecVec(pObjectPoints[i], m_tPbar, m_pP[i]);
00101
00102
00103 m_pQ = new Vec3d[m_nPoints];
00104
00105
00106 m_pF = new Mat3d[m_nPoints];
00107 }
00108
00109 CObjectPose::~CObjectPose()
00110 {
00111 delete [] m_pP;
00112 delete [] m_pQ;
00113 delete [] m_pF;
00114 }
00115
00116
00117
00118
00119
00120
00121 bool CObjectPose::EstimatePose(const Vec2d *pImagePoints,
00122 Mat3d &rotationMatrix, Vec3d &translationVector,
00123 const CCalibration *pCalibration, int nMaxIterations)
00124 {
00125 if (m_nPoints < 3)
00126 {
00127 printf("error: too few points for object pose estimation.\n");
00128 return false;
00129 }
00130
00131 int i;
00132
00133
00134 const Vec2d &focalLength = pCalibration->GetCameraParameters().focalLength;
00135 const Vec2d &principalPoint = pCalibration->GetCameraParameters().principalPoint;
00136
00137 for (i = 0; i < m_nPoints; i++)
00138 {
00139 m_pQ[i].x = (pImagePoints[i].x - principalPoint.x) / focalLength.x;
00140 m_pQ[i].y = (pImagePoints[i].y - principalPoint.y) / focalLength.y;
00141 m_pQ[i].z = 1.0;
00142 }
00143
00144
00145 for (i = 0; i < m_nPoints; i++)
00146 {
00147 const float scalar = 1.0f / Math3d::SquaredLength(m_pQ[i]);
00148 Math3d::MulVecTransposedVec(m_pQ[i], m_pQ[i], m_pF[i]);
00149 Math3d::MulMatScalar(m_pF[i], scalar, m_pF[i]);
00150 }
00151
00152
00153 Mat3d sum;
00154 Mat3d temp;
00155
00156 sum = m_pF[0];
00157 for (i = 1; i < m_nPoints; i++)
00158 Math3d::AddToMat(sum, m_pF[i]);
00159
00160 Math3d::MulMatScalar(sum, 1.0f / m_nPoints, sum);
00161
00162 Math3d::SubtractMatMat(Math3d::unit_mat, sum, temp);
00163
00164 Math3d::Invert(temp, temp);
00165
00166 Math3d::MulMatScalar(temp, 1.0f / m_nPoints, m_tFactor);
00167
00168 float old_error, new_error;
00169 int it = 0;
00170
00171 AbsKernel(rotationMatrix, translationVector, old_error);
00172 it++;
00173 AbsKernel(rotationMatrix, translationVector, new_error);
00174 it++;
00175
00176 while (fabsf((old_error - new_error) / old_error) > TOL && new_error > EPSILON && it < nMaxIterations)
00177 {
00178 old_error = new_error;
00179 AbsKernel(rotationMatrix, translationVector, new_error);
00180 it++;
00181 }
00182
00183
00184 Vec3d vec;
00185 Math3d::MulMatVec(rotationMatrix, m_tPbar, vec);
00186 Math3d::SubtractVecVec(translationVector, vec, translationVector);
00187
00188
00189 const Mat3d &Rc = pCalibration->m_rotation_inverse;
00190 const Vec3d &tc = pCalibration->m_translation_inverse;
00191 Math3d::MulMatMat(Rc, rotationMatrix, rotationMatrix);
00192 Math3d::MulMatVec(Rc, translationVector, tc, translationVector);
00193
00194 return true;
00195 }
00196
00197 void CObjectPose::AbsKernel(Mat3d &R, Vec3d &t, float &error)
00198 {
00199 int i;
00200
00201
00202 for (i = 0; i < m_nPoints; i++)
00203 Math3d::MulMatVec(m_pF[i], m_pQ[i], m_pQ[i]);
00204
00205
00206 Vec3d qbar;
00207 qbar = m_pQ[0];
00208 for (i = 1; i < m_nPoints; i++)
00209 Math3d::AddToVec(qbar, m_pQ[i]);
00210 Math3d::MulVecScalar(qbar, 1.0f / m_nPoints, qbar);
00211 for (i = 0; i < m_nPoints; i++)
00212 Math3d::SubtractVecVec(m_pQ[i], qbar, m_pQ[i]);
00213
00214
00215 CDoubleMatrix fM(3, 3);
00216 Mat3d temp;
00217 for (i = 0; i < 9; i++)
00218 fM.data[i] = 0;
00219 for (i = 0; i < m_nPoints; i++)
00220 {
00221 Math3d::MulVecTransposedVec(m_pP[i], m_pQ[i], temp);
00222 fM.data[0] = fM.data[0] + temp.r1; fM.data[1] = fM.data[1] + temp.r2; fM.data[2] = fM.data[2] + temp.r3;
00223 fM.data[3] = fM.data[3] + temp.r4; fM.data[4] = fM.data[4] + temp.r5; fM.data[5] = fM.data[5] + temp.r6;
00224 fM.data[6] = fM.data[6] + temp.r7; fM.data[7] = fM.data[7] + temp.r8; fM.data[8] = fM.data[8] + temp.r9;
00225 }
00226
00227
00228 CDoubleMatrix fU(3, 3);
00229 CDoubleMatrix fS(3, 3);
00230 CDoubleMatrix fV(3, 3);
00231 LinearAlgebra::SVD(&fM, &fS, &fU, &fV);
00232
00233
00234 Mat3d transU;
00235 LinearAlgebra::Transpose(&fU, &fU);
00236 transU.r1 = float(fU.data[0]); transU.r2 = float(fU.data[1]); transU.r3 = float(fU.data[2]);
00237 transU.r4 = float(fU.data[3]); transU.r5 = float(fU.data[4]); transU.r6 = float(fU.data[5]);
00238 transU.r7 = float(fU.data[6]); transU.r8 = float(fU.data[7]); transU.r9 = float(fU.data[8]);
00239
00240
00241 temp.r1 = float(fV.data[0]); temp.r2 = float(fV.data[1]); temp.r3 = float(fV.data[2]);
00242 temp.r4 = float(fV.data[3]); temp.r5 = float(fV.data[4]); temp.r6 = float(fV.data[5]);
00243 temp.r7 = float(fV.data[6]); temp.r8 = float(fV.data[7]); temp.r9 = float(fV.data[8]);
00244 Math3d::MulMatMat(temp, transU, R);
00245
00246 if (Math3d::Det(R) > 0)
00247 {
00248
00249
00250 t = tEstimate(R);
00251
00252 if (t.z < 0)
00253 {
00254
00255 temp.r1 = float(-fV.data[0]); temp.r2 = float(-fV.data[1]); temp.r3 = float(fV.data[2]);
00256 temp.r4 = float(-fV.data[3]); temp.r5 = float(-fV.data[4]); temp.r6 = float(fV.data[5]);
00257 temp.r7 = float(-fV.data[6]); temp.r8 = float(-fV.data[7]); temp.r9 = float(fV.data[8]);
00258 Math3d::MulMatMat(temp, transU, R);
00259
00260 t = tEstimate(R);
00261 }
00262 }
00263 else
00264 {
00265
00266 temp.r1 = float(fV.data[0]); temp.r2 = float(fV.data[1]); temp.r3 = float(-fV.data[2]);
00267 temp.r4 = float(fV.data[3]); temp.r5 = float(fV.data[4]); temp.r6 = float(-fV.data[5]);
00268 temp.r7 = float(fV.data[6]); temp.r8 = float(fV.data[7]); temp.r9 = float(-fV.data[8]);
00269 Math3d::MulMatMat(temp, transU, R);
00270
00271 t = tEstimate(R);
00272
00273 if (t.z < 0)
00274 {
00275
00276 temp.r1 = float(-fV.data[0]); temp.r2 = float(-fV.data[1]); temp.r3 = float(-fV.data[2]);
00277 temp.r4 = float(-fV.data[3]); temp.r5 = float(-fV.data[4]); temp.r6 = float(-fV.data[5]);
00278 temp.r7 = float(-fV.data[6]); temp.r8 = float(-fV.data[7]); temp.r9 = float(-fV.data[8]);
00279 Math3d::MulMatMat(temp, transU, R);
00280
00281 t = tEstimate(R);
00282 }
00283 }
00284
00285
00286 for (i = 0; i < m_nPoints; i++)
00287 {
00288
00289 Math3d::MulMatVec(R, m_pP[i], m_pQ[i]);
00290 Math3d::AddVecVec(m_pQ[i], t, m_pQ[i]);
00291 }
00292
00293
00294 error = 0.0f;
00295 Vec3d vec;
00296
00297 for (i = 0; i < m_nPoints; i++)
00298 {
00299
00300 Math3d::SubtractMatMat(Math3d::unit_mat, m_pF[i], temp);
00301 Math3d::MulMatVec(temp, m_pQ[i], vec);
00302
00303 error += Math3d::SquaredLength(vec);
00304 }
00305 }
00306
00307 Vec3d CObjectPose::tEstimate(Mat3d &R)
00308 {
00309 Vec3d sum = Math3d::zero_vec;
00310 Vec3d temp;
00311
00312
00313 for (int i = 0; i < m_nPoints; i++)
00314 {
00315 Math3d::MulMatVec(R, m_pP[i], temp);
00316 Math3d::MulMatVec(m_pF[i], temp, temp);
00317 Math3d::AddToVec(sum, temp);
00318 }
00319
00320 Math3d::MulMatVec(m_tFactor, sum, sum);
00321
00322 return sum;
00323 }