Isis 3 Programmer Reference
NewHorizonsMvicFrameCameraDistortionMap.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 "Constants.h"
27 #include "FunctionTools.h"
28 #include "IString.h"
30 
31 #include "CameraFocalPlaneMap.h"
32 
33 
34 #include <QDebug>
35 
36 
37 using namespace boost::math;
38 using namespace std;
39 using namespace Isis;
40 
41 namespace Isis {
54  NewHorizonsMvicFrameCameraDistortionMap::NewHorizonsMvicFrameCameraDistortionMap(Camera *parent,
55  vector<double> xDistortionCoeffs,
56  vector<double> yDistortionCoeffs) :
57  CameraDistortionMap(parent, 1.0) {
58 
59  m_xDistortionCoeffs = xDistortionCoeffs;
60  m_yDistortionCoeffs = yDistortionCoeffs;
61 
62  double pixelPitch = p_camera->PixelPitch();
63 
64  m_focalPlaneHalf_x = 0.5 * p_camera->Samples() * pixelPitch; // 32.5 mm
65  m_focalPlaneHalf_y = 0.5 * p_camera->Lines() * pixelPitch; // 0.832 mm
66  }
67 
68 
72  }
73 
74 
75 // /**
76 // * Testing method to output corrections in x and y at pixel centers for entire focal plane.
77 // * Output in csv format for viewing/plotting in Excel.
78 // */
79 //bool NewHorizonsMvicFrameCameraDistortionMap::outputDeltas() {
80 //
81 // QString ofname("mvic_frame_deltas.csv");
82 // std::ofstream fp_out(ofname.toLatin1().data(), std::ios::out);
83 // if (!fp_out)
84 // return false;
85 //
86 // char buf[1056];
87 //
88 // double deltax, deltay;
89 //
90 // for (double line = 0.5; line <= 128.5; line += 1.0) { // loop in y direction
91 // for (double sample=0.5; sample <= 5000.5; sample += 1.0) { // loop in x direction
92 //
93 // p_camera->FocalPlaneMap()->SetDetector(sample,line);
94 //
95 // double fplanex = p_camera->FocalPlaneMap()->FocalPlaneX();
96 // double fplaney = p_camera->FocalPlaneMap()->FocalPlaneY();
97 //
98 // SetFocalPlane(fplanex,fplaney);
99 //
100 // deltax = fplanex - p_undistortedFocalPlaneX;
101 // deltay = fplaney - p_undistortedFocalPlaneY;
102 //
103 // sprintf(buf, "%lf,%lf,%lf,%lf\n", sample, deltax/0.013, line, deltay/0.013);
104 //
105 // fp_out << buf;
106 // }
107 // }
108 //
109 // fp_out.close();
110 //
111 // return true;
112 //}
113 
114 
125  bool NewHorizonsMvicFrameCameraDistortionMap::SetFocalPlane(const double dx, const double dy) {
126 
127  p_focalPlaneX = dx;
128  p_focalPlaneY = dy;
129 
130  // in case of failures, initialize undistorted focal plane coordinates to the distorted
131  // coordinate values
134 
135  // if x and/or y lie outside of the detector, do NOT apply distortion
136  // set undistorted focal plane values to be identical to raw values
137  if ((fabs(dx) > m_focalPlaneHalf_x) || (fabs(dy) > m_focalPlaneHalf_y)) {
138  return true;
139  }
140 
141  // shift from ISIS MVIC FT image coordinate system with +x to the left and +y down to
142  // the desired system of +x to the right and +y up
143  // e.g. negate x and y
144 
145  // scale x and y to lie in the range -1.0 to +1.0
146  // this is requirement for Legendre Polynomials, man
147  double xscaled = -dx/m_focalPlaneHalf_x;
148  double yscaled = -dy/m_focalPlaneHalf_y;
149 
150  // compute distortion corrections in x and y using Legendre Polynomials
151  // these corrections are also in the -1.0 to +1.0 range
152  // if Legendre computations fail, we set undistorted focal plane x and y
153  // to be identical to distorted x and y and return true
154  double deltax, deltay;
155  if (!computeDistortionCorrections(xscaled, yscaled, deltax, deltay)) {
156  return true;
157  }
158 
159  // apply the corrections to original x,y
160  xscaled += deltax;
161  yscaled += deltay;
162 
163  // scale back from range of '-1.0 to +1.0' to the detector, '-32.5 to 32.5 mm'
165  p_undistortedFocalPlaneY = -yscaled * m_focalPlaneHalf_y;
166 
167  return true;
168  }
169 
170 
171 // bool NewHorizonsMvicFrameCameraDistortionMap::SetFocalPlane(const double dx, const double dy) {
172 
173 // p_focalPlaneX = dx;
174 // p_focalPlaneY = dy;
175 
176 // // if x and/or y lie outside of the detector, do NOT apply distortion
177 // // set undistorted focal plane values to be identical to raw values
178 // if ((fabs(dx) > m_focalPlaneHalf_x) || (fabs(dy) > m_focalPlaneHalf_y)) {
179 // p_undistortedFocalPlaneX = dx;
180 // p_undistortedFocalPlaneY = dy;
181 
182 // return true;
183 // }
184 
185 // // scale x and y to lie in the range -1.0 to +1.0
186 // // this is requirement for Legendre Polynomials, man
187 // double xscaled = dx/m_focalPlaneHalf_x;
188 // double yscaled = dy/m_focalPlaneHalf_y;
189 
190 // // compute distortion corrections in x and y using Legendre Polynomials
191 // // these corrections are also in the -1.0 to +1.0 range
192 // double deltax, deltay;
193 // computeDistortionCorrections(xscaled, yscaled, deltax, deltay);
194 
195 // // apply the corrections
196 // xscaled += deltax;
197 // yscaled += deltay;
198 
199 // // scale back from range of '-1.0 to +1.0' to the detector, '-32.656 to 32.656 mm'
200 // p_undistortedFocalPlaneX = xscaled * m_focalPlaneHalf_x;
201 // p_undistortedFocalPlaneY = yscaled * m_focalPlaneHalf_y;
202 
203 // return true;
204 // }
205 
206 
220 
221  // image coordinates prior to introducing distortion
224 
225  double xScaledDistortion, yScaledDistortion;
226 
227  // scale undistorted coordinates to range of -1.0 to +1.0
228  double xtScaled = -ux/m_focalPlaneHalf_x;
229  double ytScaled = -uy/m_focalPlaneHalf_y;
230 
231  double uxScaled = xtScaled;
232  double uyScaled = ytScaled;
233 
234  double xScaledPrevious = 1000000.0;
235  double yScaledPrevious = 1000000.0;
236 
237  double tolerance = 0.000001;
238 
239  bool bConverged = false;
240 
241  // iterating to introduce distortion...
242  // we stop when the difference between distorted coordinates
243  // in successive iterations is at or below the given tolerance
244  for( int i = 0; i < 50; i++ ) {
245 
246  // compute distortion in x and y (scaled to -1.0 - +1.0) using Legendre Polynomials
247  computeDistortionCorrections(xtScaled, ytScaled, xScaledDistortion, yScaledDistortion);
248 
249  // update scaled image coordinates
250  xtScaled = uxScaled - xScaledDistortion;
251  ytScaled = uyScaled - yScaledDistortion;
252 
253  // check for convergence
254  if((fabs(xtScaled - xScaledPrevious) <= tolerance) && (fabs(ytScaled - yScaledPrevious) <= tolerance)) {
255  bConverged = true;
256  break;
257  }
258 
259  xScaledPrevious = xtScaled;
260  yScaledPrevious = ytScaled;
261  }
262 
263  if (bConverged) {
264  // scale coordinates back to detector (-32.5 to +32.5)
265  xtScaled *= -m_focalPlaneHalf_x;
266  ytScaled *= -m_focalPlaneHalf_y;
267 
268  // set distorted coordinates
269  p_focalPlaneX = xtScaled;
270  p_focalPlaneY = ytScaled;
271  }
272 
273  return bConverged;
274  }
275 // bool NewHorizonsMvicFrameCameraDistortionMap::SetUndistortedFocalPlane(const double ux, const double uy) {
276 
277 // // image coordinates prior to introducing distortion
278 // p_undistortedFocalPlaneX = ux;
279 // p_undistortedFocalPlaneY = uy;
280 
281 // double xScaledDistortion, yScaledDistortion;
282 
283 // // scale undistorted coordinates to range of -1.0 to +1.0
284 // double xtScaled = ux/m_focalPlaneHalf_x;
285 // double ytScaled = uy/m_focalPlaneHalf_y;
286 
287 // double uxScaled = xtScaled;
288 // double uyScaled = ytScaled;
289 
290 // double xScaledPrevious = 1000000.0;
291 // double yScaledPrevious = 1000000.0;
292 
293 // double tolerance = 0.000001;
294 
295 // bool bConverged = false;
296 
297 // // iterating to introduce distortion...
298 // // we stop when the difference between distorted coordinates
299 // // in successive iterations is at or below the given tolerance
300 // for( int i = 0; i < 50; i++ ) {
301 
302 // // compute distortion in x and y (scaled to -1.0 - +1.0) using Legendre Polynomials
303 // computeDistortionCorrections(xtScaled, ytScaled, xScaledDistortion, yScaledDistortion);
304 
305 // // update scaled image coordinates
306 // xtScaled = uxScaled - xScaledDistortion;
307 // ytScaled = uyScaled - yScaledDistortion;
308 
309 // // check for convergence
310 // if((fabs(xtScaled - xScaledPrevious) <= tolerance) && (fabs(ytScaled - yScaledPrevious) <= tolerance)) {
311 // bConverged = true;
312 // break;
313 // }
314 
315 // xScaledPrevious = xtScaled;
316 // yScaledPrevious = ytScaled;
317 // }
318 
319 // if (bConverged) {
320 // // scale coordinates back to detector (-32.656 to +32.656)
321 // xtScaled *= m_focalPlaneHalf_x;
322 // ytScaled *= m_focalPlaneHalf_y;
323 
324 // // set distorted coordinates
325 // p_focalPlaneX = xtScaled;
326 // p_focalPlaneY = ytScaled;
327 // }
328 
329 // return bConverged;
330 // }
331 
332 
348  const double yscaled,
349  double &deltax, double &deltay) {
350 
351  double lpx0, lpx1, lpx2, lpx3, lpx4, lpx5;
352  double lpy0, lpy1, lpy2, lpy3, lpy4, lpy5;
353 
354  // Legendre polynomials
355  // boost library method legendre_p will generate an exception if xscaled or yscaled do not lie
356  // between -1 to 1 (inclusive). In this event we return false.
357  try {
358  lpx0 = legendre_p(0,xscaled);
359  lpx1 = legendre_p(1,xscaled);
360  lpx2 = legendre_p(2,xscaled);
361  lpx3 = legendre_p(3,xscaled);
362  lpx4 = legendre_p(4,xscaled);
363  lpx5 = legendre_p(5,xscaled);
364  lpy0 = legendre_p(0,yscaled);
365  lpy1 = legendre_p(1,yscaled);
366  lpy2 = legendre_p(2,yscaled);
367  lpy3 = legendre_p(3,yscaled);
368  lpy4 = legendre_p(4,yscaled);
369  lpy5 = legendre_p(5,yscaled);
370  }
371  // TESTING NOTE: Could not find a way to cause this error. If one is found a test should be added
372  catch (const std::exception& e) {
373  return false;
374  }
375 
376  deltax =
377  m_xDistortionCoeffs[0] * lpx0 * lpy1 +
378  m_xDistortionCoeffs[1] * lpx1 * lpy0 +
379  m_xDistortionCoeffs[2] * lpx0 * lpy2 +
380  m_xDistortionCoeffs[3] * lpx1 * lpy1 +
381  m_xDistortionCoeffs[4] * lpx2 * lpy0 +
382  m_xDistortionCoeffs[5] * lpx0 * lpy3 +
383  m_xDistortionCoeffs[6] * lpx1 * lpy2 +
384  m_xDistortionCoeffs[7] * lpx2 * lpy1 +
385  m_xDistortionCoeffs[8] * lpx3 * lpy0 +
386  m_xDistortionCoeffs[9] * lpx0 * lpy4 +
387  m_xDistortionCoeffs[10] * lpx1 * lpy3 +
388  m_xDistortionCoeffs[11] * lpx2 * lpy2 +
389  m_xDistortionCoeffs[12] * lpx3 * lpy1 +
390  m_xDistortionCoeffs[13] * lpx4 * lpy0 +
391  m_xDistortionCoeffs[14] * lpx0 * lpy5 +
392  m_xDistortionCoeffs[15] * lpx1 * lpy4 +
393  m_xDistortionCoeffs[16] * lpx2 * lpy3 +
394  m_xDistortionCoeffs[17] * lpx3 * lpy2 +
395  m_xDistortionCoeffs[18] * lpx4 * lpy1 +
396  m_xDistortionCoeffs[19] * lpx5 * lpy0;
397 
398  deltay =
399  m_yDistortionCoeffs[0] * lpx0 * lpy1 +
400  m_yDistortionCoeffs[1] * lpx1 * lpy0 +
401  m_yDistortionCoeffs[2] * lpx0 * lpy2 +
402  m_yDistortionCoeffs[3] * lpx1 * lpy1 +
403  m_yDistortionCoeffs[4] * lpx2 * lpy0 +
404  m_yDistortionCoeffs[5] * lpx0 * lpy3 +
405  m_yDistortionCoeffs[6] * lpx1 * lpy2 +
406  m_yDistortionCoeffs[7] * lpx2 * lpy1 +
407  m_yDistortionCoeffs[8] * lpx3 * lpy0 +
408  m_yDistortionCoeffs[9] * lpx0 * lpy4 +
409  m_yDistortionCoeffs[10] * lpx1 * lpy3 +
410  m_yDistortionCoeffs[11] * lpx2 * lpy2 +
411  m_yDistortionCoeffs[12] * lpx3 * lpy1 +
412  m_yDistortionCoeffs[13] * lpx4 * lpy0 +
413  m_yDistortionCoeffs[14] * lpx0 * lpy5 +
414  m_yDistortionCoeffs[15] * lpx1 * lpy4 +
415  m_yDistortionCoeffs[16] * lpx2 * lpy3 +
416  m_yDistortionCoeffs[17] * lpx3 * lpy2 +
417  m_yDistortionCoeffs[18] * lpx4 * lpy1 +
418  m_yDistortionCoeffs[19] * lpx5 * lpy0;
419 
420  return true;
421  }
422 }
double p_focalPlaneX
Distorted focal plane x.
std::vector< double > m_yDistortionCoeffs
by Keith Harrison (Interface Control Document section 10.3.1.2)
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.
Namespace for the standard library.
Unless noted otherwise, the portions of Isis written by the USGS are public domain.
double p_undistortedFocalPlaneX
Undistorted focal plane x.
Camera * p_camera
The camera to distort/undistort.
bool computeDistortionCorrections(const double xscaled, const double yscaled, double &deltax, double &deltay)
Compute distortion corrections in x and y direction.
virtual bool SetFocalPlane(const double dx, const double dy)
Testing method to output corrections in x and y at pixel centers for entire focal plane...
Distort/undistort focal plane coordinates.
double PixelPitch() const
Returns the pixel pitch.
Definition: Camera.cpp:2754
double p_focalPlaneY
Distorted focal plane y.
double p_undistortedFocalPlaneY
Undistorted focal plane y.
std::vector< double > m_xDistortionCoeffs
distortion coefficients in x and y as determined
int Lines() const
Returns the number of lines in the image.
Definition: Camera.cpp:2798
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