Orfeo Toolbox  3.16
itkMultiScaleHessianBasedMeasureImageFilter.txx
Go to the documentation of this file.
1 /*=========================================================================
2 
3  Program: Insight Segmentation & Registration Toolkit
4  Module: $RCSfile: itkMultiScaleHessianBasedMeasureImageFilter.txx,v $
5  Language: C++
6  Date: $Date: 2010-06-16 00:52:50 $
7  Version: $Revision: 1.15 $
8 
9  Copyright (c) Insight Software Consortium. All rights reserved.
10  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.
11 
12  This software is distributed WITHOUT ANY WARRANTY; without even
13  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14  PURPOSE. See the above copyright notices for more information.
15 
16 =========================================================================*/
17 #ifndef __itkMultiScaleHessianBasedMeasureImageFilter_txx
18 #define __itkMultiScaleHessianBasedMeasureImageFilter_txx
19 
21 #include "itkImageRegionIterator.h"
23 #include "vnl/vnl_math.h"
24 
25 namespace itk
26 {
27 
31 template <typename TInputImage,
32  typename THessianImage,
33  typename TOutputImage>
34 MultiScaleHessianBasedMeasureImageFilter
35 <TInputImage,THessianImage,TOutputImage>
37 {
38  m_NonNegativeHessianBasedMeasure = true;
39 
40  m_SigmaMinimum = 0.2;
41  m_SigmaMaximum = 2.0;
42 
43  m_NumberOfSigmaSteps = 10;
44  m_SigmaStepMethod = Self::LogarithmicSigmaSteps;
45 
46  m_HessianFilter = HessianFilterType::New();
47  m_HessianToMeasureFilter = NULL;
48 
49  //Instantiate Update buffer
50  m_UpdateBuffer = UpdateBufferType::New();
51 
52  m_GenerateScalesOutput = false;
53  m_GenerateHessianOutput = false;
54 
55  typename ScalesImageType::Pointer scalesImage = ScalesImageType::New();
56  typename HessianImageType::Pointer hessianImage = HessianImageType::New();
58  this->ProcessObject::SetNthOutput(1,scalesImage.GetPointer());
59  this->ProcessObject::SetNthOutput(2,hessianImage.GetPointer());
60 }
61 
62 template <typename TInputImage,
63  typename THessianImage,
64  typename TOutputImage>
65 void
67 <TInputImage,THessianImage,TOutputImage>
68 ::EnlargeOutputRequestedRegion (DataObject *output)
69 {
70  // currently this filter can not stream so we must set the outputs
71  // requested region to the largest
73 }
74 
75 template <typename TInputImage,
76  typename THessianImage,
77  typename TOutputImage>
79  <TInputImage,THessianImage,TOutputImage>::DataObjectPointer
81 <TInputImage,THessianImage,TOutputImage>
82 ::MakeOutput(unsigned int idx)
83 {
84  if (idx == 1)
85  {
86  return static_cast<DataObject*>(ScalesImageType::New().GetPointer());
87  }
88  if (idx == 2)
89  {
90  return static_cast<DataObject*>(HessianImageType::New().GetPointer());
91  }
92  return Superclass::MakeOutput(idx);
93 }
94 
95 template <typename TInputImage,
96  typename THessianImage,
97  typename TOutputImage>
98 void
100 <TInputImage,THessianImage,TOutputImage>
101 ::AllocateUpdateBuffer()
102 {
103  /* The update buffer looks just like the output and holds the best response
104  in the objectness measure */
105 
106  typename TOutputImage::Pointer output = this->GetOutput();
107 
108  // this copies meta data describing the output such as origin,
109  // spacing and the largest region
110  m_UpdateBuffer->CopyInformation(output);
111 
112  m_UpdateBuffer->SetRequestedRegion(output->GetRequestedRegion());
113  m_UpdateBuffer->SetBufferedRegion(output->GetBufferedRegion());
114  m_UpdateBuffer->Allocate();
115 
116  // Update buffer is used for > comparisons so make it really really small,
117  // just to be sure. Thanks to Hauke Heibel.
118  if (m_NonNegativeHessianBasedMeasure)
119  {
120  m_UpdateBuffer->FillBuffer( itk::NumericTraits< BufferValueType >::Zero );
121  }
122  else
123  {
124  m_UpdateBuffer->FillBuffer( itk::NumericTraits< BufferValueType >::NonpositiveMin() );
125  }
126 }
127 
128 template <typename TInputImage,
129  typename THessianImage,
130  typename TOutputImage>
131 void
133 <TInputImage,THessianImage,TOutputImage>
134 ::GenerateData()
135 {
136  // TODO: Move the allocation to a derived AllocateOutputs method
137  // Allocate the output
138  this->GetOutput()->SetBufferedRegion(this->GetOutput()->GetRequestedRegion());
139  this->GetOutput()->Allocate();
140 
141  if( m_HessianToMeasureFilter.IsNull() )
142  {
143  itkExceptionMacro( " HessianToMeasure filter is not set. Use SetHessianToMeasureFilter() " );
144  }
145 
146  if (m_GenerateScalesOutput)
147  {
148  typename ScalesImageType::Pointer scalesImage =
149  dynamic_cast<ScalesImageType*>(this->ProcessObject::GetOutput(1));
150 
151  scalesImage->SetBufferedRegion(scalesImage->GetRequestedRegion());
152  scalesImage->Allocate();
153  scalesImage->FillBuffer(0);
154  }
155 
156  if (m_GenerateHessianOutput)
157  {
158  typename HessianImageType::Pointer hessianImage =
159  dynamic_cast<HessianImageType*>(this->ProcessObject::GetOutput(2));
160 
161  hessianImage->SetBufferedRegion(hessianImage->GetRequestedRegion());
162  hessianImage->Allocate();
163  // SymmetricSecondRankTensor is already filled with zero elements at construction.
164  // No strict need of filling the buffer, but we do it explicitly here to make sure.
165  typename HessianImageType::PixelType zeroTensor(0.0);
166  hessianImage->FillBuffer(zeroTensor);
167  }
168 
169  // Allocate the buffer
170  AllocateUpdateBuffer();
171 
172  typename InputImageType::ConstPointer input = this->GetInput();
173 
174  this->m_HessianFilter->SetInput(input);
175 
176  this->m_HessianFilter->SetNormalizeAcrossScale(true);
177 
178  // Create a process accumulator for tracking the progress of this
179  // minipipeline
181  progress = ProgressAccumulator::New();
182  progress->SetMiniPipelineFilter(this);
183 
184  // prevent a divide by zero
185  if ( m_NumberOfSigmaSteps > 0 )
186  {
187  progress->RegisterInternalFilter( this->m_HessianFilter, .5/m_NumberOfSigmaSteps );
188  progress->RegisterInternalFilter( this->m_HessianToMeasureFilter, .5/m_NumberOfSigmaSteps );
189  }
190 
191  double sigma = m_SigmaMinimum;
192 
193  int scaleLevel = 1;
194 
195  while (sigma <= m_SigmaMaximum)
196  {
197  if ( m_NumberOfSigmaSteps == 0 )
198  {
199  break;
200  }
201 
202  itkDebugMacro ( << "Computing measure for scale with sigma = " << sigma );
203 
204  m_HessianFilter->SetSigma( sigma );
205 
206  m_HessianToMeasureFilter->SetInput ( m_HessianFilter->GetOutput() );
207 
208  m_HessianToMeasureFilter->Update();
209 
210  this->UpdateMaximumResponse(sigma);
211 
212  sigma = this->ComputeSigmaValue( scaleLevel );
213 
214  scaleLevel++;
215 
216  // reset the progress accumulator after each pass to continue
217  // addtion of progress for the next pass
218  progress->ResetFilterProgressAndKeepAccumulatedProgress();
219 
220 
221  if ( m_NumberOfSigmaSteps == 1 )
222  {
223  break;
224  }
225  }
226 
227  // Write out the best response to the output image
228  // we can assume that the meta-data should match between these two
229  // image, therefore we iterate over the desired output region
230  OutputRegionType outputRegion = this->GetOutput()->GetBufferedRegion();
231  ImageRegionIterator<UpdateBufferType> it( m_UpdateBuffer, outputRegion );
232  it.GoToBegin();
233 
234  ImageRegionIterator<TOutputImage> oit( this->GetOutput(), outputRegion );
235  oit.GoToBegin();
236 
237  while(!oit.IsAtEnd())
238  {
239  oit.Value() = static_cast< OutputPixelType >( it.Get() );
240  ++oit;
241  ++it;
242  }
243 
244  // Release data from the update buffer.
245  m_UpdateBuffer->ReleaseData();
246 }
247 
248 template <typename TInputImage,
249  typename THessianImage,
250  typename TOutputImage>
251 void
253 <TInputImage,THessianImage,TOutputImage>
254 ::UpdateMaximumResponse(double sigma)
255 {
256  // the meta-data should match between these images, therefore we
257  // iterate over the desired output region
258  OutputRegionType outputRegion = this->GetOutput()->GetBufferedRegion();
259  ImageRegionIterator<UpdateBufferType> oit( m_UpdateBuffer, outputRegion );
260 
261  typename ScalesImageType::Pointer scalesImage = static_cast<ScalesImageType*>(this->ProcessObject::GetOutput(1));
263 
264  typename HessianImageType::Pointer hessianImage = static_cast<HessianImageType*>(this->ProcessObject::GetOutput(2));
266 
267  oit.GoToBegin();
268  if (m_GenerateScalesOutput)
269  {
270  osit = ImageRegionIterator<ScalesImageType> ( scalesImage, outputRegion );
271  osit.GoToBegin();
272  }
273  if (m_GenerateHessianOutput)
274  {
275  ohit = ImageRegionIterator<HessianImageType> ( hessianImage, outputRegion );
276  ohit.GoToBegin();
277  }
278 
279  typedef typename HessianToMeasureFilterType::OutputImageType HessianToMeasureOutputImageType;
280 
281  ImageRegionIterator<HessianToMeasureOutputImageType> it( m_HessianToMeasureFilter->GetOutput(), outputRegion );
282  ImageRegionIterator<HessianImageType> hit( m_HessianFilter->GetOutput(), outputRegion );
283 
284  it.GoToBegin();
285  hit.GoToBegin();
286 
287  while(!oit.IsAtEnd())
288  {
289  if( oit.Value() < it.Value() )
290  {
291  oit.Value() = it.Value();
292  if (m_GenerateScalesOutput)
293  {
294  osit.Value() = static_cast< ScalesPixelType >( sigma );
295  }
296  if (m_GenerateHessianOutput)
297  {
298  ohit.Value() = hit.Value();
299  }
300  }
301  ++oit;
302  ++it;
303  if (m_GenerateScalesOutput)
304  {
305  ++osit;
306  }
307  if (m_GenerateHessianOutput)
308  {
309  ++ohit;
310  ++hit;
311  }
312  }
313 }
314 
315 template <typename TInputImage,
316  typename THessianImage,
317  typename TOutputImage>
318 double
320 <TInputImage,THessianImage,TOutputImage>
321 ::ComputeSigmaValue(int scaleLevel)
322 {
323  double sigmaValue;
324 
325  if (m_NumberOfSigmaSteps < 2)
326  {
327  return m_SigmaMinimum;
328  }
329 
330  switch (m_SigmaStepMethod)
331  {
332  case Self::EquispacedSigmaSteps:
333  {
334  const double stepSize = vnl_math_max(1e-10, ( m_SigmaMaximum - m_SigmaMinimum ) / (m_NumberOfSigmaSteps - 1));
335  sigmaValue = m_SigmaMinimum + stepSize * scaleLevel;
336  break;
337  }
338  case Self::LogarithmicSigmaSteps:
339  {
340  const double stepSize = vnl_math_max(1e-10, ( vcl_log(m_SigmaMaximum) - vcl_log(m_SigmaMinimum) ) / (m_NumberOfSigmaSteps - 1));
341  sigmaValue = vcl_exp( vcl_log (m_SigmaMinimum) + stepSize * scaleLevel);
342  break;
343  }
344  default:
345  throw ExceptionObject(__FILE__, __LINE__,"Invalid SigmaStepMethod.",ITK_LOCATION);
346  break;
347  }
348 
349  return sigmaValue;
350 }
351 
352 template <typename TInputImage,
353  typename THessianImage,
354  typename TOutputImage>
355 void
357 <TInputImage,THessianImage,TOutputImage>
358 ::SetSigmaStepMethodToEquispaced()
359 {
360  this->SetSigmaStepMethod(Self::EquispacedSigmaSteps);
361 }
362 
363 template <typename TInputImage,
364  typename THessianImage,
365  typename TOutputImage>
366 void
368 <TInputImage,THessianImage,TOutputImage>
369 ::SetSigmaStepMethodToLogarithmic()
370 {
371  this->SetSigmaStepMethod(Self::LogarithmicSigmaSteps);
372 }
373 
376 template <typename TInputImage,
377  typename THessianImage,
378  typename TOutputImage>
379 const
382 <TInputImage,THessianImage,TOutputImage>
383 ::GetHessianOutput() const
384 {
385  return static_cast<const HessianImageType*>(this->ProcessObject::GetOutput(2));
386 }
387 
390 template <typename TInputImage,
391  typename THessianImage,
392  typename TOutputImage>
393 const
396 <TInputImage,THessianImage,TOutputImage>
397 ::GetScalesOutput() const
398 {
399  return static_cast<const ScalesImageType*>(this->ProcessObject::GetOutput(1));
400 }
401 
402 template <typename TInputImage,
403  typename THessianImage,
404  typename TOutputImage>
405 void
407 <TInputImage,THessianImage,TOutputImage>
408 ::PrintSelf(std::ostream& os, Indent indent) const
409 {
410  Superclass::PrintSelf(os, indent);
411 
412  os << indent << "SigmaMinimum: " << m_SigmaMinimum << std::endl;
413  os << indent << "SigmaMaximum: " << m_SigmaMaximum << std::endl;
414  os << indent << "NumberOfSigmaSteps: " << m_NumberOfSigmaSteps << std::endl;
415  os << indent << "SigmaStepMethod: " << m_SigmaStepMethod << std::endl;
416  os << indent << "HessianToMeasureFilter: " << m_HessianToMeasureFilter << std::endl;
417  os << indent << "NonNegativeHessianBasedMeasure: " << m_NonNegativeHessianBasedMeasure << std::endl;
418  os << indent << "GenerateScalesOutput: " << m_GenerateScalesOutput << std::endl;
419  os << indent << "GenerateHessianOutput: " << m_GenerateHessianOutput << std::endl;
420 }
421 
422 
423 } // end namespace itk
424 
425 #endif

Generated at Sat Feb 2 2013 23:54:54 for Orfeo Toolbox with doxygen 1.8.1.1