OTB  10.0.0
Orfeo Toolbox
otbLandsatTMIndices.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 otbLandsatTMIndices_h
22 #define otbLandsatTMIndices_h
23 
24 #include "otbMath.h"
25 #include "otbBandName.h"
26 #include "itkVariableLengthVector.h"
27 #include "otbFuzzyVariable.h"
28 #include <vector>
29 #include <algorithm>
30 #include <string>
31 
32 namespace otb
33 {
34 
35 namespace Functor
36 {
37 
38 namespace LandsatTM
39 {
40 
42 enum SATType
43 {
44  L5,
45  L7
46 };
49 {
52  Celsius
53 };
56 {
59 };
79 template <class TInput, class TOutput>
81 {
82 public:
83  // operators !=
84  bool operator!=(const LandsatTMIndexBase&) const
85  {
86  return false;
87  }
88  // operator ==
89  bool operator==(const LandsatTMIndexBase& other) const
90  {
91  return !(*this != other);
92  }
94 
97  : m_EpsilonToBeConsideredAsZero(0.0000001),
98  m_TM1(0),
99  m_TM2(1),
100  m_TM3(2),
101  m_TM4(3),
102  m_TM5(4),
103  m_TM60(5),
104  m_TM61(5),
105  m_TM62(6),
106  m_TM7(7),
107  m_SAT(L7),
108  m_Degree(Celsius),
110  {
111  }
114  {
115  }
116 
118  void SetIndex(BandName::LandsatTMBandNames band, unsigned int channel)
119  {
120  switch (band)
121  {
122  case BandName::TM1:
123  m_TM1 = channel;
124  break;
125  case BandName::TM2:
126  m_TM2 = channel;
127  break;
128  case BandName::TM3:
129  m_TM3 = channel;
130  break;
131  case BandName::TM4:
132  m_TM4 = channel;
133  break;
134  case BandName::TM5:
135  m_TM5 = channel;
136  break;
137  case BandName::TM60:
138  m_TM60 = channel;
139  break;
140  case BandName::TM61:
141  m_TM61 = channel;
142  break;
143  case BandName::TM62:
144  m_TM62 = channel;
145  break;
146  case BandName::TM7:
147  m_TM7 = channel;
148  break;
149  }
150  }
151 
153  unsigned int GetIndex(BandName::LandsatTMBandNames band) const
154  {
155  switch (band)
156  {
157  case BandName::TM1:
158  return m_TM1;
159  break;
160  case BandName::TM2:
161  return m_TM2;
162  break;
163  case BandName::TM3:
164  return m_TM3;
165  break;
166  case BandName::TM4:
167  return m_TM4;
168  break;
169  case BandName::TM5:
170  return m_TM5;
171  break;
172  case BandName::TM60:
173  return m_TM60;
174  break;
175  case BandName::TM61:
176  return m_TM61;
177  break;
178  case BandName::TM62:
179  return m_TM62;
180  break;
181  case BandName::TM7:
182  return m_TM7;
183  break;
184  }
185  return m_TM1;
186  }
188 
189  unsigned int GetTM1() const
190  {
191  return this->m_TM1;
192  }
193 
194  unsigned int GetTM2() const
195  {
196  return this->m_TM2;
197  }
198 
199  unsigned int GetTM3() const
200  {
201  return this->m_TM3;
202  }
203 
204  unsigned int GetTM4() const
205  {
206  return this->m_TM4;
207  }
208 
209  unsigned int GetTM5() const
210  {
211  return this->m_TM5;
212  }
213 
214  unsigned int GetTM60() const
215  {
216  return this->m_TM60;
217  }
218 
219  unsigned int GetTM61() const
220  {
221  return this->m_TM61;
222  }
223 
224  unsigned int GetTM62() const
225  {
226  return this->m_TM62;
227  }
228 
229  unsigned int GetTM7() const
230  {
231  return this->m_TM7;
232  }
233 
234  void SetSAT(SATType sat)
235  {
236 
237  this->m_SAT = sat;
238 
239  if (sat == L5)
240  {
241  m_TM1 = 0;
242  m_TM2 = 1;
243  m_TM3 = 2;
244  m_TM4 = 3;
245  m_TM5 = 4;
246  m_TM60 = 5;
247  m_TM7 = 6;
248  m_SAT = L5;
249  }
250  else
251  {
252  m_TM1 = 0;
253  m_TM2 = 1;
254  m_TM3 = 2;
255  m_TM4 = 3;
256  m_TM5 = 4;
257  m_TM61 = 5;
258  m_TM62 = 6;
259  m_TM7 = 7;
260  m_SAT = L7;
261  }
262  }
263 
264  SATType GetSAT() const
265  {
266  return this->m_SAT;
267  }
268 
270  {
271  this->m_Degree = deg;
272  }
273 
275  {
276  return this->m_Degree;
277  }
278 
280  {
281  this->m_Reflectance = ref;
282  }
283 
285  {
286  return this->m_Reflectance;
287  }
288 
290  {
291  return this->m_EpsilonToBeConsideredAsZero;
292  }
293 
294 protected:
296 
297  TInput PrepareValues(const TInput& inputPixel)
298  {
299 
300  TInput newPix(inputPixel);
301  if (this->m_Degree == Kelvin)
302  {
303  if (this->m_SAT == L5)
304  {
305  newPix[this->m_TM60] = newPix[this->m_TM60] - 273.15;
306  }
307  else
308  {
309  newPix[this->m_TM61] = newPix[this->m_TM61] - 273.15;
310  newPix[this->m_TM62] = newPix[this->m_TM62] - 273.15;
311  }
312  }
313  else if (this->m_Degree == HundredsKelvin)
314  {
315  if (this->m_SAT == L5)
316  {
317  newPix[this->m_TM60] = newPix[this->m_TM60] / 100. - 273.15;
318  }
319  else
320  {
321  newPix[this->m_TM61] = newPix[this->m_TM61] / 100. - 273.15;
322  newPix[this->m_TM62] = newPix[this->m_TM62] / 100. - 273.15;
323  }
324  }
325  if (this->m_Reflectance == Thousands)
326  {
327  newPix[this->m_TM1] = newPix[this->m_TM1] / 1000.;
328  newPix[this->m_TM2] = newPix[this->m_TM2] / 1000.;
329  newPix[this->m_TM3] = newPix[this->m_TM3] / 1000.;
330  newPix[this->m_TM4] = newPix[this->m_TM4] / 1000.;
331  newPix[this->m_TM5] = newPix[this->m_TM5] / 1000.;
332  newPix[this->m_TM7] = newPix[this->m_TM7] / 1000.;
333  }
334 
335  return newPix;
336  }
337 
338 
340 
341  unsigned int m_TM1;
342  unsigned int m_TM2;
343  unsigned int m_TM3;
344  unsigned int m_TM4;
345  unsigned int m_TM5;
346  unsigned int m_TM60;
347  unsigned int m_TM61;
348  unsigned int m_TM62;
349  unsigned int m_TM7;
350 
354 };
355 
356 
365 template <class TInput, class TOutput>
366 class LandsatTMIndex : public LandsatTMIndexBase<TInput, TOutput>
367 {
368 public:
369  // Operator performing the work
370  inline TOutput operator()(const TInput& inputPixel) const;
371 
373  virtual std::string GetName() const = 0;
374 
376  {
377  }
378  ~LandsatTMIndex() override
379  {
380  }
381 };
382 
400 template <class TInput, class TOutput>
401 class Bright : public LandsatTMIndex<TInput, TOutput>
402 {
403 public:
405  std::string GetName() const override
406  {
407  return "Bright";
408  }
409 
411  {
412  }
413  ~Bright() override
414  {
415  }
416 
417  inline TOutput operator()(const TInput& inputPixel)
418  {
419 
420  TInput newPixel(this->PrepareValues(inputPixel));
421  double result = (newPixel[this->m_TM1] + newPixel[this->m_TM2] + 2 * newPixel[this->m_TM3] + 2 * newPixel[this->m_TM4] + newPixel[this->m_TM5] +
422  newPixel[this->m_TM7]) /
423  8.0;
424  return static_cast<TOutput>(result);
425  }
426 };
427 
445 template <class TInput, class TOutput>
446 class Vis : public LandsatTMIndex<TInput, TOutput>
447 {
448 public:
450  std::string GetName() const override
451  {
452  return "Vis";
453  }
454 
455  Vis()
456  {
457  }
458  ~Vis() override
459  {
460  }
461 
462  inline TOutput operator()(const TInput& inputPixel)
463  {
464  TInput newPixel(this->PrepareValues(inputPixel));
465  double result = (newPixel[this->m_TM1] + newPixel[this->m_TM2] + newPixel[this->m_TM3]) / 3.0;
466  return static_cast<TOutput>(result);
467  }
468 };
469 
470 
480 template <class TInput, class TOutput>
481 class NIR : public LandsatTMIndex<TInput, TOutput>
482 {
483 public:
485  std::string GetName() const override
486  {
487  return "NIR";
488  }
489 
490  NIR()
491  {
492  }
493  ~NIR() override
494  {
495  }
496 
497  inline TOutput operator()(const TInput& inputPixel)
498  {
499  TInput newPixel(this->PrepareValues(inputPixel));
500  double result = newPixel[this->m_TM4];
501  return static_cast<TOutput>(result);
502  }
503 };
504 
514 template <class TInput, class TOutput>
515 class MIR1 : public LandsatTMIndex<TInput, TOutput>
516 {
517 public:
519  std::string GetName() const override
520  {
521  return "MIR1";
522  }
523 
525  {
526  }
527  ~MIR1() override
528  {
529  }
530 
531  inline TOutput operator()(const TInput& inputPixel)
532  {
533  TInput newPixel(this->PrepareValues(inputPixel));
534  double result = newPixel[this->m_TM5];
535  return static_cast<TOutput>(result);
536  }
537 };
538 
548 template <class TInput, class TOutput>
549 class MIR2 : public LandsatTMIndex<TInput, TOutput>
550 {
551 public:
553  std::string GetName() const override
554  {
555  return "MIR2";
556  }
557 
559  {
560  }
561  ~MIR2() override
562  {
563  }
564 
565  inline TOutput operator()(const TInput& inputPixel)
566  {
567  TInput newPixel(this->PrepareValues(inputPixel));
568  double result = newPixel[this->m_TM7];
569  return static_cast<TOutput>(result);
570  }
571 };
572 
582 template <class TInput, class TOutput>
583 class TIR : public LandsatTMIndex<TInput, TOutput>
584 {
585 public:
587  std::string GetName() const override
588  {
589  return "TIR";
590  }
591 
592  TIR()
593  {
594  }
595  ~TIR() override
596  {
597  }
598 
599  inline TOutput operator()(const TInput& inputPixel)
600  {
601  TInput newPixel(this->PrepareValues(inputPixel));
602  double result = newPixel[this->m_TM62];
603 
604  if (this->m_SAT == L5)
605  result = newPixel[this->m_TM60];
606 
607  return static_cast<TOutput>(result);
608  }
609 };
610 
630 template <class TInput, class TOutput>
631 class MIRTIR : public LandsatTMIndex<TInput, TOutput>
632 {
633 public:
635  std::string GetName() const override
636  {
637  return "MIRTIR";
638  }
639 
641  {
642  }
643  ~MIRTIR() override
644  {
645  }
646 
647  inline TOutput operator()(const TInput& inputPixel)
648  {
649  TInput newPixel(this->PrepareValues(inputPixel));
650  double tir = newPixel[this->m_TM62];
651  double mir1 = newPixel[this->m_TM5];
652 
653  if (this->m_SAT == L5)
654  tir = newPixel[this->m_TM60];
655 
656  double result = 255 * (1 - mir1) * (tir + 100) / 100.;
657 
658  return static_cast<TOutput>(result);
659  }
660 };
661 
672 template <class TInput, class TOutput>
673 class NDVI : public LandsatTMIndex<TInput, TOutput>
674 {
675 public:
677  std::string GetName() const override
678  {
679  return "NDVI";
680  }
681 
683  {
684  }
685  ~NDVI() override
686  {
687  }
688 
689  inline TOutput operator()(const TInput& inputPixel)
690  {
691  TInput newPixel(this->PrepareValues(inputPixel));
692  double result = (newPixel[this->m_TM4] - newPixel[this->m_TM3]) / (newPixel[this->m_TM4] + newPixel[this->m_TM3] + this->m_EpsilonToBeConsideredAsZero);
693 
694  return static_cast<TOutput>(result);
695  }
696 };
697 
720 template <class TInput, class TOutput>
721 class NDBSI : public LandsatTMIndex<TInput, TOutput>
722 {
723 public:
725  std::string GetName() const override
726  {
727  return "NDBSI";
728  }
729 
731  {
732  }
733  ~NDBSI() override
734  {
735  }
736 
737  inline TOutput operator()(const TInput& inputPixel)
738  {
739  TInput newPixel(this->PrepareValues(inputPixel));
740  double result = (newPixel[this->m_TM5] - newPixel[this->m_TM4]) / (newPixel[this->m_TM5] + newPixel[this->m_TM4] + this->m_EpsilonToBeConsideredAsZero);
741 
742  return static_cast<TOutput>(result);
743  }
744 };
745 
764 template <class TInput, class TOutput>
765 class BIO : public LandsatTMIndex<TInput, TOutput>
766 {
767 public:
769  std::string GetName() const override
770  {
771  return "BIO";
772  }
773 
774  BIO()
775  {
776  }
777  ~BIO() override
778  {
779  }
780 
781  inline TOutput operator()(const TInput& inputPixel)
782  {
783  TInput newPixel(this->PrepareValues(inputPixel));
784  double result = ((newPixel[this->m_TM5] + newPixel[this->m_TM3]) - (newPixel[this->m_TM4] + newPixel[this->m_TM1])) /
785  ((newPixel[this->m_TM5] + newPixel[this->m_TM3]) + (newPixel[this->m_TM4] + newPixel[this->m_TM1]));
786 
787  return static_cast<TOutput>(result);
788  }
789 };
790 
791 
810 template <class TInput, class TOutput>
811 class NDSI : public LandsatTMIndex<TInput, TOutput>
812 {
813 public:
815  std::string GetName() const override
816  {
817  return "NDSI";
818  }
819 
821  {
822  }
823  ~NDSI() override
824  {
825  }
826 
827  inline TOutput operator()(const TInput& inputPixel)
828  {
829  TInput newPixel(this->PrepareValues(inputPixel));
830  double result = (newPixel[this->m_TM2] - newPixel[this->m_TM5]) / (newPixel[this->m_TM2] + newPixel[this->m_TM5] + this->m_EpsilonToBeConsideredAsZero);
831 
832  return static_cast<TOutput>(result);
833  }
834 };
835 
868 template <class TInput, class TOutput>
869 class NDSIVis : public LandsatTMIndex<TInput, TOutput>
870 {
871 public:
873  std::string GetName() const override
874  {
875  return "NDSIVis";
876  }
877 
879  {
880  }
881  ~NDSIVis() override
882  {
883  }
884 
885  inline TOutput operator()(const TInput& inputPixel)
886  {
887  TInput newPixel(this->PrepareValues(inputPixel));
888  double vis = (newPixel[this->m_TM1] + newPixel[this->m_TM2] + newPixel[this->m_TM3]) / 3.0;
889  double result = (vis - newPixel[this->m_TM5]) / (vis + newPixel[this->m_TM5] + this->m_EpsilonToBeConsideredAsZero);
890 
891  return static_cast<TOutput>(result);
892  }
893 };
894 
915 template <class TInput, class TOutput>
916 class NDBBBI : public LandsatTMIndex<TInput, TOutput>
917 {
918 public:
920  std::string GetName() const override
921  {
922  return "NDBBBI";
923  }
924 
926  {
927  }
928  ~NDBBBI() override
929  {
930  }
931 
932  inline TOutput operator()(const TInput& inputPixel)
933  {
934  TInput newPixel(this->PrepareValues(inputPixel));
935  double result = (newPixel[this->m_TM1] - newPixel[this->m_TM5]) / (newPixel[this->m_TM1] + newPixel[this->m_TM5] + this->m_EpsilonToBeConsideredAsZero);
936  return static_cast<TOutput>(result);
937  }
938 };
939 
961 template <class TInput>
962 class LinguisticVariables : public LandsatTMIndexBase<TInput, itk::FixedArray<unsigned int, 11>>
963 {
964 public:
965  typedef typename TInput::ValueType PrecisionType;
966  typedef typename itk::FixedArray<unsigned int, 11> OutputPixelType;
968 
970  {
971  MINlv = 0,
974  MAXlv = 2,
975  High = MAXlv
976  };
977  enum Indices
978  {
979  MINid = 0,
990  MAXid = 10,
991  ndbsi = MAXid
992  };
993 
995  virtual std::string GetName() const
996  {
997  return "LandsatTM Linguistic Variables";
998  }
999 
1001  {
1013 
1014  PrecisionType maximumValue = itk::NumericTraits<PrecisionType>::max();
1015  PrecisionType minimumValue = itk::NumericTraits<PrecisionType>::NonpositiveMin();
1016 
1017  // the thresholds are computed wrt Baraldi's paper (normalized 0-255 values)
1018  m_FvBright->SetMembership(Low, minimumValue, minimumValue, 40 / 255., 40 / 255.);
1019  m_FvBright->SetMembership(Medium, 40 / 255., 40 / 255., 60 / 255., 60 / 255.);
1020  m_FvBright->SetMembership(High, 60 / 255., 60 / 255., maximumValue, maximumValue);
1021 
1022  m_FvVis->SetMembership(Low, minimumValue, minimumValue, 30 / 255., 30 / 255.);
1023  m_FvVis->SetMembership(Medium, 30 / 255., 30 / 255., 50 / 255., 50 / 255.);
1024  m_FvVis->SetMembership(High, 50 / 255., 50 / 255., maximumValue, maximumValue);
1025 
1026  m_FvNIR->SetMembership(Low, minimumValue, minimumValue, 40 / 255., 40 / 255.);
1027  m_FvNIR->SetMembership(Medium, 40 / 255., 40 / 255., 60 / 255., 60 / 255.);
1028  m_FvNIR->SetMembership(High, 60 / 255., 60 / 255., maximumValue, maximumValue);
1029 
1030  m_FvMIR1->SetMembership(Low, minimumValue, minimumValue, 40 / 255., 40 / 255.);
1031  m_FvMIR1->SetMembership(Medium, 40 / 255., 40 / 255., 60 / 255., 60 / 255.);
1032  m_FvMIR1->SetMembership(High, 60 / 255., 60 / 255., maximumValue, maximumValue);
1033 
1034  m_FvMIR2->SetMembership(Low, minimumValue, minimumValue, 30 / 255., 30 / 255.);
1035  m_FvMIR2->SetMembership(Medium, 30 / 255., 30 / 255., 50 / 255., 50 / 255.);
1036  m_FvMIR2->SetMembership(High, 50 / 255., 50 / 255., maximumValue, maximumValue);
1037 
1038  m_FvTIR->SetMembership(Low, minimumValue, minimumValue, 0, 0);
1039  m_FvTIR->SetMembership(Medium, 0, 0, 28, 28);
1040  m_FvTIR->SetMembership(High, 28, 28, maximumValue, maximumValue);
1041 
1042  m_FvMIRTIR->SetMembership(Low, minimumValue, minimumValue, 180, 180);
1043  m_FvMIRTIR->SetMembership(Medium, 180, 180, 220, 220);
1044  m_FvMIRTIR->SetMembership(High, 220, 220, maximumValue, maximumValue);
1045 
1046  m_FvNDSIVis->SetMembership(Low, minimumValue, minimumValue, 0, 0);
1047  m_FvNDSIVis->SetMembership(Medium, 0, 0, 0.5, 0.5);
1048  m_FvNDSIVis->SetMembership(High, 0.5, 0.5, maximumValue, maximumValue);
1049 
1050  m_FvNDBBBI->SetMembership(Low, minimumValue, minimumValue, -0.20, -0.20);
1051  m_FvNDBBBI->SetMembership(Medium, -0.20, -0.20, 0.10, 0.10);
1052  m_FvNDBBBI->SetMembership(High, 0.10, 0.10, maximumValue, maximumValue);
1053 
1054  m_FvNDVI->SetMembership(Low, minimumValue, minimumValue, 0.35, 0.35);
1055  m_FvNDVI->SetMembership(Medium, 0.35, 0.35, 0.6, 0.6);
1056  m_FvNDVI->SetMembership(High, 0.6, 0.6, maximumValue, maximumValue);
1057 
1058  m_FvNDBSI->SetMembership(Low, minimumValue, minimumValue, -0.20, -0.20);
1059  m_FvNDBSI->SetMembership(Medium, -0.20, -0.20, 0.0, 0.0);
1060  m_FvNDBSI->SetMembership(High, 0.0, 0.0, maximumValue, maximumValue);
1061  }
1063  {
1064  }
1065 
1066  inline itk::FixedArray<unsigned int, 11> operator()(const TInput& inputPixel)
1067  {
1068  TInput newPixel(this->PrepareValues(inputPixel));
1069  itk::FixedArray<unsigned int, 11> result;
1070 
1071  result[bright] = m_FvBright->GetMaxVar(Bright<TInput, PrecisionType>()(newPixel));
1072  result[vis] = m_FvVis->GetMaxVar(Vis<TInput, PrecisionType>()(newPixel));
1073  result[nir] = m_FvNIR->GetMaxVar(NIR<TInput, PrecisionType>()(newPixel));
1074  result[mir1] = m_FvMIR1->GetMaxVar(MIR1<TInput, PrecisionType>()(newPixel));
1075 
1077  mir2F.SetSAT(this->m_SAT);
1078  result[mir2] = m_FvMIR2->GetMaxVar(mir2F(newPixel));
1079 
1081  tirF.SetSAT(this->m_SAT);
1082  result[tir] = m_FvTIR->GetMaxVar(tirF(newPixel));
1083 
1085  mirtirF.SetSAT(this->m_SAT);
1086  result[mirtir] = m_FvMIRTIR->GetMaxVar(mirtirF(newPixel));
1087 
1088  result[ndsivis] = m_FvNDSIVis->GetMaxVar(NDSIVis<TInput, PrecisionType>()(newPixel));
1089 
1090  result[ndbbbi] = m_FvNDBBBI->GetMaxVar(NDBBBI<TInput, PrecisionType>()(newPixel));
1091 
1092  result[ndvi] = m_FvNDVI->GetMaxVar(NDVI<TInput, PrecisionType>()(newPixel));
1093 
1094  result[ndbsi] = m_FvNDBSI->GetMaxVar(NDBSI<TInput, PrecisionType>()(newPixel));
1095 
1096  return result;
1097  }
1098 
1099 protected:
1111 };
1112 
1113 
1131 template <class TInput, class TOutput>
1132 class KernelSpectralRule : public LandsatTMIndexBase<TInput, TOutput>
1133 {
1134 public:
1135  typedef typename TInput::ValueType PrecisionType;
1136  typedef bool OutputPixelType;
1137 
1139  virtual std::string GetName() const
1140  {
1141  return "LandsatTM KernelSpectralRule";
1142  }
1143 
1145  {
1146  }
1148  {
1149  }
1150 
1152  {
1153  this->m_TV1 = tv1;
1154  }
1155 
1157  {
1158  this->m_TV2 = tv2;
1159  }
1160 
1162  {
1163  return this->m_TV1;
1164  }
1165 
1166  PrecisionType GetTV2() const
1167  {
1168  return this->m_TV2;
1169  }
1170 
1171 protected:
1173  PrecisionType m_TV1;
1174 
1177 
1178  void SetMinMax(const TInput& inputPixel, PrecisionType* max13, PrecisionType* min123, PrecisionType* max123, PrecisionType* min12347, PrecisionType* max12347,
1179  PrecisionType* max234, PrecisionType* max45)
1180  {
1181  std::vector<PrecisionType> v13;
1182  v13.push_back(inputPixel[this->m_TM1]);
1183  v13.push_back(inputPixel[this->m_TM3]);
1184 
1185  *max13 = *(std::max_element(v13.begin(), v13.end()));
1186 
1187 
1188  std::vector<PrecisionType> v123;
1189  v123.push_back(inputPixel[this->m_TM1]);
1190  v123.push_back(inputPixel[this->m_TM2]);
1191  v123.push_back(inputPixel[this->m_TM3]);
1192 
1193  *max123 = *(std::max_element(v123.begin(), v123.end()));
1194  *min123 = *(std::min_element(v123.begin(), v123.end()));
1195 
1196 
1197  std::vector<PrecisionType> v12347;
1198  v12347.push_back(inputPixel[this->m_TM1]);
1199  v12347.push_back(inputPixel[this->m_TM2]);
1200  v12347.push_back(inputPixel[this->m_TM3]);
1201  v12347.push_back(inputPixel[this->m_TM4]);
1202  v12347.push_back(inputPixel[this->m_TM7]);
1203 
1204  *max12347 = *(std::max_element(v12347.begin(), v12347.end()));
1205  *min12347 = *(std::min_element(v12347.begin(), v12347.end()));
1206 
1207  std::vector<PrecisionType> v234;
1208  v234.push_back(inputPixel[this->m_TM2]);
1209  v234.push_back(inputPixel[this->m_TM3]);
1210  v234.push_back(inputPixel[this->m_TM4]);
1211 
1212  *max234 = *(std::max_element(v234.begin(), v234.end()));
1213 
1214  std::vector<PrecisionType> v45;
1215  v45.push_back(inputPixel[this->m_TM4]);
1216  v45.push_back(inputPixel[this->m_TM5]);
1217 
1218  *max45 = *(std::max_element(v45.begin(), v45.end()));
1219  }
1220 };
1221 
1237 template <class TInput, class TOutput>
1238 class ThickCloudsSpectralRule : public KernelSpectralRule<TInput, TOutput>
1239 {
1240 public:
1241  typedef typename TInput::ValueType PrecisionType;
1242  typedef bool OutputPixelType;
1243 
1245  std::string GetName() const override
1246  {
1247  return "LandsatTM ThickCloudsSpectralRule";
1248  }
1249 
1251  {
1252  }
1254  {
1255  }
1256 
1257  inline TOutput operator()(const TInput& inputPixel)
1258  {
1259  TInput newPixel(this->PrepareValues(inputPixel));
1260  PrecisionType max13;
1261  PrecisionType max123;
1262  PrecisionType min123;
1263  PrecisionType max12347;
1264  PrecisionType min12347;
1265  PrecisionType max234;
1266  PrecisionType max45;
1267  this->SetMinMax(newPixel, &max13, &min123, &max123, &min12347, &max12347, &max234, &max45);
1268 
1269  bool result = (((min123 >= (this->m_TV1 * max123) && (max123 <= this->m_TV1 * newPixel[this->m_TM4])) ||
1270  ((newPixel[this->m_TM2] >= this->m_TV1 * max13) && (max123 <= newPixel[this->m_TM4]))) &&
1271  (newPixel[this->m_TM5] <= this->m_TV1 * newPixel[this->m_TM4]) && (newPixel[this->m_TM5] >= this->m_TV1 * max123) &&
1272  (newPixel[this->m_TM7] <= this->m_TV1 * newPixel[this->m_TM4]));
1273 
1274  return static_cast<TOutput>(result);
1275  }
1276 };
1277 
1293 template <class TInput, class TOutput>
1294 class ThinCloudsSpectralRule : public KernelSpectralRule<TInput, TOutput>
1295 {
1296 public:
1297  typedef typename TInput::ValueType PrecisionType;
1298  typedef bool OutputPixelType;
1299 
1301  std::string GetName() const override
1302  {
1303  return "LandsatTM ThinCloudsSpectralRule";
1304  }
1305 
1307  {
1308  }
1310  {
1311  }
1312 
1313  inline TOutput operator()(const TInput& inputPixel)
1314  {
1315  TInput newPixel(this->PrepareValues(inputPixel));
1316  PrecisionType max13;
1317  PrecisionType max123;
1318  PrecisionType min123;
1319  PrecisionType max12347;
1320  PrecisionType min12347;
1321  PrecisionType max234;
1322  PrecisionType max45;
1323  this->SetMinMax(newPixel, &max13, &min123, &max123, &min12347, &max12347, &max234, &max45);
1324 
1325 
1326  bool result = (min123 >= (this->m_TV1 * max123)) && (newPixel[this->m_TM4] >= max123) &&
1327  !((newPixel[this->m_TM1] <= newPixel[this->m_TM2] && newPixel[this->m_TM2] <= newPixel[this->m_TM3] &&
1328  newPixel[this->m_TM3] <= newPixel[this->m_TM4]) &&
1329  (newPixel[this->m_TM3] >= this->m_TV1 * newPixel[this->m_TM4])) &&
1330  (newPixel[this->m_TM4] >= this->m_TV1 * newPixel[this->m_TM5]) && (newPixel[this->m_TM5] >= this->m_TV1 * newPixel[this->m_TM4]) &&
1331  (newPixel[this->m_TM5] >= this->m_TV1 * max123) && (newPixel[this->m_TM5] >= this->m_TV1 * newPixel[this->m_TM7]);
1332 
1333  return static_cast<TOutput>(result);
1334  }
1335 };
1336 
1352 template <class TInput, class TOutput>
1353 class SnowOrIceSpectralRule : public KernelSpectralRule<TInput, TOutput>
1354 {
1355 public:
1356  typedef typename TInput::ValueType PrecisionType;
1357  typedef bool OutputPixelType;
1358 
1360  std::string GetName() const override
1361  {
1362  return "LandsatTM SnowOrIceSpectralRule";
1363  }
1364 
1366  {
1367  }
1369  {
1370  }
1371 
1372  inline TOutput operator()(const TInput& inputPixel)
1373  {
1374  TInput newPixel(this->PrepareValues(inputPixel));
1375  PrecisionType max13;
1376  PrecisionType max123;
1377  PrecisionType min123;
1378  PrecisionType max12347;
1379  PrecisionType min12347;
1380  PrecisionType max234;
1381  PrecisionType max45;
1382  this->SetMinMax(newPixel, &max13, &min123, &max123, &min12347, &max12347, &max234, &max45);
1383 
1384 
1385  bool result = (min123 >= (this->m_TV1 * max123)) && (newPixel[this->m_TM4] >= (this->m_TV1 * max123)) &&
1386  (newPixel[this->m_TM5] <= this->m_TV2 * newPixel[this->m_TM4]) && (newPixel[this->m_TM5] <= this->m_TV1 * min123) &&
1387  (newPixel[this->m_TM5] <= this->m_TV1 * max123) && (newPixel[this->m_TM7] <= this->m_TV2 * newPixel[this->m_TM4]) &&
1388  (newPixel[this->m_TM7] <= this->m_TV1 * min123);
1389 
1390  return static_cast<TOutput>(result);
1391  }
1392 };
1393 
1394 
1410 template <class TInput, class TOutput>
1411 class WaterOrShadowSpectralRule : public KernelSpectralRule<TInput, TOutput>
1412 {
1413 public:
1414  typedef typename TInput::ValueType PrecisionType;
1415  typedef bool OutputPixelType;
1416 
1418  std::string GetName() const override
1419  {
1420  return "LandsatTM WaterOrShadowSpectralRule";
1421  }
1422 
1424  {
1425  }
1427  {
1428  }
1429 
1430  inline TOutput operator()(const TInput& inputPixel)
1431  {
1432  TInput newPixel(this->PrepareValues(inputPixel));
1433  bool result = (newPixel[this->m_TM1] >= newPixel[this->m_TM2]) && (newPixel[this->m_TM2] >= newPixel[this->m_TM3]) &&
1434  (newPixel[this->m_TM3] >= newPixel[this->m_TM4]) && (newPixel[this->m_TM4] >= newPixel[this->m_TM5]) &&
1435  (newPixel[this->m_TM4] >= newPixel[this->m_TM7]);
1436 
1437  return static_cast<TOutput>(result);
1438  }
1439 };
1440 
1441 
1457 template <class TInput, class TOutput>
1459 {
1460 public:
1461  typedef typename TInput::ValueType PrecisionType;
1462  typedef bool OutputPixelType;
1463 
1465  std::string GetName() const override
1466  {
1467  return "LandsatTM PitbogOrGreenhouseSpectralRule";
1468  }
1469 
1471  {
1472  }
1474  {
1475  }
1476 
1477  inline TOutput operator()(const TInput& inputPixel)
1478  {
1479  TInput newPixel(this->PrepareValues(inputPixel));
1480  PrecisionType max13;
1481  PrecisionType max123;
1482  PrecisionType min123;
1483  PrecisionType max12347;
1484  PrecisionType min12347;
1485  PrecisionType max234;
1486  PrecisionType max45;
1487  this->SetMinMax(newPixel, &max13, &min123, &max123, &min12347, &max12347, &max234, &max45);
1488 
1489 
1490  bool result = (newPixel[this->m_TM3] >= this->m_TV1 * newPixel[this->m_TM1]) && (newPixel[this->m_TM1] >= this->m_TV1 * newPixel[this->m_TM3]) &&
1491  (max123 <= this->m_TV1 * newPixel[this->m_TM4]) && (newPixel[this->m_TM5] <= this->m_TV1 * newPixel[this->m_TM4]) &&
1492  (newPixel[this->m_TM3] >= this->m_TV2 * newPixel[this->m_TM5]) && (min123 >= this->m_TV1 * newPixel[this->m_TM7]);
1493 
1494 
1495  return static_cast<TOutput>(result);
1496  }
1497 };
1498 
1514 template <class TInput, class TOutput>
1515 class DominantBlueSpectralRule : public KernelSpectralRule<TInput, TOutput>
1516 {
1517 public:
1518  typedef typename TInput::ValueType PrecisionType;
1519  typedef bool OutputPixelType;
1520 
1522  std::string GetName() const override
1523  {
1524  return "LandsatTM DominantBlueSpectralRule";
1525  }
1526 
1528  {
1529  }
1531  {
1532  }
1533 
1534  inline TOutput operator()(const TInput& inputPixel)
1535  {
1536  TInput newPixel(this->PrepareValues(inputPixel));
1537  bool result = (newPixel[this->m_TM1] >= this->m_TV1 * newPixel[this->m_TM2]) && (newPixel[this->m_TM1] >= this->m_TV1 * newPixel[this->m_TM3]) &&
1538  (newPixel[this->m_TM1] >= this->m_TV1 * newPixel[this->m_TM4]) && (newPixel[this->m_TM1] >= this->m_TV1 * newPixel[this->m_TM5]) &&
1539  (newPixel[this->m_TM1] >= this->m_TV1 * newPixel[this->m_TM7]);
1540 
1541 
1542  return static_cast<TOutput>(result);
1543  }
1544 };
1545 
1546 
1562 template <class TInput, class TOutput>
1563 class VegetationSpectralRule : public KernelSpectralRule<TInput, TOutput>
1564 {
1565 public:
1566  typedef typename TInput::ValueType PrecisionType;
1567  typedef bool OutputPixelType;
1568 
1570  std::string GetName() const override
1571  {
1572  return "LandsatTM VegetationSpectralRule";
1573  }
1574 
1576  {
1577  }
1579  {
1580  }
1581 
1582  inline TOutput operator()(const TInput& inputPixel)
1583  {
1584  TInput newPixel(this->PrepareValues(inputPixel));
1585  PrecisionType max13;
1586  PrecisionType max123;
1587  PrecisionType min123;
1588  PrecisionType max12347;
1589  PrecisionType min12347;
1590  PrecisionType max234;
1591  PrecisionType max45;
1592  this->SetMinMax(newPixel, &max13, &min123, &max123, &min12347, &max12347, &max234, &max45);
1593 
1594 
1595  bool result = (newPixel[this->m_TM2] >= this->m_TV2 * newPixel[this->m_TM1]) && (newPixel[this->m_TM2] >= this->m_TV1 * newPixel[this->m_TM3]) &&
1596  (newPixel[this->m_TM3] < this->m_TV1 * newPixel[this->m_TM4]) && (newPixel[this->m_TM4] > max123) &&
1597  (newPixel[this->m_TM5] < this->m_TV1 * newPixel[this->m_TM4]) && (newPixel[this->m_TM5] >= this->m_TV1 * newPixel[this->m_TM3]) &&
1598  (newPixel[this->m_TM7] < this->m_TV1 * newPixel[this->m_TM5]);
1599 
1600 
1601  return static_cast<TOutput>(result);
1602  }
1603 };
1604 
1605 
1621 template <class TInput, class TOutput>
1622 class RangelandSpectralRule : public KernelSpectralRule<TInput, TOutput>
1623 {
1624 public:
1625  typedef typename TInput::ValueType PrecisionType;
1626  typedef bool OutputPixelType;
1627 
1629  std::string GetName() const override
1630  {
1631  return "LandsatTM RangelandSpectralRule";
1632  }
1633 
1635  {
1636  }
1638  {
1639  }
1640 
1641  inline TOutput operator()(const TInput& inputPixel)
1642  {
1643  TInput newPixel(this->PrepareValues(inputPixel));
1644  PrecisionType max13;
1645  PrecisionType max123;
1646  PrecisionType min123;
1647  PrecisionType max12347;
1648  PrecisionType min12347;
1649  PrecisionType max234;
1650  PrecisionType max45;
1651  this->SetMinMax(newPixel, &max13, &min123, &max123, &min12347, &max12347, &max234, &max45);
1652 
1653 
1654  bool result = (newPixel[this->m_TM2] >= this->m_TV2 * newPixel[this->m_TM1]) && (newPixel[this->m_TM2] >= this->m_TV1 * newPixel[this->m_TM3]) &&
1655  (newPixel[this->m_TM4] > max123) && (newPixel[this->m_TM3] < this->m_TV1 * newPixel[this->m_TM4]) &&
1656  (newPixel[this->m_TM4] >= this->m_TV1 * newPixel[this->m_TM5]) && (newPixel[this->m_TM5] >= this->m_TV1 * newPixel[this->m_TM4]) &&
1657  (newPixel[this->m_TM5] > max123) && (newPixel[this->m_TM7] < this->m_TV1 * max45) && (newPixel[this->m_TM5] >= newPixel[this->m_TM7]);
1658 
1659 
1660  return static_cast<TOutput>(result);
1661  }
1662 };
1663 
1679 template <class TInput, class TOutput>
1681 {
1682 public:
1683  typedef typename TInput::ValueType PrecisionType;
1684  typedef bool OutputPixelType;
1685 
1687  std::string GetName() const override
1688  {
1689  return "LandsatTM BarrenLandOrBuiltUpOrCloudsSpectralRule";
1690  }
1691 
1693  {
1694  }
1696  {
1697  }
1698 
1699  inline TOutput operator()(const TInput& inputPixel)
1700  {
1701  TInput newPixel(this->PrepareValues(inputPixel));
1702  PrecisionType max13;
1703  PrecisionType max123;
1704  PrecisionType min123;
1705  PrecisionType max12347;
1706  PrecisionType min12347;
1707  PrecisionType max234;
1708  PrecisionType max45;
1709  this->SetMinMax(newPixel, &max13, &min123, &max123, &min12347, &max12347, &max234, &max45);
1710 
1711 
1712  bool result = (newPixel[this->m_TM3] >= this->m_TV2 * newPixel[this->m_TM1]) && (newPixel[this->m_TM3] >= this->m_TV1 * newPixel[this->m_TM2]) &&
1713  (newPixel[this->m_TM4] >= this->m_TV1 * max123) && (newPixel[this->m_TM5] >= max123) &&
1714  (newPixel[this->m_TM5] >= this->m_TV1 * newPixel[this->m_TM4]) && (newPixel[this->m_TM5] >= this->m_TV1 * newPixel[this->m_TM7]) &&
1715  (newPixel[this->m_TM7] >= this->m_TV2 * max45);
1716 
1717  return static_cast<TOutput>(result);
1718  }
1719 };
1720 
1736 template <class TInput, class TOutput>
1738 {
1739 public:
1740  typedef typename TInput::ValueType PrecisionType;
1741  typedef bool OutputPixelType;
1742 
1744  std::string GetName() const override
1745  {
1746  return "LandsatTM FlatResponseBarrenLandOrBuiltUpSpectralRule";
1747  }
1748 
1750  {
1751  }
1753  {
1754  }
1755 
1756  inline TOutput operator()(const TInput& inputPixel)
1757  {
1758  TInput newPixel(this->PrepareValues(inputPixel));
1759  PrecisionType max13;
1760  PrecisionType max123;
1761  PrecisionType min123;
1762  PrecisionType max12347;
1763  PrecisionType min12347;
1764  PrecisionType max234;
1765  PrecisionType max45;
1766  this->SetMinMax(newPixel, &max13, &min123, &max123, &min12347, &max12347, &max234, &max45);
1767 
1768 
1769  bool result = (newPixel[this->m_TM5] >= this->m_TV1 * max12347) && (min12347 >= this->m_TV2 * newPixel[this->m_TM5]);
1770 
1771  return static_cast<TOutput>(result);
1772  }
1773 };
1774 
1775 
1791 template <class TInput, class TOutput>
1793 {
1794 public:
1795  typedef typename TInput::ValueType PrecisionType;
1796  typedef bool OutputPixelType;
1797 
1799  std::string GetName() const override
1800  {
1801  return "LandsatTM ShadowWithBarrenLandSpectralRule";
1802  }
1803 
1805  {
1806  }
1808  {
1809  }
1810 
1811  inline TOutput operator()(const TInput& inputPixel)
1812  {
1813  TInput newPixel(this->PrepareValues(inputPixel));
1814  bool result = (newPixel[this->m_TM1] >= newPixel[this->m_TM2]) && (newPixel[this->m_TM2] >= newPixel[this->m_TM3]) &&
1815  (newPixel[this->m_TM3] >= this->m_TV1 * newPixel[this->m_TM4]) && (newPixel[this->m_TM1] >= newPixel[this->m_TM5]) &&
1816  (newPixel[this->m_TM5] >= this->m_TV1 * newPixel[this->m_TM4]) && (newPixel[this->m_TM5] >= this->m_TV1 * newPixel[this->m_TM7]);
1817 
1818  return static_cast<TOutput>(result);
1819  }
1820 };
1821 
1822 
1838 template <class TInput, class TOutput>
1840 {
1841 public:
1842  typedef typename TInput::ValueType PrecisionType;
1843  typedef bool OutputPixelType;
1844 
1846  std::string GetName() const override
1847  {
1848  return "LandsatTM ShadowWithVegetationSpectralRule";
1849  }
1850 
1852  {
1853  }
1855  {
1856  }
1857 
1858  inline TOutput operator()(const TInput& inputPixel)
1859  {
1860  TInput newPixel(this->PrepareValues(inputPixel));
1861  bool result = (newPixel[this->m_TM1] >= newPixel[this->m_TM2]) && (newPixel[this->m_TM2] >= newPixel[this->m_TM3]) &&
1862  (newPixel[this->m_TM1] >= this->m_TV2 * newPixel[this->m_TM4]) && (newPixel[this->m_TM3] < this->m_TV1 * newPixel[this->m_TM4]) &&
1863  (newPixel[this->m_TM5] < this->m_TV1 * newPixel[this->m_TM4]) && (newPixel[this->m_TM3] >= this->m_TV2 * newPixel[this->m_TM5]) &&
1864  (newPixel[this->m_TM7] < this->m_TV1 * newPixel[this->m_TM4]);
1865 
1866  return static_cast<TOutput>(result);
1867  }
1868 };
1869 
1870 
1886 template <class TInput, class TOutput>
1887 class ShadowCloudOrSnowSpectralRule : public KernelSpectralRule<TInput, TOutput>
1888 {
1889 public:
1890  typedef typename TInput::ValueType PrecisionType;
1891  typedef bool OutputPixelType;
1892 
1894  std::string GetName() const override
1895  {
1896  return "LandsatTM ShadowCloudOrSnowSpectralRule";
1897  }
1898 
1900  {
1901  }
1903  {
1904  }
1905 
1906  inline TOutput operator()(const TInput& inputPixel)
1907  {
1908  TInput newPixel(this->PrepareValues(inputPixel));
1909  PrecisionType max13;
1910  PrecisionType max123;
1911  PrecisionType min123;
1912  PrecisionType max12347;
1913  PrecisionType min12347;
1914  PrecisionType max234;
1915  PrecisionType max45;
1916  this->SetMinMax(newPixel, &max13, &min123, &max123, &min12347, &max12347, &max234, &max45);
1917 
1918 
1919  bool result = (newPixel[this->m_TM1] >= this->m_TV1 * max234) && (max234 >= this->m_TV1 * newPixel[this->m_TM1]) &&
1920  (newPixel[this->m_TM5] < newPixel[this->m_TM1]) && (newPixel[this->m_TM7] < this->m_TV1 * newPixel[this->m_TM1]);
1921 
1922  return static_cast<TOutput>(result);
1923  }
1924 };
1925 
1926 
1942 template <class TInput, class TOutput>
1943 class WetlandSpectralRule : public KernelSpectralRule<TInput, TOutput>
1944 {
1945 public:
1946  typedef typename TInput::ValueType PrecisionType;
1947  typedef bool OutputPixelType;
1948 
1950  std::string GetName() const override
1951  {
1952  return "LandsatTM WetlandSpectralRule";
1953  }
1954 
1956  {
1957  }
1959  {
1960  }
1961 
1962  inline TOutput operator()(const TInput& inputPixel)
1963  {
1964  TInput newPixel(this->PrepareValues(inputPixel));
1965  bool result = (newPixel[this->m_TM1] >= newPixel[this->m_TM2]) && (newPixel[this->m_TM2] >= newPixel[this->m_TM3]) &&
1966  (newPixel[this->m_TM1] >= this->m_TV1 * newPixel[this->m_TM4]) && (newPixel[this->m_TM3] < newPixel[this->m_TM4]) &&
1967  (newPixel[this->m_TM4] >= this->m_TV1 * newPixel[this->m_TM5]) && (newPixel[this->m_TM5] >= this->m_TV1 * newPixel[this->m_TM4]) &&
1968  (newPixel[this->m_TM3] >= this->m_TV2 * newPixel[this->m_TM5]) && (newPixel[this->m_TM5] >= newPixel[this->m_TM7]);
1969 
1970  return static_cast<TOutput>(result);
1971  }
1972 };
1973 
1974 
1975 } // namespace LandsatTM
1976 } // namespace Functor
1977 } // namespace otb
1978 
1979 #endif
std::string GetName() const override
TOutput operator()(const TInput &inputPixel)
std::string GetName() const override
TOutput operator()(const TInput &inputPixel)
void SetMinMax(const TInput &inputPixel, PrecisionType *max13, PrecisionType *min123, PrecisionType *max123, PrecisionType *min12347, PrecisionType *max12347, PrecisionType *max234, PrecisionType *max45)
Base class for Landsat-TM indices.
void SetIndex(BandName::LandsatTMBandNames band, unsigned int channel)
unsigned int GetIndex(BandName::LandsatTMBandNames band) const
bool operator==(const LandsatTMIndexBase &other) const
bool operator!=(const LandsatTMIndexBase &) const
TInput PrepareValues(const TInput &inputPixel)
Prepare the values so they are normalized and in C.
virtual std::string GetName() const =0
TOutput operator()(const TInput &inputPixel) const
otb::FuzzyVariable< unsigned short, PrecisionType > FuzzyVarType
itk::FixedArray< unsigned int, 11 > operator()(const TInput &inputPixel)
itk::FixedArray< unsigned int, 11 > OutputPixelType
TOutput operator()(const TInput &inputPixel)
std::string GetName() const override
std::string GetName() const override
TOutput operator()(const TInput &inputPixel)
TOutput operator()(const TInput &inputPixel)
std::string GetName() const override
TOutput operator()(const TInput &inputPixel)
std::string GetName() const override
std::string GetName() const override
TOutput operator()(const TInput &inputPixel)
TOutput operator()(const TInput &inputPixel)
std::string GetName() const override
TOutput operator()(const TInput &inputPixel)
std::string GetName() const override
std::string GetName() const override
TOutput operator()(const TInput &inputPixel)
std::string GetName() const override
TOutput operator()(const TInput &inputPixel)
TOutput operator()(const TInput &inputPixel)
TOutput operator()(const TInput &inputPixel)
std::string GetName() const override
TOutput operator()(const TInput &inputPixel)
std::string GetName() const override
TOutput operator()(const TInput &inputPixel)
TOutput operator()(const TInput &inputPixel)
Class to represent a fuzzy N-valued variable.
itk::SmartPointer< Self > Pointer
static Pointer New()
DegreeType
Thermal band in Kelvin or Celsius.
ReflectanceType
Reflectances in thousands or in (0-1)
The "otb" namespace contains all Orfeo Toolbox (OTB) classes.