OTB  10.0.0
Orfeo Toolbox
otbMaximumAutocorrelationFactorImageFilter.hxx
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2005-2024 Centre National d'Etudes Spatiales (CNES)
3  *
4  * This file is part of Orfeo Toolbox
5  *
6  * https://www.orfeo-toolbox.org/
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  */
20 
21 #ifndef otbMaximumAutocorrelationFactorImageFilter_hxx
22 #define otbMaximumAutocorrelationFactorImageFilter_hxx
23 
26 #include "otbMath.h"
27 #include "itkSubtractImageFilter.h"
28 
29 #include "vnl/algo/vnl_matrix_inverse.h"
30 #include "vnl/algo/vnl_generalized_eigensystem.h"
31 
32 #include "itkChangeInformationImageFilter.h"
33 #include "itkImageRegionIterator.h"
34 #include "itkProgressReporter.h"
35 
36 namespace otb
37 {
38 template <class TInputImage, class TOutputImage>
40 {
41  m_CovarianceEstimator = CovarianceEstimatorType::New();
42  m_CovarianceEstimatorH = CovarianceEstimatorType::New();
43  m_CovarianceEstimatorV = CovarianceEstimatorType::New();
44  this->DynamicMultiThreadingOn();
45 }
46 
47 template <class TInputImage, class TOutputImage>
49 {
50  // Call superclass implementation
51  Superclass::GenerateOutputInformation();
52 
53  // Retrieve input images pointers
54  TInputImage* inputPtr = const_cast<TInputImage*>(this->GetInput());
55  // TOutputImage * outputPtr = this->GetOutput();
56 
57  // TODO: set the number of output components
58  unsigned int nbComp = inputPtr->GetNumberOfComponentsPerPixel();
59 
60  // Compute Dh and Dv
62  typedef itk::SubtractImageFilter<InternalImageType, InternalImageType, InternalImageType> DifferenceFilterType;
63  typedef itk::ChangeInformationImageFilter<InternalImageType> ChangeInformationImageFilter;
64 
65  InputImageRegionType largestInputRegion = inputPtr->GetLargestPossibleRegion();
66  InputImageRegionType referenceRegion;
67  InputImageSizeType size = largestInputRegion.GetSize();
68  size[0] -= 1;
69  size[1] -= 1;
70  referenceRegion.SetSize(size);
71  InputImageIndexType index = largestInputRegion.GetIndex();
72  referenceRegion.SetIndex(index);
73 
74  InputImageRegionType dhRegion;
75  InputImageRegionType dvRegion;
76 
77  index[0] += 1;
78 
79  dhRegion.SetSize(size);
80  dhRegion.SetIndex(index);
81 
82  index[0] -= 1;
83  index[1] += 1;
84 
85  dvRegion.SetSize(size);
86  dvRegion.SetIndex(index);
87 
88  typename ExtractFilterType::Pointer referenceExtract = ExtractFilterType::New();
89  referenceExtract->SetInput(inputPtr);
90  referenceExtract->SetExtractionRegion(referenceRegion);
91 
92  typename ExtractFilterType::Pointer dhExtract = ExtractFilterType::New();
93  dhExtract->SetInput(inputPtr);
94  dhExtract->SetExtractionRegion(dhRegion);
95 
96  typename ChangeInformationImageFilter::Pointer dhExtractShift = ChangeInformationImageFilter::New();
97  dhExtractShift->SetInput(dhExtract->GetOutput());
98  dhExtractShift->SetReferenceImage(referenceExtract->GetOutput());
99  dhExtractShift->SetUseReferenceImage(true);
100  dhExtractShift->SetChangeOrigin(true);
101 
102  typename ExtractFilterType::Pointer dvExtract = ExtractFilterType::New();
103  dvExtract->SetInput(inputPtr);
104  dvExtract->SetExtractionRegion(dvRegion);
105 
106  typename ChangeInformationImageFilter::Pointer dvExtractShift = ChangeInformationImageFilter::New();
107  dvExtractShift->SetInput(dvExtract->GetOutput());
108  dvExtractShift->SetReferenceImage(referenceExtract->GetOutput());
109  dvExtractShift->SetUseReferenceImage(true);
110  dvExtractShift->SetChangeOrigin(true);
111 
112 
113  typename DifferenceFilterType::Pointer diffh = DifferenceFilterType::New();
114  diffh->SetInput1(referenceExtract->GetOutput());
115  diffh->SetInput2(dhExtractShift->GetOutput());
116 
117  typename DifferenceFilterType::Pointer diffv = DifferenceFilterType::New();
118  diffv->SetInput1(referenceExtract->GetOutput());
119  diffv->SetInput2(dvExtractShift->GetOutput());
120 
121  // Compute pooled sigma (using sigmadh and sigmadv)
122  m_CovarianceEstimatorH->SetInput(diffh->GetOutput());
123  m_CovarianceEstimatorH->Update();
124  VnlMatrixType sigmadh = m_CovarianceEstimatorH->GetCovariance().GetVnlMatrix();
125 
126  m_CovarianceEstimatorV->SetInput(diffv->GetOutput());
127  m_CovarianceEstimatorV->Update();
128  VnlMatrixType sigmadv = m_CovarianceEstimatorV->GetCovariance().GetVnlMatrix();
129 
130  // Simple pool
131  VnlMatrixType sigmad = 0.5 * (sigmadh + sigmadv);
132 
133  // Compute the original image covariance
134  referenceExtract->SetExtractionRegion(inputPtr->GetLargestPossibleRegion());
135  m_CovarianceEstimator->SetInput(referenceExtract->GetOutput());
136  m_CovarianceEstimator->Update();
137  VnlMatrixType sigma = m_CovarianceEstimator->GetCovariance().GetVnlMatrix();
138 
139  m_Mean = VnlVectorType(nbComp, 0);
140 
141  for (unsigned int i = 0; i < nbComp; ++i)
142  {
143  m_Mean[i] = m_CovarianceEstimator->GetMean()[i];
144  }
145 
146  vnl_generalized_eigensystem ges(sigmad, sigma);
147  VnlMatrixType d = ges.D.as_matrix();
148  m_V = ges.V;
149 
150  m_AutoCorrelation = VnlVectorType(nbComp, 1.);
151  m_AutoCorrelation -= 0.5 * d.get_diagonal();
152 
153  VnlMatrixType invstderr = VnlMatrixType(nbComp, nbComp, 0);
154  invstderr.set_diagonal(sigma.get_diagonal());
155  invstderr = invstderr.apply(&std::sqrt);
156  invstderr = invstderr.apply(&InverseValue);
157 
158  VnlMatrixType invstderrmaf = VnlMatrixType(nbComp, nbComp, 0);
159  invstderrmaf.set_diagonal((m_V.transpose() * sigma * m_V).get_diagonal());
160  invstderrmaf = invstderrmaf.apply(&std::sqrt);
161  invstderrmaf = invstderrmaf.apply(&InverseValue);
162 
163  VnlMatrixType aux1 = invstderr * sigma * m_V * invstderrmaf;
164 
165  VnlMatrixType sign = VnlMatrixType(nbComp, nbComp, 0);
166 
167  VnlVectorType aux2 = VnlVectorType(nbComp, 0);
168 
169  for (unsigned int i = 0; i < nbComp; ++i)
170  {
171  aux2 = aux2 + aux1.get_row(i);
172  }
173 
174  sign.set_diagonal(aux2);
175  sign = sign.apply(&SignOfValue);
176 
177  // There is no need for scaling since vnl_generalized_eigensystem
178  // already gives unit variance
179  m_V = m_V * sign;
180 }
181 
182 template <class TInputImage, class TOutputImage>
184 {
185  // Retrieve input images pointers
186  const TInputImage* inputPtr = this->GetInput();
187  TOutputImage* outputPtr = this->GetOutput();
188 
189 
190  typedef itk::ImageRegionConstIterator<InputImageType> ConstIteratorType;
191  typedef itk::ImageRegionIterator<OutputImageType> IteratorType;
192 
193  IteratorType outIt(outputPtr, outputRegionForThread);
194  ConstIteratorType inIt(inputPtr, outputRegionForThread);
195 
196  inIt.GoToBegin();
197  outIt.GoToBegin();
198 
199  // Get the number of components for each image
200  unsigned int outNbComp = outputPtr->GetNumberOfComponentsPerPixel();
201 
202  while (!inIt.IsAtEnd() && !outIt.IsAtEnd())
203  {
204  VnlVectorType x(outNbComp, 0);
205  VnlVectorType maf(outNbComp, 0);
206 
207  for (unsigned int i = 0; i < outNbComp; ++i)
208  {
209  x[i] = inIt.Get()[i];
210  }
211 
212  maf = (x - m_Mean) * m_V;
213 
214  typename OutputImageType::PixelType outPixel(outNbComp);
215 
216  for (unsigned int i = 0; i < outNbComp; ++i)
217  {
218  outPixel[i] = maf[i];
219  }
220 
221  outIt.Set(outPixel);
222 
223  ++inIt;
224  ++outIt;
225  }
226 }
227 }
228 
229 #endif
void DynamicThreadedGenerateData(const OutputImageRegionType &outputRegionForThread) override
Extract a spatial or spectral subset of a multi-channel image.
The "otb" namespace contains all Orfeo Toolbox (OTB) classes.
T InverseValue(const T &value)
Definition: otbMath.h:96
T SignOfValue(const T &value)
Definition: otbMath.h:102