OTB  10.0.0
Orfeo Toolbox
otbGammaMAPImageFilter.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 otbGammaMAPImageFilter_hxx
22 #define otbGammaMAPImageFilter_hxx
23 
24 #include "otbGammaMAPImageFilter.h"
25 
26 #include "itkDataObject.h"
27 #include "itkConstNeighborhoodIterator.h"
28 #include "itkNeighborhoodInnerProduct.h"
29 #include "itkImageRegionIterator.h"
30 #include "itkNeighborhoodAlgorithm.h"
31 #include "itkOffset.h"
32 
33 
34 namespace otb
35 {
36 
40 template <class TInputImage, class TOutputImage>
42 {
43  m_Radius.Fill(1);
44  SetNbLooks(1.0);
45  this->DynamicMultiThreadingOn();
46 }
48 
49 template <class TInputImage, class TOutputImage>
51 {
52  // call the superclass' implementation of this method
53  Superclass::GenerateInputRequestedRegion();
54 
55  // get pointers to the input and output
56  typename Superclass::InputImagePointer inputPtr = const_cast<TInputImage*>(this->GetInput());
57  typename Superclass::OutputImagePointer outputPtr = this->GetOutput();
58 
59  if (!inputPtr || !outputPtr)
60  {
61  return;
62  }
63 
64  // get a copy of the input requested region (should equal the output
65  // requested region)
66  typename TInputImage::RegionType inputRequestedRegion;
67  inputRequestedRegion = inputPtr->GetRequestedRegion();
68 
69  // pad the input requested region by the operator radius
70  inputRequestedRegion.PadByRadius(m_Radius);
71 
72  // crop the input requested region at the input's largest possible region
73  if (inputRequestedRegion.Crop(inputPtr->GetLargestPossibleRegion()))
74  {
75  inputPtr->SetRequestedRegion(inputRequestedRegion);
76  return;
77  }
78  else
79  {
80  // Couldn't crop the region (requested region is outside the largest
81  // possible region). Throw an exception.
82 
83  // store what we tried to request (prior to trying to crop)
84  inputPtr->SetRequestedRegion(inputRequestedRegion);
85 
86  // build an exception
87  itk::InvalidRequestedRegionError e(__FILE__, __LINE__);
88  std::ostringstream msg;
89  msg << static_cast<const char*>(this->GetNameOfClass()) << "::GenerateInputRequestedRegion()";
90  e.SetLocation(msg.str());
91  e.SetDescription("Requested region is (at least partially) outside the largest possible region.");
92  e.SetDataObject(inputPtr);
93  throw e;
94  }
95 }
96 
97 template <class TInputImage, class TOutputImage>
99 {
100  unsigned int i;
101  itk::ZeroFluxNeumannBoundaryCondition<InputImageType> nbc;
102 
103  itk::ConstNeighborhoodIterator<InputImageType> bit;
104  itk::ImageRegionIterator<OutputImageType> it;
105 
106  typename OutputImageType::Pointer output = this->GetOutput();
107  typename InputImageType::ConstPointer input = this->GetInput();
108 
109  // Find the data-set boundary "faces"
110  typename itk::NeighborhoodAlgorithm::ImageBoundaryFacesCalculator<InputImageType>::FaceListType faceList;
111  typename itk::NeighborhoodAlgorithm::ImageBoundaryFacesCalculator<InputImageType>::FaceListType::iterator fit;
112 
113  itk::NeighborhoodAlgorithm::ImageBoundaryFacesCalculator<InputImageType> bC;
114  faceList = bC(input, outputRegionForThread, m_Radius);
115 
116  // InputRealType pixel;
117  InputRealType sum;
118  InputRealType sum2;
119 
120  double Ci, Ci2, Cu, Cu2, E_I, I, Var_I, dPixel, alpha, b, d, Cmax;
121 
122  // Compute the ratio using the number of looks
123  Cu2 = 1.0 / m_NbLooks;
124  Cu = std::sqrt(Cu2);
125 
126  // Process each of the boundary faces. These are N-d regions which border
127  // the edge of the buffer.
128  for (fit = faceList.begin(); fit != faceList.end(); ++fit)
129  {
130  bit = itk::ConstNeighborhoodIterator<InputImageType>(m_Radius, input, *fit);
131  const unsigned int neighborhoodSize = bit.Size();
132  it = itk::ImageRegionIterator<OutputImageType>(output, *fit);
133  bit.OverrideBoundaryCondition(&nbc);
134 
135  bit.GoToBegin();
136  it.GoToBegin();
137 
138 
139  while (!bit.IsAtEnd())
140  {
141  sum = itk::NumericTraits<InputRealType>::Zero;
142  sum2 = itk::NumericTraits<InputRealType>::Zero;
143 
144  // Parcours du voisinage
145  for (i = 0; i < neighborhoodSize; ++i)
146  {
147  dPixel = static_cast<double>(bit.GetPixel(i));
148  sum += dPixel;
149  }
150  E_I = sum / static_cast<double>(neighborhoodSize);
151 
152  for (i = 0; i < neighborhoodSize; ++i)
153  {
154  dPixel = static_cast<double>(bit.GetPixel(i));
155  sum2 += (dPixel - E_I) * (dPixel - E_I);
156  }
157  Var_I = sum2 / static_cast<double>(neighborhoodSize - 1);
158 
159  I = static_cast<double>(bit.GetCenterPixel());
160 
161  Ci2 = Var_I / (E_I * E_I);
162  Ci = std::sqrt(Ci2);
163 
164  const double epsilon = 0.0000000001;
165  if (std::abs(E_I) < epsilon)
166  {
167  dPixel = itk::NumericTraits<OutputPixelType>::Zero;
168  }
169  else if (std::abs(Var_I) < epsilon)
170  {
171  dPixel = E_I;
172  }
173  else if (Ci2 < Cu2)
174  {
175  dPixel = E_I;
176  }
177  else
178  {
179  Cmax = std::sqrt(2.0) * Cu;
180 
181  if (Ci < Cmax)
182  {
183  alpha = (1 + Cu2) / (Ci2 - Cu2);
184  b = alpha - m_NbLooks - 1;
185  d = E_I * E_I * b * b + 4 * alpha * m_NbLooks * E_I * I;
186  dPixel = (b * E_I + std::sqrt(d)) / (2 * alpha);
187  }
188  else
189  dPixel = I;
190  }
191 
192  // set the weighted value
193  it.Set(static_cast<OutputPixelType>(dPixel));
194 
195  ++bit;
196  ++it;
197  }
198  }
199 }
200 
204 template <class TInputImage, class TOutput>
205 void GammaMAPImageFilter<TInputImage, TOutput>::PrintSelf(std::ostream& os, itk::Indent indent) const
206 {
207  Superclass::PrintSelf(os, indent);
208  os << indent << "Radius: " << m_Radius << std::endl;
209 }
211 
212 } // end namespace otb
213 
214 #endif
void GenerateInputRequestedRegion() override
OutputImageType::PixelType OutputPixelType
OutputImageType::RegionType OutputImageRegionType
void DynamicThreadedGenerateData(const OutputImageRegionType &outputRegionForThread) override
void PrintSelf(std::ostream &os, itk::Indent indent) const override
itk::NumericTraits< InputPixelType >::RealType InputRealType
The "otb" namespace contains all Orfeo Toolbox (OTB) classes.