Main Page | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | File Members

RadialLensCorrection.cxx

Go to the documentation of this file.
00001 // This is oxl/oxp/RadialLensCorrection.cxx
00002 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00003 #pragma implementation
00004 #endif
00005 
00006 #include "RadialLensCorrection.h"
00007 
00008 #include <vcl_cassert.h>
00009 #include <vcl_iostream.h>
00010 #include <vnl/vnl_math.h>
00011 
00012 RadialLensCorrection::RadialLensCorrection(double cx, double cy, double sx, double sy, double k2, double k4)
00013 {
00014   init(cx, cy, sx, sy, k2, k4);
00015 }
00016 
00017 RadialLensCorrection::RadialLensCorrection(double k2)
00018 {
00019   init(0, 0, 1, 1, k2, 0);
00020 }
00021 
00022 RadialLensCorrection::RadialLensCorrection(int w, int h, double k2)
00023 {
00024   assert(0);
00025   init(w/2, h/2, 2.0, 1.0, 4 * k2 / (w*w + h*h), 0);
00026 }
00027 
00028 void RadialLensCorrection::init(double cx, double cy, double sx, double sy, double k2, double k4)
00029 {
00030   _cx = cx;
00031   _cy = cy;
00032   _sx = sx;
00033   _sy = sy;
00034   _k2 = k2;
00035   _k4 = k4;
00036   // vcl_cerr << "RDC params: c(" << cx << ',' << cy << ") scale "
00037   //          << sx << " x " << sy << ", K=[" << k2 << ' ' << k4 << "].\n";
00038 
00039   _invsx = 1.0 / _sx;
00040   _invsy = 1.0 / _sy;
00041 
00042   // Approximately scale to maintain image size
00043   _invsx /= (1 + _k2);
00044   _invsy /= (1 + _k2);
00045 }
00046 
00047 void RadialLensCorrection::implement_map(double x1, double y1, double* x2, double* y2)
00048 {
00049   // center
00050   double dx = _sx*(x1 - _cx);
00051   double dy = _sy*(y1 - _cy);
00052 
00053   // warp
00054   double r2 = dx*dx + dy*dy;
00055   double correction = 1 + _k2 * r2 + _k4 * r2*r2;
00056   // so now r2c = r2 * correction
00057 
00058   double dxc = dx * correction;
00059   double dyc = dy * correction;
00060 
00061   // decenter
00062   *x2 = dxc * _invsx + _cx;
00063   *y2 = dyc * _invsy + _cy;
00064 }
00065 
00066 void RadialLensCorrection::implement_inverse_map(double x2, double y2, double* x1, double* y1)
00067 {
00068   // center
00069   double dxc = _sx * (x2 - _cx);
00070   double dyc = _sy * (y2 - _cy);
00071 
00072   // dewarp
00073   double r2c = dxc*dxc + dyc*dyc;
00074   if (r2c == 0 || _k2 == 0) {
00075     *x1 = x2;
00076     *y1 = y2;
00077     return;
00078   }
00079   double rc = vcl_sqrt(r2c);
00080   // So rc = r (1 + k2 r^2)
00081   // Thf r = fsolve(k2 r^3 + r - rc = 0)
00082   // from Devernay and Faugeras:
00083   assert (_k4 == 0);
00084   double c =  1 / _k2;
00085   double d = -rc * c;
00086 
00087   // r^3 + c * r + d = 0;
00088   double Q = -c / 3;
00089   double R = d / 2;
00090 
00091   double DELTA = R*R - Q*Q*Q;
00092   double r;
00093   if (DELTA < 0)  {
00094     double S = vnl_math_cuberoot(vcl_sqrt(R*R-DELTA));
00095     double T = vcl_atan(vcl_sqrt(-DELTA)/R) / 3.0;
00096     r = -S * vcl_cos(T) + S * vcl_sqrt(3.0) * vcl_sin(T);
00097     r = -r;
00098     double res = (r*(1 + _k2 * r * r) - rc);
00099     if (vcl_fabs(res) > 1e-11) {
00100       vcl_cerr << "RES = " << res << " -- call awf!\n";
00101     }
00102   } else {
00103     double t = -vnl_math_sgn(R) * vnl_math_cuberoot(vcl_fabs(R) + vcl_sqrt(DELTA));
00104 
00105     if (t == 0)
00106       r = 0;
00107     else
00108       r = t + Q / t;
00109 #if 0
00110     vcl_cerr <<  "+RES = " << (r*(1 + _k2 * r * r) - rc) << ' '
00111              << (vcl_fabs(t*t*t) - (vcl_fabs(R)  + vcl_sqrt(DELTA))) << vcl_endl;
00112 #endif
00113   }
00114   // end D & F
00115 
00116 
00117   double correction = r / rc;
00118   if (correction < 0) correction = -correction;
00119 
00120   double dx = dxc * correction;
00121   double dy = dyc * correction;
00122 
00123   // decenter
00124   *x1 = dx * _invsx + _cx;
00125   *y1 = dy * _invsy + _cy;
00126 }

Generated on Thu Jan 10 14:46:06 2008 for contrib/oxl/oxp by  doxygen 1.4.4