Isis 3 Programmer Reference
NewHorizonsMvicTdiCameraDistortionMap.cpp
Go to the documentation of this file.
1 
20 #include <cmath>
21 #include <iostream>
22 
23 #include <boost/math/special_functions/legendre.hpp>
24 
25 #include "Camera.h"
26 #include "CameraFocalPlaneMap.h"
27 #include "Constants.h"
28 #include "FunctionTools.h"
29 #include "IString.h"
32 
33 #include <QDebug>
34 
35 
36 using namespace boost::math;
37 using namespace std;
38 using namespace Isis;
39 
40 namespace Isis {
58  NewHorizonsMvicTdiCameraDistortionMap::NewHorizonsMvicTdiCameraDistortionMap(
59  Camera *parent,
60  vector<double> xDistortionCoeffs,
61  vector<double> yDistortionCoeffs,
62  vector<double> residualColDistCoeffs,
63  vector<double> residualRowDistCoeffs) :
64  CameraDistortionMap(parent, 1.0) {
65 
66  m_xDistortionCoeffs = xDistortionCoeffs;
67  m_yDistortionCoeffs = yDistortionCoeffs;
68 
69  m_residualColDistCoeffs = residualColDistCoeffs;
70  m_residualRowDistCoeffs = residualRowDistCoeffs;
71 
72  // half of detector in x is 32.5 mm
74  }
75 
76 
80  }
81 
82 
99  // TODO: Don't really like this - we always return true, even in event of failures
100  bool NewHorizonsMvicTdiCameraDistortionMap::SetFocalPlane(const double dx, const double dy) {
101 
102  p_focalPlaneX = dx;
103  p_focalPlaneY = dy;
104 
105  // initialize undistorted focal plane coordinates to the distorted
106  // coordinate values
109 
110  // if x lies outside of the detector, do NOT apply distortion
111  // set undistorted focal plane values to be identical to raw values
112  if ((fabs(dx) > m_focalPlaneHalf_x)) {
113  return true;
114  }
115 
116  // scale x to lie in the range -1.0 to +1.0
117  // this is required for Legendre Polynomials, man
118  double xscaled = -dx / m_focalPlaneHalf_x;
119 
120  // compute distortion corrections in x using Legendre Polynomials
121  // these corrections are also in the -1.0 to +1.0 range
122  double deltax1 = 0.0;
123  if (!computeDistortionCorrections(xscaled, 0.0, deltax1)) {
124  return true;
125  }
126 
127  // now compute residual distortion corrections (per Jason Cook)
128  // TODO: implementation not complete
129  double deltax2 = 0.0;
130  double deltay2 = 0.0;
131  computeResidualDistortionCorrections(dx, deltax2, deltay2);
132 
133  // apply the corrections
134  xscaled += deltax1;
135 
136  // scale back from range of '-1.0 to +1.0' to the detector, '-32.5 to 32.5 mm'
137 // p_undistortedFocalPlaneX = -xscaled * m_focalPlaneHalf_x;
138 // p_undistortedFocalPlaneY = p_focalPlaneY;
139  p_undistortedFocalPlaneX = -xscaled * m_focalPlaneHalf_x + deltax2;
141 
142  return true;
143  }
144 
145 
160 
161  // image coordinates prior to introducing distortion
164 
165  double xt = ux;
166  double yt = uy;
167 
168 // p_focalPlaneX = p_undistortedFocalPlaneX;
169 // p_focalPlaneY = p_undistortedFocalPlaneY;
170 // return true;
171 
172  // scale undistorted coordinates to range of -1.0 to +1.0
173  double uxScaled = -ux/m_focalPlaneHalf_x;
174  double xtScaled;
175  double xprevious, yprevious;
176  double scaledDeltax;
177  double deltax2 = 0.0;
178  double deltay2 = 0.0;
179 
180  xprevious = 1000000.0;
181  yprevious = 1000000.0;
182 
183  double tolerance = 0.000001;
184 
185  bool bConverged = false;
186 
187  // iterating to introduce distortion...
188  // we stop when the difference between distorted coordinates
189  // in successive iterations is at or below the given tolerance
190  for ( int i = 0; i < 50; i++ ) {
191 
192  xtScaled = -xt / m_focalPlaneHalf_x;
193 
194  // Changed this failure mode from a throw to return false. These functions should never
195  // throw, the callers are not catching, so bad things happen. The callers should be checking
196  // the return status
197  if (fabs(xtScaled) > 1.0) {
198  return bConverged;
199  }
200 
201  // compute scaled distortion in x (scaled to -1.0 - +1.0) using Legendre Polynomials
202  computeDistortionCorrections(xtScaled, 0.0, scaledDeltax);
203 
204  // compute residual distortion in unscaled focal plane coordinates
205  computeResidualDistortionCorrections(xt, deltax2, deltay2);
206 
207  // update unscaled coordinates
208  xt = -(uxScaled-scaledDeltax) * m_focalPlaneHalf_x - deltax2;
209  yt = uy - deltay2;
210 
211  // check for convergenceyScaledDistortion
212  if ((fabs(xt - xprevious) <= tolerance) && (fabs(yt - yprevious) <= tolerance)) {
213  bConverged = true;
214  break;
215  }
216 
217  xprevious = xt;
218  yprevious = yt;
219  }
220 
221  if (bConverged) {
222  // scale x coord inate back to detector (-32.5 to +32.5)
223  // xtScaled *= -m_focalPlaneHalf_x;
224 
225  // set distorted coordinates
226  p_focalPlaneX = xt;
227  p_focalPlaneY = yt;
228  }
229 
230  return bConverged;
231  }
232 
233 
249  const double xscaled,
250  const double yscaled,
251  double &deltax) {
252 
253  double lpx0, lpx1, lpx2, lpx3, lpx4, lpx5;
254  double lpy0, lpy1, lpy2, lpy3, lpy4, lpy5;
255 
256  // Legendre polynomials
257  try {
258  lpx0 = legendre_p(0,xscaled);
259  lpx1 = legendre_p(1,xscaled);
260  lpx2 = legendre_p(2,xscaled);
261  lpx3 = legendre_p(3,xscaled);
262  lpx4 = legendre_p(4,xscaled);
263  lpx5 = legendre_p(5,xscaled);
264  lpy0 = legendre_p(0,yscaled);
265  lpy1 = legendre_p(1,yscaled);
266  lpy2 = legendre_p(2,yscaled);
267  lpy3 = legendre_p(3,yscaled);
268  lpy4 = legendre_p(4,yscaled);
269  lpy5 = legendre_p(5,yscaled);
270  }
271  catch (const std::exception& e) {
272  return false;
273  }
274 
275  deltax =
276  m_xDistortionCoeffs[0] * lpx0 * lpy1 +
277  m_xDistortionCoeffs[1] * lpx1 * lpy0 +
278  m_xDistortionCoeffs[2] * lpx0 * lpy2 +
279  m_xDistortionCoeffs[3] * lpx1 * lpy1 +
280  m_xDistortionCoeffs[4] * lpx2 * lpy0 +
281  m_xDistortionCoeffs[5] * lpx0 * lpy3 +
282  m_xDistortionCoeffs[6] * lpx1 * lpy2 +
283  m_xDistortionCoeffs[7] * lpx2 * lpy1 +
284  m_xDistortionCoeffs[8] * lpx3 * lpy0 +
285  m_xDistortionCoeffs[9] * lpx0 * lpy4 +
286  m_xDistortionCoeffs[10] * lpx1 * lpy3 +
287  m_xDistortionCoeffs[11] * lpx2 * lpy2 +
288  m_xDistortionCoeffs[12] * lpx3 * lpy1 +
289  m_xDistortionCoeffs[13] * lpx4 * lpy0 +
290  m_xDistortionCoeffs[14] * lpx0 * lpy5 +
291  m_xDistortionCoeffs[15] * lpx1 * lpy4 +
292  m_xDistortionCoeffs[16] * lpx2 * lpy3 +
293  m_xDistortionCoeffs[17] * lpx3 * lpy2 +
294  m_xDistortionCoeffs[18] * lpx4 * lpy1 +
295  m_xDistortionCoeffs[19] * lpx5 * lpy0;
296 
297  return true;
298  }
299 
300 
312  double &residualDeltax,
313  double &residualDeltay) {
314 
315  double s = 2500.5 - dx/0.013;
316 
317  residualDeltax = s * m_residualColDistCoeffs[1] +
318  pow(s,2) * m_residualColDistCoeffs[2] +
319  pow(s,3) * m_residualColDistCoeffs[3] +
320  pow(s,4) * m_residualColDistCoeffs[4] +
321  pow(s,5) * m_residualColDistCoeffs[5];
322 
323  residualDeltay = s * m_residualRowDistCoeffs[1] +
324  pow(s,2) * m_residualRowDistCoeffs[2] +
325  pow(s,3) * m_residualRowDistCoeffs[3] +
326  pow(s,4) * m_residualRowDistCoeffs[4] +
327  pow(s,5) * m_residualRowDistCoeffs[5];
328 
329  // convert to mm (correction for negative x to the left)
330  residualDeltax *= -p_camera->PixelPitch();
331  residualDeltay *= p_camera->PixelPitch();
332  }
333 
334 
336 // * Testing method to output corrections in x and y at pixel centers for entire focal plane.
337 // * Output in csv format for viewing/plotting in Excel.
338 // */
339 //bool NewHorizonsMvicTdiCameraDistortionMap::outputResidualDeltas() {
340 //
341 // QString ofname("mvic_tdi_residual_deltas.csv");
342 // std::ofstream fp_out(ofname.toLatin1().data(), std::ios::out);
343 // if (!fp_out)
344 // return false;
345 //
346 // char buf[1056];
347 //
348 // double residualColDelta;
349 //
350 // for (int s=0; s <= 5000; s++) { // loop in sample direction
351 // residualColDelta = m_residualColDistCoeffs[0] +
352 // s * m_residualColDistCoeffs[1] +
353 // pow(double(s),2) * m_residualColDistCoeffs[2] +
354 // pow(double(s),3) * m_residualColDistCoeffs[3] +
355 // pow(double(s),4) * m_residualColDistCoeffs[4] +
356 // pow(double(s),5) * m_residualColDistCoeffs[5];
357 // sprintf(buf, "%d,%lf\n", s, residualColDelta);
358 // fp_out << buf;
359 // }
360 //
361 // fp_out.close();
362 //
363 // return true;
364 //}
365 
366 }
double p_focalPlaneX
Distorted focal plane x.
vector< double > m_residualColDistCoeffs
residual distortion coefficients as determined
bool computeDistortionCorrections(const double xscaled, const double yscaled, double &deltax)
Compute distortion corrections in x and y direction.
void computeResidualDistortionCorrections(const double dx, double &residualDeltax, double &residualDeltay)
Compute residual distortion corrections in row and column direction TODO: Implementati plete...
Namespace for the standard library.
double m_focalPlaneHalf_x
half of focal plane x and y dimensions in mm
virtual bool SetUndistortedFocalPlane(const double ux, const double uy)
Compute distorted focal plane x/y.
double p_undistortedFocalPlaneX
Undistorted focal plane x.
Camera * p_camera
The camera to distort/undistort.
std::vector< double > m_xDistortionCoeffs
distortion coefficients in x and y as determined
Unless noted otherwise, the portions of Isis written by the USGS are public domain.
Distort/undistort focal plane coordinates.
double PixelPitch() const
Returns the pixel pitch.
Definition: Camera.cpp:2754
vector< double > m_residualRowDistCoeffs
by Jason Cook, SWRI (MVIC Distortion)
double p_focalPlaneY
Distorted focal plane y.
double p_undistortedFocalPlaneY
Undistorted focal plane y.
int Samples() const
Returns the number of samples in the image.
Definition: Camera.cpp:2788
Namespace for ISIS/Bullet specific routines.
Definition: Apollo.h:31
std::vector< double > m_yDistortionCoeffs
by Keith Harrison (Interface Control Document section 10.3.1.2)
virtual bool SetFocalPlane(const double dx, const double dy)
Compute undistorted focal plane x/y.