[Insight-users] Resampling an image to iso voxels
Luis Ibanez
luis . ibanez at kitware . com
Thu, 04 Dec 2003 10:44:03 -0500
Hi Ralf,
For converting your image into an isotropic image
you don't need to use the scaling transform, just use
the *Identity* transform. Since ITK resampling happens
in physical coordinates, and transforms specify the
convertion from physical coordinates A to physical
coordinates B, you simply need to set a null transform.
The actual resampling is performed by specifying a new
*pixel spacing* for the output image as well as a new
image size.
You will find a new example on how to convert images
to Isotropic voxels under
Insight/Examples/Filtering/
ResampleVolumesToBeIsotropic.cxx
http://www . itk . org/cgi-bin/cvsweb . cgi/Insight/Examples/Filtering/ResampleVolumesToBeIsotropic . cxx?cvsroot=Insight&sortby=date
You actually use this example as a command line utility.
If you look at the code in this example, please note that
you must smooth an image along the dimensions that are going
to be sub-sampled. This is needed to avoid the superposition
of spectra in the Fourier space.
Please let us know if you have any problems,
Thanks
Luis
---------------------
Ralf o Floca wrote:
> Hello
>
> I have a problem with resampling in the following situation:
> I have a few 3d images (analyze or stacks of 2D dicom images) with a
> spacing in some cases unequal to 1.
> After reading the volumes, I want to convert them to an iso voxel
> spacing of 1. I have chosen a resample filter with a scale transform to
> manage this task, the code for this is something like that:
>
> void ConvertImageToIsoSpacing(OutputImageType::Pointer& m_Image)
> {
> itk::FixedArray< double, iDimension> scales;
> const double* pdSpacing = m_Image->GetSpacing();
> double dNewSpacing[3];
>
> itk::Size<iDimension> newSize;
> const itk::Size<iDimension>& oldSize =
> m_Image->GetLargestPossibleRegion().GetSize();
>
> for (int iIndex=0; iIndex< 3; iIndex ++, pdSpacing++)
> { //Calculate the scaling for the transform and the size of the output
> dNewSpacing[iIndex] = 1.0;
> if (*pdSpacing!=0) scales[iIndex] = 1/(*pdSpacing);
>
> newSize[iIndex] = oldSize[iIndex]*(*pdSpacing);
> };
>
> OutputImageType::Pointer m_ImageTemp = OutputImageType::New();
>
> typedef itk::ResampleImageFilter< OutputImageType, OutputImageType >
> ResampleType;
> typedef itk::ScaleTransform< double, iDimension > ScaleType;
>
> ResampleType::Pointer resampler = ResampleType::New();
>
> ScaleType::Pointer scaler = ScaleType::New();
> scaler->SetScale(scales);
>
> resampler->SetTransform(scaler);
> resampler->SetSize(newSize);
> resampler->SetOutputOrigin(m_Image->GetOrigin());
> resampler->SetOutputSpacing(dNewSpacing);
> resampler->SetDefaultPixelValue( 0 );
> resampler->SetInput(m_Image);
>
> m_ImageTemp = resampler->GetOutput();
> resampler->Update();
> m_Image = m_ImageTemp;
> };
>
> For dicom-stacks it seems to work fine, but when using it with an image
> saved as an analyze the resampling produces bad results for spacings
> unequal to 1, because the output images seemed to be double scaled
> (e.g.: when the spacing is 1.5, the image is scaled by 0.444.. -and not
> 0.666..-, but the new image size is correct, so overlapping parts are
> cut away). I was able to locate the reason for the "double use" of the
> scaling, but I don't know where the misuse is in my code.
>
> 1. 1st time the scaling is used is in the resample filter
> (itkResampleImageFilter.txx, Line 220):
> // Compute corresponding input pixel position
> inputPoint = m_Transform->TransformPoint(outputPoint);
> There the outputPoint is scaled the first time.
>
> 2. Then by the interpolation in line 227, which uses
> itkImage::TransformPhysicalPointToContinousIndex() (itkImage.h, line
> 259), where the inputPoint origin difference is divided by the input
> image spacing. At the end the output index has been divided twice by
> spacing to get the input index.
>
> If it not an error in the design, I would be glad if someone can show me
> my misuse of itk.
>
> The reason, why the dicom stacks are converted without error in most
> cases, leads me to my next question/problem. I extrapolate the z spacing
> myself from the dicom stack and actualize the image, loaded with the
> help of the itkImageSeriesReader. To do this, I use following piece of
> code:
>
> const double* pdSpacing = m_Image->GetSpacing();
> double dNewSpacing[3] = {1};
>
> for (int iIndex=0; iIndex< 2; iIndex ++, pdSpacing++)
> {
> dNewSpacing[iIndex] = *pdSpacing;
> };
>
> dNewSpacing[2] = dSliceThickness
> //dSliceThickness is the z spacing extrapolated from the dicom
> slices;
>
> m_Image->SetSpacing(dNewSpacing);
>
> The spacing is now actualized and every thing seems to be fine. But when
> I convert the image (with the function listed above) and reach the
> BeforeThreadedGenerateData function of the ResampleImageFilter (line
> 174) where the input image of the interpolator is to be set, the spacing
> of the input image is 1.
> So there is no error when converting the image, because the input point
> is divided by 1 when converting it to index, but I don't know, what I'm
> doing wrong to lose the spacing information.
>
> Thank you, for working through this long mail. Hope, someone can give me
> a or some clues.
>
> Ralf o Floca
>
> _______________________________________________
> Insight-users mailing list
> Insight-users at itk . org
> http://www . itk . org/mailman/listinfo/insight-users
>