USGS

Isis 3.0 Object Programmers' Reference

Home

ForstnerOperator.cpp
1 #include "ForstnerOperator.h"
2 #include "Chip.h"
3 #include "FourierTransform.h"
4 #include "tnt/tnt_array2d.h"
5 #include "jama/jama_lu.h"
6 #include <complex>
7 
8 namespace Isis {
18 
19  int nSamp = ft.NextPowerOfTwo(chip.Samples() - 1);
20  int nLine = ft.NextPowerOfTwo(chip.Lines() - 1);
21 
22  TNT::Array2D< std::complex<double> > Guu(nLine, nSamp);
23  TNT::Array2D< std::complex<double> > Guv(nLine, nSamp);
24  TNT::Array2D< std::complex<double> > Gvv(nLine, nSamp);
25 
26  // calculate the diagonal gradients
27  // (if any of the four pixels are special
28  // the gradients are zeroed out)
29  // and perform the fourier transform in the
30  // line direction on the 3 matrices
31  for(int i = 0; i < Guu.dim1(); i++) {
32  std::vector< std::complex<double> > line1(Guu.dim2());
33  std::vector< std::complex<double> > line2(Guv.dim2());
34  std::vector< std::complex<double> > line3(Gvv.dim2());
35 
36  double gu, gv;
37 
38  for(int j = 0; j < Guu.dim2(); j++) {
39  if(i > chip.Lines() - 2 || j > chip.Samples() - 2 ||
40  IsSpecial(chip.GetValue(j + 1, i + 1)) || IsSpecial(chip.GetValue(j + 1, i + 2)) ||
41  IsSpecial(chip.GetValue(j + 2, i + 1)) || IsSpecial(chip.GetValue(j + 2, i + 2))) {
42  gu = 0.0;
43  gv = 0.0;
44  }
45  else {
46  gu = chip.GetValue(j + 1, i + 1) - chip.GetValue(j + 2, i + 2);
47  gv = chip.GetValue(j + 2, i + 1) - chip.GetValue(j + 1, i + 2);
48  }
49 
50  line1[j] = gu * gu;
51  line2[j] = gu * gv;
52  line3[j] = gv * gv;
53  }
54 
55  std::vector< std::complex<double> > transform1 = ft.Transform(line1);
56  std::vector< std::complex<double> > transform2 = ft.Transform(line2);
57  std::vector< std::complex<double> > transform3 = ft.Transform(line3);
58 
59  //copy the transformed data back into the matrices
60  for(int j = 0; j < Guu.dim2(); j++) {
61  Guu[i][j] = transform1[j];
62  Guv[i][j] = transform2[j];
63  Gvv[i][j] = transform3[j];
64  }
65  }
66 
67  // perform the fourier transform in the
68  // sample direction on the 3 matrices
69  for(int j = 0; j < Guu.dim2(); j++) {
70  std::vector< std::complex<double> > samp1(Guu.dim1());
71  std::vector< std::complex<double> > samp2(Guv.dim1());
72  std::vector< std::complex<double> > samp3(Gvv.dim1());
73 
74  for(int i = 0; i < Guu.dim1(); i++) {
75  samp1[i] = Guu[i][j];
76  samp2[i] = Guv[i][j];
77  samp3[i] = Gvv[i][j];
78  }
79 
80  std::vector< std::complex<double> > transform1 = ft.Transform(samp1);
81  std::vector< std::complex<double> > transform2 = ft.Transform(samp2);
82  std::vector< std::complex<double> > transform3 = ft.Transform(samp3);
83 
84  //copy the transformed data back into the matrices
85  for(int i = 0; i < Guu.dim1(); i++) {
86  Guu[i][j] = transform1[i];
87  Guv[i][j] = transform2[i];
88  Gvv[i][j] = transform3[i];
89  }
90  }
91 
92  // First, multiply the three transformed matrices
93  // Then, compute the 2d inverse of the
94  // transformed data starting with the line direction
95  // For convenience, put it back in Guu
96  for(int i = 0; i < Guu.dim1(); i++) {
97  std::vector< std::complex<double> > line(Guu.dim2());
98 
99  for(int j = 0; j < Guu.dim2(); j++) {
100  line[j] = Guu[i][j] * Guv[i][j] * Gvv[i][j];
101  }
102 
103  std::vector< std::complex<double> > transform = ft.Transform(line);
104 
105  //copy the transformed data back into the matrix
106  for(int j = 0; j < Guu.dim2(); j++) {
107  Guu[i][j] = transform[j];
108  }
109  }
110 
111  // After inverting, the matrix will contain N in the upper right
112  // The trace of N determines the roundness of the chip
113  // and the determinant determines the chip's weight
114  // In this case, we will look only at the weight
115  TNT::Array2D<double> N(chip.Lines() - 1, chip.Samples() - 1);
116 
117  // And then the sample direction
118  for(int j = 0; j < N.dim2(); j++) {
119  std::vector< std::complex<double> > samp(Guu.dim1());
120 
121  for(int i = 0; i < Guu.dim1(); i++) {
122  samp[i] = Guu[i][j];
123  }
124 
125  std::vector< std::complex<double> > transform = ft.Transform(samp);
126 
127  //copy the transformed data back into the matrix
128  for(int i = 0; i < N.dim1(); i++) {
129  N[i][j] = real(transform[i]);
130  }
131  }
132 
133  JAMA::LU<double> lu(N);
134 
135  // use LU decomposition to calculate the determinant
136  return abs(lu.det());
137  }
138 }
139 
140 extern "C" Isis::InterestOperator *ForstnerOperatorPlugin(Isis::Pvl &pvl) {
141  return new Isis::ForstnerOperator(pvl);
142 }
143