freCenteredAffineTransformController.cxx

Go to the documentation of this file.
00001 /*=========================================================================
00002 
00003   Program:   F.R.E.E. - flexible registration evaluation engine
00004   Version:   v.1.0.0
00005   Date:      $Date: 2006/09/01 12:00:00 $
00006   Module:    $RCSfile: freCenteredAffineTransformController.cxx,v $
00007   Language:  C++
00008 
00009 
00010 
00011   Copyright (c) 2007 Ralf o Floca (Department of Medical Informatics,
00012   Institute for Medical Biometry and Informatics, University of Heidelberg,
00013   Germany). All rights reserved.
00014   See FREECopyright.txt or http://www.mi.med.uni-hd.de/free/copyright.htm
00015   for details.
00016 
00017      This software is distributed WITHOUT ANY WARRANTY; without even 
00018      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
00019      PURPOSE.  See the above copyright notices for more information.
00020 
00021 =========================================================================*/
00022 
00023 #include "freCenteredAffineTransformController.h"
00024 
00025 #include "freIntensityImageMediaController.h"
00026 #include "freTransformSetupAdaptor.h"
00027 
00028 #include "itkPoint.h"
00029 #include "itkCenteredTransformInitializer.h"
00030 
00031 namespace FREE
00032 {
00033 
00037 
00038 
00039 CenteredAffine2DTransformController::
00040 CenteredAffine2DTransformController()
00041 {
00042   this->UpdateControllerID(ControllerID::CenteredAffine2DTransformController);
00043   this->m_Description = "A affine transformation (2 Dimensions), composed of rotation (around a specified center), scaling, shearing and translation.";
00044 };
00045 
00046 void
00047 CenteredAffine2DTransformController::
00048 GenerateProfile(CtrlProfile::ControllerProfile& profile, 
00049                 const SessionComponentCache* pComponentCache,
00050                 bool bRegardOldSetup) const
00051 {
00052   Superclass::GenerateProfile(profile,pComponentCache,bRegardOldSetup);
00053 
00054   //Parameters
00055   profile.Parameters().AddParameter(cParam_InitialTransformValues,CtrlProfile::Parameter::PVTDouble,"1..4: elements of the 2x2 matrix\n5..6: rotation center (x/y)\n7..8: elements of the translation vector.",8,"0");
00056   profile.Parameters().AddParameter(cParam_CurrentTransformValues,CtrlProfile::Parameter::PVTDouble,"1..4: elements of the 2x2 matrix\n5..6: rotation center (x/y)\n7..8: elements of the translation vector.",8,"0");
00057   profile.Parameters().AddParameter(cParam_TransformScale,CtrlProfile::Parameter::PVTDouble,"1..4: elements of the 2x2 matrix\n5..6: rotation center (x/y)\n7..8: elements of the translation vector.",8,"1",-1,true);
00058 
00059   profile.MediaMap().AddMedia("movingInitialImage",ControllerID::IntensityImage2DMediaController,DASet,2);
00060   profile.MediaMap().AddMedia("fixedInitialImage",ControllerID::IntensityImage2DMediaController,DASet,2);
00061 };
00062 
00063 bool
00064 CenteredAffine2DTransformController::
00065 SetInitialTransformValues( ComponentType* pTransformComponent,
00066                            SessionComponentCache* pComponentCache,
00067                            SessionInfo* pSessionInfo,
00068                            const int& iInitializeByITV) const
00069 {
00070   int iCenterType;
00071   
00072   if (!pComponentCache->SetupIsAssigned()) throwCtrlExceptionMacro("","Cannot initialize transform values, transform setup is not assigned in cache.");
00073   ComponentSetup* pTransformSetup = pComponentCache->Setup();
00074 
00075   if (!pTransformSetup->Parameters().GetParameterValue("CenterType",iCenterType)) throwExceptionMacro("Missing parameter: " << "CenterType");
00076   
00077   TransformSetupAdaptor adaptor(pTransformSetup);
00078   ReferencePointsAccessor<2> pointsAccessor(pComponentCache);
00079 
00080         //2D version
00081         //Calculate the centers
00082         ParameterArrayType fixedCenter(2);
00083         ParameterArrayType movingCenter(2);
00084 
00085         if (2==(iInitializeByITV&2))
00086         { //Center is stored in the ITV and should be used
00087           // center point x/y
00088           ParameterArrayType itv = adaptor.GetInitialTransformParameters();
00089           for (int iIndex=0; iIndex<2; iIndex++)
00090           {
00091                 movingCenter[iIndex] = itv[4+iIndex];
00092                 fixedCenter[iIndex] = itv[4+iIndex] - itv[6+iIndex];
00093           };
00094         }
00095         else
00096         { 
00097           if (iCenterType==0)
00098           { //First paire of reference points are the center points
00099       if (!pointsAccessor.MovingPointsExist()) throwCtrlExceptionMacro("","Cannot set moving center via reference points. No moving reference point set defined. Please check media linkage.");
00100       if (!pointsAccessor.FixedPointsExist()) throwCtrlExceptionMacro("","Cannot set fixed center via reference points. No fixed reference point set defined. Please check media linkage.");
00101                 fixedCenter = pointsAccessor.GetFixedPointArray(0);
00102                 movingCenter = pointsAccessor.GetMovingPointArray(0);
00103           }
00104           else
00105           {
00106                 //Center should be calculated
00107                 CenterInitializer<PixelType,2> centerInitializer;
00108           
00109                 if (iCenterType==1) centerInitializer.GeometryOn();
00110                 else centerInitializer.MomentsOn();
00111 
00112     typedef ImageTypes<2>::InternalImageType InternalImageType;
00113     
00114     SessionAccessor::GenericMediaPointer smpGenericInitialFixedImage = SessionAccessor::GetLinkedMedia("fixedInitialImage",pComponentCache,pSessionInfo);
00115     if (smpGenericInitialFixedImage.IsNull()) throwCtrlExceptionMacro("","Cannot set fixed center via initial image. No initial fixed image linked. Please check media linkage.");
00116     SessionAccessor::GenericMediaPointer smpGenericInitialMovingImage = SessionAccessor::GetLinkedMedia("movingInitialImage",pComponentCache,pSessionInfo);
00117     if (smpGenericInitialMovingImage.IsNull()) throwCtrlExceptionMacro("","Cannot set moving center via initial image. No initial fixed image linked. Please check media linkage.");
00118     
00119     InternalImageType* pInitialFixedImage = 0;
00120     InternalImageType* pInitialMovingImage = 0;
00121 
00122     try
00123     {
00124       pInitialFixedImage = dynamic_cast<InternalImageType*>(smpGenericInitialFixedImage.GetPointer());
00125     }
00126     catchAllNPassMacro("Error while casting initial fixed image");
00127     if (!pInitialFixedImage) throwCtrlExceptionMacro("","Error while casting initial fixed image.");
00128 
00129     try
00130     {
00131       pInitialMovingImage = dynamic_cast<InternalImageType*>(smpGenericInitialMovingImage.GetPointer());
00132     }
00133     catchAllNPassMacro("Error while casting initial fixed image");
00134     if (!pInitialMovingImage) throwCtrlExceptionMacro("","Error while casting initial fixed image.");
00135 
00136     centerInitializer.SetImage(pInitialFixedImage);
00137                 centerInitializer.GetCenter(fixedCenter);
00138 
00139                 centerInitializer.SetImage(pInitialMovingImage);
00140                 centerInitializer.GetCenter(movingCenter);
00141           }
00142         }
00143 
00144         //Calculate the translation
00145         ParameterArrayType translation(2);
00146         for (int iIndex=0; iIndex<2; iIndex++)
00147         {
00148           translation[iIndex] = movingCenter[iIndex]-fixedCenter[iIndex];
00149         };
00150 
00151     //add the calculated initial translation and center to the setup - to be present
00152     //for the Registrator - when using set initial position.
00153         for (int iIndex=0; iIndex<2; iIndex++)
00154         {
00155           pTransformSetup->Parameters().SetParameterValue(cParam_CurrentTransformValues,fixedCenter[iIndex],4+iIndex);
00156           pTransformSetup->Parameters().SetParameterValue(cParam_CurrentTransformValues,translation[iIndex],6+iIndex);
00157         };
00158 
00159         if (!(1==(iInitializeByITV&1)))
00160         { //Rotation should be calculated
00161     if (!pointsAccessor.MovingPointsExist()) throwCtrlExceptionMacro("","Cannot estimate rotation via reference points. No moving reference point set defined. Please check media linkage.");
00162     if (!pointsAccessor.FixedPointsExist()) throwCtrlExceptionMacro("","Cannot estimate rotation via via reference points. No fixed reference point set defined. Please check media linkage.");
00163 
00164           RotationInitializer<2> rotationInitializer;
00165           
00166           rotationInitializer.SetCenterPair(movingCenter,fixedCenter);
00167 
00168           //Add all references
00169           int iIndex = 0;
00170           if (iCenterType==0) iIndex = 1; //first reference is the center point;
00171           for (iIndex; iIndex<pointsAccessor.GetFixedPointsCount(); iIndex++)
00172           {
00173                 rotationInitializer.AddReferencePair(pointsAccessor.GetMovingPointArray(iIndex),pointsAccessor.GetFixedPointArray(iIndex));
00174           };
00175 
00176           //set schedule
00177           rotationInitializer.ClearSchedule(false);
00178           rotationInitializer.AddToSchedule(RA_Z);
00179 
00180           rotationInitializer.ComputeRotations();
00181 
00182           //add angel to the parameters. Angel must be inverted, because itk uses back transform
00183           //(fixed to moving) and the initial calculation uses forward transform to allow an intuitive
00184           //parameter setting
00185           double dAngel = -1*rotationInitializer.GetRotation(RA_Z);
00186           //Set rotation matrix
00187           pTransformSetup->Parameters().SetParameterValue(cParam_CurrentTransformValues,cos(dAngel),0);
00188           pTransformSetup->Parameters().SetParameterValue(cParam_CurrentTransformValues,-sin(dAngel),1);
00189           pTransformSetup->Parameters().SetParameterValue(cParam_CurrentTransformValues,sin(dAngel),2);
00190           pTransformSetup->Parameters().SetParameterValue(cParam_CurrentTransformValues,cos(dAngel),3);
00191         }
00192 
00193   return true;
00194 };
00195 
00199 
00200 
00201 CenteredAffine3DTransformController::
00202 CenteredAffine3DTransformController()
00203 {
00204   this->UpdateControllerID(ControllerID::CenteredAffine3DTransformController);
00205   this->m_Description = "A affine transformation (3 Dimensions), composed of rotation (around a specified center), scaling, shearing and translation.";
00206 };
00207 
00208 void
00209 CenteredAffine3DTransformController::
00210 GenerateProfile(CtrlProfile::ControllerProfile& profile, 
00211                 const SessionComponentCache* pComponentCache,
00212                 bool bRegardOldSetup) const
00213 {
00214   Superclass::GenerateProfile(profile,pComponentCache,bRegardOldSetup);
00215 
00216   //Parameters
00217   profile.Parameters().AddParameter("InitialRotationAxis",Parameter::PVTInteger,"Indicates the type of rotation used for initialisation, if the reference initialisation is used.\n0: The rotation axis is calculated as cross product of the reverence - centerpoint vectors.\n1: x axis\n2: y axis\n3: z axis\n4:Composing (in reading order) a z rotation, y rotation, x rotation\n5:Smart composing (like composing, but rotation is weightened).",1,"0");
00218   profile.Parameters().AddParameter(cParam_InitialTransformValues,CtrlProfile::Parameter::PVTDouble,"1..9: elements of the 3x3 matrix\n10..12: rotation center (x/y/z)\n13..15: elements of the translation vector.",15,"0");
00219   profile.Parameters().AddParameter(cParam_CurrentTransformValues,CtrlProfile::Parameter::PVTDouble,"1..9: elements of the 3x3 matrix\n10..12: rotation center (x/y/z)\n13..15: elements of the translation vector.",15,"0");
00220   profile.Parameters().AddParameter(cParam_TransformScale,CtrlProfile::Parameter::PVTDouble,"1..9: elements of the 3x3 matrix\n10..12: rotation center (x/y/z)\n13..15: elements of the translation vector.",15,"1",-1,true);
00221 
00222   profile.MediaMap().AddMedia("movingInitialImage",ControllerID::IntensityImage3DMediaController,DASet,3);
00223   profile.MediaMap().AddMedia("fixedInitialImage",ControllerID::IntensityImage3DMediaController,DASet,3);
00224 };
00225 
00226 bool
00227 CenteredAffine3DTransformController::
00228 SetInitialTransformValues( ComponentType* pTransformComponent,
00229                            SessionComponentCache* pComponentCache,
00230                            SessionInfo* pSessionInfo,
00231                            const int& iInitializeByITV) const
00232 {
00233   int iCenterType;
00234 
00235   if (!pComponentCache->SetupIsAssigned()) throwCtrlExceptionMacro("","Cannot initialize transform values, transform setup is not assigned in cache.");
00236   ComponentSetup* pTransformSetup = pComponentCache->Setup();
00237 
00238   if (!pTransformSetup->Parameters().GetParameterValue("CenterType",iCenterType)) throwExceptionMacro("Missing parameter: " << "CenterType");
00239 
00240   //3D version
00241   TransformSetupAdaptor adaptor(pTransformSetup);
00242   ReferencePointsAccessor<3> pointsAccessor(pComponentCache);
00243 
00244   //Calculate the Centers
00245   ParameterArrayType fixedCenter(3);
00246   ParameterArrayType movingCenter(3);
00247 
00248   if (2==(iInitializeByITV&2))
00249   { //Center is stored in the ITV and should be used
00250     // center point x/y/z
00251     ParameterArrayType itv = adaptor.GetInitialTransformParameters();
00252     for (int iIndex=0; iIndex<3; iIndex++)
00253     {
00254       movingCenter[iIndex] = itv[9+iIndex];
00255       fixedCenter[iIndex] = itv[9+iIndex] - itv[12+iIndex];
00256     };
00257   }
00258   else
00259   { 
00260     if (iCenterType==0)
00261     { //First paire of reference points are the center points
00262       if (!pointsAccessor.MovingPointsExist()) throwCtrlExceptionMacro("","Cannot set moving center via reference points. No moving reference point set defined. Please check media linkage.");
00263       if (!pointsAccessor.FixedPointsExist()) throwCtrlExceptionMacro("","Cannot set fixed center via reference points. No fixed reference point set defined. Please check media linkage.");
00264       fixedCenter = pointsAccessor.GetFixedPointArray(0);
00265       movingCenter = pointsAccessor.GetMovingPointArray(0);
00266     }
00267     else
00268     {
00269       //Center should be calculated
00270       CenterInitializer<PixelType,3> centerInitializer;
00271 
00272       if (iCenterType==1) centerInitializer.GeometryOn();
00273       else centerInitializer.MomentsOn();
00274 
00275       typedef ImageTypes<3>::InternalImageType InternalImageType;
00276       
00277       SessionAccessor::GenericMediaPointer smpGenericInitialFixedImage = SessionAccessor::GetLinkedMedia("fixedInitialImage",pComponentCache,pSessionInfo);
00278       if (smpGenericInitialFixedImage.IsNull()) throwCtrlExceptionMacro("","Cannot set fixed center via initial image. No initial fixed image linked. Please check media linkage.");
00279       SessionAccessor::GenericMediaPointer smpGenericInitialMovingImage = SessionAccessor::GetLinkedMedia("movingInitialImage",pComponentCache,pSessionInfo);
00280       if (smpGenericInitialMovingImage.IsNull()) throwCtrlExceptionMacro("","Cannot set moving center via initial image. No initial fixed image linked. Please check media linkage.");
00281       
00282       InternalImageType* pInitialFixedImage = 0;
00283       InternalImageType* pInitialMovingImage = 0;
00284 
00285       try
00286       {
00287         pInitialFixedImage = dynamic_cast<InternalImageType*>(smpGenericInitialFixedImage.GetPointer());
00288       }
00289       catchAllNPassMacro("Error while casting initial fixed image");
00290       if (!pInitialFixedImage) throwCtrlExceptionMacro("","Error while casting initial fixed image.");
00291 
00292       try
00293       {
00294         pInitialMovingImage = dynamic_cast<InternalImageType*>(smpGenericInitialMovingImage.GetPointer());
00295       }
00296       catchAllNPassMacro("Error while casting initial fixed image");
00297       if (!pInitialMovingImage) throwCtrlExceptionMacro("","Error while casting initial fixed image.");
00298 
00299       centerInitializer.SetImage(pInitialFixedImage);
00300       centerInitializer.GetCenter(fixedCenter);
00301 
00302       centerInitializer.SetImage(pInitialMovingImage);
00303       centerInitializer.GetCenter(movingCenter);
00304     }
00305   }
00306 
00307   //Calculate the translation
00308   ParameterArrayType translation(3);
00309   for (int iIndex=0; iIndex<3; iIndex++)
00310   {
00311     translation[iIndex] = movingCenter[iIndex]-fixedCenter[iIndex];
00312   };
00313 
00314     //add the calculated initial translation and center to the setup - to be present
00315     //for the Registrator - when using set initial position.
00316   for (int iIndex=0; iIndex<3; iIndex++)
00317   {
00318     pTransformSetup->Parameters().SetParameterValue(cParam_CurrentTransformValues,fixedCenter[iIndex],9+iIndex);
00319     pTransformSetup->Parameters().SetParameterValue(cParam_CurrentTransformValues,translation[iIndex],12+iIndex);
00320   };
00321 
00322   if (!(1==(iInitializeByITV&1)))
00323   { //Rotation should be calculated
00324     if (!pointsAccessor.MovingPointsExist()) throwCtrlExceptionMacro("","Cannot estimate rotation via reference points. No moving reference point set defined. Please check media linkage.");
00325     if (!pointsAccessor.FixedPointsExist()) throwCtrlExceptionMacro("","Cannot estimate rotation via via reference points. No fixed reference point set defined. Please check media linkage.");
00326 
00327     RotationInitializer<3> rotationInitializer;
00328 
00329     rotationInitializer.SetCenterPair(movingCenter,fixedCenter);
00330 
00331     //Add all references
00332     int iIndex = 0;
00333     if (iCenterType==0) iIndex = 1; //first reference is the center point;
00334     for (iIndex; iIndex<pointsAccessor.GetFixedPointsCount(); iIndex++)
00335     {
00336       rotationInitializer.AddReferencePair(pointsAccessor.GetMovingPointArray(iIndex),pointsAccessor.GetFixedPointArray(iIndex));
00337     };
00338 
00339     //set schedule
00340     int iInitialRotationAxis;
00341     if (!pTransformSetup->Parameters().GetParameterValue("InitialRotationAxis",iInitialRotationAxis)) throwExceptionMacro("Missing parameter: " << "InitialRotationAxis");
00342 
00343     rotationInitializer.ClearSchedule(false);
00344     if ((iInitialRotationAxis<1) | (4 == (iInitialRotationAxis & 4))) rotationInitializer.AddToSchedule(RA_Z);
00345     if ((iInitialRotationAxis<1) | (2 == (iInitialRotationAxis & 2))) rotationInitializer.AddToSchedule(RA_Y);
00346     if ((iInitialRotationAxis<1) | (1 == (iInitialRotationAxis & 1))) rotationInitializer.AddToSchedule(RA_X);
00347 
00348     rotationInitializer.SetUseRotationWeight(iInitialRotationAxis==-1);
00349 
00350     rotationInitializer.ComputeRotations();
00351 
00352     typedef itk::AffineTransform<ScalarType,3> CalculateTransformType;
00353     CalculateTransformType::Pointer rotationTransform = CalculateTransformType::New();
00354 
00355     for ( RotationAxisType axis = RA_Z; axis>=RA_X; axis--)
00356     {
00357       Vector3DType rotationAxis;
00358       rotationAxis.Fill(0);
00359       rotationAxis[axis]=1;
00360 
00361       //add angel to the parameters. Angel must be inverted, because itk uses back transform
00362       //(fixed to moving) and the initial calculation uses forward transform to allow an intuitive
00363       double dAngel = -1*rotationInitializer.GetRotation(axis);
00364 
00365       //compute matrix for the rotation
00366       CalculateTransformType::Pointer oneRotation = CalculateTransformType::New();
00367       oneRotation->Rotate3D(rotationAxis,dAngel);
00368 
00369       //add the rotation of this step to the whole transformation
00370       rotationTransform->Compose(oneRotation,false);
00371     };
00372 
00373     //Set rotation matrix
00374     CalculateTransformType::MatrixType rotation = rotationTransform->GetMatrix();
00375 
00376     for (int iIndex=0; iIndex<9; iIndex++)
00377     {
00378       pTransformSetup->Parameters().SetParameterValue(cParam_CurrentTransformValues,rotation[(iIndex/3)][(iIndex%3)],iIndex);
00379     }
00380   };
00381   return true;
00382 };
00383 
00384 
00385 
00386 } //end of namespace free

Generated at Sat Oct 13 15:27:41 2007 for f.r.e.e. - Flexible Registration and Evaluation Engine by doxygen 1.5.3 written by Dimitri van Heesch, © 1997-2000