Orfeo Toolbox  3.16
itkGaussianBlurImageFunction.txx
Go to the documentation of this file.
1 /*=========================================================================
2 
3  Program: Insight Segmentation & Registration Toolkit
4  Module: $RCSfile: itkGaussianBlurImageFunction.txx,v $
5  Language: C++
6  Date: $Date: 2009-06-17 14:43: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 __itkGaussianBlurImageFunction_txx
18 #define __itkGaussianBlurImageFunction_txx
19 
22 
23 namespace itk
24 {
25 
27 template <class TInputImage,class TOutput>
30 {
31  typename GaussianFunctionType::ArrayType mean;
32  mean[0]=0.0f;
33  for(unsigned int i=0;i<itkGetStaticConstMacro(ImageDimension);i++)
34  {
35  m_Sigma[i] = 1.0f;
36  m_MaximumError[i] = 0.001f;
37  m_MaximumKernelWidth = 32;
38  m_Extent[i] = 1.0f;
39  }
40  m_UseImageSpacing = true;
41 
42  m_GaussianFunction = GaussianFunctionType::New();
43  m_GaussianFunction->SetMean(mean);
44  m_GaussianFunction->SetNormalized(false); // faster
45  m_OperatorImageFunction = OperatorImageFunctionType::New();
46  m_InternalImage = InternalImageType::New();
47  this->RecomputeGaussianKernel();
48  m_Caster = CastImageFilterType::New();
49 }
50 
52 template <class TInputImage,class TOutput>
53 void
56 {
57  Superclass::SetInputImage(ptr);
58  m_Caster->SetInput(ptr);
59  m_Caster->Update();
60  m_OperatorImageFunction->SetInputImage(m_Caster->GetOutput());
61 }
62 
63 
65 template <class TInputImage,class TOutput>
66 void
68 ::PrintSelf(std::ostream& os, Indent indent) const
69 {
70  this->Superclass::PrintSelf(os,indent);
71 
72  for(unsigned int i=0;i<itkGetStaticConstMacro(ImageDimension);i++)
73  {
74  os << indent << "Sigma["<< i << "] : " << m_Sigma[i] << std::endl;
75  os << indent << "MaximumError["<< i << "] : " << m_MaximumError[i] << std::endl;
76  os << indent << "Extent["<< i << "] : " << m_Extent[i] << std::endl;
77  }
78  os << indent << "MaximumKernelWidth: " << m_MaximumKernelWidth << std::endl;
79  os << indent << "UseImageSpacing: " << m_UseImageSpacing << std::endl;
80 
81  os << indent << "Internal Image : " << m_InternalImage << std::endl;
82  os << indent << "Image Caster : " << m_Caster << std::endl;
83 
84 }
85 
87 template <class TInputImage,class TOutput>
88 void
90 ::SetSigma(const double* sigma)
91 {
92  unsigned int i;
93  for (i=0; i<itkGetStaticConstMacro(ImageDimension); i++)
94  {
95  if ( sigma[i] != m_Sigma[i] )
96  {
97  break;
98  }
99  }
100  if ( i < itkGetStaticConstMacro(ImageDimension) )
101  {
102  for (i=0; i<itkGetStaticConstMacro(ImageDimension); i++)
103  {
104  m_Sigma[i] = sigma[i];
105  }
106  this->RecomputeGaussianKernel();
107  }
108 }
109 
110 
112 template <class TInputImage,class TOutput>
113 void
115 ::SetSigma( const double sigma)
116 {
117  unsigned int i;
118  for (i=0; i<itkGetStaticConstMacro(ImageDimension); i++)
119  {
120  if ( sigma != m_Sigma[i] )
121  {
122  break;
123  }
124  }
125  if ( i < itkGetStaticConstMacro(ImageDimension) )
126  {
127  for (i=0; i<itkGetStaticConstMacro(ImageDimension); i++)
128  {
129  m_Sigma[i] = sigma;
130  }
131  this->RecomputeGaussianKernel();
132  }
133 }
134 
136 template <class TInputImage,class TOutput>
137 void
139 ::SetExtent(const double* extent)
140 {
141  unsigned int i;
142  for (i=0; i<itkGetStaticConstMacro(ImageDimension); i++)
143  {
144  if ( extent[i] != m_Extent[i] )
145  {
146  break;
147  }
148  }
149  if ( i < itkGetStaticConstMacro(ImageDimension) )
150  {
151  for (i=0; i<itkGetStaticConstMacro(ImageDimension); i++)
152  {
153  m_Extent[i] = extent[i];
154  }
155  this->RecomputeGaussianKernel();
156  }
157 }
158 
159 
161 template <class TInputImage,class TOutput>
162 void
164 ::SetExtent( const double extent)
165 {
166  unsigned int i;
167  for (i=0; i<itkGetStaticConstMacro(ImageDimension); i++)
168  {
169  if ( extent != m_Extent[i] )
170  {
171  break;
172  }
173  }
174  if ( i < itkGetStaticConstMacro(ImageDimension) )
175  {
176  for (i=0; i<itkGetStaticConstMacro(ImageDimension); i++)
177  {
178  m_Extent[i] = extent;
179  }
180  this->RecomputeGaussianKernel();
181  }
182 }
183 
187 template <class TInputImage,class TOutput>
188 void
191 {
192 
193  typename InternalImageType::SizeType size;
194  // Compute the convolution of each kernel in each direction
195  for(unsigned int direction=0;direction<itkGetStaticConstMacro(ImageDimension);direction++)
196  {
197  GaussianOperatorType gaussianOperator;
198 
199  gaussianOperator.SetDirection(direction);
200  gaussianOperator.SetMaximumError(m_MaximumError[direction]);
201  gaussianOperator.SetMaximumKernelWidth(m_MaximumKernelWidth);
202 
203  if( (m_UseImageSpacing == true) && (this->GetInputImage()) )
204  {
205  if (this->GetInputImage()->GetSpacing()[direction] == 0.0)
206  {
207  itkExceptionMacro(<< "Pixel spacing cannot be zero");
208  }
209  else
210  {
211  gaussianOperator.SetVariance(m_Sigma[direction]*m_Sigma[direction] / this->GetInputImage()->GetSpacing()[direction]);
212  }
213  }
214  else
215  {
216  gaussianOperator.SetVariance(m_Sigma[direction]*m_Sigma[direction]);
217  }
218 
219  gaussianOperator.CreateDirectional();
220  m_OperatorArray[direction] = gaussianOperator;
221  size[direction] = gaussianOperator.GetSize()[direction];
222  }
223 
224  // Allocate the internal image
225  m_InternalImage = InternalImageType::New();
226  typename InternalImageType::RegionType region;
227  region.SetSize(size);
228  m_InternalImage->SetRegions(region);
229  m_InternalImage->Allocate();
230  m_InternalImage->FillBuffer(0);
231 }
232 
234 template <class TInputImage,class TOutput>
235 TOutput
237 ::EvaluateAtIndex(const IndexType& index) const
238 {
239  return this->EvaluateAtIndex( index, m_OperatorArray );
240 }
241 
243 template <class TInputImage,class TOutput>
244 TOutput
246 ::EvaluateAtIndex(const IndexType& index, const OperatorArrayType & operatorArray ) const
247 {
248  // First time we use the complete image and fill the internal image
249  m_OperatorImageFunction->SetInputImage(m_Caster->GetOutput());
250  m_OperatorImageFunction->SetOperator(operatorArray[0]);
251 
252  // if 1D Image we return the result
253  if(itkGetStaticConstMacro(ImageDimension) == 1)
254  {
255  return m_OperatorImageFunction->EvaluateAtIndex(index);
256  }
257 
258  // Compute the centered index of the neighborhood
259  IndexType centerIndex;
260  for(unsigned int i=0;i<itkGetStaticConstMacro(ImageDimension);i++)
261  {
262  centerIndex[i] = (unsigned long)((float)m_InternalImage->GetBufferedRegion().GetSize()[i]/2.0);
263  }
264 
265  // first direction
266  typename InternalImageType::IndexType ind;
267  ind = index;
268 
269  //Define the region of the iterator
270  typename InternalImageType::RegionType region;
271  typename InternalImageType::SizeType size = m_InternalImage->GetBufferedRegion().GetSize();
272  size[0]=1;
273  region.SetSize(size);
274 
275  for(unsigned int i = 0;i<itkGetStaticConstMacro(ImageDimension);i++)
276  {
277  if(i != 0)
278  {
279  ind[i] -= centerIndex[i];
280  }
281  }
282  region.SetIndex(ind);
283 
284  typename InternalImageType::RegionType regionN;
285  regionN.SetSize(size);
286  ind = centerIndex;
287  for(unsigned int i = 0;i<itkGetStaticConstMacro(ImageDimension);i++)
288  {
289  if(i != 0)
290  {
291  ind[i] = 0;
292  }
293  }
294  regionN.SetIndex(ind);
295 
296  typename InternalImageType::RegionType regionS = region;
297  regionS.Crop( m_Caster->GetOutput()->GetBufferedRegion() );
298 
299  itk::ImageLinearConstIteratorWithIndex<InternalImageType> it(m_Caster->GetOutput(),regionS);
300  itk::ImageLinearIteratorWithIndex<InternalImageType> itN(m_InternalImage,regionN);
301  it.SetDirection(1);
302  itN.SetDirection(1);
303  it.GoToBeginOfLine();
304  itN.GoToBeginOfLine();
305  while( !it.IsAtEnd() )
306  {
307  while( !it.IsAtEndOfLine() )
308  {
309  itN.Set(m_OperatorImageFunction->EvaluateAtIndex(it.GetIndex()));
310  ++it;
311  ++itN;
312  }
313  it.NextLine();
314  itN.NextLine();
315  }
316 
317  // Do the convolution in other directions
318  for(unsigned int direction=1;direction<itkGetStaticConstMacro(ImageDimension);direction++)
319  {
320 
321  size[direction] = 1;
322  ind = centerIndex;
323  for(unsigned int i = 0;i<itkGetStaticConstMacro(ImageDimension);i++)
324  {
325  if(i > direction)
326  {
327  ind[i] = 0;
328  }
329  }
330  region.SetSize(size);
331  region.SetIndex(ind);
332 
333 
334  m_OperatorImageFunction->SetInputImage(m_InternalImage);
335  m_OperatorImageFunction->SetOperator(operatorArray[direction]);
336 
337  itk::ImageLinearIteratorWithIndex<InternalImageType> itr(m_InternalImage,region);
338 
339  unsigned int dir = direction +1;
340  if(dir == itkGetStaticConstMacro(ImageDimension))
341  {
342  dir = itkGetStaticConstMacro(ImageDimension)-1;
343  }
344 
345  itr.SetDirection(dir);
346  itr.GoToBeginOfLine();
347  while(!itr.IsAtEnd())
348  {
349  while(!itr.IsAtEndOfLine())
350  {
351  itr.Set(m_OperatorImageFunction->EvaluateAtIndex(itr.GetIndex()));
352  ++itr;
353  }
354  itr.NextLine();
355  }
356  }
357 
358  return m_InternalImage->GetPixel(centerIndex);
359 
360 }
361 
362 
365 template <class TInputImage,class TOutput>
366 void
368 ::RecomputeContinuousGaussianKernel(const double* offset) const
369 {
370  for(unsigned int direction=0;direction<itkGetStaticConstMacro(ImageDimension);direction++)
371  {
372  NeighborhoodType gaussianNeighborhood;
374  typename NeighborhoodType::SizeType size;
375  size.Fill(0);
376  size[direction] = (unsigned long)(m_Sigma[direction]*m_Extent[direction]);
377 
378  gaussianNeighborhood.SetRadius(size);
379 
380  typename NeighborhoodType::Iterator it = gaussianNeighborhood.Begin();
381 
383  s[0]=m_Sigma[direction];
384  m_GaussianFunction->SetSigma(s);
385 
386  unsigned int i=0;
387  float sum = 0;
388  while(it != gaussianNeighborhood.End() )
389  {
390  pt[0]= gaussianNeighborhood.GetOffset(i)[direction]-offset[direction];
391  if( (m_UseImageSpacing == true) && (this->GetInputImage()) )
392  {
393  if (this->GetInputImage()->GetSpacing()[direction] == 0.0)
394  {
395  itkExceptionMacro(<< "Pixel spacing cannot be zero");
396  }
397  else
398  {
399  pt[0] *= this->GetInputImage()->GetSpacing()[direction];
400  }
401  }
402 
403  (*it)= m_GaussianFunction->Evaluate(pt);
404  sum += (*it);
405  i++;
406  it++;
407  }
408 
409  // Make the filter DC-Constant
410  it = gaussianNeighborhood.Begin();
411  while(it != gaussianNeighborhood.End() )
412  {
413  (*it) /= sum;
414  it++;
415  }
416  m_ContinuousOperatorArray[direction] = gaussianNeighborhood;
417  }
418 }
419 
421 template <class TInputImage,class TOutput>
422 TOutput
424 ::Evaluate(const PointType& point) const
425 {
426  ContinuousIndexType cindex;
427 
428  this->m_InternalImage->TransformPhysicalPointToContinuousIndex( point, cindex );
429 
430  return this->EvaluateAtContinuousIndex( cindex );
431 }
432 
434 template <class TInputImage,class TOutput>
435 TOutput
438 {
439  IndexType index;
440 
441  index.CopyWithRound( cindex );
442 
443  double offset[itkGetStaticConstMacro(ImageDimension)];
444  for(unsigned int i=0; i<itkGetStaticConstMacro(ImageDimension);i++)
445  {
446  offset[i] = cindex[i] - index[i];
447  }
448 
449  this->RecomputeContinuousGaussianKernel( offset );
450 
451  return this->EvaluateAtIndex( index, m_ContinuousOperatorArray );
452 }
453 
454 } // end namespace itk
455 
456 #endif

Generated at Sat May 18 2013 23:40:00 for Orfeo Toolbox with doxygen 1.8.3.1