Isis 3 Programmer Reference
ForstnerOperator.cpp
1
6/* SPDX-License-Identifier: CC0-1.0 */
7#include "ForstnerOperator.h"
8#include "Chip.h"
9#include "FourierTransform.h"
10#include "tnt/tnt_array2d.h"
11#include "jama/jama_lu.h"
12#include <complex>
13
14namespace Isis {
24
25 int nSamp = ft.NextPowerOfTwo(chip.Samples() - 1);
26 int nLine = ft.NextPowerOfTwo(chip.Lines() - 1);
27
28 TNT::Array2D< std::complex<double> > Guu(nLine, nSamp);
29 TNT::Array2D< std::complex<double> > Guv(nLine, nSamp);
30 TNT::Array2D< std::complex<double> > Gvv(nLine, nSamp);
31
32 // calculate the diagonal gradients
33 // (if any of the four pixels are special
34 // the gradients are zeroed out)
35 // and perform the fourier transform in the
36 // line direction on the 3 matrices
37 for(int i = 0; i < Guu.dim1(); i++) {
38 std::vector< std::complex<double> > line1(Guu.dim2());
39 std::vector< std::complex<double> > line2(Guv.dim2());
40 std::vector< std::complex<double> > line3(Gvv.dim2());
41
42 double gu, gv;
43
44 for(int j = 0; j < Guu.dim2(); j++) {
45 if(i > chip.Lines() - 2 || j > chip.Samples() - 2 ||
46 IsSpecial(chip.GetValue(j + 1, i + 1)) || IsSpecial(chip.GetValue(j + 1, i + 2)) ||
47 IsSpecial(chip.GetValue(j + 2, i + 1)) || IsSpecial(chip.GetValue(j + 2, i + 2))) {
48 gu = 0.0;
49 gv = 0.0;
50 }
51 else {
52 gu = chip.GetValue(j + 1, i + 1) - chip.GetValue(j + 2, i + 2);
53 gv = chip.GetValue(j + 2, i + 1) - chip.GetValue(j + 1, i + 2);
54 }
55
56 line1[j] = gu * gu;
57 line2[j] = gu * gv;
58 line3[j] = gv * gv;
59 }
60
61 std::vector< std::complex<double> > transform1 = ft.Transform(line1);
62 std::vector< std::complex<double> > transform2 = ft.Transform(line2);
63 std::vector< std::complex<double> > transform3 = ft.Transform(line3);
64
65 //copy the transformed data back into the matrices
66 for(int j = 0; j < Guu.dim2(); j++) {
67 Guu[i][j] = transform1[j];
68 Guv[i][j] = transform2[j];
69 Gvv[i][j] = transform3[j];
70 }
71 }
72
73 // perform the fourier transform in the
74 // sample direction on the 3 matrices
75 for(int j = 0; j < Guu.dim2(); j++) {
76 std::vector< std::complex<double> > samp1(Guu.dim1());
77 std::vector< std::complex<double> > samp2(Guv.dim1());
78 std::vector< std::complex<double> > samp3(Gvv.dim1());
79
80 for(int i = 0; i < Guu.dim1(); i++) {
81 samp1[i] = Guu[i][j];
82 samp2[i] = Guv[i][j];
83 samp3[i] = Gvv[i][j];
84 }
85
86 std::vector< std::complex<double> > transform1 = ft.Transform(samp1);
87 std::vector< std::complex<double> > transform2 = ft.Transform(samp2);
88 std::vector< std::complex<double> > transform3 = ft.Transform(samp3);
89
90 //copy the transformed data back into the matrices
91 for(int i = 0; i < Guu.dim1(); i++) {
92 Guu[i][j] = transform1[i];
93 Guv[i][j] = transform2[i];
94 Gvv[i][j] = transform3[i];
95 }
96 }
97
98 // First, multiply the three transformed matrices
99 // Then, compute the 2d inverse of the
100 // transformed data starting with the line direction
101 // For convenience, put it back in Guu
102 for(int i = 0; i < Guu.dim1(); i++) {
103 std::vector< std::complex<double> > line(Guu.dim2());
104
105 for(int j = 0; j < Guu.dim2(); j++) {
106 line[j] = Guu[i][j] * Guv[i][j] * Gvv[i][j];
107 }
108
109 std::vector< std::complex<double> > transform = ft.Transform(line);
110
111 //copy the transformed data back into the matrix
112 for(int j = 0; j < Guu.dim2(); j++) {
113 Guu[i][j] = transform[j];
114 }
115 }
116
117 // After inverting, the matrix will contain N in the upper right
118 // The trace of N determines the roundness of the chip
119 // and the determinant determines the chip's weight
120 // In this case, we will look only at the weight
121 TNT::Array2D<double> N(chip.Lines() - 1, chip.Samples() - 1);
122
123 // And then the sample direction
124 for(int j = 0; j < N.dim2(); j++) {
125 std::vector< std::complex<double> > samp(Guu.dim1());
126
127 for(int i = 0; i < Guu.dim1(); i++) {
128 samp[i] = Guu[i][j];
129 }
130
131 std::vector< std::complex<double> > transform = ft.Transform(samp);
132
133 //copy the transformed data back into the matrix
134 for(int i = 0; i < N.dim1(); i++) {
135 N[i][j] = real(transform[i]);
136 }
137 }
138
139 JAMA::LU<double> lu(N);
140
141 // use LU decomposition to calculate the determinant
142 return abs(lu.det());
143 }
144}
145
146extern "C" Isis::InterestOperator *ForstnerOperatorPlugin(Isis::Pvl &pvl) {
147 return new Isis::ForstnerOperator(pvl);
148}
A small chip of data used for pattern matching.
Definition Chip.h:86
double GetValue(int sample, int line)
Loads a Chip with a value.
Definition Chip.h:145
int Samples() const
Definition Chip.h:99
int Lines() const
Definition Chip.h:106
Forstner interest operator.
virtual double Interest(Chip &chip)
This method returns the amount of interest for the given chip.
Fourier Transform class.
int NextPowerOfTwo(int n)
This function returns the next power of two greater than or equal to n.
Interest Operator class.
Container for cube-like labels.
Definition Pvl.h:119
This is free and unencumbered software released into the public domain.
Definition Apollo.h:16
bool IsSpecial(const double d)
Returns if the input pixel is special.