AVIMultiChannelRAndGAndNIRVegetationIndexImageFilter.cxx 8.93 KB
Newer Older
1
/*
Julien Michel's avatar
Julien Michel committed
2
 * Copyright (C) 2005-2019 Centre National d'Etudes Spatiales (CNES)
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
 *
 * This file is part of Orfeo Toolbox
 *
 *     https://www.orfeo-toolbox.org/
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
20

21

22 23 24 25 26 27 28 29 30 31 32 33
/* Example usage:
./AVIMultiChannelRAndGAndNIRVegetationIndexImageFilter Input/verySmallFSATSW.tif \
                                                       Output/AVIMultiChannelRAndGAndNIRVegetationIndex.tif \
                                                       Output/pretty_FSATSW.png \
                                                       Output/pretty_AVIMultiChannelRAndGAndNIRVegetationIndex.png \
                                                       3 \
                                                       2 \
                                                       4 \
                                                       660 \
                                                       560 \
                                                       830
*/
34 35 36 37 38 39 40


// \index{otb::VegetationIndex}
// \index{otb::VegetationIndex!header}
//
//
// The following example illustrates the use of the
41
// itk::UnaryFunctorImageFilter with the
42
// use of the Angular Vegetation Index (AVI).
Emmanuel Christophe's avatar
Emmanuel Christophe committed
43
// The equation for the Angular Vegetation Index involves the gren, red
Jordi Inglada's avatar
Jordi Inglada committed
44
// and near infra-red bands. $\lambda_1$, $\lambda_2$ and $\lambda_3$ are the mid-band
45
// wavelengths for the green, red and NIR bands and $\tan^{-1}$ is the arctangent function.
46 47 48 49
//
// The AVI expression is
//
// \begin{equation}
Jordi Inglada's avatar
Jordi Inglada committed
50
// \mathbf{A_1} = \frac{\lambda_3-\lambda_2}{\lambda_2}
51 52
// \end{equation}
// \begin{equation}
Jordi Inglada's avatar
Jordi Inglada committed
53
// \mathbf{A_2} = \frac{\lambda_2-\lambda_1}{\lambda_2}
54 55 56
// \end{equation}
//
// \begin{equation}
Jordi Inglada's avatar
Jordi Inglada committed
57
// \mathbf{AVI} = \tan^{-1}\left({\frac{A_1}{NIR-R}}\right) + \tan^{-1}\left({\frac{A_2}{G-R}}\right)
58 59 60 61 62
// \end{equation}
//
// For more details, refer to Plummer work \cite{AVI}.
//
//
63
// Let's look at the minimal code required to use this
64
// algorithm.
65

66 67
#include "otbVegetationIndicesFunctor.h"
#include "itkUnaryFunctorImageFilter.h"
68 69 70 71 72 73 74 75 76

#include "otbImage.h"
#include "otbImageFileReader.h"
#include "otbImageFileWriter.h"
#include "itkRescaleIntensityImageFilter.h"
#include "otbVectorRescaleIntensityImageFilter.h"
#include "otbMultiChannelExtractROI.h"
#include "itkThresholdImageFilter.h"

77
int main(int argc, char* argv[])
78
{
OTB Bot's avatar
STYLE  
OTB Bot committed
79
  if (argc < 11)
80
  {
81 82
    std::cerr << "Missing Parameters " << std::endl;
    std::cerr << "Usage: " << argv[0];
83
    std::cerr << " inputImage , outputImage , prettyInput , prettyOutput , redChannel , greenChannel , nirChannel ,";
84 85
    std::cerr << " lambdaR, lambdaG, lambdaNIR " << std::endl;
    return 1;
86
  }
87 88 89 90 91

  // The image types are now defined using pixel types and
  // dimension. The input image is defined as an \doxygen{otb}{VectorImage},
  // the output is a \doxygen{otb}{Image}.

92
  const unsigned int                                  Dimension = 2;
93 94
  typedef double                                      InputPixelType;
  typedef float                                       OutputPixelType;
OTB Bot's avatar
STYLE  
OTB Bot committed
95 96
  typedef otb::VectorImage<InputPixelType, Dimension> InputImageType;
  typedef otb::Image<OutputPixelType, Dimension>      OutputImageType;
97 98 99 100 101 102 103 104

  // We instantiate reader and writer types
  typedef otb::ImageFileReader<InputImageType>  ReaderType;
  typedef otb::ImageFileWriter<OutputImageType> WriterType;

  // The AVI (Angular Vegetation Index) is
  // instantiated using the image pixel types as template parameters.

105
  typedef otb::Functor::AVI<InputPixelType, InputPixelType, InputPixelType, OutputPixelType> FunctorType;
106 107

  // The
108
  // \doxygen{itk}{UnaryFunctorImageFilter}
109 110 111
  // type is defined using the image types and the AVI functor as
  // template parameters. We then instantiate the filter itself.

112
  typedef itk::UnaryFunctorImageFilter<InputImageType, OutputImageType, FunctorType> AVIImageFilterTypeType;
113

114
  AVIImageFilterTypeType::Pointer filter = AVIImageFilterTypeType::New();
115 116 117 118 119 120

  ReaderType::Pointer reader = ReaderType::New();
  WriterType::Pointer writer = WriterType::New();

  //  Now the input image is set and a name is given to the output image.

OTB Bot's avatar
STYLE  
OTB Bot committed
121 122
  reader->SetFileName(argv[1]);
  writer->SetFileName(argv[2]);
123 124 125

  // The three used index bands (red, green and NIR) are declared.

126 127 128
  filter->GetFunctor().SetRedIndex(::atoi(argv[5]));
  filter->GetFunctor().SetGreenIndex(::atoi(argv[6]));
  filter->GetFunctor().SetNIRIndex(::atoi(argv[7]));
129

OTB Bot's avatar
STYLE  
OTB Bot committed
130
  // The $\lambda$ R, G and NIR parameters are set. The
131
  // \doxygen{otb::Functor}{AVI}
Emmanuel Christophe's avatar
Emmanuel Christophe committed
132 133
  // class sets the default values of $\lambda$ to $660$, $560$ and
  // $830$.
134 135 136 137 138 139 140 141

  filter->GetFunctor().SetLambdaR(::atof(argv[8]));
  filter->GetFunctor().SetLambdaG(::atof(argv[9]));
  filter->GetFunctor().SetLambdaNir(::atof(argv[10]));

  // The filter input is linked to the reader output and
  // the filter output is linked to the writer input.

OTB Bot's avatar
STYLE  
OTB Bot committed
142
  filter->SetInput(reader->GetOutput());
143

OTB Bot's avatar
STYLE  
OTB Bot committed
144
  writer->SetInput(filter->GetOutput());
145 146 147 148 149 150

  //  The invocation of the \code{Update()} method on the writer triggers the
  //  execution of the pipeline.  It is recommended to place update calls in a
  //  \code{try/catch} block in case errors occur and exceptions are thrown.

  try
151
  {
152
    writer->Update();
153
  }
OTB Bot's avatar
STYLE  
OTB Bot committed
154
  catch (itk::ExceptionObject& excep)
155
  {
156 157
    std::cerr << "Exception caught !" << std::endl;
    std::cerr << excep << std::endl;
158
  }
OTB Bot's avatar
STYLE  
OTB Bot committed
159
  catch (...)
160
  {
161 162
    std::cout << "Unknown exception !" << std::endl;
    return EXIT_FAILURE;
163
  }
164 165

  // Pretty image creation for the printing
166 167 168 169 170 171 172 173 174 175 176
  typedef otb::Image<unsigned char, Dimension>                                                OutputPrettyImageType;
  typedef otb::VectorImage<unsigned char, Dimension>                                          OutputVectorPrettyImageType;
  typedef otb::ImageFileWriter<OutputVectorPrettyImageType>                                   WriterVectorPrettyType;
  typedef otb::ImageFileWriter<OutputPrettyImageType>                                         WriterPrettyType;
  typedef itk::RescaleIntensityImageFilter<OutputImageType, OutputPrettyImageType>            RescalerType;
  typedef otb::VectorRescaleIntensityImageFilter<InputImageType, OutputVectorPrettyImageType> VectorRescalerType;
  typedef otb::MultiChannelExtractROI<unsigned char, unsigned char>                           ChannelExtractorType;

  VectorRescalerType::Pointer     vectRescaler     = VectorRescalerType::New();
  ChannelExtractorType::Pointer   selecter         = ChannelExtractorType::New();
  WriterVectorPrettyType::Pointer vectPrettyWriter = WriterVectorPrettyType::New();
OTB Bot's avatar
STYLE  
OTB Bot committed
177 178

  OutputVectorPrettyImageType::PixelType minimum, maximum;
179 180 181 182 183 184
  minimum.SetSize(reader->GetOutput()->GetNumberOfComponentsPerPixel());
  maximum.SetSize(reader->GetOutput()->GetNumberOfComponentsPerPixel());
  minimum.Fill(0);
  maximum.Fill(255);
  vectRescaler->SetOutputMinimum(minimum);
  vectRescaler->SetOutputMaximum(maximum);
185
  //  vectRescaler->SetClampThreshold(1);
OTB Bot's avatar
STYLE  
OTB Bot committed
186
  vectRescaler->SetInput(reader->GetOutput());
187 188 189

  selecter->SetInput(vectRescaler->GetOutput());
  selecter->SetChannel(3);
Jordi Inglada's avatar
Jordi Inglada committed
190 191
  selecter->SetChannel(2);
  selecter->SetChannel(1);
192

OTB Bot's avatar
STYLE  
OTB Bot committed
193 194
  vectPrettyWriter->SetFileName(argv[3]);
  vectPrettyWriter->SetInput(selecter->GetOutput());
195

OTB Bot's avatar
STYLE  
OTB Bot committed
196
  typedef itk::ThresholdImageFilter<OutputImageType> ThresholderType;
197 198

  ThresholderType::Pointer thresholder = ThresholderType::New();
OTB Bot's avatar
STYLE  
OTB Bot committed
199 200 201
  thresholder->SetInput(filter->GetOutput());
  thresholder->SetOutsideValue(1.0);
  thresholder->ThresholdOutside(-1.0, 0.05);
202 203 204 205
  thresholder->Update();

  RescalerType::Pointer     rescaler     = RescalerType::New();
  WriterPrettyType::Pointer prettyWriter = WriterPrettyType::New();
OTB Bot's avatar
STYLE  
OTB Bot committed
206
  rescaler->SetInput(thresholder->GetOutput());
207 208
  rescaler->SetOutputMinimum(0);
  rescaler->SetOutputMaximum(255);
OTB Bot's avatar
STYLE  
OTB Bot committed
209 210
  prettyWriter->SetFileName(argv[4]);
  prettyWriter->SetInput(rescaler->GetOutput());
211 212

  try
213
  {
214 215
    prettyWriter->Update();
    vectPrettyWriter->Update();
216
  }
OTB Bot's avatar
STYLE  
OTB Bot committed
217
  catch (itk::ExceptionObject& excep)
218
  {
219 220
    std::cerr << "Exception caught !" << std::endl;
    std::cerr << excep << std::endl;
221
  }
OTB Bot's avatar
STYLE  
OTB Bot committed
222
  catch (...)
223
  {
224 225
    std::cout << "Unknown exception !" << std::endl;
    return EXIT_FAILURE;
226
  }
227 228 229 230

  return EXIT_SUCCESS;

  // Let's now run this example using as input the image
231
  // \code{verySmallFSATSW.tif} provided in the
232 233 234 235
  // directory \code{Examples/Data}.
  //
  //
  // \begin{figure} \center
236
  // \includegraphics[width=0.24\textwidth]{pretty_FSATSW.eps}
237 238
  // \includegraphics[width=0.24\textwidth]{pretty_AVIMultiChannelRAndGAndNIRVegetationIndex.eps}
  // \itkcaption[AVI Example]{AVI result on the right with the left image in input.}
239
  // \label{fig:AVIMultiChannelRAndGAndNIRIndexImageFilter}
240 241
  // \end{figure}
}