Orfeo Toolbox  3.16
ScalarImageKmeansClassifier.cxx
Go to the documentation of this file.
1 /*=========================================================================
2 
3  Program: ORFEO Toolbox
4  Language: C++
5  Date: $Date$
6  Version: $Revision$
7 
8 
9  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
10  See OTBCopyright.txt for details.
11 
12 
13  This software is distributed WITHOUT ANY WARRANTY; without even
14  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  PURPOSE. See the above copyright notices for more information.
16 
17 =========================================================================*/
18 
19 
20 // Software Guide : BeginCommandLineArgs
21 // INPUTS: {QB_Suburb.png}
22 // OUTPUTS: {QB_Suburb_labelled.png}
23 // 0 4 79.5097 138.136 213.846 25.9395
24 // NORMALIZE_EPS_OUTPUT_OF: {QB_Suburb_labelled.png}
25 // Software Guide : EndCommandLineArgs
26 
27 // Software Guide : BeginLatex
28 //
29 // This example shows how to use the KMeans model for classifying the pixel of
30 // a scalar image.
31 //
32 // The \subdoxygen{itk}{Statistics}{ScalarImageKmeansImageFilter} is used for taking
33 // a scalar image and applying the K-Means algorithm in order to define classes
34 // that represents statistical distributions of intensity values in the pixels.
35 // The classes are then used in this filter for generating a labeled image where
36 // every pixel is assigned to one of the classes.
37 //
38 // Software Guide : EndLatex
39 
40 // Software Guide : BeginCodeSnippet
41 #include "otbImage.h"
42 #include "otbImageFileReader.h"
43 #include "otbImageFileWriter.h"
45 // Software Guide : EndCodeSnippet
46 
47 int main(int argc, char * argv[])
48 {
49  if (argc < 5)
50  {
51  std::cerr << "Usage: " << std::endl;
52  std::cerr << argv[0];
53  std::cerr << " inputScalarImage outputLabeledImage contiguousLabels";
54  std::cerr << " numberOfClasses mean1 mean2... meanN " << std::endl;
55  return EXIT_FAILURE;
56  }
57 
58  const char * inputImageFileName = argv[1];
59 
60 // Software Guide : BeginLatex
61 //
62 // First we define the pixel type and dimension of the image that we intend to
63 // classify. With this image type we can also declare the
64 // \doxygen{otb}{ImageFileReader} needed for reading the input image, create one and
65 // set its input filename.
66 //
67 // Software Guide : EndLatex
68 
69 // Software Guide : BeginCodeSnippet
70  typedef signed short PixelType;
71  const unsigned int Dimension = 2;
72 
73  typedef otb::Image<PixelType, Dimension> ImageType;
74 
75  typedef otb::ImageFileReader<ImageType> ReaderType;
76  ReaderType::Pointer reader = ReaderType::New();
77  reader->SetFileName(inputImageFileName);
78 // Software Guide : EndCodeSnippet
79 
80 // Software Guide : BeginLatex
81 //
82 // With the \code{ImageType} we instantiate the type of the
83 // \doxygen{itk}{ScalarImageKmeansImageFilter} that will compute the K-Means model
84 // and then classify the image pixels.
85 //
86 // Software Guide : EndLatex
87 
88 // Software Guide : BeginCodeSnippet
89  typedef itk::ScalarImageKmeansImageFilter<ImageType> KMeansFilterType;
90 
91  KMeansFilterType::Pointer kmeansFilter = KMeansFilterType::New();
92 
93  kmeansFilter->SetInput(reader->GetOutput());
94 
95  const unsigned int numberOfInitialClasses = atoi(argv[4]);
96 // Software Guide : EndCodeSnippet
97 
98 // Software Guide : BeginLatex
99 //
100 // In general the classification will produce as output an image whose pixel
101 // values are integers associated to the labels of the classes. Since typically
102 // these integers will be generated in order (0, 1, 2, ...N), the output image
103 // will tend to look very dark when displayed with naive viewers. It is
104 // therefore convenient to have the option of spreading the label values over
105 // the dynamic range of the output image pixel type. When this is done, the
106 // dynamic range of the pixels is divided by the number of classes in order to
107 // define the increment between labels. For example, an output image of 8 bits
108 // will have a dynamic range of [0:255], and when it is used for holding four
109 // classes, the non-contiguous labels will be (0, 64, 128, 192). The selection of
110 // the mode to use is done with the method \code{SetUseContiguousLabels()}.
111 //
112 // Software Guide : EndLatex
113 
114 // Software Guide : BeginCodeSnippet
115  const unsigned int useNonContiguousLabels = atoi(argv[3]);
116 
117  kmeansFilter->SetUseNonContiguousLabels(useNonContiguousLabels);
118 // Software Guide : EndCodeSnippet
119 
120  const unsigned int argoffset = 5;
121 
122  if (static_cast<unsigned int>(argc) <
123  numberOfInitialClasses + argoffset)
124  {
125  std::cerr << "Error: " << std::endl;
126  std::cerr << numberOfInitialClasses << " classes has been specified ";
127  std::cerr << "but no enough means have been provided in the command ";
128  std::cerr << "line arguments " << std::endl;
129  return EXIT_FAILURE;
130  }
131 
132 // Software Guide : BeginLatex
133 //
134 // For each one of the classes we must provide a tentative initial value for
135 // the mean of the class. Given that this is a scalar image, each one of the
136 // means is simply a scalar value. Note however that in a general case of
137 // K-Means, the input image would be a vector image and therefore the means
138 // will be vectors of the same dimension as the image pixels.
139 //
140 // Software Guide : EndLatex
141 
142 // Software Guide : BeginCodeSnippet
143  for (unsigned k = 0; k < numberOfInitialClasses; ++k)
144  {
145  const double userProvidedInitialMean = atof(argv[k + argoffset]);
146  kmeansFilter->AddClassWithInitialMean(userProvidedInitialMean);
147  }
148 // Software Guide : EndCodeSnippet
149 
150  const char * outputImageFileName = argv[2];
151 
152 // Software Guide : BeginLatex
153 //
154 // The \doxygen{itk}{ScalarImageKmeansImageFilter} is predefined for producing an 8
155 // bits scalar image as output. This output image contains labels associated
156 // to each one of the classes in the K-Means algorithm. In the following lines
157 // we use the \code{OutputImageType} in order to instantiate the type of a
158 // \doxygen{otb}{ImageFileWriter}. Then create one, and connect it to the output of
159 // the classification filter.
160 //
161 // Software Guide : EndLatex
162 
163 // Software Guide : BeginCodeSnippet
164  typedef KMeansFilterType::OutputImageType OutputImageType;
165 
166  typedef otb::ImageFileWriter<OutputImageType> WriterType;
167 
168  WriterType::Pointer writer = WriterType::New();
169 
170  writer->SetInput(kmeansFilter->GetOutput());
171 
172  writer->SetFileName(outputImageFileName);
173 // Software Guide : EndCodeSnippet
174 
175 // Software Guide : BeginLatex
176 //
177 // We are now ready for triggering the execution of the pipeline. This is done
178 // by simply invoking the \code{Update()} method in the writer. This call will
179 // propagate the update request to the reader and then to the classifier.
180 //
181 // Software Guide : EndLatex
182 
183 // Software Guide : BeginCodeSnippet
184  try
185  {
186  writer->Update();
187  }
188  catch (itk::ExceptionObject& excp)
189  {
190  std::cerr << "Problem encountered while writing ";
191  std::cerr << " image file : " << argv[2] << std::endl;
192  std::cerr << excp << std::endl;
193  return EXIT_FAILURE;
194  }
195 // Software Guide : EndCodeSnippet
196 
197 // Software Guide : BeginLatex
198 //
199 // At this point the classification is done, the labeled image is saved in a
200 // file, and we can take a look at the means that were found as a result of the
201 // model estimation performed inside the classifier filter.
202 //
203 // Software Guide : EndLatex
204 
205 // Software Guide : BeginCodeSnippet
206  KMeansFilterType::ParametersType estimatedMeans =
207  kmeansFilter->GetFinalMeans();
208 
209  const unsigned int numberOfClasses = estimatedMeans.Size();
210 
211  for (unsigned int i = 0; i < numberOfClasses; ++i)
212  {
213  std::cout << "cluster[" << i << "] ";
214  std::cout << " estimated mean : " << estimatedMeans[i] << std::endl;
215  }
216 // Software Guide : EndCodeSnippet
217 
218 // Software Guide : BeginLatex
219 //
220 // \begin{figure} \center
221 // \includegraphics[width=0.44\textwidth]{QB_Suburb.eps}
222 // \includegraphics[width=0.44\textwidth]{QB_Suburb_labelled.eps}
223 // \itkcaption[Output of the KMeans classifier]{Effect of the
224 // KMeans classifier. Left: original image. Right: image of classes.}
225 // \label{fig:ScalarImageKMeansClassifierOutput}
226 // \end{figure}
227 //
228 // Figure \ref{fig:ScalarImageKMeansClassifierOutput}
229 // illustrates the effect of this filter with three classes.
230 // The means can be estimated by ScalarImageKmeansModelEstimator.cxx.
231 //
232 // Software Guide : EndLatex
233 
234  return EXIT_SUCCESS;
235 
236 }

Generated at Sun Feb 3 2013 00:59:33 for Orfeo Toolbox with doxygen 1.8.1.1