OTB  10.0.0
Orfeo Toolbox
otbLandsatTMSpectralRuleBasedClassifier.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 otbLandsatTMSRBC_h
22 #define otbLandsatTMSRBC_h
23 
24 #include "otbLandsatTMIndices.h"
25 #include <string>
26 
27 namespace otb
28 {
29 
30 namespace Functor
31 {
32 
33 namespace LandsatTM
34 {
35 
62 template <class TInput, class TOutput>
63 class SpectralRuleBasedClassifier : public KernelSpectralRule<TInput, TOutput>
64 {
65 public:
66  // Spectral categories
68  {
69  NOCLASS, // 0 -if the pixel is not classified; just for error
70  // checking; different from SU, which is a real rejection
71  // class
72  TKCL, // 1 -thick clouds
73  TNCL, // 2 -thin clouds; possible confusions with cold light toned
74  // (highly reflective) barren land and range land
75  SN, // 3 -snow
76  ICSN, // 4 -ice or snow
77  DPWASH, // 5 -deep clear water and shadow areas; possible confusions
78  // with lava rocks
79  SLWASH, // 6 -shallow clear water and shadow areas
80  PBHNDVI, // 7 -pit bog with high NDVI
81  PBMNDVI, // 8 -pit bog with medium NDVI
82  PBLNDVI, // 9 -pit bog with low NDVI; possible confusions with
83  // greenhouses
84  SVHNIR, // 10 - strong vegetation with high NIR; includes broadleaved
85  // decideous forests, vegetated cropland and pastures;
86  // possible confusions with mixed forests
87  SVLNIR, // 11 -strong vegetation with low NIR; includes evergreen
88  // forests and mixed forests; possible confusions with
89  // forest land in shadow areas
90  AVHNIR, // 12 -average vegetation with high NIR; includes cropland and
91  // pastures; possible confusions with evergreen forests
92  // and mixed forests
93  AVLNIR, // 13 -average vegetation with low NIR; includes evergreen
94  // forests, especially coniferous; possible confusions
95  // with forest land in shadow areas
96  WVHNIR, // 14 -weak vegetation with high NIR; includes scarcely
97  // vegetated areas
98  WVLNIR, // 15 -weak vegetation with low NIR; includes forested wetland
99  SSRHNIR, // 16 -strong shrub rangeland with high NIR; includes
100  // herbaceous rangeland; possible confusions with shrub
101  // and brush rangeland
102  SSRLNIR, // 17 -strong shrub rangeland with low NIR; includes shrub
103  // and brush rangeland; possible confusions with
104  // herbaceous rangeland
105  ASRHNIR, // 18 -average shrub rangeland with high NIR; includes
106  // herbaceous rangeland; possible confusions with shrub
107  // and brush rangeland
108  ASRLNIR, // 19 -average shrub rangeland with low NIR; includes shrub
109  // and brush rangeland; possible confusions with
110  // herbaceous rangeland
111  SHR, // 20 - strong herbaceous rangeland; possible confusions with
112  // vegetated cropland ans pastures
113  AHR, // 21 -average herbaceous rangeland; includes herbaceous
114  // rangeland and barren land scarcely vegetated; possible
115  // confusions with vegetated cropland and pastures
116  DR, // 22 -dark rangeland; includes mixed rangeland eventually in
117  // shadow areas and non forested wetland; possible
118  // confusions with mixed urban or built up
119  BBBHTIRF, // 23 -bright barren land or built up with high TIR and flat
120  // spectral response; includes urban or built up and
121  // concrete roads
122  BBBHTIRNF, // 24 -bright barren land or built up with high TIR and non flat
123  // spectral response;
124  BBBLTIRF, // 25 -bright barren land or built up with low TIR and flat
125  // spectral response; includes urban or built up and
126  // concrete roads
127  BBBLTIRNF, // 26 -bright barren land or built up with low TIR and non flat
128  // spectral response;
129  SBBHTIRF, // 27 -strong barren land or built up with high TIR and flat
130  // spectral response; includes urban or built up and
131  // concrete roads
132  SBBHTIRNF, // 28 -strong barren land or built up with high TIR with non flat
133  // spectral response; includes ploughed fields, barren
134  // land -- including bare exposed rocks -- and beaches
135  SBBLTIRF, // 29 -strong barren land or built up with low TIR and flat
136  // spectral response; includes urban or built up and
137  // concrete roads
138  SBBLTIRNF, // 30 -strong barren land or built up with low TIR with non flat
139  // spectral response; includes ploughed fields, barren
140  // land -- including bare exposed rocks -- and beaches
141  ABBHTIRF, // 31 -average barren land or built up with high TIR and flat
142  // spectral response; includes urban or built up and
143  // concrete roads
144  ABBHTIRNF, // 32 -average barren land or built up with high TIR with non flat
145  // spectral response
146  ABBLTIRF, // 33 -average barren land or built up with low TIR and flat
147  // spectral response; includes urban or built up and
148  // concrete roads
149  ABBLTIRNF, // 34 -average barren land or built up with low TIR with non flat
150  // spectral response
151  DBBHTIRF, // 35 -dark barren land or built up with high TIR and flat
152  // spectral response; includes urban or built up land,
153  // in particular parking lots, concrete roads, asphalt
154  // roads, grey-brown tile roofs, tan composite shingle
155  // roofs; possible confusions with barren land on dark
156  // mountain slopes including burned areas and bare
157  // exposed rocks, especially dark-toned soil
158  DBBHTIRNF, // 36 -dark barren land or built up with high TIR and non
159  // flat spectral response; includes barren land, bare
160  // exposed rocks, especially dark-toned soil
161  DBBLTIRF, // 37 -dark barren land or built up with low TIR and flat
162  // spectral response; includes urban or built up land,
163  // in particular parking lots, concrete roads, asphalt
164  // roads, grey-brown tile roofs, tan composite shingle
165  // roofs; possible confusions with barren land on dark
166  // mountain slopes including burned areas and bare
167  // exposed rocks, especially dark-toned soil
168  DBBLTIRNF, // 38 -dark barren land or built up with low TIR and non
169  // flat spectral response; includes barren land, bare
170  // exposed rocks, especially dark-toned soil
171  WR, // 39 -weak rangeland; includes herbaceous rangeland
172  SHV, // 40 -shadow area with vegetation; possible confusions
173  // with non forested wetland
174  SHB, // 41 -shadow with barren land; includes also lava rock;
175  // possible confusions with built up areas, especially
176  // asphalt roads
177  SHCL, // 42 -clouds in shadow areas
178  TWASHSN, // 43 -snow in shadow areas
179  WE, // 44 -non forested wetland; possible confusions with
180  // shadow areas with vegetation
181  TWA, // 45 -turbid water; possible confusions with shadow areas
182  SU // 46 -shadow areas or unknown pixels
183  };
184  typedef typename TInput::ValueType PrecisionType;
185  typedef bool OutputPixelType;
186 
188  std::string GetName() const override
189  {
190  return "LandsatTM SpectralRuleBasedClassifier";
191  }
192 
194  {
195  }
197  {
198  }
199 
200  inline TOutput operator()(const TInput& inputPixel)
201  {
202  // We normalize the pixel just once, so that the indices do not
203  // need to do it
204  TInput newPixel(this->PrepareValues(inputPixel));
205 
206 
207  // Get the linguistic variables
208  typedef LinguisticVariables<TInput> LVType;
209  LVType lvf = LVType();
210  lvf.SetSAT(this->m_SAT);
211  typename LVType::OutputPixelType lv = lvf(newPixel);
212 
213 
214  typedef ThickCloudsSpectralRule<TInput, bool> TKCLSRType;
215  TKCLSRType tkclsrf = TKCLSRType();
216  tkclsrf.SetTV1(this->m_TV1);
217  tkclsrf.SetTV2(this->m_TV2);
218  tkclsrf.SetSAT(this->m_SAT);
219 
220  bool tkclsr = tkclsrf(newPixel);
221 
222  typedef ThinCloudsSpectralRule<TInput, bool> TNCLSRType;
223  TNCLSRType tnclsrf = TNCLSRType();
224  tnclsrf.SetTV1(this->m_TV1);
225  tnclsrf.SetTV2(this->m_TV2);
226  tnclsrf.SetSAT(this->m_SAT);
227 
228  bool tnclsr = tnclsrf(newPixel);
229 
230  bool lBright = (lv[LVType::bright] == LVType::Low);
231  bool lVis = (lv[LVType::vis] == LVType::Low);
232  bool lNIR = (lv[LVType::nir] == LVType::Low);
233  bool hNDSIVis = (lv[LVType::ndsivis] == LVType::High);
234  bool lMIR1 = (lv[LVType::mir1] == LVType::Low);
235  bool lMIR2 = (lv[LVType::mir2] == LVType::Low);
236  bool hTIR = (lv[LVType::tir] == LVType::High);
237  bool hMIRTIR = (lv[LVType::mirtir] == LVType::High);
238  bool mMIRTIR = (lv[LVType::mirtir] == LVType::Medium);
239  bool lMIRTIR = (lv[LVType::mirtir] == LVType::Low);
240 
241 
242  // cloud spectral category
243  bool clsc = (tkclsr || tnclsr) && !(lBright || lVis || lNIR || hNDSIVis || lMIR1 || lMIR2 || hTIR || hMIRTIR);
244 
245  // thick cloud spectral category
246  if (clsc && lMIRTIR)
247  return static_cast<TOutput>(TKCL);
248 
249  // thin cloud spectral category
250  if (clsc && mMIRTIR)
251  return static_cast<TOutput>(TNCL);
252 
253 
254  typedef SnowOrIceSpectralRule<TInput, bool> SNICSRType;
255  SNICSRType snicsrf = SNICSRType();
256  snicsrf.SetTV1(this->m_TV1);
257  snicsrf.SetTV2(this->m_TV2);
258  snicsrf.SetSAT(this->m_SAT);
259 
260  bool snicsr = snicsrf(newPixel);
261 
262  bool lNDBSI = (lv[LVType::ndbsi] == LVType::Low);
263  bool lNDSIVis = (lv[LVType::ndsivis] == LVType::Low);
264  bool hMIR1 = (lv[LVType::mir1] == LVType::High);
265  bool hMIR2 = (lv[LVType::mir2] == LVType::High);
266 
267  // snow or ice spectral category
268  bool snicsc = (snicsr && lNDBSI && !(lBright || lVis || lNDSIVis || lNIR || hMIR1 || hMIR2 || hTIR));
269 
270  // snow spectral category
271  if (snicsc && hNDSIVis)
272  return static_cast<TOutput>(SN);
273 
274  bool mNDSIVis = (lv[LVType::ndsivis] == LVType::Medium);
275  // ice or snow spectral category
276  if (snicsc && mNDSIVis)
277  return static_cast<TOutput>(ICSN);
278 
279 
280  typedef WaterOrShadowSpectralRule<TInput, bool> WASHSRType;
281  WASHSRType washsrf = WASHSRType();
282  washsrf.SetTV1(this->m_TV1);
283  washsrf.SetTV2(this->m_TV2);
284  washsrf.SetSAT(this->m_SAT);
285 
286  bool washsr = washsrf(newPixel);
287 
288 
289  bool lNDVI = (lv[LVType::ndvi] == LVType::Low);
290  bool lTIR = (lv[LVType::tir] == LVType::Low);
291  // water or shadow spectral category
292  bool washsc = washsr && lBright && lVis && lNDVI && lNIR && lMIR1 && lMIR2 && !(lTIR);
293 
294 
295  // deep water or shadow spectral category
296  if (washsc && hNDSIVis)
297  return static_cast<TOutput>(DPWASH);
298 
299  // shallow water or shadow spectral category
300  if (washsc && !(hNDSIVis))
301  return static_cast<TOutput>(SLWASH);
302 
303 
305  PBGHSRType pbghsrf = PBGHSRType();
306  pbghsrf.SetTV1(this->m_TV1);
307  pbghsrf.SetTV2(this->m_TV2);
308  pbghsrf.SetSAT(this->m_SAT);
309 
310  bool pbghsr = pbghsrf(newPixel);
311 
312  // Pit bog spectral category
313  bool pbsc = pbghsr && lMIR1 && lMIR2 && lNDBSI && !(lNIR);
314 
315  bool mNDVI = (lv[LVType::ndvi] == LVType::Medium);
316  bool hNDVI = (lv[LVType::ndvi] == LVType::High);
317  // Pit bog categories for each ndvi
318  if (pbsc && hNDVI)
319  return static_cast<TOutput>(PBHNDVI);
320  if (pbsc && mNDVI)
321  return static_cast<TOutput>(PBMNDVI);
322  if (pbsc && lNDVI)
323  return static_cast<TOutput>(PBLNDVI);
324 
325 
326  typedef VegetationSpectralRule<TInput, bool> VSRType;
327  VSRType vsrf = VSRType();
328  vsrf.SetTV1(this->m_TV1);
329  vsrf.SetTV2(this->m_TV2);
330  vsrf.SetSAT(this->m_SAT);
331 
332  bool vsr = vsrf(newPixel);
333 
334  bool hNDBSI = (lv[LVType::ndbsi] == LVType::High);
335  bool hNIR = (lv[LVType::nir] == LVType::High);
336 
337  // strong vegetation spectral category
338  bool svsc = vsr && hNDVI && !(hMIR1 || hMIR2 || hNDBSI);
339 
340  if (svsc && hNIR)
341  return static_cast<TOutput>(SVHNIR);
342  if (svsc && !(hNIR))
343  return static_cast<TOutput>(SVLNIR);
344 
346  SHVSRType shvsrf = SHVSRType();
347  shvsrf.SetTV1(this->m_TV1);
348  shvsrf.SetTV2(this->m_TV2);
349  shvsrf.SetSAT(this->m_SAT);
350 
351  bool shvsr = shvsrf(newPixel);
352 
353 
355  DBSRType dbsrf = DBSRType();
356  dbsrf.SetTV1(this->m_TV1);
357  dbsrf.SetTV2(this->m_TV2);
358  dbsrf.SetSAT(this->m_SAT);
359 
360  bool dbsr = dbsrf(newPixel);
361 
362  // average vegetation spectral category
363  bool avsc = (vsr || shvsr) && mNDVI && !(hMIR1 || hMIR2 || hNDBSI || dbsr);
364 
365  if (avsc && hNIR)
366  return static_cast<TOutput>(AVHNIR);
367  if (avsc && !(hNIR))
368  return static_cast<TOutput>(AVLNIR);
369 
370  typedef RangelandSpectralRule<TInput, bool> RSRType;
371  RSRType rsrf = RSRType();
372  rsrf.SetTV1(this->m_TV1);
373  rsrf.SetTV2(this->m_TV2);
374  rsrf.SetSAT(this->m_SAT);
375 
376  bool rsr = rsrf(newPixel);
377 
378  // weak vegetation spectral category
379  bool wvsc = (vsr || rsr || shvsr) && lNDVI && lNDBSI && lMIR1 && lMIR2 && !(dbsr);
380 
381  if (wvsc && hNIR)
382  return static_cast<TOutput>(WVHNIR);
383  if (wvsc && !(hNIR))
384  return static_cast<TOutput>(WVLNIR);
385 
386  bool mNDBSI = (lv[LVType::ndbsi] == LVType::Medium);
387  // strong shrub rangeland spectral category
388  bool ssrsc = rsr && hNDVI && mNDBSI;
389  if (ssrsc && hNIR)
390  return static_cast<TOutput>(SSRHNIR);
391  if (ssrsc && !(hNIR))
392  return static_cast<TOutput>(SSRLNIR);
393 
394  typedef WetlandSpectralRule<TInput, bool> WESRType;
395  WESRType wesrf = WESRType();
396  wesrf.SetTV1(this->m_TV1);
397  wesrf.SetTV2(this->m_TV2);
398  wesrf.SetSAT(this->m_SAT);
399 
400  bool wesr = wesrf(newPixel);
401 
402  // average shrub rangeland spectral category
403  bool asrsc = rsr && mNDVI && mNDBSI && !(shvsr || wesr);
404  if (asrsc && hNIR)
405  return static_cast<TOutput>(ASRHNIR);
406  if (asrsc && !(hNIR))
407  return static_cast<TOutput>(ASRLNIR);
408 
409 
410  // strong herbaceous rangeland spectral category
411  bool shrsc = rsr && hNDVI && hNDBSI;
412  if (shrsc)
413  return static_cast<TOutput>(SHR);
414 
416  BBCSRType bbcsrf = BBCSRType();
417  bbcsrf.SetTV1(this->m_TV1);
418  bbcsrf.SetTV2(this->m_TV2);
419  bbcsrf.SetSAT(this->m_SAT);
420 
421  bool bbcsr = bbcsrf(newPixel);
422  // average herbaceous rangeland spectral category
423  bool ahrsc = (rsr || bbcsr) && mNDVI && hNDBSI;
424  if (ahrsc)
425  return static_cast<TOutput>(AHR);
426 
427  // dark rangeland spectral category
428  bool drsc = (vsr || rsr) && lNDVI && lMIR2 && !(hNIR || hMIR1 || lNDBSI);
429  if (drsc)
430  return static_cast<TOutput>(DR);
431 
432  // bright barren land or built up spectral category
433  bool bbbsc = bbcsr && hNIR && lNDVI && hNDBSI && !(lMIR1 || lMIR2);
434 
435  bool lNDBBBI = (lv[LVType::ndbbbi] == LVType::Low);
436 
437  bool bbbhtirsc = bbbsc && hTIR;
438 
439  if (bbbhtirsc && !(lNDBBBI))
440  return static_cast<TOutput>(BBBHTIRF);
441  if (bbbhtirsc && lNDBBBI)
442  return static_cast<TOutput>(BBBHTIRNF);
443 
444  bool bbbltirsc = bbbsc && !(hTIR);
445  if (bbbltirsc && !(lNDBBBI))
446  return static_cast<TOutput>(BBBLTIRF);
447  if (bbbltirsc && lNDBBBI)
448  return static_cast<TOutput>(BBBLTIRNF);
449 
451  FBBSRType fbbsrf = FBBSRType();
452  fbbsrf.SetTV1(this->m_TV1);
453  fbbsrf.SetTV2(this->m_TV2);
454  fbbsrf.SetSAT(this->m_SAT);
455 
456  bool fbbsr = fbbsrf(newPixel);
457  // strong barren land or built up spectral category
458  bool sbbsc = (bbcsr || fbbsr) && lNDVI && hNDBSI && !(hNIR || lMIR1);
459 
460  bool sbbhtirsc = sbbsc && hTIR;
461 
462  if (sbbhtirsc && (dbsr || fbbsr))
463  return static_cast<TOutput>(SBBHTIRF);
464  if (sbbhtirsc && !(dbsr || fbbsr))
465  return static_cast<TOutput>(SBBHTIRNF);
466 
467  bool sbbltirsc = sbbsc && !(hTIR);
468  if (sbbltirsc && (dbsr || fbbsr))
469  return static_cast<TOutput>(SBBLTIRF);
470  if (sbbltirsc && !((dbsr || fbbsr)))
471  return static_cast<TOutput>(SBBLTIRNF);
472 
473  // average barren land or built up spectral category
474  bool abbsc = (bbcsr || fbbsr) && lNDVI && mNDBSI && !(lMIR1);
475 
476  bool abbhtirsc = abbsc && hTIR;
477 
478  if (abbhtirsc && !(lNDBBBI))
479  return static_cast<TOutput>(ABBHTIRF);
480  if (abbhtirsc && lNDBBBI)
481  return static_cast<TOutput>(ABBHTIRNF);
482 
483  bool abbltirsc = abbsc && !(hTIR);
484  if (abbltirsc && !(lNDBBBI))
485  return static_cast<TOutput>(ABBLTIRF);
486  if (abbltirsc && lNDBBBI)
487  return static_cast<TOutput>(ABBLTIRNF);
488 
489  // dark barren land or built
490  bool dbbsc = (bbcsr || fbbsr) && lNDVI && lMIR1 && !(hNIR || hMIR2 || lNDBSI);
491 
492  bool dbbhtirsc = dbbsc && hTIR;
493 
494  if (dbbhtirsc && (dbsr || fbbsr))
495  return static_cast<TOutput>(DBBHTIRF);
496  if (dbbhtirsc && !(dbsr || fbbsr))
497  return static_cast<TOutput>(DBBHTIRNF);
498 
499  bool dbbltirsc = dbbsc && !(hTIR);
500  if (dbbltirsc && (dbsr || fbbsr))
501  return static_cast<TOutput>(DBBLTIRF);
502  if (dbbltirsc && !((dbsr || fbbsr)))
503  return static_cast<TOutput>(DBBLTIRNF);
504 
505  // weak rangeland spectral category
506  bool wrsc = rsr && lNDVI && !(lNDBSI);
507  if (wrsc)
508  return static_cast<TOutput>(WR);
509 
510  // shadow area with vegetation spectral category
511  bool shvsc = dbsr && shvsr && lBright && lVis && lNIR && lMIR1 && lMIR2 && !(hNDVI);
512  if (shvsc)
513  return static_cast<TOutput>(SHV);
514 
516  SHBSRType shbsrf = SHBSRType();
517  shbsrf.SetTV1(this->m_TV1);
518  shbsrf.SetTV2(this->m_TV2);
519  shbsrf.SetSAT(this->m_SAT);
520 
521  bool shbsr = shbsrf(newPixel);
522  // shadow with barren land spectral category
523  bool shbsc = dbsr && shbsr && lBright && lVis && lNDVI && lNIR && lMIR1 && lMIR2;
524  if (shbsc)
525  return static_cast<TOutput>(SHB);
526 
527  typedef ShadowCloudOrSnowSpectralRule<TInput, bool> SHCLSNSRType;
528  SHCLSNSRType shclsnsrf = SHCLSNSRType();
529  shclsnsrf.SetTV1(this->m_TV1);
530  shclsnsrf.SetTV2(this->m_TV2);
531  shclsnsrf.SetSAT(this->m_SAT);
532 
533  bool shclsnsr = shclsnsrf(newPixel);
534  // clouds in shadow areas spectral category
535  bool shclsc = dbsr && shclsnsr && !(hNDSIVis || lNIR || lBright || lVis || hNDBSI || hTIR);
536  if (shclsc)
537  return static_cast<TOutput>(SHCL);
538 
539  bool hBright = (lv[LVType::bright] == LVType::High);
540  bool hVis = (lv[LVType::vis] == LVType::High);
541  // turbid water or shadow snow spectral category
542  bool twashsnsc = dbsr && shclsnsr && hNDSIVis && lNIR && lMIR1 && lMIR2 && !(hBright || hVis || hNDBSI || hTIR);
543  if (twashsnsc)
544  return static_cast<TOutput>(TWASHSN);
545 
546  // non forested wetland spectral category
547  bool wesc = dbsr && wesr && lBright && lVis && lNIR && lMIR1 && lMIR2 && !(hNDVI || hNDBSI || lNDSIVis);
548  if (wesc)
549  return static_cast<TOutput>(WE);
550 
551  // turbid water spectral category
552  bool twasc = dbsr && lNDVI && lMIR1 && lMIR2 && !(hBright || hVis || hNIR || lNDSIVis);
553  if (twasc)
554  return static_cast<TOutput>(TWA);
555 
556  return static_cast<TOutput>(SU);
557  }
558 };
559 
560 
561 } // namespace LandsatTM
562 } // namespace Functor
563 } // namespace otb
564 
565 #endif
TInput PrepareValues(const TInput &inputPixel)
Prepare the values so they are normalized and in C.
Implementation of the SpectralRuleBasedClassifier for Landsat TM image land cover classification as d...
The "otb" namespace contains all Orfeo Toolbox (OTB) classes.