00001
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
00037
00038
00039 _invsx = 1.0 / _sx;
00040 _invsy = 1.0 / _sy;
00041
00042
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
00050 double dx = _sx*(x1 - _cx);
00051 double dy = _sy*(y1 - _cy);
00052
00053
00054 double r2 = dx*dx + dy*dy;
00055 double correction = 1 + _k2 * r2 + _k4 * r2*r2;
00056
00057
00058 double dxc = dx * correction;
00059 double dyc = dy * correction;
00060
00061
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
00069 double dxc = _sx * (x2 - _cx);
00070 double dyc = _sy * (y2 - _cy);
00071
00072
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
00081
00082
00083 assert (_k4 == 0);
00084 double c = 1 / _k2;
00085 double d = -rc * c;
00086
00087
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
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
00124 *x1 = dx * _invsx + _cx;
00125 *y1 = dy * _invsy + _cy;
00126 }