Isis 3 Programmer Reference
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 }
A small chip of data used for pattern matching.
Definition: Chip.h:102
std::vector< std::complex< double > > Transform(std::vector< std::complex< double > > input)
Applies the Fourier transform on the input data and returns the result.
Interest Operator class.
int NextPowerOfTwo(int n)
This function returns the next power of two greater than or equal to n.
int Lines() const
Definition: Chip.h:122
virtual double Interest(Chip &chip)
This method returns the amount of interest for the given chip.
bool IsSpecial(const double d)
Returns if the input pixel is special.
Definition: SpecialPixel.h:212
Container for cube-like labels.
Definition: Pvl.h:135
int Samples() const
Definition: Chip.h:115
Forstner interest operator.
Namespace for ISIS/Bullet specific routines.
Definition: Apollo.h:31
double GetValue(int sample, int line)
Loads a Chip with a value.
Definition: Chip.h:161
Fourier Transform class.