ClassificationMapRegularizationExample.cxx 5.81 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


// After having generated a classification map, it is possible to
// regularize such a labeled image in order to obtain more homogeneous
24
// areas, which facilitates its interpretation. For this
25 26 27
// purpose, the \doxygen{otb}{NeighborhoodMajorityVotingImageFilter} was
// implemented. Like a morphological filter, this filter uses majority
// voting in a ball shaped neighborhood in order to set each pixel of the
28
// classification map to the most representative label value in its
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
// neighborhood.
//
// In this example we will illustrate its use. We start by including the
// appropriate header file.

#include "otbNeighborhoodMajorityVotingImageFilter.h"

#include "itkMacro.h"
#include "otbImage.h"
#include <iostream>

#include <otbImageFileReader.h>
#include "otbImageFileWriter.h"


44
int main(int itkNotUsed(argc), char* argv[])
45
{
46 47 48
  // Since the input image is a classification map, we will assume a
  // single band input image for which each pixel value is a label coded
  // on 8 bits as an integer between 0 and 255.
49

50
  typedef unsigned char IOLabelPixelType; // 8 bits
51
  const unsigned int    Dimension = 2;
52

53 54 55
  // Thus, both input and output images are single band labeled images,
  // which are composed of the same type of pixels in this example
  // (unsigned char).
56

57
  typedef otb::Image<IOLabelPixelType, Dimension> IOLabelImageType;
58 59


60 61 62 63 64 65
  // We can now define the type for the neighborhood majority voting filter,
  // which is templated over its input and output images types as well as its
  // structuring element type. Choosing only the input image type in the template
  // of this filter induces that, both input and output images types are the same
  // and that the structuring element is a ball
  // (\doxygen{itk}{BinaryBallStructuringElement}).
66

67
  // Neighborhood majority voting filter type
68
  typedef otb::NeighborhoodMajorityVotingImageFilter<IOLabelImageType> NeighborhoodMajorityVotingFilterType;
69 70


71 72 73 74 75 76 77
  // Since the \doxygen{otb}{NeighborhoodMajorityVotingImageFilter} is a
  // neighborhood based image filter, it is necessary to set the structuring
  // element which will be used for the majority voting process. By default, the
  // structuring element is a ball
  // (\doxygen{itk}{BinaryBallStructuringElement}) with a radius defined by two sizes
  // (respectively along X and Y). Thus, it is possible to handle anisotropic
  // structuring elements such as ovals.
78

79 80
  // Binary ball Structuring Element type
  typedef NeighborhoodMajorityVotingFilterType::KernelType StructuringType;
81
  typedef StructuringType::RadiusType                      RadiusType;
82 83


84
  // Finally, we define the reader and the writer.
85

86 87
  typedef otb::ImageFileReader<IOLabelImageType> ReaderType;
  typedef otb::ImageFileWriter<IOLabelImageType> WriterType;
88 89


90 91
  const char* inputFileName  = argv[1];
  const char* outputFileName = argv[2];
92

93

94 95
  // We instantiate the \doxygen{otb}{NeighborhoodMajorityVotingImageFilter} and the
  // reader objects.
96 97 98 99

  // Neighborhood majority voting filter
  NeighborhoodMajorityVotingFilterType::Pointer NeighMajVotingFilter;
  NeighMajVotingFilter = NeighborhoodMajorityVotingFilterType::New();
100

101 102
  ReaderType::Pointer reader = ReaderType::New();
  reader->SetFileName(inputFileName);
103 104


105 106 107 108 109
  std::string      KeepOriginalLabelBoolStr = argv[3];
  unsigned int     radiusX                  = atoi(argv[4]);
  unsigned int     radiusY                  = atoi(argv[5]);
  IOLabelPixelType noDataValue              = atoi(argv[6]);
  IOLabelPixelType undecidedValue           = atoi(argv[7]);
110 111


112 113
  // The ball shaped structuring element seBall is instantiated and its
  // two radii along X and Y are initialized.
114

115
  StructuringType seBall;
116
  RadiusType      rad;
117

118 119 120 121 122
  rad[0] = radiusX;
  rad[1] = radiusY;

  seBall.SetRadius(rad);
  seBall.CreateStructuringElement();
123 124


125 126
  // Then, this ball shaped neighborhood is used as the kernel structuring element
  // for the \doxygen{otb}{NeighborhoodMajorityVotingImageFilter}.
127 128 129

  NeighMajVotingFilter->SetKernel(seBall);

130 131
  // Not classified input pixels are assumed to have the noDataValue label
  // and will keep this label in the output image.
132 133 134 135

  NeighMajVotingFilter->SetLabelForNoDataPixels(noDataValue);


136 137 138 139 140 141
  // Furthermore, since the majority voting regularization may lead to different
  // majority labels in the neighborhood, in this case, it would be important to define
  // the filter's behaviour. For this purpose, a Boolean parameter is used
  // in the filter to choose whether pixels with more than one majority class are set
  // to undecidedValue (true), or to their Original labels (false = default value)
  // in the output image.
142 143 144


  NeighMajVotingFilter->SetLabelForUndecidedPixels(undecidedValue);
145

146 147 148 149 150 151 152 153 154 155
  if (KeepOriginalLabelBoolStr.compare("true") == 0)
  {
    NeighMajVotingFilter->SetKeepOriginalLabelBool(true);
  }
  else
  {
    NeighMajVotingFilter->SetKeepOriginalLabelBool(false);
  }


156 157
  // We plug the pipeline and
  // trigger its execution by updating the output of the writer.
158 159 160


  NeighMajVotingFilter->SetInput(reader->GetOutput());
161

162 163 164 165
  WriterType::Pointer writer = WriterType::New();
  writer->SetFileName(outputFileName);
  writer->SetInput(NeighMajVotingFilter->GetOutput());
  writer->Update();
166

167 168
  return EXIT_SUCCESS;
}