Orfeo Toolbox  3.16
itkRecursiveSeparableImageFilter.txx
Go to the documentation of this file.
1 /*=========================================================================
2 
3  Program: Insight Segmentation & Registration Toolkit
4  Module: $RCSfile: itkRecursiveSeparableImageFilter.txx,v $
5  Language: C++
6  Date: $Date: 2009-08-21 20:27:43 $
7  Version: $Revision: 1.44 $
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 __itkRecursiveSeparableImageFilter_txx
18 #define __itkRecursiveSeparableImageFilter_txx
19 
21 #include "itkObjectFactory.h"
24 #include "itkProgressReporter.h"
25 #include <new>
26 
27 
28 namespace itk
29 {
30 
31 template <typename TInputImage, typename TOutputImage>
34 {
35  m_Direction = 0;
36  this->SetNumberOfRequiredOutputs( 1 );
37  this->SetNumberOfRequiredInputs( 1 );
38 }
39 
40 
44 template <typename TInputImage, typename TOutputImage>
45 void
47 ::SetInputImage( const TInputImage * input )
48 {
49  // ProcessObject is not const_correct so this const_cast is required
51  const_cast< TInputImage * >(input) );
52 }
53 
54 
58 template <typename TInputImage, typename TOutputImage>
59 const TInputImage *
62 {
63  return dynamic_cast<const TInputImage *>(
65 }
66 
67 
71 template <typename TInputImage, typename TOutputImage>
72 void
75  RealType *scratch,unsigned int ln)
76 {
81  // this value is assumed to exist from the border to infinity.
82  const RealType outV1 = data[0];
83 
87  scratch[0] = RealType( outV1 * m_N0 + outV1 * m_N1 + outV1 * m_N2 + outV1 * m_N3 );
88  scratch[1] = RealType( data[1] * m_N0 + outV1 * m_N1 + outV1 * m_N2 + outV1 * m_N3 );
89  scratch[2] = RealType( data[2] * m_N0 + data[1] * m_N1 + outV1 * m_N2 + outV1 * m_N3 );
90  scratch[3] = RealType( data[3] * m_N0 + data[2] * m_N1 + data[1] * m_N2 + outV1 * m_N3 );
91 
92  // note that the outV1 value is multiplied by the Boundary coefficients m_BNi
93  scratch[0] -= RealType( outV1 * m_BN1 + outV1 * m_BN2 + outV1 * m_BN3 + outV1 * m_BN4 );
94  scratch[1] -= RealType( scratch[0] * m_D1 + outV1 * m_BN2 + outV1 * m_BN3 + outV1 * m_BN4 );
95  scratch[2] -= RealType( scratch[1] * m_D1 + scratch[0] * m_D2 + outV1 * m_BN3 + outV1 * m_BN4 );
96  scratch[3] -= RealType( scratch[2] * m_D1 + scratch[1] * m_D2 + scratch[0] * m_D3 + outV1 * m_BN4 );
97 
101  for( unsigned int i=4; i<ln; i++ )
102  {
103  scratch[i] = RealType( data[i] * m_N0 + data[i-1] * m_N1 + data[i-2] * m_N2 + data[i-3] * m_N3 );
104  scratch[i] -= RealType( scratch[i-1] * m_D1 + scratch[i-2] * m_D2 + scratch[i-3] * m_D3 + scratch[i-4] * m_D4 );
105  }
106 
110  for( unsigned int i=0; i<ln; i++ )
111  {
112  outs[i] = scratch[i];
113  }
114 
115 
116 
121  // this value is assumed to exist from the border to infinity.
122  const RealType outV2 = data[ln-1];
123 
127  scratch[ln-1] = RealType( outV2 * m_M1 + outV2 * m_M2 + outV2 * m_M3 + outV2 * m_M4);
128  scratch[ln-2] = RealType( data[ln-1] * m_M1 + outV2 * m_M2 + outV2 * m_M3 + outV2 * m_M4);
129  scratch[ln-3] = RealType( data[ln-2] * m_M1 + data[ln-1] * m_M2 + outV2 * m_M3 + outV2 * m_M4);
130  scratch[ln-4] = RealType( data[ln-3] * m_M1 + data[ln-2] * m_M2 + data[ln-1] * m_M3 + outV2 * m_M4);
131 
132  // note that the outV2value is multiplied by the Boundary coefficients m_BMi
133  scratch[ln-1] -= RealType( outV2 * m_BM1 + outV2 * m_BM2 + outV2 * m_BM3 + outV2 * m_BM4);
134  scratch[ln-2] -= RealType( scratch[ln-1] * m_D1 + outV2 * m_BM2 + outV2 * m_BM3 + outV2 * m_BM4);
135  scratch[ln-3] -= RealType( scratch[ln-2] * m_D1 + scratch[ln-1] * m_D2 + outV2 * m_BM3 + outV2 * m_BM4);
136  scratch[ln-4] -= RealType( scratch[ln-3] * m_D1 + scratch[ln-2] * m_D2 + scratch[ln-1] * m_D3 + outV2 * m_BM4);
137 
141  for( unsigned int i=ln-4; i>0; i-- )
142  {
143  scratch[i-1] = RealType( data[i] * m_M1 + data[i+1] * m_M2 + data[i+2] * m_M3 + data[i+3] * m_M4 );
144  scratch[i-1] -= RealType( scratch[i] * m_D1 + scratch[i+1] * m_D2 + scratch[i+2] * m_D3 + scratch[i+3] * m_D4 );
145  }
146 
150  for( unsigned int i=0; i<ln; i++ )
151  {
152  outs[i] += scratch[i];
153  }
154 }
155 
156 
157 //
158 // we need all of the image in just the "Direction" we are separated into
159 //
160 template <typename TInputImage, typename TOutputImage>
161 void
164 {
165  TOutputImage *out = dynamic_cast<TOutputImage*>(output);
166 
167  if (out)
168  {
169  OutputImageRegionType outputRegion = out->GetRequestedRegion();
170  const OutputImageRegionType &largestOutputRegion = out->GetLargestPossibleRegion();
171 
172  // verify sane parameter
173  if ( this->m_Direction >= outputRegion.GetImageDimension() )
174  {
175  itkExceptionMacro("Direction selected for filtering is greater than ImageDimension")
176  }
177 
178  // expand output region to match largest in the "Direction" dimension
179  outputRegion.SetIndex( m_Direction, largestOutputRegion.GetIndex(m_Direction) );
180  outputRegion.SetSize( m_Direction, largestOutputRegion.GetSize(m_Direction) );
181 
182  out->SetRequestedRegion( outputRegion );
183  }
184 }
185 
186 
187 template <typename TInputImage, typename TOutputImage>
188 int
190 ::SplitRequestedRegion(int i, int num, OutputImageRegionType& splitRegion)
191 {
192  // Get the output pointer
193  OutputImageType * outputPtr = this->GetOutput();
194  const typename TOutputImage::SizeType& requestedRegionSize
195  = outputPtr->GetRequestedRegion().GetSize();
196 
197  int splitAxis;
198  typename TOutputImage::IndexType splitIndex;
199  typename TOutputImage::SizeType splitSize;
200 
201  // Initialize the splitRegion to the output requested region
202  splitRegion = outputPtr->GetRequestedRegion();
203  splitIndex = splitRegion.GetIndex();
204  splitSize = splitRegion.GetSize();
205 
206  // split on the outermost dimension available
207  // and avoid the current dimension
208  splitAxis = outputPtr->GetImageDimension() - 1;
209  while (requestedRegionSize[splitAxis] == 1 || splitAxis == (int)m_Direction)
210  {
211  --splitAxis;
212  if (splitAxis < 0)
213  { // cannot split
214  itkDebugMacro(" Cannot Split");
215  return 1;
216  }
217  }
218 
219  // determine the actual number of pieces that will be generated
220  typename TOutputImage::SizeType::SizeValueType range = requestedRegionSize[splitAxis];
221  int valuesPerThread = (int)vcl_ceil(range/(double)num);
222  int maxThreadIdUsed = (int)vcl_ceil(range/(double)valuesPerThread) - 1;
223 
224  // Split the region
225  if (i < maxThreadIdUsed)
226  {
227  splitIndex[splitAxis] += i*valuesPerThread;
228  splitSize[splitAxis] = valuesPerThread;
229  }
230  if (i == maxThreadIdUsed)
231  {
232  splitIndex[splitAxis] += i*valuesPerThread;
233  // last thread needs to process the "rest" dimension being split
234  splitSize[splitAxis] = splitSize[splitAxis] - i*valuesPerThread;
235  }
236 
237  // set the split region ivars
238  splitRegion.SetIndex( splitIndex );
239  splitRegion.SetSize( splitSize );
240 
241  itkDebugMacro(" Split Piece: " << splitRegion );
242 
243  return maxThreadIdUsed + 1;
244 }
245 
246 
247 template <typename TInputImage, typename TOutputImage>
248 void
251 {
253 
254  typename TInputImage::ConstPointer inputImage( this->GetInputImage () );
255  typename TOutputImage::Pointer outputImage( this->GetOutput() );
256 
257  const unsigned int imageDimension = inputImage->GetImageDimension();
258 
259  if( this->m_Direction >= imageDimension )
260  {
261  itkExceptionMacro("Direction selected for filtering is greater than ImageDimension");
262  }
263 
264  const typename InputImageType::SpacingType & pixelSize
265  = inputImage->GetSpacing();
266 
267  this->SetUp( pixelSize[m_Direction] );
268 
269  RegionType region = outputImage->GetRequestedRegion();
270 
271  const unsigned int ln = region.GetSize()[ this->m_Direction ];
272 
273  if( ln < 4 )
274  {
275  itkExceptionMacro("The number of pixels along direction " << this->m_Direction << " is less than 4. This filter requires a minimum of four pixels along the dimension to be processed.");
276  }
277 
278 }
279 
280 
285 template <typename TInputImage, typename TOutputImage>
286 void
288 ::ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, int threadId)
289 {
290  typedef typename TOutputImage::PixelType OutputPixelType;
291 
292  typedef ImageLinearConstIteratorWithIndex< TInputImage > InputConstIteratorType;
293  typedef ImageLinearIteratorWithIndex< TOutputImage > OutputIteratorType;
294 
296 
297  typename TInputImage::ConstPointer inputImage( this->GetInputImage () );
298  typename TOutputImage::Pointer outputImage( this->GetOutput() );
299 
300  RegionType region = outputRegionForThread;
301 
302  InputConstIteratorType inputIterator( inputImage, region );
303  OutputIteratorType outputIterator( outputImage, region );
304 
305  inputIterator.SetDirection( this->m_Direction );
306  outputIterator.SetDirection( this->m_Direction );
307 
308 
309  const unsigned int ln = region.GetSize()[ this->m_Direction ];
310 
311  RealType *inps = 0;
312  RealType *outs = 0;
313  RealType *scratch = 0;
314 
315  try
316  {
317  inps = new RealType[ ln ];
318  }
319  catch( std::bad_alloc & )
320  {
321  itkExceptionMacro("Problem allocating memory for internal computations");
322  }
323 
324  try
325  {
326  outs = new RealType[ ln ];
327  }
328  catch( std::bad_alloc & )
329  {
330  delete [] inps;
331  itkExceptionMacro("Problem allocating memory for internal computations");
332  }
333 
334  try
335  {
336  scratch = new RealType[ln];
337  }
338  catch( std::bad_alloc &)
339  {
340  delete [] inps;
341  delete [] outs;
342  itkExceptionMacro("Problem allocating memory for internal computations");
343  }
344 
345  inputIterator.GoToBegin();
346  outputIterator.GoToBegin();
347 
348  const typename TInputImage::OffsetValueType * offsetTable = inputImage->GetOffsetTable();
349 
350  const unsigned int numberOfLinesToProcess = offsetTable[ TInputImage::ImageDimension ] / ln;
351  ProgressReporter progress(this, threadId, numberOfLinesToProcess, 10 );
352 
353 
354  try // this try is intended to catch an eventual AbortException.
355  {
356  while( !inputIterator.IsAtEnd() && !outputIterator.IsAtEnd() )
357  {
358  unsigned int i=0;
359  while( !inputIterator.IsAtEndOfLine() )
360  {
361  inps[i++] = inputIterator.Get();
362  ++inputIterator;
363  }
364 
365  this->FilterDataArray( outs, inps, scratch, ln );
366 
367  unsigned int j=0;
368  while( !outputIterator.IsAtEndOfLine() )
369  {
370  outputIterator.Set( static_cast<OutputPixelType>( outs[j++] ) );
371  ++outputIterator;
372  }
373 
374  inputIterator.NextLine();
375  outputIterator.NextLine();
376 
377  // Although the method name is CompletedPixel(),
378  // this is being called after each line is processed
379  progress.CompletedPixel();
380  }
381  }
382  catch( ProcessAborted & )
383  {
384  // User aborted filter excecution Here we catch an exception thrown by the
385  // progress reporter and rethrow it with the correct line number and file
386  // name. We also invoke AbortEvent in case some observer was interested on
387  // it.
388  // release locally allocated memory
389  delete [] outs;
390  delete [] inps;
391  delete [] scratch;
392  // Throw the final exception.
393  ProcessAborted e(__FILE__,__LINE__);
394  e.SetDescription("Process aborted.");
395  e.SetLocation(ITK_LOCATION);
396  throw e;
397  }
398 
399  delete [] outs;
400  delete [] inps;
401  delete [] scratch;
402 }
403 
404 
405 template <typename TInputImage, typename TOutputImage>
406 void
408 ::PrintSelf(std::ostream& os, Indent indent) const
409 {
410  Superclass::PrintSelf(os,indent);
411 
412  os << indent << "Direction: " << m_Direction << std::endl;
413 }
414 
415 } // end namespace itk
416 
417 #endif

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