00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00024
00025 #include <qvmath/qvreprojectionerror.h>
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 void evaluateReprojectionResidualsAndJacobian( const double q1, const double q2, const double q3, const double q4,
00057 const double tx, const double ty, const double tz,
00058 const double px, const double py,
00059 const double x, const double y, const double z,
00060 double *residual, double *jacobian)
00061 {
00062 const double t1 = q1 * q1;
00063 const double t2 = q2 * q2;
00064 const double t3 = q3 * q3;
00065 const double t4 = q4 * q4;
00066 const double t5 = t1 + t2 + t3 + t4;
00067 const double t6 = 0.1e1 / t5;
00068 const double t7 = -t2 - t3;
00069 const double t12 = q1 * q2;
00070 const double t13 = q3 * q4;
00071 const double t14 = t12 - t13;
00072 const double t18 = q3 * q1;
00073 const double t19 = q2 * q4;
00074 const double t20 = t18 + t19;
00075 const double t24 = (0.1e1 + 0.20e1 * t6 * t7) * x + 0.20e1 * t6 * t14 * y + 0.20e1 * t6 * t20 * z + tx;
00076 const double t25 = t18 - t19;
00077 const double t29 = q2 * q3;
00078 const double t30 = q1 * q4;
00079 const double t31 = t29 + t30;
00080 const double t35 = -t2 - t1;
00081 const double t40 = 0.20e1 * t6 * t25 * x + 0.20e1 * t6 * t31 * y + (0.1e1 + 0.20e1 * t6 * t35) * z + tz;
00082 const double t41 = 0.1e1 / t40;
00083 const double t43 = t24 * t41 - px;
00084 const double t44 = t43 * t43;
00085 const double t45 = t12 + t13;
00086 const double t49 = -t3 - t1;
00087 const double t54 = t29 - t30;
00088 const double t58 = 0.20e1 * t6 * t45 * x + (0.1e1 + 0.20e1 * t6 * t49) * y + 0.20e1 * t6 * t54 * z + ty;
00089 const double t60 = t58 * t41 - py;
00090 const double t61 = t60 * t60;
00091 const double t63 = sqrt(t44 + t61);
00092 const double t64 = 0.1e1 / t63;
00093 const double t65 = t5 * t5;
00094 const double t66 = 0.1e1 / t65;
00095 const double t67 = t66 * t7;
00096 const double t68 = q1 * x;
00097 const double t71 = t66 * t14;
00098 const double t72 = y * q1;
00099 const double t75 = t6 * q2;
00100 const double t77 = 0.20e1 * t75 * y;
00101 const double t78 = t66 * t20;
00102 const double t79 = z * q1;
00103 const double t82 = t6 * q3;
00104 const double t84 = 0.20e1 * t82 * z;
00105 const double t87 = t40 * t40;
00106 const double t88 = 0.1e1 / t87;
00107 const double t89 = t24 * t88;
00108 const double t90 = t66 * t25;
00109 const double t94 = 0.20e1 * t82 * x;
00110 const double t95 = t66 * t31;
00111 const double t98 = t6 * q4;
00112 const double t100 = 0.20e1 * t98 * y;
00113 const double t101 = t66 * t35;
00114 const double t104 = t6 * q1;
00115 const double t105 = 0.40e1 * t104;
00116 const double t108 = -0.40e1 * t90 * t68 + t94 - 0.40e1 * t95 * t72 + t100 + (-0.40e1 * t101 * q1 - t105) * z;
00117 const double t112 = t66 * t45;
00118 const double t116 = 0.20e1 * t75 * x;
00119 const double t117 = t66 * t49;
00120 const double t122 = t66 * t54;
00121 const double t126 = 0.20e1 * t98 * z;
00122 const double t129 = t58 * t88;
00123 const double t138 = 0.40e1 * t75;
00124 const double t141 = y * q2;
00125 const double t145 = 0.20e1 * t104 * y;
00126 const double t146 = z * q2;
00127 const double t151 = x * q2;
00128 const double t155 = 0.20e1 * t98 * x;
00129 const double t159 = 0.20e1 * t82 * y;
00130 const double t164 = -0.40e1 * t90 * t151 - t155 - 0.40e1 * t95 * t141 + t159 + (-0.40e1 * t101 * q2 - t138) * z;
00131 const double t171 = 0.20e1 * t104 * x;
00132 const double t186 = 0.40e1 * t82;
00133 const double t189 = y * q3;
00134 const double t192 = z * q3;
00135 const double t196 = 0.20e1 * t104 * z;
00136 const double t199 = x * q3;
00137 const double t206 = -0.40e1 * t90 * t199 + t171 - 0.40e1 * t95 * t189 + t77 - 0.40e1 * t101 * t192;
00138 const double t219 = 0.20e1 * t75 * z;
00139 const double t228 = q4 * x;
00140 const double t231 = y * q4;
00141 const double t234 = z * q4;
00142 const double t245 = -0.40e1 * t90 * t228 - t116 - 0.40e1 * t95 * t231 + t145 - 0.40e1 * t101 * t234;
00143
00144 jacobian[0] = t64 * (t43 * ((-0.40e1 * t67 * t68 - 0.40e1 * t71 * t72 + t77 - 0.40e1 * t78 * t79 + t84) * t41 - t89 * t108) + t60 * ((-0.40e1 * t112 * t68 + t116 + (-0.40e1 * t117 * q1 - t105) * y - 0.40e1 * t122 * t79 - t126) * t41 - t129 * t108));
00145 jacobian[1] = t64 * (t43 * (((-0.40e1 * t67 * q2 - t138) * x - 0.40e1 * t71 * t141 + t145 - 0.40e1 * t78 * t146 + t126) * t41 - t89 * t164) + t60 * ((-0.40e1 * t112 * t151 + t171 - 0.40e1 * t117 * t141 - 0.40e1 * t122 * t146 + t84) * t41 - t129 * t164));
00146 jacobian[2] = t64 * (t43 * (((-0.40e1 * t67 * q3 - t186) * x - 0.40e1 * t71 * t189 - t100 - 0.40e1 * t78 * t192 + t196) * t41 - t89 * t206) + t60 * ((-0.40e1 * t112 * t199 + t155 + (-0.40e1 * t117 * q3 - t186) * y - 0.40e1 * t122 * t192 + t219) * t41 - t129 * t206));
00147 jacobian[3] = t64 * (t43 * ((-0.40e1 * t67 * t228 - 0.40e1 * t71 * t231 - t159 - 0.40e1 * t78 * t234 + t219) * t41 - t89 * t245) + t60 * ((-0.40e1 * t112 * t228 + t94 - 0.40e1 * t117 * t231 - 0.40e1 * t122 * t234 - t196) * t41 - t129 * t245));
00148 jacobian[4] = t64 * t43 * t41;
00149 jacobian[5] = t64 * t60 * t41;
00150 jacobian[6] = t64 * (-t43 * t24 * t88 - t60 * t58 * t88);
00151 residual[0] = t63;
00152 }
00153
00154 QVEuclideanMapping3 optimizeReprojectionErrorForCameraPose(const QVEuclideanMapping3 &camera0, const QList<QPointF> &points2D, const QList<QV3DPointF> &points3D, const int iterations)
00155 {
00156 const int n = points2D.size();
00157
00158 QVVector x = camera0;
00159 for(int i = 0; i < iterations; i++)
00160 {
00161 QVVector f_x(n);
00162 QVMatrix J(n, 7);
00163 double *data_f_x = f_x.data(),
00164 *data_J = J.getWriteData();
00165
00166 QListIterator<QPointF> iteratorPoints2D(points2D);
00167 QListIterator<QV3DPointF> iteratorPoints3D(points3D);
00168
00169 int j = 0;
00170 while (iteratorPoints2D.hasNext())
00171 {
00172 const QPointF p2D = iteratorPoints2D.next();
00173 const QV3DPointF p3D = iteratorPoints3D.next();
00174 evaluateReprojectionResidualsAndJacobian(x[0], x[1], x[2], x[3], x[4], x[5], x[6], p2D.x(), p2D.y(), p3D.x(), p3D.y(), p3D.z(), data_f_x + j, data_J + (7*j));
00175 j++;
00176 }
00177
00178 QVMatrix H = J.dotProduct(J, true, false);
00179 for(int i = 0; i < H.getCols(); i++)
00180 H(i,i) += 0.01;
00181 QVVector b = J.dotProduct(f_x, true);
00182
00183 QVVector xInc;
00184 solveByCholeskyDecomposition(H, xInc, b);
00185
00186 x = x - xInc;
00187 }
00188
00189 return QVEuclideanMapping3(x);
00190 }
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221 void reprojectionResidualsAndJacobianFor3DPoint( const double q1, const double q2, const double q3, const double q4,
00222 const double tx, const double ty, const double tz,
00223 const double px, const double py,
00224 const double x, const double y, const double z,
00225 double *residual, double *jacobian)
00226 {
00227 const double t1 = q1 * q1;
00228 const double t2 = q2 * q2;
00229 const double t3 = q3 * q3;
00230 const double t4 = q4 * q4;
00231 const double t6 = 0.1e1 / (t1 + t2 + t3 + t4);
00232 const double t10 = 0.1e1 + 0.20e1 * t6 * (-t2 - t3);
00233 const double t12 = q1 * q2;
00234 const double t13 = q3 * q4;
00235 const double t15 = t6 * (t12 - t13);
00236 const double t18 = q3 * q1;
00237 const double t19 = q2 * q4;
00238 const double t21 = t6 * (t18 + t19);
00239 const double t24 = t10 * x + 0.20e1 * t15 * y + 0.20e1 * t21 * z + tx;
00240 const double t26 = t6 * (t18 - t19);
00241 const double t29 = q2 * q3;
00242 const double t30 = q1 * q4;
00243 const double t32 = t6 * (t29 + t30);
00244 const double t38 = 0.1e1 + 0.20e1 * t6 * (-t2 - t1);
00245 const double t40 = 0.20e1 * t26 * x + 0.20e1 * t32 * y + t38 * z + tz;
00246 const double t41 = 0.1e1 / t40;
00247 const double t43 = t24 * t41 - px;
00248 const double t44 = t43 * t43;
00249 const double t46 = t6 * (t12 + t13);
00250 const double t52 = 0.1e1 + 0.20e1 * t6 * (-t3 - t1);
00251 const double t55 = t6 * (t29 - t30);
00252 const double t58 = 0.20e1 * t46 * x + t52 * y + 0.20e1 * t55 * z + ty;
00253 const double t60 = t58 * t41 - py;
00254 const double t61 = t60 * t60;
00255 const double t63 = sqrt(t44 + t61);
00256 const double t64 = 0.1e1 / t63;
00257 const double t66 = t40 * t40;
00258 const double t67 = 0.1e1 / t66;
00259 const double t68 = t24 * t67;
00260 const double t75 = t58 * t67;
00261 jacobian[0] = t64 * (t43 * (t10 * t41 - 0.20e1 * t68 * t26) + t60 * (0.20e1 * t46 * t41 - 0.20e1 * t75 * t26));
00262 jacobian[1] = t64 * (t43 * (0.20e1 * t15 * t41 - 0.20e1 * t68 * t32) + t60 * (t52 * t41 - 0.20e1 * t75 * t32));
00263 jacobian[2] = t64 * (t43 * (0.20e1 * t21 * t41 - t68 * t38) + t60 * (0.20e1 * t55 * t41 - t75 * t38));
00264 residual[0] = t63;
00265 }
00266
00267 QV3DPointF optimizeReprojectionErrorFor3DPoint(const QV3DPointF &point3D, const QList<QVEuclideanMapping3> &cameraPoses, const QHash<int, QPointF> &projectionsOfAPoint, const int iterations, const double lambda)
00268 {
00269 const int n = projectionsOfAPoint.count();
00270
00271 QVVector x = point3D;
00272 for(int i = 0; i < iterations; i++)
00273 {
00274 QVVector f_x(n);
00275 QVMatrix J(n, 3);
00276 double *data_f_x = f_x.data(),
00277 *data_J = J.getWriteData();
00278
00279 QHashIterator<int, QPointF> it(projectionsOfAPoint);
00280 int j=0;
00281 while (it.hasNext())
00282 {
00283 it.next();
00284 const QPointF p2D = it.value();
00285 const QVVector v = cameraPoses[it.key()];
00286
00287 reprojectionResidualsAndJacobianFor3DPoint(v[0], v[1], v[2], v[3], v[4], v[5], v[6], p2D.x(), p2D.y(), x[0], x[1], x[2], data_f_x + j, data_J + (3*j));
00288 j++;
00289 }
00290
00291 QVMatrix H = J.dotProduct(J, true, false);
00292 for(int i = 0; i < H.getCols(); i++)
00293 H(i,i) += lambda;
00294 QVVector b = J.dotProduct(f_x, true);
00295
00296 QVVector xInc;
00297 solveByCholeskyDecomposition(H, xInc, b);
00298
00299 x = x - xInc;
00300 }
00301
00302 return x;
00303 }
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334 void evaluateReprojectionResidualsAndJacobianCauchyDistribution(
00335 const double q1, const double q2, const double q3, const double q4,
00336 const double tx, const double ty, const double tz,
00337 const QPointF p2D, const QV3DPointF p3D,
00338 const double sigma,
00339 double *residual, double *jacobian)
00340 {
00341
00342 const double px = p2D.x(),
00343 py = p2D.y(),
00344 x = p3D.x(),
00345 y = p3D.y(),
00346 z = p3D.z();
00347
00348 const double t1 = q1 * q1;
00349 const double t2 = q2 * q2;
00350 const double t3 = q3 * q3;
00351 const double t4 = q4 * q4;
00352 const double t5 = t1 + t2 + t3 + t4;
00353 const double t6 = 0.1e1 / t5;
00354 const double t7 = -t2 - t3;
00355 const double t10 = 0.1e1 + 0.20e1 * t6 * t7;
00356 const double t11 = x - tx;
00357 const double t13 = q1 * q2;
00358 const double t14 = q3 * q4;
00359 const double t15 = t13 - t14;
00360 const double t16 = t6 * t15;
00361 const double t17 = y - ty;
00362 const double t20 = q3 * q1;
00363 const double t21 = q2 * q4;
00364 const double t22 = t20 + t21;
00365 const double t23 = t6 * t22;
00366 const double t24 = z - tz;
00367 const double t27 = t10 * t11 + 0.20e1 * t16 * t17 + 0.20e1 * t23 * t24;
00368 const double t28 = t20 - t21;
00369 const double t29 = t6 * t28;
00370 const double t32 = q2 * q3;
00371 const double t33 = q1 * q4;
00372 const double t34 = t32 + t33;
00373 const double t35 = t6 * t34;
00374 const double t38 = -t2 - t1;
00375 const double t41 = 0.1e1 + 0.20e1 * t6 * t38;
00376 const double t43 = 0.20e1 * t29 * t11 + 0.20e1 * t35 * t17 + t41 * t24;
00377 const double t44 = 0.1e1 / t43;
00378 const double t46 = t27 * t44 - px;
00379 const double t47 = t5 * t5;
00380 const double t48 = 0.1e1 / t47;
00381 const double t49 = t48 * t7;
00382 const double t50 = q1 * t11;
00383 const double t53 = t48 * t15;
00384 const double t54 = t17 * q1;
00385 const double t57 = t6 * q2;
00386 const double t59 = 0.20e1 * t57 * t17;
00387 const double t60 = t48 * t22;
00388 const double t61 = t24 * q1;
00389 const double t64 = t6 * q3;
00390 const double t66 = 0.20e1 * t64 * t24;
00391 const double t69 = t43 * t43;
00392 const double t70 = 0.1e1 / t69;
00393 const double t71 = t27 * t70;
00394 const double t72 = t48 * t28;
00395 const double t76 = 0.20e1 * t64 * t11;
00396 const double t77 = t48 * t34;
00397 const double t80 = t6 * q4;
00398 const double t82 = 0.20e1 * t80 * t17;
00399 const double t83 = t48 * t38;
00400 const double t86 = t6 * q1;
00401 const double t87 = 0.40e1 * t86;
00402 const double t90 = -0.40e1 * t72 * t50 + t76 - 0.40e1 * t77 * t54 + t82 + (-0.40e1 * t83 * q1 - t87) * t24;
00403 const double t94 = t13 + t14;
00404 const double t95 = t6 * t94;
00405 const double t98 = -t3 - t1;
00406 const double t101 = 0.1e1 + 0.20e1 * t6 * t98;
00407 const double t103 = t32 - t33;
00408 const double t104 = t6 * t103;
00409 const double t107 = 0.20e1 * t95 * t11 + t101 * t17 + 0.20e1 * t104 * t24;
00410 const double t109 = t107 * t44 - py;
00411 const double t110 = t48 * t94;
00412 const double t114 = 0.20e1 * t57 * t11;
00413 const double t115 = t48 * t98;
00414 const double t120 = t48 * t103;
00415 const double t124 = 0.20e1 * t80 * t24;
00416 const double t127 = t107 * t70;
00417 const double t132 = sigma * sigma;
00418 const double t133 = 0.1e1 / t132;
00419 const double t135 = t46 * t46;
00420 const double t136 = t109 * t109;
00421 const double t139 = 0.1e1 + (t135 + t136) * t133;
00422 const double t140 = 0.1e1 / t139;
00423 const double t144 = 0.40e1 * t57;
00424 const double t147 = t17 * q2;
00425 const double t151 = 0.20e1 * t86 * t17;
00426 const double t152 = t24 * q2;
00427 const double t157 = t11 * q2;
00428 const double t161 = 0.20e1 * t80 * t11;
00429 const double t165 = 0.20e1 * t64 * t17;
00430 const double t170 = -0.40e1 * t72 * t157 - t161 - 0.40e1 * t77 * t147 + t165 + (-0.40e1 * t83 * q2 - t144) * t24;
00431 const double t177 = 0.20e1 * t86 * t11;
00432 const double t192 = 0.40e1 * t64;
00433 const double t195 = t17 * q3;
00434 const double t198 = t24 * q3;
00435 const double t202 = 0.20e1 * t86 * t24;
00436 const double t205 = t11 * q3;
00437 const double t212 = -0.40e1 * t72 * t205 + t177 - 0.40e1 * t77 * t195 + t59 - 0.40e1 * t83 * t198;
00438 const double t225 = 0.20e1 * t57 * t24;
00439 const double t234 = q4 * t11;
00440 const double t237 = t17 * q4;
00441 const double t240 = t24 * q4;
00442 const double t251 = -0.40e1 * t72 * t234 - t114 - 0.40e1 * t77 * t237 + t151 - 0.40e1 * t83 * t240;
00443 const double t310 = log(t139);
00444
00445 jacobian[0] = 0.2e1 * (t46 * ((-0.40e1 * t49 * t50 - 0.40e1 * t53 * t54 + t59 - 0.40e1 * t60 * t61 + t66) * t44 - t71 * t90) + t109 * ((-0.40e1 * t110 * t50 + t114 + (-0.40e1 * t115 * q1 - t87) * t17 - 0.40e1 * t120 * t61 - t124) * t44 - t127 * t90)) * t133 * t140;
00446 jacobian[1] = 0.2e1 * (t46 * (((-0.40e1 * t49 * q2 - t144) * t11 - 0.40e1 * t53 * t147 + t151 - 0.40e1 * t60 * t152 + t124) * t44 - t71 * t170) + t109 * ((-0.40e1 * t110 * t157 + t177 - 0.40e1 * t115 * t147 - 0.40e1 * t120 * t152 + t66) * t44 - t127 * t170)) * t133 * t140;
00447 jacobian[2] = 0.2e1 * (t46 * (((-0.40e1 * t49 * q3 - t192) * t11 - 0.40e1 * t53 * t195 - t82 - 0.40e1 * t60 * t198 + t202) * t44 - t71 * t212) + t109 * ((-0.40e1 * t110 * t205 + t161 + (-0.40e1 * t115 * q3 - t192) * t17 - 0.40e1 * t120 * t198 + t225) * t44 - t127 * t212)) * t133 * t140;
00448 jacobian[3] = 0.2e1 * (t46 * ((-0.40e1 * t49 * t234 - 0.40e1 * t53 * t237 - t165 - 0.40e1 * t60 * t240 + t225) * t44 - t71 * t251) + t109 * ((-0.40e1 * t110 * t234 + t76 - 0.40e1 * t115 * t237 - 0.40e1 * t120 * t240 - t202) * t44 - t127 * t251)) * t133 * t140;
00449 jacobian[4] = 0.2e1 * (t46 * (-t10 * t44 + 0.20e1 * t71 * t29) + t109 * (-0.20e1 * t95 * t44 + 0.20e1 * t127 * t29)) * t133 * t140;
00450 jacobian[5] = 0.2e1 * (t46 * (-0.20e1 * t16 * t44 + 0.20e1 * t71 * t35) + t109 * (-t101 * t44 + 0.20e1 * t127 * t35)) * t133 * t140;
00451 jacobian[6] = 0.2e1 * (t46 * (-0.20e1 * t23 * t44 + t71 * t41) + t109 * (-0.20e1 * t104 * t44 + t127 * t41)) * t133 * t140;
00452 residual[0] = t310;
00453 }
00454
00455 QVCameraPose optimizeReprojectionErrorForCameraPoseCauchy(const QVCameraPose &cameraPose, const QList<QPointF> &points2D, const QList<QV3DPointF> &points3D, const int iterations, const double lambda, const double sigma)
00456 {
00457 const int n = points2D.size();
00458
00459 QVVector x = cameraPose;
00460 for(int i = 0; i < iterations; i++)
00461 {
00462 QVVector f_x(n);
00463 QVMatrix J(n, 7);
00464 double *data_f_x = f_x.data(),
00465 *data_J = J.getWriteData();
00466
00467 QListIterator<QPointF> iteratorPoints2D(points2D);
00468 QListIterator<QV3DPointF> iteratorPoints3D(points3D);
00469
00470 int j = 0;
00471 while (iteratorPoints2D.hasNext())
00472 {
00473 const QPointF p2D = iteratorPoints2D.next();
00474 const QV3DPointF p3D = iteratorPoints3D.next();
00475 evaluateReprojectionResidualsAndJacobianCauchyDistribution(x[0], x[1], x[2], x[3], x[4], x[5], x[6], p2D, p3D, sigma, data_f_x + j, data_J + (7*j));
00476 j++;
00477 }
00478
00479 Q_ASSERT(not f_x.containsNaN());
00480 Q_ASSERT(not J.containsNaN());
00481
00482 QVMatrix H = J.dotProduct(J, true, false);
00483 for(int i = 0; i < H.getCols(); i++)
00484 H(i,i) += lambda;
00485 QVVector b = J.dotProduct(f_x, true);
00486
00487 QVVector xInc;
00488 solveByCholeskyDecomposition(H, xInc, b);
00489
00490 x = x - xInc;
00491 }
00492
00493 return QVCameraPose(x);
00494 }
00495