[Insight-users] How to transfer a set of 2D image data to a 3D image data?

Luis Ibanez luis.ibanez at kitware.com
Thu, 05 Feb 2004 17:09:09 -0500


Hi Chunyan,

The JoinSeriesImageFilter<> that you posted
to the list looks like a very useful filter.

Would you be willing to contribute this
code to ITK ?


Please let us know,


Thanks


    Luis



-------------------------
HIRAKI Hideaki wrote:

> vtkImageAppend in VTK can do it.
> But if you want to process with itk::Image, 
> the attached code may help you.
> 
> Regards,
> 
> Hideaki Hiraki
> 
> 
> "jiang" <jiang at TI.Uni-Trier.DE> wrote:
> 
>>Dear itk-users,
>>I have a set of 2D image data. The type is, for example:
>>  typedef   unsigned char                      PixelType;
>>  typedef   itk::Image< InputPixelType, 2 >    ImageType;
>>
>>Now I want to transfer them to 3D image data:
>>  typedef   itk::Image< InputPixelType, 3 >    VolumeType;
>>
>>Then transfer the volume to vtk data in order to render it. How should I do?
>>
>>
>>Thanks a lot!
>>
>>
>>
>>Chunyan
>>
>>
>>
>>------------------------------------------------------------------------
>>
>>/*=========================================================================
>>
>>  Program:   Insight Segmentation & Registration Toolkit
>>  Module:    $RCSfile$
>>  Language:  C++
>>  Date:      $Date$
>>  Version:   $Revision$
>>
>>  Copyright (c) Insight Software Consortium. All rights reserved.
>>  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.
>>
>>     This software is distributed WITHOUT ANY WARRANTY; without even 
>>     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
>>     PURPOSE.  See the above copyright notices for more information.
>>
>>=========================================================================*/
>>#ifndef __itkJoinSeriesImageFilter_h
>>#define __itkJoinSeriesImageFilter_h
>>
>>#include "itkImageToImageFilter.h"
>>
>>namespace itk
>>{
>>
>>/** \class JoinSeriesImageFilter
>> * \brief Join N-D images into an (N+1)-D image
>> *
>> * Details should be described here.
>> *
>> * \ingroup GeometricTransforms
>> *
>> */
>>template <class TInputImage, class TOutputImage>
>>class ITK_EXPORT JoinSeriesImageFilter:
>>    public ImageToImageFilter<TInputImage,TOutputImage>
>>{
>>public:
>>  /** Standard class typedefs. */
>>  typedef JoinSeriesImageFilter  Self;
>>  typedef ImageToImageFilter<TInputImage,TOutputImage>  Superclass;
>>  typedef SmartPointer<Self>  Pointer;
>>  typedef SmartPointer<const Self>  ConstPointer;
>>
>>  /** Method for creation through the object factory. */
>>  itkNewMacro(Self);
>>
>>  /** Run-time type information (and related methods). */
>>  itkTypeMacro(JoinSeriesImageFilter, ImageToImageFilter);
>>
>>  /** Compiler can't inherit typedef? */
>>  typedef typename Superclass::InputImageType InputImageType;
>>  typedef typename Superclass::OutputImageType OutputImageType;
>>  typedef typename InputImageType::Pointer InputImagePointer;
>>  typedef typename OutputImageType::Pointer OutputImagePointer;
>>  typedef typename InputImageType::RegionType InputImageRegionType;
>>  typedef typename OutputImageType::RegionType OutputImageRegionType;
>>
>>  /** Compiler can't inherit ImageDimension enumeration? */
>>  itkStaticConstMacro(InputImageDimension, unsigned int,
>>                      TInputImage::ImageDimension);
>>  itkStaticConstMacro(OutputImageDimension, unsigned int,
>>                      TOutputImage::ImageDimension);
>>
>>  /** IndexValueType is used to switch among the inputs and
>>   * is used as the index value of the new dimension */
>>  typedef unsigned int IndexValueType;
>>
>>  /** Set/Get spacing of the new dimension */
>>  itkSetMacro(Spacing, double);
>>  itkGetMacro(Spacing, double);
>>
>>  /** Set/Get origin of the new dimension */
>>  itkSetMacro(Origin, double);
>>  itkGetMacro(Origin, double);
>>
>>protected:
>>  JoinSeriesImageFilter();
>>  ~JoinSeriesImageFilter() {};
>>  void PrintSelf(std::ostream& os, Indent indent) const;
>>
>>  /** Overrides GenerateOutputInformation() in order to produce
>>   * an image which has a different information than the first input.
>>   * \sa ProcessObject::GenerateOutputInformaton() */
>>  virtual void GenerateOutputInformation();
>>
>>  /** Overrides GenerateInputRequestedRegion() in order to inform
>>   * the pipeline execution model of different input requested regions
>>   * than the output requested region.
>>   * \sa ImageToImageFilter::GenerateInputRequestedRegion() */
>>  virtual void GenerateInputRequestedRegion();
>>
>>  /** JoinSeriesImageFilter can be implemented as a multithreaded filter.
>>   * \sa ImageSource::ThreadedGenerateData(),
>>   *     ImageSource::GenerateData() */
>>  virtual void ThreadedGenerateData(const OutputImageRegionType&
>>                                    outputRegionForThread, int threadId );
>>
>>private:
>>  JoinSeriesImageFilter(const Self&); //purposely not implemented
>>  void operator=(const Self&); //purposely not implemented
>>
>>  double m_Spacing;
>>  double m_Origin;
>>
>>};
>>
>>  
>>} // end namespace itk
>>  
>>#ifndef ITK_MANUAL_INSTANTIATION
>>#include "itkJoinSeriesImageFilter.txx"
>>#endif
>>  
>>#endif
>>
>>
>>------------------------------------------------------------------------
>>
>>#ifndef _itkJoinSeriesImageFilter_txx
>>#define _itkJoinSeriesImageFilter_txx
>>
>>#include "itkJoinSeriesImageFilter.h"
>>#include "itkProgressReporter.h"
>>#include "itkImageRegionConstIterator.h"
>>#include "itkImageRegionIterator.h"
>>
>>namespace itk
>>{
>>
>>template <class TInputImage, class TOutputImage>
>>JoinSeriesImageFilter<TInputImage,TOutputImage>
>>::JoinSeriesImageFilter() 
>>{
>>  m_Spacing = 1.0;
>>  m_Origin = 0.0;
>>}
>>
>>
>>template <class TInputImage, class TOutputImage>
>>void 
>>JoinSeriesImageFilter<TInputImage,TOutputImage>
>>::PrintSelf(std::ostream& os, Indent indent) const
>>{
>>  Superclass::PrintSelf(os,indent);
>>
>>  os << indent << "Spacing: " << m_Spacing << std::endl;
>>  os << indent << "Origin: " << m_Origin << std::endl;
>>}
>>
>>/**
>> * \sa UnaryFunctorImageFilter::GenerateOutputInformation()
>> */
>>template <class TInputImage, class TOutputImage>
>>void
>>JoinSeriesImageFilter<TInputImage,TOutputImage>
>>::GenerateOutputInformation()
>>{
>>  // do not call the superclass' implementation of this method since
>>  // this filter allows the input the output to be of different dimensions
>> 
>>  // get pointers to the input and output
>>  typename Superclass::OutputImagePointer      outputPtr = this->GetOutput();
>>  typename Superclass::InputImageConstPointer  inputPtr  = this->GetInput();
>>
>>  if ( !outputPtr || !inputPtr)
>>    {
>>    return;
>>    }
>>
>>  // Set the output image largest possible region.  Use a RegionCopier
>>  // so that the input and output images can be different dimensions.
>>  OutputImageRegionType outputLargestPossibleRegion;
>>  this->CallCopyInputRegionToOutputRegion(outputLargestPossibleRegion,
>>                                          inputPtr->GetLargestPossibleRegion());
>>
>>  // for the new dimension, assuming the index has been set 0.
>>  outputLargestPossibleRegion.SetSize(InputImageDimension,
>>                                      this->GetNumberOfInputs());
>>
>>  outputPtr->SetLargestPossibleRegion( outputLargestPossibleRegion );
>>
>>  // Set the output spacing and origin
>>  const ImageBase<InputImageDimension> *phyData;
>>
>>  phyData
>>    = dynamic_cast<const ImageBase<InputImageDimension>*>(this->GetInput());
>>
>>  if (phyData)
>>    {
>>    // Copy what we can from the image from spacing and origin of the input
>>    // This logic needs to be augmented with logic that select which
>>    // dimensions to copy
>>    unsigned int i;
>>    const typename InputImageType::SpacingType&
>>      inputSpacing = inputPtr->GetSpacing();
>>    const typename InputImageType::PointType&
>>      inputOrigin = inputPtr->GetOrigin();
>>
>>    typename OutputImageType::SpacingType outputSpacing;
>>    typename OutputImageType::PointType outputOrigin;
>>
>>    // copy the input to the output and fill the rest of the
>>    // output with zeros.
>>    for (i=0; i < InputImageDimension; ++i)
>>      {
>>      outputSpacing[i] = inputSpacing[i];
>>      outputOrigin[i] = inputOrigin[i];
>>      }
>>    for (; i < OutputImageDimension; ++i)
>>      {
>>      outputSpacing[i] = 1.0;
>>      outputOrigin[i] = 0.0;
>>      }
>>
>>    // for the new dimension
>>    outputSpacing[InputImageDimension] = this->GetSpacing();
>>    outputOrigin[InputImageDimension] = this->GetOrigin();
>>
>>    // set the spacing and origin
>>    outputPtr->SetSpacing( outputSpacing );
>>    outputPtr->SetOrigin( outputOrigin );
>>    }
>>  else
>>    {
>>    // pointer could not be cast back down
>>    itkExceptionMacro(<< "itk::JoinSeriesImageFilter::GenerateOutputInformation "
>>                      << "cannot cast input to "
>>                      << typeid(ImageBase<InputImageDimension>*).name() );
>>    }
>>}
>>
>>
>>template <class TInputImage, class TOutputImage>
>>void
>>JoinSeriesImageFilter<TInputImage,TOutputImage>
>>::GenerateInputRequestedRegion()
>>{
>>  Superclass::GenerateInputRequestedRegion();
>>
>>  OutputImageRegionType outputRegion = this->GetOutput()->GetRequestedRegion();
>>  IndexValueType begin = outputRegion.GetIndex(InputImageDimension);
>>  IndexValueType end = begin + outputRegion.GetSize(InputImageDimension);
>>  for (IndexValueType idx = 0; idx < this->GetNumberOfInputs(); ++idx)
>>    {
>>    InputImagePointer inputPtr = 
>>      const_cast<InputImageType *>(this->GetInput(idx));
>>    if ( !inputPtr )
>>      {
>>      itkExceptionMacro(<< "missing input " << idx);
>>      }
>>
>>    InputImageRegionType inputRegion; // assuming default is null
>>    if ( begin <= idx && idx < end )
>>      {
>>      this->CallCopyOutputRegionToInputRegion(inputRegion, outputRegion);
>>      }
>>    inputPtr->SetRequestedRegion(inputRegion);
>>    }
>>}
>>
>>
>>template <class TInputImage, class TOutputImage>
>>void
>>JoinSeriesImageFilter<TInputImage,TOutputImage>
>>::ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread,
>>                       int threadId)
>>{
>>  itkDebugMacro(<<"Actually executing");
>>
>>  ProgressReporter progress(this, threadId, outputRegionForThread.GetNumberOfPixels());
>>
>>  OutputImageRegionType outputRegion = outputRegionForThread;
>>  outputRegion.SetSize(InputImageDimension, 1);
>>
>>  InputImageRegionType inputRegion;
>>  this->CallCopyOutputRegionToInputRegion(inputRegion, outputRegionForThread);
>>
>>  IndexValueType begin = outputRegionForThread.GetIndex(InputImageDimension);
>>  IndexValueType end =
>>    begin + outputRegionForThread.GetSize(InputImageDimension);
>>  for (IndexValueType idx = begin; idx < end; ++idx)
>>    {
>>    outputRegion.SetIndex(InputImageDimension, idx);
>>    ImageRegionIterator<OutputImageType>
>>      outIt(this->GetOutput(), outputRegion);
>>    ImageRegionConstIterator<InputImageType>
>>      inIt(this->GetInput(idx), inputRegion);
>>    outIt.GoToBegin();
>>    inIt.GoToBegin();
>>    while( !outIt.IsAtEnd() )
>>      {
>>      outIt.Set( inIt.Get() );
>>      ++outIt;
>>      ++inIt;
>>      progress.CompletedPixel();
>>      }
>>    }
>>}
>>
>>
>>} // end namespace itk
>>
>>#endif