OTB  9.0.0
Orfeo Toolbox
otbMarkovRandomFieldFilter.hxx
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2005-2022 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 
22 #ifndef otbMarkovRandomFieldFilter_hxx
23 #define otbMarkovRandomFieldFilter_hxx
25 
26 namespace otb
27 {
28 template <class TInputImage, class TClassifiedImage>
30  : m_NumberOfClasses(0),
31  m_MaximumNumberOfIterations(50),
32  m_ErrorCounter(0),
33  m_ImageDeltaEnergy(0.0),
34  m_NeighborhoodRadius(1),
35  m_TotalNumberOfValidPixelsInOutputImage(1),
36  m_TotalNumberOfPixelsInInputImage(1),
37  m_ErrorTolerance(0.0),
38  m_SmoothingFactor(1.0),
39  m_NumberOfIterations(0),
40  m_Lambda(1.0),
41  m_ExternalClassificationSet(false),
42  m_StopCondition(MaximumNumberOfIterations)
43 {
44  m_Generator = RandomGeneratorType::GetInstance();
45  m_Generator->SetSeed();
46 
47  this->SetNumberOfRequiredInputs(1);
49  {
50  std::ostringstream msg;
51  msg << "Input image dimension: " << InputImageDimension << " != output image dimension: " << ClassifiedImageDimension;
52  throw itk::ExceptionObject(__FILE__, __LINE__, msg.str(), ITK_LOCATION);
53  }
55  // m_MRFNeighborhoodWeight.resize(0);
56  // m_NeighborInfluence.resize(0);
57  // m_DummyVector.resize(0);
58  // this->SetMRFNeighborhoodWeight( m_DummyVector );
59  // this->SetDefaultMRFNeighborhoodWeight();
60 
61  // srand((unsigned)time(0));
62 }
63 
64 template <class TInputImage, class TClassifiedImage>
66 {
67  m_ExternalClassificationSet = true;
68  // Process object is not const-correct so the const_cast is required here
69  this->itk::ProcessObject::SetNthInput(1, const_cast<TrainingImageType*>(trainingImage));
70  this->Modified();
71 }
72 
73 template <class TInputImage, class TClassifiedImage>
76 {
77  if (this->GetNumberOfInputs() < 2)
78  {
79  return nullptr;
80  }
81  return static_cast<const TrainingImageType*>(this->itk::ProcessObject::GetInput(1));
82 }
83 
84 template <class TInputImage, class TClassifiedImage>
85 void MarkovRandomFieldFilter<TInputImage, TClassifiedImage>::PrintSelf(std::ostream& os, itk::Indent indent) const
86 {
87  Superclass::PrintSelf(os, indent);
88 
89  os << indent << " MRF Image filter object " << std::endl;
90 
91  os << indent << " Number of classes: " << m_NumberOfClasses << std::endl;
92 
93  os << indent << " Maximum number of iterations: " << m_MaximumNumberOfIterations << std::endl;
94 
95  os << indent << " Error tolerance for convergence: " << m_ErrorTolerance << std::endl;
96 
97  os << indent << " Size of the MRF neighborhood radius:" << m_InputImageNeighborhoodRadius << std::endl;
98 
99  os << indent << "StopCondition: " << m_StopCondition << std::endl;
100 
101  os << indent << " Number of iterations: " << m_NumberOfIterations << std::endl;
102 
103  os << indent << " Lambda: " << m_Lambda << std::endl;
104 } // end PrintSelf
105 
109 template <class TInputImage, class TClassifiedImage>
111 {
112  // this filter requires the all of the input images
113  // to be at the size of the output requested region
114  InputImagePointer inputPtr = const_cast<InputImageType*>(this->GetInput());
115  OutputImagePointer outputPtr = this->GetOutput();
116  inputPtr->SetRequestedRegion(outputPtr->GetRequestedRegion());
117 }
119 
123 template <class TInputImage, class TClassifiedImage>
125 {
126  // this filter requires the all of the output image to be in
127  // the buffer
128  TClassifiedImage* imgData;
129  imgData = dynamic_cast<TClassifiedImage*>(output);
130  imgData->SetRequestedRegionToLargestPossibleRegion();
131 }
133 
137 template <class TInputImage, class TClassifiedImage>
139 {
140  typename TInputImage::ConstPointer input = this->GetInput();
141  typename TClassifiedImage::Pointer output = this->GetOutput();
142  output->SetLargestPossibleRegion(input->GetLargestPossibleRegion());
143 }
145 
146 template <class TInputImage, class TClassifiedImage>
148 {
149 
150  // InputImageConstPointer inputImage = this->GetInput();
151 
152  // Allocate memory for the labelled images
153  this->Allocate();
154 
155  // Branch the pipeline
156  this->Initialize();
157 
158  // Run the Markov random field
159  this->ApplyMarkovRandomFieldFilter();
160 
161 } // end GenerateData
162 
166 template <class TInputImage, class TClassifiedImage>
168 {
169  // Set up the neighbor hood
170  NeighborhoodRadiusType radius;
171  for (unsigned int i = 0; i < InputImageDimension; ++i)
172  {
173  radius[i] = radiusValue;
174  }
175  this->SetNeighborhoodRadius(radius);
177 
178 } // end SetNeighborhoodRadius
179 
183 template <class TInputImage, class TClassifiedImage>
185 {
186  NeighborhoodRadiusType radius;
187  for (unsigned int i = 0; i < InputImageDimension; ++i)
188  {
189  radius[i] = radiusArray[i];
190  }
191  // Set up the neighbor hood
192  this->SetNeighborhoodRadius(radius);
194 
195 } // end SetNeighborhoodRadius
196 
200 template <class TInputImage, class TClassifiedImage>
202 {
203  // Set up the neighbor hood
204  for (unsigned int i = 0; i < InputImageDimension; ++i)
205  {
206  m_InputImageNeighborhoodRadius[i] = radius[i];
207  m_LabelledImageNeighborhoodRadius[i] = radius[i];
208  }
210 
211 } // end SetNeighborhoodRadius
212 //-------------------------------------------------------
213 
217 template <class TInputImage, class TClassifiedImage>
219 {
220  // Set the output labelled and allocate the memory
221  LabelledImagePointer outputPtr = this->GetOutput();
222 
223  // Allocate the output buffer memory
224  outputPtr->SetBufferedRegion(outputPtr->GetRequestedRegion());
225  outputPtr->Allocate();
226 
227  // Copy input data in the output buffer memory or
228  // initialize to random values if not set
229  LabelledImageRegionIterator outImageIt(outputPtr, outputPtr->GetRequestedRegion());
230 
231  if (m_ExternalClassificationSet)
232  {
233  typename TrainingImageType::ConstPointer trainingImage = this->GetTrainingInput();
234  LabelledImageRegionConstIterator trainingImageIt(trainingImage, outputPtr->GetRequestedRegion());
235 
236  while (!outImageIt.IsAtEnd())
237  {
238  LabelledImagePixelType labelvalue = static_cast<LabelledImagePixelType>(trainingImageIt.Get());
239 
240  outImageIt.Set(labelvalue);
241  ++trainingImageIt;
242  ++outImageIt;
243  } // end while
244  }
245  else // set to random value
246  {
247  // srand((unsigned)time(0));
248  while (!outImageIt.IsAtEnd())
249  {
250  LabelledImagePixelType randomvalue = static_cast<LabelledImagePixelType>(m_Generator->GetIntegerVariate() % static_cast<int>(m_NumberOfClasses));
251  outImageIt.Set(randomvalue);
252  ++outImageIt;
253  } // end while
254  }
255 
256 } // Allocate
257 
261 template <class TInputImage, class TClassifiedImage>
263 {
264 
265  m_ImageDeltaEnergy = 0.0;
266 
267  InputImageSizeType inputImageSize = this->GetInput()->GetBufferedRegion().GetSize();
268 
269  //---------------------------------------------------------------------
270  // Get the number of valid pixels in the output MRF image
271  //---------------------------------------------------------------------
272 
273  m_TotalNumberOfPixelsInInputImage = 1;
274  m_TotalNumberOfValidPixelsInOutputImage = 1;
275 
276  for (unsigned int i = 0; i < InputImageDimension; ++i)
277  {
278  m_TotalNumberOfPixelsInInputImage *= static_cast<int>(inputImageSize[i]);
279 
280  m_TotalNumberOfValidPixelsInOutputImage *= (static_cast<int>(inputImageSize[i]) - 2 * m_InputImageNeighborhoodRadius[i]);
281  }
282 
283  srand((unsigned)time(nullptr));
284 
285  if (!m_EnergyRegularization)
286  {
287  itkExceptionMacro(<< "EnergyRegularization is not present");
288  }
289 
290  if (!m_EnergyFidelity)
291  {
292  itkExceptionMacro(<< "EnergyFidelity is not present");
293  }
294 
295  if (!m_Optimizer)
296  {
297  itkExceptionMacro(<< "Optimizer is not present");
298  }
299 
300  if (!m_Sampler)
301  {
302  itkExceptionMacro(<< "Sampler is not present");
303  }
304 
305  m_Sampler->SetLambda(m_Lambda);
306  m_Sampler->SetEnergyRegularization(m_EnergyRegularization);
307  m_Sampler->SetEnergyFidelity(m_EnergyFidelity);
308  m_Sampler->SetNumberOfClasses(m_NumberOfClasses);
309 }
310 
314 template <class TInputImage, class TClassifiedImage>
316 {
317 
318  // Note: error should be defined according to the number of valid pixel in the output
319  int maxNumPixelError = itk::Math::Round<int, double>(m_ErrorTolerance * m_TotalNumberOfPixelsInInputImage);
320 
321  m_NumberOfIterations = 0;
322  m_ErrorCounter = m_TotalNumberOfValidPixelsInOutputImage;
323 
324  while ((m_NumberOfIterations < m_MaximumNumberOfIterations) && (m_ErrorCounter >= maxNumPixelError))
325  {
326  otbMsgDevMacro(<< "Iteration No." << m_NumberOfIterations);
327 
328  this->MinimizeOnce();
329 
330  otbMsgDevMacro(<< "m_ErrorCounter/m_TotalNumberOfPixelsInInputImage: " << m_ErrorCounter / ((double)(m_TotalNumberOfPixelsInInputImage)));
331  otbMsgDevMacro(<< "m_ImageDeltaEnergy: " << m_ImageDeltaEnergy);
332 
333  ++m_NumberOfIterations;
334  }
335 
336  otbMsgDevMacro(<< "m_NumberOfIterations: " << m_NumberOfIterations);
337  otbMsgDevMacro(<< "m_MaximumNumberOfIterations: " << m_MaximumNumberOfIterations);
338  otbMsgDevMacro(<< "m_ErrorCounter: " << m_ErrorCounter);
339  otbMsgDevMacro(<< "maxNumPixelError: " << maxNumPixelError);
340 
341  // Determine stop condition
342  if (m_NumberOfIterations >= m_MaximumNumberOfIterations)
343  {
344  m_StopCondition = MaximumNumberOfIterations;
345  }
346  else if (m_ErrorCounter <= maxNumPixelError)
347  {
348  m_StopCondition = ErrorTolerance;
349  }
350 
351 } // ApplyMarkovRandomFieldFilter
352 
356 template <class TInputImage, class TClassifiedImage>
358 {
359  LabelledImageNeighborhoodIterator labelledIterator(m_LabelledImageNeighborhoodRadius, this->GetOutput(), this->GetOutput()->GetLargestPossibleRegion());
360  InputImageNeighborhoodIterator dataIterator(m_InputImageNeighborhoodRadius, this->GetInput(), this->GetInput()->GetLargestPossibleRegion());
361  m_ErrorCounter = 0;
363 
364  for (labelledIterator.GoToBegin(), dataIterator.GoToBegin(); !labelledIterator.IsAtEnd(); ++labelledIterator, ++dataIterator)
365  {
366 
368  bool changeValueBool;
369  m_Sampler->Compute(dataIterator, labelledIterator);
370  value = m_Sampler->GetValue();
371  changeValueBool = m_Optimizer->Compute(m_Sampler->GetDeltaEnergy());
372  if (changeValueBool)
373  {
374  labelledIterator.SetCenterPixel(value);
375  ++m_ErrorCounter;
376  m_ImageDeltaEnergy += m_Sampler->GetDeltaEnergy();
377  }
378  }
379 }
380 
381 } // namespace otb
382 
383 #endif
otb::MarkovRandomFieldFilter::LabelledImagePixelType
TClassifiedImage::PixelType LabelledImagePixelType
Definition: otbMarkovRandomFieldFilter.h:134
otb::MarkovRandomFieldFilter::m_Generator
RandomGeneratorType::Pointer m_Generator
Definition: otbMarkovRandomFieldFilter.h:363
otb::MarkovRandomFieldFilter::TrainingImageType
TClassifiedImage TrainingImageType
Definition: otbMarkovRandomFieldFilter.h:121
otb::MarkovRandomFieldFilter::InputImagePointer
TInputImage::Pointer InputImagePointer
Definition: otbMarkovRandomFieldFilter.h:104
otb::MarkovRandomFieldFilter::LabelledImageNeighborhoodIterator
itk::NeighborhoodIterator< TClassifiedImage > LabelledImageNeighborhoodIterator
Definition: otbMarkovRandomFieldFilter.h:173
otb::MarkovRandomFieldFilter::ApplyMarkovRandomFieldFilter
virtual void ApplyMarkovRandomFieldFilter()
Definition: otbMarkovRandomFieldFilter.hxx:315
otb::MarkovRandomFieldFilter::SetNeighborhoodRadius
void SetNeighborhoodRadius(const NeighborhoodRadiusType &)
Definition: otbMarkovRandomFieldFilter.hxx:201
otb::MarkovRandomFieldFilter::OutputImagePointer
Superclass::OutputImagePointer OutputImagePointer
Definition: otbMarkovRandomFieldFilter.h:94
otb::MarkovRandomFieldFilter::ClassifiedImageDimension
static const unsigned int ClassifiedImageDimension
Definition: otbMarkovRandomFieldFilter.h:153
otb::MarkovRandomFieldFilter::Initialize
void Initialize()
Definition: otbMarkovRandomFieldFilter.hxx:262
otb
The "otb" namespace contains all Orfeo Toolbox (OTB) classes.
Definition: otbJoinContainer.h:32
otb::MarkovRandomFieldFilter::EnlargeOutputRequestedRegion
void EnlargeOutputRequestedRegion(itk::DataObject *) override
Definition: otbMarkovRandomFieldFilter.hxx:124
otb::MarkovRandomFieldFilter::MinimizeOnce
virtual void MinimizeOnce()
Definition: otbMarkovRandomFieldFilter.hxx:357
otb::MarkovRandomFieldFilter::LabelledImageRegionConstIterator
itk::ImageRegionConstIterator< TClassifiedImage > LabelledImageRegionConstIterator
Definition: otbMarkovRandomFieldFilter.h:150
otbMarkovRandomFieldFilter.h
otb::MarkovRandomFieldFilter::m_InputImageNeighborhoodRadius
InputImageNeighborhoodRadiusType m_InputImageNeighborhoodRadius
Definition: otbMarkovRandomFieldFilter.h:336
otb::MarkovRandomFieldFilter::InputImageType
TInputImage InputImageType
Definition: otbMarkovRandomFieldFilter.h:100
otb::MarkovRandomFieldFilter::GenerateOutputInformation
void GenerateOutputInformation() override
Definition: otbMarkovRandomFieldFilter.hxx:138
otb::MarkovRandomFieldFilter::LabelledImagePointer
TClassifiedImage::Pointer LabelledImagePointer
Definition: otbMarkovRandomFieldFilter.h:130
otb::MarkovRandomFieldFilter::LabelledImageRegionIterator
itk::ImageRegionIterator< TClassifiedImage > LabelledImageRegionIterator
Definition: otbMarkovRandomFieldFilter.h:148
otb::MarkovRandomFieldFilter::m_NeighborhoodRadius
int m_NeighborhoodRadius
Definition: otbMarkovRandomFieldFilter.h:345
otb::MarkovRandomFieldFilter::NeighborhoodRadiusType
TInputImage::SizeType NeighborhoodRadiusType
Definition: otbMarkovRandomFieldFilter.h:159
otb::MarkovRandomFieldFilter::InputImageDimension
static const unsigned int InputImageDimension
Definition: otbMarkovRandomFieldFilter.h:118
otb::MarkovRandomFieldFilter::GenerateInputRequestedRegion
void GenerateInputRequestedRegion() override
Definition: otbMarkovRandomFieldFilter.hxx:110
otb::MarkovRandomFieldFilter::SetTrainingInput
virtual void SetTrainingInput(const TrainingImageType *trainingImage)
Definition: otbMarkovRandomFieldFilter.hxx:65
otb::MarkovRandomFieldFilter::InputImageNeighborhoodIterator
itk::ConstNeighborhoodIterator< TInputImage > InputImageNeighborhoodIterator
Definition: otbMarkovRandomFieldFilter.h:162
otb::MarkovRandomFieldFilter::GetTrainingInput
const TrainingImageType * GetTrainingInput(void)
Definition: otbMarkovRandomFieldFilter.hxx:75
otbMsgDevMacro
#define otbMsgDevMacro(x)
Definition: otbMacro.h:64
otb::MarkovRandomFieldFilter::MarkovRandomFieldFilter
MarkovRandomFieldFilter()
Definition: otbMarkovRandomFieldFilter.hxx:29
otb::MarkovRandomFieldFilter::Allocate
void Allocate()
Definition: otbMarkovRandomFieldFilter.hxx:218
otb::MarkovRandomFieldFilter::GenerateData
void GenerateData() override
Definition: otbMarkovRandomFieldFilter.hxx:147
otb::MarkovRandomFieldFilter::PrintSelf
void PrintSelf(std::ostream &os, itk::Indent indent) const override
Definition: otbMarkovRandomFieldFilter.hxx:85
otb::MarkovRandomFieldFilter::InputImageSizeType
TInputImage::SizeType InputImageSizeType
Definition: otbMarkovRandomFieldFilter.h:334