[Insight-users] A working code for rotating a 3D array with VersorRigid3DTransform

rama rama at robots.ox.ac.uk
Tue Sep 20 14:00:51 EDT 2005


Hi All,

After a very long discussion on the ITK forum regarding rotation of a 3D 
cube, I am able to get it work properly. Thanks to Luis, Karthik, 
Marius, Tamburo and others for their suggestions in this case. Actually 
the problem of memory leak that I raised before is my mistake. I think I 
am overshadowed by the ITK stuff and could not point that memory leak 
before hand. But I was able to solve it. Please refer to messages with 
the title "[Insight-users] confusion with specifying origin for 3D 
affine transformations - itkAffineTransform" for the actual discussion.

Here I am giving the working code snippet, with which one can rotate an 
array cube (a 3D array) about a given center point. Someone might find 
it useful in future. Also if anyone can suggest any optimizations to the 
code below, I will be thankful. One thing which is making me skeptical 
from the beginning is, why should I use ResampleImageFilter when I don't 
need it. Other than using a filter, I did not find any way of feeding in 
data directly to the VersorRigid3DTransfom class. so, any suggestions in 
this case will be helpful.

Here is the working code using the class VersorRigid3DTransform, which 
rotates an array about a given center point around X-Axis.

const unsigned int Dimension=3;
typedef unsigned char InputPixelType;
typedef unsigned char OutputPixelType;
typedef itk::Image<InputPixelType, Dimension> InputImage;
typedef itk::Image<OutputPixelType, Dimension> OutputImage;

typedef itk::ResampleImageFilter<InputImage, OutputImage> Resampler;
Resampler::Pointer resampler=Resampler::New();

typedef itk::ImportImageFilter<InputPixelType, Dimension> 
ImportImgFromArray;   //filter to get data from a C++ array
ImportImgFromArray::Pointer importFilter = ImportImgFromArray::New();

ImportImgFromArray::SizeType size;
size[0]=xPixels;
size[1]=yPixels;
size[2]=zPixels;

ImportImgFromArray::IndexType start;
start.Fill(0);

ImportImgFromArray::RegionType region;
region.SetIndex(start);
region.SetSize(size);
importFilter->SetRegion(region);

double origin[Dimension];
origin[0]=0.0;      //values indicating that origin is set to the 
(0,0,0) index in the array
origin[1]=0.0;
origin[2]=0.0;
importFilter->SetOrigin(origin);

double spacing[Dimension];
spacing[0]=PixelXWidth;
spacing[1]=PixelYWidth;
spacing[2]=PixelZWidth;
importFilter->SetSpacing(spacing);

unsigned char *tempBuffer;
tempBuffer = new unsigned char[size[0]*size[1]*size[2]];

//here comes your data. store your data into this buffer or directly 
specify a pointer of your data in the function below

importFilter->SetImportPointer(tempBuffer, size[0]*size[1]*size[2], false);

typedef itk::NearestNeighborInterpolateImageFunction<InputImage, double> 
Interpolator;
Interpolator::Pointer interpolator=Interpolator::New();
resampler->SetInterpolator(interpolator);

resampler->SetDefaultPixelValue(0);
resampler->SetSize(size);
resampler->SetOutputOrigin(origin);
resampler->SetOutputSpacing(spacing);

typedef itk::VersorRigid3DTransform<double> TransformType;
TransformType::Pointer transform=TransformType::New();

TransformType::InputPointType centerPoint;      //you specify a center 
point here.
centerPoint[0]=(xPixels * PixelXWidth)/2.0;      // here the trick is, 
you are actually shifting
centerPoint[1]=(yPixels * PixelYWidth)/2.0;      //the center point from 
the origin to the point
centerPoint[2]=(zPixels * PixelZWidth)/2.0;      //you want, here it is 
the center point of the cube.
transform->SetCenter(centerPoint);                  //Consider that 
origin initially is at the top-back-left of the cube
                                                                         
//However, this will vary from case to case. This just provides a 
helpful hint.


typedef TransformType::VersorType VersorType;
typedef VersorType::VectorType VectorType;

VersorType rotation;
VectorType axis;

axis[0]=1.0;         //rotate around X-Axis
axis[1]=0.0;
axis[2]=0.0;

rotation.Set(axis, angleInDeg * DegToRad);   //angleInDeg is a variable 
which carries angle of rotation in degrees

transform->SetRotation(rotation);

resampler->SetTransform(transform);

resampler->SetInput(importFilter->GetOutput());
resampler->Update();

InputImage::PixelContainer *container;
container=resampler->GetOutput()->GetPixelContainer();
//container->SetContainerManageMemory(false);   //it is disabled here. 
If you don't want your buffer to be deallocated,
                                                                         
      //uncomment this line here.
unsigned char *tempBuffer2=container->GetImportPointer();

// at this point store the resultant data from tempBuffer2 to the place 
you want. This will be destroyed automatically
//when the 'resampler' filter goes out of scope.

delete [] tempBuffer;

I hope this will help someone else in future in cases of urgency.

thanks and regards,
Rama.




More information about the Insight-users mailing list