[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