OTB  10.0.0
Orfeo Toolbox
otbImageToReflectanceImageFilter.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1999-2011 Insight Software Consortium
3  * Copyright (C) 2005-2024 Centre National d'Etudes Spatiales (CNES)
4  *
5  * This file is part of Orfeo Toolbox
6  *
7  * https://www.orfeo-toolbox.org/
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  * http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  */
21 
22 #ifndef otbImageToReflectanceImageFilter_h
23 #define otbImageToReflectanceImageFilter_h
24 
27 
28 namespace otb
29 {
30 namespace Functor
31 {
45 template <class TInput, class TOutput>
47 {
48 public:
50  {
51  }
53  {
54  }
55 
58 
59  void SetAlpha(double alpha)
60  {
62  }
63  void SetBeta(double beta)
64  {
66  }
67  void SetSolarIllumination(double solarIllumination)
68  {
69  m_LumToReflecFunctor.SetSolarIllumination(solarIllumination);
70  }
72  {
74  }
75  void SetUseClamp(bool useClamp)
76  {
78  }
79 
80  double GetAlpha()
81  {
82  return m_ImToLumFunctor.GetAlpha();
83  }
84  double GetBeta()
85  {
86  return m_ImToLumFunctor.GetBeta();
87  }
89  {
91  }
93  {
95  }
96  bool GetUseClamp()
97  {
99  }
100 
101  inline TOutput operator()(const TInput& inPixel) const
102  {
103  TOutput outPixel;
104  TOutput tempPix;
105  tempPix = m_ImToLumFunctor(inPixel);
106  outPixel = m_LumToReflecFunctor(tempPix);
107 
108  return outPixel;
109  }
110 
111 private:
114 };
115 }
116 
137 template <class TInputImage, class TOutputImage>
140  TInputImage, TOutputImage,
141  typename Functor::ImageToReflectanceImageFunctor<typename TInputImage::InternalPixelType, typename TOutputImage::InternalPixelType>>
142 {
143 public:
145  itkStaticConstMacro(InputImageDimension, unsigned int, TInputImage::ImageDimension);
146  itkStaticConstMacro(OutputImageDimension, unsigned int, TOutputImage::ImageDimension);
148 
150  typedef TInputImage InputImageType;
151  typedef TOutputImage OutputImageType;
153 
157  typedef itk::SmartPointer<Self> Pointer;
158  typedef itk::SmartPointer<const Self> ConstPointer;
159 
161  itkNewMacro(Self);
162 
164  itkTypeMacro(ImageToReflectanceImageFilter, UnaryImageFunctorWithVectorImageFiltermageFilter);
165 
167  typedef typename InputImageType::PixelType InputPixelType;
168  typedef typename InputImageType::InternalPixelType InputInternalPixelType;
169  typedef typename InputImageType::RegionType InputImageRegionType;
170  typedef typename OutputImageType::PixelType OutputPixelType;
171  typedef typename OutputImageType::InternalPixelType OutputInternalPixelType;
172  typedef typename OutputImageType::RegionType OutputImageRegionType;
173 
174  typedef typename itk::VariableLengthVector<double> VectorType;
175 
177  typedef typename InputImageType::SizeType SizeType;
178 
180  itkSetMacro(Alpha, VectorType);
181 
183  itkGetConstReferenceMacro(Alpha, VectorType);
184 
186  itkSetMacro(Beta, VectorType);
187 
189  itkGetConstReferenceMacro(Beta, VectorType);
190 
192  itkSetMacro(SolarIllumination, VectorType);
193 
195  itkGetConstReferenceMacro(SolarIllumination, VectorType);
196 
198  itkSetMacro(ZenithalSolarAngle, double);
199 
201  itkGetConstReferenceMacro(ZenithalSolarAngle, double);
202 
204  itkSetMacro(UseClamp, bool);
205 
207  itkGetConstReferenceMacro(UseClamp, bool);
208 
210  virtual void SetElevationSolarAngle(double elevationAngle)
211  {
212  double zenithalAngle = 90.0 - elevationAngle;
213  if (this->m_ZenithalSolarAngle != zenithalAngle)
214  {
215  this->m_ZenithalSolarAngle = zenithalAngle;
216  this->Modified();
217  }
218  }
220 
221  virtual double GetElevationSolarAngle() const
222  {
223  return 90.0 - this->m_ZenithalSolarAngle;
224  }
225 
228  {
229  m_FluxNormalizationCoefficient = coef;
230  m_IsSetFluxNormalizationCoefficient = true;
231  this->Modified();
232  }
234 
236  void SetSolarDistance(double value)
237  {
238  m_SolarDistance = value;
239  m_IsSetSolarDistance = true;
240  this->Modified();
241  }
242 
244  itkGetConstReferenceMacro(SolarDistance, double);
245 
247  itkSetMacro(IsSetSolarDistance, bool);
248 
250  itkGetConstReferenceMacro(IsSetSolarDistance, bool);
251 
253  itkSetClampMacro(Day, int, 1, 31);
254 
256  itkGetConstReferenceMacro(Day, int);
257 
259  itkSetClampMacro(Month, int, 1, 12);
260 
262  itkGetConstReferenceMacro(Month, int);
263 
264 protected:
267  : m_ZenithalSolarAngle(120.), // invalid value which will lead to negative radiometry
268  m_FluxNormalizationCoefficient(1.),
269  m_UseClamp(true),
270  m_IsSetFluxNormalizationCoefficient(false),
271  m_Day(0),
272  m_Month(0),
273  m_SolarDistance(1.0),
274  m_IsSetSolarDistance(false)
275  {
276  m_Alpha.SetSize(0);
277  m_Beta.SetSize(0);
278  m_SolarIllumination.SetSize(0);
279  };
281 
284  {
285  }
286 
288  void BeforeThreadedGenerateData(void) override
289  {
290  const auto & metadata = this->GetInput()->GetImageMetadata();
291 
292  if (m_Alpha.GetSize() == 0 && metadata.HasBandMetadata(MDNum::PhysicalGain))
293  {
294  m_Alpha = metadata.GetAsVector(MDNum::PhysicalGain);
295  }
296 
297  if (m_Beta.GetSize() == 0 && metadata.HasBandMetadata(MDNum::PhysicalBias))
298  {
299  m_Beta = metadata.GetAsVector(MDNum::PhysicalBias);
300  }
301 
302  if (m_Day == 0 && (!m_IsSetFluxNormalizationCoefficient) && (!m_IsSetSolarDistance)
303  && metadata.Has(MDTime::AcquisitionDate))
304  {
305  m_Day = metadata[MDTime::AcquisitionDate].GetDay();
306  }
307 
308  if (m_Month == 0 && (!m_IsSetFluxNormalizationCoefficient) && (!m_IsSetSolarDistance)
309  && metadata.Has(MDTime::AcquisitionDate))
310  {
311  m_Month = metadata[MDTime::AcquisitionDate].GetMonth();
312  }
313 
314  if (m_SolarIllumination.GetSize() == 0 && metadata.HasBandMetadata(MDNum::SolarIrradiance))
315  {
316  m_SolarIllumination = metadata.GetAsVector(MDNum::SolarIrradiance);
317  }
318 
319  if (m_ZenithalSolarAngle == 120.0 && metadata.Has(MDNum::SunElevation))
320  {
321  // the zenithal angle is the complementary of the elevation angle
322  m_ZenithalSolarAngle = 90.0 - metadata[MDNum::SunElevation];
323  }
324 
325  otbMsgDevMacro(<< "Using correction parameters: ");
326  otbMsgDevMacro(<< "Alpha (gain): " << m_Alpha);
327  otbMsgDevMacro(<< "Beta (bias): " << m_Beta);
328  otbMsgDevMacro(<< "Day: " << m_Day);
329  otbMsgDevMacro(<< "Month: " << m_Month);
330  otbMsgDevMacro(<< "Solar irradiance: " << m_SolarIllumination);
331  otbMsgDevMacro(<< "Zenithal angle: " << m_ZenithalSolarAngle);
332 
333  if ((m_Alpha.GetSize() != this->GetInput()->GetNumberOfComponentsPerPixel()) || (m_Beta.GetSize() != this->GetInput()->GetNumberOfComponentsPerPixel()) ||
334  (m_SolarIllumination.GetSize() != this->GetInput()->GetNumberOfComponentsPerPixel()))
335  {
336  itkExceptionMacro(<< "Alpha, Beta and SolarIllumination parameters should have the same size as the number of bands");
337  }
338 
339  this->GetFunctorVector().clear();
340  for (unsigned int i = 0; i < this->GetInput()->GetNumberOfComponentsPerPixel(); ++i)
341  {
342  FunctorType functor;
343  double coefTemp = 0.;
344 
345  if (m_IsSetFluxNormalizationCoefficient)
346  {
347  coefTemp = std::cos(m_ZenithalSolarAngle * CONST_PI_180) * m_FluxNormalizationCoefficient * m_FluxNormalizationCoefficient;
348  }
349  else if (m_IsSetSolarDistance)
350  {
351  coefTemp = std::cos(m_ZenithalSolarAngle * CONST_PI_180) / (m_SolarDistance * m_SolarDistance);
352  }
353  else if (m_Day * m_Month != 0 && m_Day < 32 && m_Month < 13)
354  {
355  coefTemp = std::cos(m_ZenithalSolarAngle * CONST_PI_180) * VarSol::GetVarSol(m_Day, m_Month);
356  }
357  else
358  {
359  itkExceptionMacro(<< "Day has to be included between 1 and 31, Month between 1 and 12.");
360  }
361 
362  functor.SetIlluminationCorrectionCoefficient(1. / coefTemp);
363  functor.SetAlpha(m_Alpha[i]);
364  functor.SetBeta(m_Beta[i]);
365  functor.SetSolarIllumination(m_SolarIllumination[i]);
366  functor.SetUseClamp(m_UseClamp);
367  this->GetFunctorVector().push_back(functor);
368  }
369  }
370 
371 private:
375 
378 
381 
384 
387 
391 
393  int m_Day;
394 
396  int m_Month;
397 
400 
404 };
405 
406 } // end namespace otb
407 
408 #endif
Add beta to the quotient Input over alpha.
Call the ImageToRadianceFunctor over the input and the RadianceToReflectanceFunctor to this result.
Functor::ImageToRadianceImageFunctor< TInput, TOutput > ImToLumFunctorType
Functor::RadianceToReflectanceImageFunctor< TInput, TOutput > LumToReflecFunctorType
Convert a raw value into a reflectance value.
UnaryImageFunctorWithVectorImageFilter< InputImageType, OutputImageType, FunctorType > Superclass
Functor::ImageToReflectanceImageFunctor< typename InputImageType::InternalPixelType, typename OutputImageType::InternalPixelType > FunctorType
itk::VariableLengthVector< double > VectorType
OutputImageType::InternalPixelType OutputInternalPixelType
virtual void SetElevationSolarAngle(double elevationAngle)
InputImageType::InternalPixelType InputInternalPixelType
static double GetVarSol(const int day, const int month)
Definition: otbVarSol.h:47
The "otb" namespace contains all Orfeo Toolbox (OTB) classes.
constexpr double CONST_PI_180
Definition: otbMath.h:56
#define otbMsgDevMacro(x)
Definition: otbMacro.h:116