Isis 3.0 Programmer Reference
Back | 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 
A small chip of data used for pattern matching.
Definition: Chip.h:101
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 Samples() const
Return the number of samples in the chip.
Definition: Chip.h:114
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:199
Container for cube-like labels.
Definition: Pvl.h:135
int Lines() const
Return the number of lines in the chip.
Definition: Chip.h:121
Forstner interest operator.
double GetValue(int sample, int line)
Loads a Chip with a value.
Definition: Chip.h:158
Fourier Transform class.

U.S. Department of the Interior | U.S. Geological Survey
ISIS | Privacy & Disclaimers | Astrogeology Research Program
To contact us, please post comments and questions on the ISIS Support Center
File Modified: 07/12/2023 23:18:24