00001
00013 #ifndef PINHOLE_HPP_
00014 #define PINHOLE_HPP_
00015
00016 #include "jmath/jblas.hpp"
00017 #include "jmath/linearSolvers.hpp"
00018 #include "jmath/ublasExtra.hpp"
00019
00020 #include "jmath/matlab.hpp"
00021
00022 namespace jafar {
00023 namespace rtslam {
00024
00025 using namespace jblas;
00026
00027
00035 namespace pinhole {
00036
00037
00043 template<class V>
00044 vec2 projectPointToNormalizedPlane(const V & v) {
00045
00046 vec2 up;
00047 up(0) = v(0) / v(2);
00048 up(1) = v(1) / v(2);
00049 return up;
00050 }
00051
00058 template<class V, class P>
00059 void projectPointToNormalizedPlane(const V & v, P & up, double & dist) {
00060
00061 up(0) = v(0) / v(2);
00062 up(1) = v(1) / v(2);
00063 dist = ublas::norm_2(v);
00064 }
00065
00066
00073 template<class V, class U, class MU_v>
00074 void projectPointToNormalizedPlane(const V & v, U & up, MU_v & UP_v) {
00075
00076 up = projectPointToNormalizedPlane(v);
00077
00078 UP_v(0, 0) = 1.0 / v(2);
00079 UP_v(0, 1) = 0.0;
00080 UP_v(0, 2) = -v(0) / (v(2) * v(2));
00081 UP_v(1, 0) = 0.0;
00082 UP_v(1, 1) = 1.0 / v(2);
00083 UP_v(1, 2) = -v(1) / (v(2) * v(2));
00084
00085 }
00086
00094 template<class V, class U, class MU_v>
00095 void projectPointToNormalizedPlane(const V & v, U & up, double & dist, MU_v & UP_v) {
00096
00097 projectPointToNormalizedPlane(v, up, dist);
00098
00099 UP_v(0, 0) = 1.0 / v(2);
00100 UP_v(0, 1) = 0.0;
00101 UP_v(0, 2) = -v(0) / (v(2) * v(2));
00102 UP_v(1, 0) = 0.0;
00103 UP_v(1, 1) = 1.0 / v(2);
00104 UP_v(1, 2) = -v(1) / (v(2) * v(2));
00105
00106 }
00107
00114 template<class U>
00115 vec3 backprojectPointFromNormalizedPlane(const U & u, double depth = 1) {
00116
00117 vec3 p;
00118 p(0) = depth * u(0);
00119 p(1) = depth * u(1);
00120 p(2) = depth;
00121 return p;
00122 }
00123
00132 template<class U, class P, class MP_u, class MP_depth>
00133 void backprojectPointFromNormalizedPlane(const U & u, const double depth, P & p, MP_u & P_u, MP_depth & P_depth) {
00134 p = backprojectPointFromNormalizedPlane(u, depth);
00135
00136 P_u(0, 0) = depth;
00137 P_u(0, 1) = 0.0;
00138 P_u(1, 0) = 0.0;
00139 P_u(1, 1) = depth;
00140 P_u(2, 0) = 0.0;
00141 P_u(2, 1) = 0.0;
00142
00143 P_depth(0, 0) = u(0);
00144 P_depth(1, 0) = u(1);
00145 P_depth(2, 0) = 1.0;
00146 }
00147
00153 template<class VD>
00154 double distortFactor(const VD & d, double r2){
00155 if (d.size() == 0) return 1.0;
00156 double s = 1.0;
00157 double r2i = 1.0;
00158 for (size_t i = 0; i < d.size(); i++) {
00159 r2i = r2i * r2;
00160 s += d(i) * r2i;
00161 }
00162 return s;
00163 }
00164
00165
00172 template<class VD, class VU>
00173 jblas::vec2 distortPoint(const VD & d, const VU & up, double r2max) {
00174 size_t n = d.size();
00175 if (n == 0)
00176 return up;
00177 else {
00178 double r2 = up(0) * up(0) + up(1) * up(1);
00179 if (r2 > r2max) return up;
00180 return distortFactor(d, r2) * up;
00181
00182
00183
00184
00185
00186
00187
00188 }
00189 }
00190
00191
00199 template<class VD, class VUp, class VUd, class MUD_up>
00200 void distortPoint(const VD & d, const VUp & up, VUd & ud, double r2max, MUD_up & UD_up) {
00201 size_t n = d.size();
00202 jblas::vec2 R2_up;
00203 jblas::vec2 S_up;
00204
00205 if (n > 0)
00206 {
00207 double r2 = up(0) * up(0) + up(1) * up(1);
00208 if (r2 <= r2max)
00209 {
00210 double s = 1.0;
00211 double r2i = 1.0;
00212 double r2im1 = 1.0;
00213 double S_r2 = 0.0;
00214
00215 for (size_t i = 0; i < n; i++) {
00216 r2i = r2i * r2;
00217 s += d(i) * r2i;
00218
00219 S_r2 = S_r2 + (i + 1) * d(i) * r2im1;
00220 r2im1 = r2im1 * r2;
00221 }
00222
00223 ud = s * up;
00224
00225 R2_up(0) = 2 * up(0);
00226 R2_up(1) = 2 * up(1);
00227
00228 S_up(0) = R2_up(0) * S_r2;
00229 S_up(1) = R2_up(1) * S_r2;
00230
00231 UD_up(0, 0) = S_up(0) * up(0) + s;
00232 UD_up(0, 1) = S_up(1) * up(0);
00233 UD_up(1, 0) = S_up(0) * up(1);
00234 UD_up(1, 1) = S_up(1) * up(1) + s;
00235
00236 return;
00237 }
00238 }
00239
00240 ud = up;
00241 UD_up = jblas::identity_mat(2);
00242 }
00243
00244 template<class VC, class VU>
00245 jblas::vec2 undistortPoint(const VC & c, const VU & ud) {
00246 size_t n = c.size();
00247 if (n == 0)
00248 return ud;
00249 else {
00250 double r2 = ud(0) * ud(0) + ud(1) * ud(1);
00251 return distortFactor(c, r2) * ud;
00252
00253
00254
00255
00256
00257
00258
00259 }
00260 }
00261
00262 template<class VC, class VUd, class VUp, class MUP_ud>
00263 void undistortPoint(const VC & c, const VUd & ud, VUp & up, MUP_ud & UP_ud) {
00264 size_t n = c.size();
00265 jblas::vec2 R2_ud;
00266 jblas::vec2 S_ud;
00267
00268 if (n == 0) {
00269 up = ud;
00270 UP_ud = jblas::identity_mat(2);
00271 }
00272
00273 else {
00274 double r2 = ud(0) * ud(0) + ud(1) * ud(1);
00275 double s = 1.0;
00276 double r2i = 1.0;
00277 double r2im1 = 1.0;
00278 double S_r2 = 0.0;
00279
00280 for (size_t i = 0; i < n; i++) {
00281 r2i = r2i * r2;
00282 s += c(i) * r2i;
00283
00284 S_r2 = S_r2 + (i + 1) * c(i) * r2im1;
00285 r2im1 = r2im1 * r2;
00286 }
00287
00288 up = s * ud;
00289
00290 R2_ud(0) = 2 * ud(0);
00291 R2_ud(1) = 2 * ud(1);
00292
00293 S_ud(0) = R2_ud(0) * S_r2;
00294 S_ud(1) = R2_ud(1) * S_r2;
00295
00296 UP_ud(0, 0) = S_ud(0) * ud(0) + s;
00297 UP_ud(0, 1) = S_ud(1) * ud(0);
00298 UP_ud(1, 0) = S_ud(0) * ud(1);
00299 UP_ud(1, 1) = S_ud(1) * ud(1) + s;
00300 }
00301
00302 }
00303
00304
00311 template<class VK, class VU>
00312 jblas::vec2 pixellizePoint(const VK & k, const VU & ud) {
00313 double u_0 = k(0);
00314 double v_0 = k(1);
00315 double a_u = k(2);
00316 double a_v = k(3);
00317 vec2 u;
00318 u(0) = u_0 + a_u * ud(0);
00319 u(1) = v_0 + a_v * ud(1);
00320 return u;
00321 }
00322
00323
00331 template<class VK, class VUd, class VU, class MU_ud>
00332 void pixellizePoint(const VK & k, const VUd & ud, VU & u, MU_ud & U_ud) {
00333
00334
00335 double a_u = k(2);
00336 double a_v = k(3);
00337
00338 u = pixellizePoint(k, ud);
00339
00340 U_ud(0, 0) = a_u;
00341 U_ud(0, 1) = 0;
00342 U_ud(1, 0) = 0;
00343 U_ud(1, 1) = a_v;
00344 }
00345
00346
00353 template<class VK, class VU>
00354 jblas::vec2 depixellizePoint(const VK & k, const VU & u) {
00355 double u_0 = k(0);
00356 double v_0 = k(1);
00357 double a_u = k(2);
00358 double a_v = k(3);
00359 vec2 ud;
00360 ud(0) = (u(0) - u_0) / a_u;
00361 ud(1) = (u(1) - v_0) / a_v;
00362 return ud;
00363 }
00364
00365
00373 template<class VK, class VUd, class VU, class MUD_u>
00374 void depixellizePoint(const VK & k, const VU & u, VUd & ud, MUD_u & UD_u) {
00375
00376
00377 double a_u = k(2);
00378 double a_v = k(3);
00379
00380 ud = depixellizePoint(k, u);
00381
00382 UD_u(0, 0) = 1.0 / a_u;
00383 UD_u(0, 1) = 0.0;
00384 UD_u(1, 0) = 0.0;
00385 UD_u(1, 1) = 1.0 / a_v;
00386 }
00387
00388
00396 template<class VK, class VD, class V>
00397 vec2 projectPoint(const VK & k, const VD & d, const V & v, double r2max) {
00398 return pixellizePoint(k, distortPoint(d, projectPointToNormalizedPlane(v), r2max));
00399 }
00400
00408 template<class VK, class VD, class V, class U>
00409 void projectPoint(const VK & k, const VD & d, const V & v, U & u, double r2max, double & dist) {
00410 vec2 up;
00411 projectPointToNormalizedPlane(v, up, dist);
00412 u = pixellizePoint(k, distortPoint(d, up, r2max));
00413 }
00414
00415
00424 template<class VK, class VD, class V, class VU, class MU_v>
00425 void projectPoint(const VK & k, const VD & d, const V & v, VU & u, double r2max, MU_v & U_v) {
00426 vec2 up, ud;
00427 mat23 UP_v;
00428 mat22 UD_up, U_ud;
00429 projectPointToNormalizedPlane(v, up, UP_v);
00430 distortPoint(d, up, ud, r2max, UD_up);
00431 pixellizePoint(k, ud, u, U_ud);
00432
00433 mat23 U_v1;
00434 U_v1 = ublas::prod(UD_up, UP_v);
00435 U_v = ublas::prod(U_ud, U_v1);
00436 }
00437
00447 template<class VK, class VD, class V, class VU, class MU_v>
00448 void projectPoint(const VK & k, const VD & d, const V & v, VU & u, double r2max, double & dist, MU_v & U_v) {
00449 vec2 up, ud;
00450 mat23 UP_v;
00451 mat22 UD_up, U_ud;
00452 projectPointToNormalizedPlane(v, up, dist, UP_v);
00453 distortPoint(d, up, ud, r2max, UD_up);
00454 pixellizePoint(k, ud, u, U_ud);
00455
00456 mat23 U_v1;
00457 U_v1 = ublas::prod(UD_up, UP_v);
00458 U_v = ublas::prod(U_ud, U_v1);
00459 }
00460
00461
00470 template<class VK, class VC, class U>
00471 vec3 backprojectPoint(const VK & k, const VC & c, const U & u, const double depth = 1.0) {
00472 return backprojectPointFromNormalizedPlane(undistortPoint(c, depixellizePoint(k, u)), depth);
00473 }
00474
00485 template<class VK, class VC, class U, class P, class MP_u, class MP_depth>
00486 void backProjectPoint(const VK & k, const VC & c, const U & u, double depth, P & p, MP_u & P_u, MP_depth & P_depth) {
00487 vec2 up, ud;
00488 mat32 P_up;
00489 mat22 UP_ud, UD_u;
00490 depixellizePoint(k, u, ud, UD_u);
00491 undistortPoint(c, ud, up, UP_ud);
00492 backprojectPointFromNormalizedPlane(up, depth, p, P_up, P_depth);
00493
00494 P_u = ublas::prod(P_up, ublas::prod<mat>(UP_ud, UD_u));
00495 }
00496
00497
00503 template<class VPix>
00504 bool isInRoi(const VPix & pix, const int x, const int y, const int width, const int height) {
00505 return ((pix(0) >= x) && (pix(0) <= x + width - 1) && (pix(1) >= y) && (pix(1) <= y + height - 1));
00506 }
00507
00514 template<class VPix>
00515 bool isInImage(const VPix & pix, const int & width, const int & height) {
00516 return isInRoi(pix, 0, 0, width, height);
00517 }
00518
00519
00528 template<class Vk, class Vd, class Vc>
00529 void computeCorrectionModel(const int width, const int height, const Vk & k, const Vd & d, Vc & c, double & r_max) {
00530 size_t size = c.size();
00531
00532 if (size != 0) {
00533 #if 0
00534 double rd_max = sqrt(k(0)*k(0) / (k(2)*k(2)) + k(1)*k(1) / (k(3)*k(3)));
00535 double r_max = 1.1 * rd_max;
00536 #else
00537 double rw = std::max(k(0), (width-k(0))), rh = std::max(k(1), (height-k(1)));
00538 double rd_max = sqrt(rw*rw / (k(2)*k(2)) + rh*rh / (k(3)*k(3))) * 0.95;
00539
00540
00541 double resolution = 0.1;
00542 double r_a = 0.0, r_b = 2.01;
00543 double r_mon, rd_mon;
00544 for (int i = 0; i < 3; ++i)
00545 {
00546 double r, r2, prev_r = -1, ir, prev_ir = -1;
00547 bool decreased = false;
00548 for(r = r_a; r <= r_b; r += resolution)
00549 {
00550 r2 = (r*rd_max); r2 *= r2;
00551 ir = distortFactor(d, r2);
00552
00553 if (prev_r > -0.5 && (r*ir-prev_r*prev_ir)/(r-prev_r) < 0.5) { decreased = true; break; }
00554 prev_r = r; prev_ir = ir;
00555 }
00556 if (!decreased) { r_mon = r; rd_mon = ir; break; }
00557 r_a = r-2*resolution; r_b = r;
00558 r_mon = r-resolution; rd_mon = prev_ir;
00559 resolution /= 10;
00560 }
00561
00562 if (r_mon*rd_mon > 1)
00563 {
00564 r_a = 0.9; r_b = r_mon;
00565 while (r_b-r_a > 1e-3)
00566 {
00567 double r = (r_a+r_b)/2;
00568 double r2 = (r*rd_max); r2 *= r2;
00569 double ir = distortFactor(d, r2);
00570 if (r * ir < 1.0) r_a = r; else r_b = r;
00571
00572 }
00573 r_max = (r_b+r_a)/2 * rd_max;
00574 } else r_max = r_mon*rd_max;
00575 #endif
00576
00577 size_t N_samples = 200;
00578 double iN_samples = 1 / (double) N_samples;
00579 double rd_n, rc_2, rd_2;
00580 vec rd(N_samples+1), rc(N_samples+1);
00581 mat Rd(N_samples+1, size);
00582
00583
00584 for (size_t sample = 0; sample <= N_samples; sample++) {
00585
00586 rc(sample) = sample * r_max * iN_samples;
00587 rc_2 = rc(sample) * rc(sample);
00588 rd(sample) = distortFactor(d, rc_2) * rc(sample);
00589 rd_2 = rd(sample) * rd(sample);
00590
00591 rd_n = rd(sample);
00592
00593 for (size_t order = 0; order < size; order++) {
00594 rd_n *= rd_2;
00595 Rd(sample, order) = rd_n;
00596 }
00597 }
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608 jblas::mat RdtRd(size,size);
00609 RdtRd = ublas::prod(ublas::trans(Rd), Rd);
00610 jblas::mat iRdtRd(size, size);
00611 jmath::ublasExtra::inv(RdtRd, iRdtRd);
00612 mat iRd = ublas::prod(iRdtRd, ublas::trans<jblas::mat>(Rd));
00613
00614 c = ublas::prod(iRd,(rc-rd));
00615
00616
00617
00618 }
00619 }
00620
00621
00622 }
00623
00624 }
00625 }
00626
00627 #endif