OTB  10.0.0
Orfeo Toolbox
otbVegetationIndicesFunctor.h
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 otbVegetationIndicesFunctor_h
22 #define otbVegetationIndicesFunctor_h
23 
24 #include "otbMath.h"
25 #include "otbRadiometricIndex.h"
26 
27 namespace otb
28 {
29 
30 namespace Functor
31 {
42 template <class TInput, class TOutput>
43 class NDVI : public RadiometricIndex<TInput, TOutput>
44 {
45 public:
46  NDVI() : RadiometricIndex<TInput, TOutput>({CommonBandNames::RED, CommonBandNames::NIR})
47  {
48  }
49 
50  TOutput operator()(const itk::VariableLengthVector<TInput>& input) const override
51  {
52  auto red = this->Value(CommonBandNames::RED, input);
53  auto nir = this->Value(CommonBandNames::NIR, input);
54 
55  return static_cast<TOutput>(Compute(red, nir));
56  }
57 
58  // This static compute will be used in indices derived from NDVI
59  static double Compute(const double& red, const double& nir)
60  {
61  if (std::abs(nir + red) < RadiometricIndex<TInput, TOutput>::Epsilon)
62  {
63  return 0.;
64  }
65 
66  return (nir - red) / (nir + red);
67  }
68 };
69 
80 template <class TInput, class TOutput>
81 class RVI : public RadiometricIndex<TInput, TOutput>
82 {
83 public:
84  RVI() : RadiometricIndex<TInput, TOutput>({CommonBandNames::RED, CommonBandNames::NIR})
85  {
86  }
87 
88  TOutput operator()(const itk::VariableLengthVector<TInput>& input) const override
89  {
90  auto red = this->Value(CommonBandNames::RED, input);
91  auto nir = this->Value(CommonBandNames::NIR, input);
92 
94  {
95  return static_cast<TOutput>(0.);
96  }
97  return (static_cast<TOutput>(nir / red));
98  }
99 };
100 
115 template <class TInput, class TOutput>
116 class PVI : public RadiometricIndex<TInput, TOutput>
117 {
118 public:
119  PVI() : RadiometricIndex<TInput, TOutput>({CommonBandNames::RED, CommonBandNames::NIR})
120  {
121  }
122 
123  TOutput operator()(const itk::VariableLengthVector<TInput>& input) const override
124  {
125  auto red = this->Value(CommonBandNames::RED, input);
126  auto nir = this->Value(CommonBandNames::NIR, input);
127 
128  return (static_cast<TOutput>((nir - A * red - B) * C));
129  }
130 
132  static constexpr double A = 0.90893;
133  static constexpr double B = 7.46216;
134  static constexpr double C = 9.74;
135 };
136 
147 template <class TInput, class TOutput>
148 class SAVI : public RadiometricIndex<TInput, TOutput>
149 {
150 public:
151  SAVI() : RadiometricIndex<TInput, TOutput>({CommonBandNames::RED, CommonBandNames::NIR})
152  {
153  }
154 
155  TOutput operator()(const itk::VariableLengthVector<TInput>& input) const override
156  {
157  auto red = this->Value(CommonBandNames::RED, input);
158  auto nir = this->Value(CommonBandNames::NIR, input);
159 
160  if (std::abs(nir + red + L) < RadiometricIndex<TInput, TOutput>::Epsilon)
161  {
162  return static_cast<TOutput>(0.);
163  }
164  return (static_cast<TOutput>(((nir - red) * (1 + L)) / (nir + red + L)));
165  }
166 
168  static constexpr double L = 0.5;
169 };
170 
181 template <class TInput, class TOutput>
182 class TSAVI : public RadiometricIndex<TInput, TOutput>
183 {
184 public:
185  TSAVI() : RadiometricIndex<TInput, TOutput>({CommonBandNames::RED, CommonBandNames::NIR})
186  {
187  }
188 
189  TOutput operator()(const itk::VariableLengthVector<TInput>& input) const override
190  {
191  auto red = this->Value(CommonBandNames::RED, input);
192  auto nir = this->Value(CommonBandNames::NIR, input);
193 
194  double denominator = A * nir + red + X * (1. + A * A);
195 
196  if (std::abs(denominator) < RadiometricIndex<TInput, TOutput>::Epsilon)
197  {
198  return static_cast<TOutput>(0.);
199  }
200  return (static_cast<TOutput>((A * (nir - A * red - S)) / denominator));
201  }
202 
204  static constexpr double A = 0.7;
205  static constexpr double S = 0.9;
206 
208  static constexpr double X = 0.08;
209 };
210 
221 template <class TInput, class TOutput>
222 class WDVI : public RadiometricIndex<TInput, TOutput>
223 {
224 public:
226  WDVI() : RadiometricIndex<TInput, TOutput>({CommonBandNames::RED, CommonBandNames::NIR})
227  {
228  }
229 
230  TOutput operator()(const itk::VariableLengthVector<TInput>& input) const override
231  {
232  auto red = this->Value(CommonBandNames::RED, input);
233  auto nir = this->Value(CommonBandNames::NIR, input);
234 
235  return static_cast<TOutput>(Compute(red, nir));
236  }
237 
238  static double Compute(const double& red, const double& nir)
239  {
240  return (nir - S * red);
241  }
242 
244  static constexpr double S = 0.4;
245 };
246 
258 template <class TInput, class TOutput>
259 class MSAVI : public RadiometricIndex<TInput, TOutput>
260 {
261 public:
262  MSAVI() : RadiometricIndex<TInput, TOutput>({CommonBandNames::RED, CommonBandNames::NIR})
263  {
264  }
265 
266  TOutput operator()(const itk::VariableLengthVector<TInput>& input) const override
267  {
268  auto red = this->Value(CommonBandNames::RED, input);
269  auto nir = this->Value(CommonBandNames::NIR, input);
270 
271  double ndvi = NDVI<TInput, TOutput>::Compute(red, nir);
272  double wdvi = WDVI<TInput, TOutput>::Compute(red, nir);
273 
274  double L = 1 - 2 * S * ndvi * wdvi;
275 
276  double denominator = nir + red + L;
277 
278  if (std::abs(denominator) < RadiometricIndex<TInput, TOutput>::Epsilon)
279  {
280  return static_cast<TOutput>(0.);
281  }
282 
283  return (static_cast<TOutput>(((nir - red) * (1 + L)) / denominator));
284  }
285 
286 private:
288  static constexpr double S = 0.4;
289 };
290 
301 template <class TInput, class TOutput>
302 class MSAVI2 : public RadiometricIndex<TInput, TOutput>
303 {
304 public:
305  MSAVI2() : RadiometricIndex<TInput, TOutput>({CommonBandNames::RED, CommonBandNames::NIR})
306  {
307  }
308 
309  TOutput operator()(const itk::VariableLengthVector<TInput>& input) const override
310  {
311  auto red = this->Value(CommonBandNames::RED, input);
312  auto nir = this->Value(CommonBandNames::NIR, input);
313 
314  double sqrt_value = (2 * nir + 1) * (2 * nir + 1) - 8 * (nir - red);
315  if (sqrt_value < 0.)
316  {
317  return static_cast<TOutput>(0.);
318  }
319  return (static_cast<TOutput>((2 * nir + 1 - std::sqrt(sqrt_value)) / 2.));
320  }
321 };
322 
333 template <class TInput, class TOutput>
334 class GEMI : public RadiometricIndex<TInput, TOutput>
335 {
336 public:
337  GEMI() : RadiometricIndex<TInput, TOutput>({CommonBandNames::RED, CommonBandNames::NIR})
338  {
339  }
340 
341  TOutput operator()(const itk::VariableLengthVector<TInput>& input) const override
342  {
343  auto red = this->Value(CommonBandNames::RED, input);
344  auto nir = this->Value(CommonBandNames::NIR, input);
345 
346  double nu;
347  double num_nu;
348  double denom_nu = nir + red + 0.5;
349 
350  if (std::abs(denom_nu) < RadiometricIndex<TInput, TOutput>::Epsilon)
351  {
352  nu = 0;
353  }
354  else
355  {
356  num_nu = 2 * (nir * nir - red * red) + 1.5 * nir + 0.5 * red;
357  nu = num_nu / denom_nu;
358  }
359 
360  double denom_GEMI = 1 - red;
361  if (std::abs(denom_GEMI) < RadiometricIndex<TInput, TOutput>::Epsilon)
362  {
363  return static_cast<TOutput>(0.);
364  }
365  return (static_cast<TOutput>((nu * (1 - 0.25 * nu) - (red - 0.125)) / denom_GEMI));
366  }
367 };
368 
381 template <class TInput, class TOutput>
382 class AVI : public RadiometricIndex<TInput, TOutput>
383 {
384 public:
385  AVI() : RadiometricIndex<TInput, TOutput>({CommonBandNames::GREEN, CommonBandNames::RED, CommonBandNames::NIR})
386  {
387  }
388 
389  TOutput operator()(const itk::VariableLengthVector<TInput>& input) const override
390  {
391  auto green = this->Value(CommonBandNames::GREEN, input);
392  auto red = this->Value(CommonBandNames::RED, input);
393  auto nir = this->Value(CommonBandNames::NIR, input);
394 
395  constexpr double dfact1 = (LambdaNir - LambdaR) / LambdaR;
396  constexpr double dfact2 = (LambdaR - LambdaG) / LambdaR;
397  double dterm1;
398  double dterm2;
399  if (std::abs(nir - red) < RadiometricIndex<TInput, TOutput>::Epsilon)
400  {
401  dterm1 = 0;
402  }
403  else
404  {
405  dterm1 = std::atan(dfact1 / (nir - red));
406  }
407 
408  if (std::abs(green - red) < RadiometricIndex<TInput, TOutput>::Epsilon)
409  {
410  dterm2 = 0;
411  }
412  else
413  {
414  dterm2 = std::atan(dfact2 / (green - red));
415  }
416 
417  return static_cast<TOutput>(dterm1 + dterm2);
418  }
419 
421  static constexpr double LambdaG = 560;
422 
424  static constexpr double LambdaR = 660;
425 
427  static constexpr double LambdaNir = 830;
428 };
429 
442 template <class TInput, class TOutput>
443 class ARVI : public RadiometricIndex<TInput, TOutput>
444 {
445 public:
446  ARVI() : RadiometricIndex<TInput, TOutput>({CommonBandNames::BLUE, CommonBandNames::RED, CommonBandNames::NIR})
447  {
448  }
449 
450  TOutput operator()(const itk::VariableLengthVector<TInput>& input) const override
451  {
452  auto blue = this->Value(CommonBandNames::BLUE, input);
453  auto red = this->Value(CommonBandNames::RED, input);
454  auto nir = this->Value(CommonBandNames::NIR, input);
455 
456  double RHOrb = red - Gamma * (blue - red);
457  double denominator = nir + RHOrb;
458  if (std::abs(denominator) < RadiometricIndex<TInput, TOutput>::Epsilon)
459  {
460  return static_cast<TOutput>(0.);
461  }
462  return (static_cast<TOutput>((nir - RHOrb) / denominator));
463  }
464 
466  static constexpr double Gamma = 0.5;
467 };
468 
481 template <class TInput, class TOutput>
482 class EVI : public RadiometricIndex<TInput, TOutput>
483 {
484 public:
485  EVI() : RadiometricIndex<TInput, TOutput>({CommonBandNames::BLUE, CommonBandNames::RED, CommonBandNames::NIR})
486  {
487  }
488 
489  TOutput operator()(const itk::VariableLengthVector<TInput>& input) const override
490  {
491  auto blue = this->Value(CommonBandNames::BLUE, input);
492  auto red = this->Value(CommonBandNames::RED, input);
493  auto nir = this->Value(CommonBandNames::NIR, input);
494 
495  double denominator = nir + C1 * red - C2 * blue + L;
496  if (std::abs(denominator) < RadiometricIndex<TInput, TOutput>::Epsilon)
497  {
498  return (static_cast<TOutput>(0.));
499  }
500  return (static_cast<TOutput>(G * (nir - red) / denominator));
501  }
502 
504  static constexpr double G = 2.5;
505 
507  static constexpr double C1 = 6.0;
508 
510  static constexpr double C2 = 7.5;
511 
513  static constexpr double L = 1.0;
514 };
515 
526 template <class TInput, class TOutput>
527 class IPVI : public RadiometricIndex<TInput, TOutput>
528 {
529 public:
530  IPVI() : RadiometricIndex<TInput, TOutput>({CommonBandNames::RED, CommonBandNames::NIR})
531  {
532  }
533 
534  TOutput operator()(const itk::VariableLengthVector<TInput>& input) const override
535  {
536  auto red = this->Value(CommonBandNames::RED, input);
537  auto nir = this->Value(CommonBandNames::NIR, input);
538 
539  if (std::abs(nir + red) < RadiometricIndex<TInput, TOutput>::Epsilon)
540  {
541  return static_cast<TOutput>(0.);
542  }
543  else
544  {
545  return (static_cast<TOutput>(nir / (nir + red)));
546  }
547  }
548 };
549 
560 template <class TInput, class TOutput>
561 class TNDVI : public RadiometricIndex<TInput, TOutput>
562 {
563 public:
564  TNDVI() : RadiometricIndex<TInput, TOutput>({CommonBandNames::RED, CommonBandNames::NIR})
565  {
566  }
567 
568  TOutput operator()(const itk::VariableLengthVector<TInput>& input) const override
569  {
570  auto red = this->Value(CommonBandNames::RED, input);
571  auto nir = this->Value(CommonBandNames::NIR, input);
572 
573  double val = NDVI<TInput, TOutput>::Compute(red, nir) + 0.5;
574 
575  if (val < 0)
576  {
577  return (static_cast<TOutput>(0));
578  }
579  else
580  {
581  return (static_cast<TOutput>(std::sqrt(val)));
582  }
583  }
584 };
585 
602 template <class TInput, class TOutput>
603 class LAIFromNDVILogarithmic : public RadiometricIndex<TInput, TOutput>
604 {
605 public:
607  : RadiometricIndex<TInput, TOutput>({CommonBandNames::RED, CommonBandNames::NIR}), m_NdviSoil(0.1), m_NdviInf(0.89), m_ExtinctionCoefficient(0.71)
608  {
609  }
610 
611  void SetNdviSoil(const double& val)
612  {
613  m_NdviSoil = val;
614  }
615 
616  const double& GetNdviSoil() const
617  {
618  return m_NdviSoil;
619  }
620 
621  void SetNdviInf(const double& val)
622  {
623  m_NdviInf = val;
624  }
625 
626  const double& GetNdviInf() const
627  {
628  return m_NdviInf;
629  }
630 
631  void SetExtinctionCoefficient(const double& val)
632  {
634  }
635 
636  const double& GetExtionctionCoefficient() const
637  {
639  }
640 
641  TOutput operator()(const itk::VariableLengthVector<TInput>& input) const override
642  {
643  auto red = this->Value(CommonBandNames::RED, input);
644  auto nir = this->Value(CommonBandNames::NIR, input);
645 
646  double val = NDVI<TInput, TOutput>::Compute(red, nir);
647 
648  if (val < 0)
649  {
650  return (static_cast<TOutput>(0));
651  }
652  else
653  {
654  return static_cast<TOutput>(-(1.0 / m_ExtinctionCoefficient) * std::log((val - m_NdviInf) / (m_NdviSoil - m_NdviInf)));
655  }
656  }
657 
658  double m_NdviSoil;
659  double m_NdviInf;
661 };
662 
663 
681 template <class TInput, class TOutput>
682 class LAIFromReflectancesLinear : public RadiometricIndex<TInput, TOutput>
683 {
684 public:
685  LAIFromReflectancesLinear() : RadiometricIndex<TInput, TOutput>({CommonBandNames::RED, CommonBandNames::NIR}), m_RedCoef(-17.91), m_NirCoef(12.26)
686  {
687  }
688 
689  void SetRedCoef(const double& val)
690  {
691  m_RedCoef = val;
692  }
693 
694  const double& GetRedCoef() const
695  {
696  return m_RedCoef;
697  }
698 
699  void SetNirCoef(const double& val)
700  {
701  m_NirCoef = val;
702  }
703 
704  const double& GetNirCoef() const
705  {
706  return m_NirCoef;
707  }
708 
709  TOutput operator()(const itk::VariableLengthVector<TInput>& input) const override
710  {
711  auto red = this->Value(CommonBandNames::RED, input);
712  auto nir = this->Value(CommonBandNames::NIR, input);
713 
714  return (static_cast<TOutput>(m_RedCoef * red + m_NirCoef * nir));
715  }
716 
717  double m_RedCoef;
718  double m_NirCoef;
719 };
720 
721 
741 template <class TInput, class TOutput>
742 class LAIFromNDVIFormosat2Functor : public RadiometricIndex<TInput, TOutput>
743 {
744 public:
745  LAIFromNDVIFormosat2Functor() : RadiometricIndex<TInput, TOutput>({CommonBandNames::RED, CommonBandNames::NIR})
746  {
747  }
748 
749  TOutput operator()(const itk::VariableLengthVector<TInput>& input) const override
750  {
751  auto red = this->Value(CommonBandNames::RED, input);
752  auto nir = this->Value(CommonBandNames::NIR, input);
753 
754  if (std::abs(nir + red) < RadiometricIndex<TInput, TOutput>::Epsilon)
755  {
756  return static_cast<TOutput>(0.);
757  }
758  return static_cast<TOutput>(A * (std::exp((nir - red) / (red + nir) * B) - std::exp(C * B)));
759  }
760 
761  static constexpr double A = 0.1519;
762  static constexpr double B = 3.9443;
763  static constexpr double C = 0.13;
764 };
765 
766 
767 } // namespace Functor
768 } // namespace otb
769 
770 #endif
This functor computes the Atmospherically Resistant Vegetation Index (ARVI)
TOutput operator()(const itk::VariableLengthVector< TInput > &input) const override
static constexpr double Gamma
This functor computes the Angular Vegetation Index (AVI)
static constexpr double LambdaNir
TOutput operator()(const itk::VariableLengthVector< TInput > &input) const override
static constexpr double LambdaR
static constexpr double LambdaG
This functor computes the Enhanced Vegetation Index (EVI)
TOutput operator()(const itk::VariableLengthVector< TInput > &input) const override
static constexpr double C2
static constexpr double C1
static constexpr double L
static constexpr double G
This functor computes the Global Environment Monitoring Index (GEMI)
TOutput operator()(const itk::VariableLengthVector< TInput > &input) const override
This functor computes the Infrared Percentage Vegetation Index (IPVI)
TOutput operator()(const itk::VariableLengthVector< TInput > &input) const override
use red and nir image band to compute LAI image using formula a*(exp(nir-red)/((red+nir)*b)-exp(c*b))...
TOutput operator()(const itk::VariableLengthVector< TInput > &input) const override
TOutput operator()(const itk::VariableLengthVector< TInput > &input) const override
TOutput operator()(const itk::VariableLengthVector< TInput > &input) const override
This functor computes the Modified Soil Adjusted Vegetation Index (MSAVI2)
TOutput operator()(const itk::VariableLengthVector< TInput > &input) const override
This functor computes the Modified Soil Adjusted Vegetation Index (MSAVI)
TOutput operator()(const itk::VariableLengthVector< TInput > &input) const override
static constexpr double S
This functor computes the Normalized Difference Vegetation Index (NDVI)
static double Compute(const double &red, const double &nir)
TOutput operator()(const itk::VariableLengthVector< TInput > &input) const override
This functor computes the Perpendicular Vegetation Index (PVI)
static constexpr double B
static constexpr double A
static constexpr double C
TOutput operator()(const itk::VariableLengthVector< TInput > &input) const override
This functor computes the Ratio Vegetation Index (RVI)
TOutput operator()(const itk::VariableLengthVector< TInput > &input) const override
Base class for all radiometric indices.
double Value(BandNameType band, const itk::VariableLengthVector< TInput > &input) const
This functor computes the Soil Adjusted Vegetation Index (SAVI)
TOutput operator()(const itk::VariableLengthVector< TInput > &input) const override
static constexpr double L
This functor computes the Transformed NDVI (TNDVI)
TOutput operator()(const itk::VariableLengthVector< TInput > &input) const override
This functor computes the Transformed Soil Adjusted Vegetation Index (TSAVI)
static constexpr double S
TOutput operator()(const itk::VariableLengthVector< TInput > &input) const override
static constexpr double X
static constexpr double A
This functor computes the Weighted Difference Vegetation Index (WDVI)
static constexpr double S
TOutput operator()(const itk::VariableLengthVector< TInput > &input) const override
static double Compute(const double &red, const double &nir)
The "otb" namespace contains all Orfeo Toolbox (OTB) classes.