[Insight-users] CenteredRigid2DTransform/ResampleImageFilter
Simon Warfield
simon.warfield at childrens.harvard.edu
Mon Aug 31 09:37:11 EDT 2009
You are creating a centered transform which has 5 parameters, and
initializing it to its default settings.
Then you are setting an angle, which creates a matrix rotating about the
default center.
Then you set a new center. The documentation says:
> WARNING: When using the Center, we strongly recommend only changing
> the matrix and translation to define a transform. Changing a
> transform's center, changes the mapping between spaces - specifically,
> translation is not changed with respect to that new center, and so the
> offset is updated to * maintain the consistency with translation. If a
> center is not used, or is set before the matrix and the offset, then
> it is safe to change the offset directly. As a rule of thumb, if you
> wish to set the center explicitly, set before Offset
> <http://www.itk.org/Doxygen/html/classitk_1_1Offset.html> computations
> are done
Then you set a new translation.
The transform you are ending up with is not what you are expecting.
The bottom line is that all of the Centered* family of transforms
operate in this way that frequently surprises new users,
and has a behavior that is hard for optimizers to handle because of the
interaction between the different parameters.
I recommend not to use any of the Centered* transforms.
Instead, just use the Rigid2DTransform. Note that the Rigid2DTransform
has a center that operates as you are expecting.
It is called the 'fixed parameters'.
--
Simon
> Date: Mon, 31 Aug 2009 14:42:13 +0200
> From: Matthias Seise <Matthias.Seise at fit.fraunhofer.de>
> Subject: [Insight-users] CenteredRigid2DTransform/ResampleImageFilter
> inconsistent behavior of transformPoint() and image transform(bug?)
> To: insight-users at itk.org
> Message-ID: <4A9BC525.5000706 at fit.fraunhofer.de>
> Content-Type: text/plain; charset="iso-8859-15"
>
> Hey all,
>
> I'm struggling with the usage of itkResampleImageFilter together with
> CenteredRigid2DTransform. I just want to transform an image and write
> the full image to a PNG-file. (I'm using ITK 3.14, "Review ON")
>
> Basic "algorithm" (sample code is attached as well)
> I calculate the bounding box of the transformed image (Basically I take
> the corners of the original image, use
> transform->TransformPoints(corners) to get the new coordinates and take
> min/max coordinates as bounding box)
> Since PNG ignores origin settings I change the translation in the
> transform so that the bounding box has origin (0,0). I set the correct
> size of the output image (=size of bounding box) and the origin (0,0).
>
> The resulting image should show the full rotated image (all corners are
> within the image region which is written to the file) but the file shows
> only a cropped image (wrong translation? see attached image "out.png" )
>
> Here is the code and its output, small sample image are attached for
> testing. Any help is appreciated!
>
> Thanks for the help!
>
> CODE:
>
> #include "itkImage.h"
> #include "itkImageFileReader.h"
> #include "itkImageFileWriter.h"
> #include "itkResampleImageFilter.h"
> #include "itkIdentityTransform.h"
> #include "itkLinearInterpolateImageFunction.h"
> #include "itkRGBPixel.h"
>
> #include "itkCenteredRigid2DTransform.h"
> #include<vector>
>
> const unsigned int Dimension = 2;
> typedef unsigned char PixelType;
>
> typedef itk::Image< PixelType, Dimension > ImageType;
>
>
> typedef itk::ImageFileReader< ImageType > ReaderType;
> typedef itk::ImageFileWriter< ImageType > WriterType;
>
> typedef itk::CenteredRigid2DTransform < double > TransformType;
> // typedef itk::IdentityTransform< double, Dimension > TransformType;
> typedef itk::ResampleImageFilter<ImageType, ImageType > FilterType;
> typedef itk::LinearInterpolateImageFunction<ImageType, double >
> InterpolatorType;
>
> int main( int argc, char * argv[] )
> {
> ReaderType::Pointer reader = ReaderType::New();
> WriterType::Pointer writer = WriterType::New();
>
> reader->SetFileName( "white.png" );
> writer->SetFileName( "out.png" );
> reader->UpdateOutputInformation();
>
> TransformType::Pointer transform = TransformType::New();
> transform->SetAngle(0.3);
> double centre[2]={25,35};
> transform->SetCenter(centre);
> double transl[2]={10,20};
> transform->SetTranslation(transl);
>
> ImageType::SpacingType spacing;
> spacing = reader->GetOutput()->GetSpacing();
> ImageType::PointType origin;
> origin = reader->GetOutput()->GetOrigin();
> ImageType::DirectionType direction;
> direction=reader->GetOutput()->GetDirection();
> ImageType::SizeType size;
> size = reader->GetOutput()->GetLargestPossibleRegion().GetSize();
>
> std::vector<ImageType::PointType> pIn(4);
> std::vector<ImageType::PointType> pOut(4);
> ImageType::PointType orgN;
>
> //calculate corners
> for (int k=0;k<4;k++){
> pIn[k].Fill(0);
> }
> pIn[1][0]=origin[0];
> pIn[1][1]=origin[1]+size[1];
> pIn[2][0]=origin[0]+size[0];
> pIn[2][1]=origin[1];
> pIn[3][0]=origin[0]+size[0];
> pIn[3][1]=origin[1]+size[1];
>
> std::cout<<"Original origin: "<<origin[0]<<","<<origin[1]<<","<<std::endl;
> for (int k=0;k<4;k++)
> std::cout<<"Original corner p"<<k<<":
> "<<pIn[k][0]<<","<<pIn[k][1]<<","<<std::endl;
>
> //Transform all Points
> orgN=transform->TransformPoint(origin);
> for (int k=0;k<4;k++)
> pOut[k]=transform->TransformPoint(pIn[k]);
>
> TransformType::OutputVectorType trans=transform->GetTranslation();
>
> //calculate bounding box
> double minX,maxX;
> for (int z=0;z<2;z++){
> minX =1000000.0;
> maxX =-1000000.0;
> for (int k=0;k<4;k++){
> if (minX>pOut[k][z])
> minX=pOut[k][z];
> if (maxX<pOut[k][z])
> maxX=pOut[k][z];
> }
> size[z] = ((int) ceil(maxX)) - ((int) floor(minX));
> trans[z] -= minX;//translate bounding box to origin (0,0)
> }
>
> // set transform so that bounding box has origin(0,0)
> transform->SetTranslation(trans);
> orgN=transform->TransformPoint(origin);
> for (int k=0;k<4;k++)
> pOut[k]=transform->TransformPoint(pIn[k]);
>
> for (int k=0;k<4;k++)
> std::cout<<"Transformed corner p"<<k<<":
> "<<pOut[k][0]<<","<<pOut[k][1]<<","<<std::endl;
>
>
> std::cout<<"Size: "<<size[0]<<","<<size[1]<<","<<std::endl;
> std::cout<<"Origin: "<<origin[0]<<","<<origin[1]<<","<<std::endl;
>
> FilterType::Pointer filter = FilterType::New();
> InterpolatorType::Pointer interpolator = InterpolatorType::New();
>
> filter->SetInterpolator( interpolator );
> filter->SetDefaultPixelValue( 0 );
>
> filter->SetTransform( transform );
>
> filter->SetOutputSpacing( spacing);
> filter->SetOutputOrigin( origin );
> filter->SetOutputDirection( direction );
> filter->SetSize(size);
>
> filter->SetInput( reader->GetOutput() );
> writer->SetInput( filter->GetOutput() );
> writer->Update();
> }
>
> OUTPUT:
> Original origin: 0,0,
> Original corner p0: 0,0,
> Original corner p1: 0,70,
> Original corner p2: 50,0,
> Original corner p3: 50,70,
> Transformed corner p0: 20.6864,0,
> Transformed corner p1: -3.55271e-15,66.8736,
> Transformed corner p2: 68.4532,14.776,
> Transformed corner p3: 47.7668,81.6496,
> Size: 70,82,
> Origin: 0,0,
>
--
Simon
More information about the Insight-users
mailing list