cmtkMakeInitialAffineTransformation.cxx

Go to the documentation of this file.
00001 /*
00002 //
00003 //  Copyright 1997-2009 Torsten Rohlfing
00004 //
00005 //  Copyright 2004-2010 SRI International
00006 //
00007 //  This file is part of the Computational Morphometry Toolkit.
00008 //
00009 //  http://www.nitrc.org/projects/cmtk/
00010 //
00011 //  The Computational Morphometry Toolkit is free software: you can
00012 //  redistribute it and/or modify it under the terms of the GNU General Public
00013 //  License as published by the Free Software Foundation, either version 3 of
00014 //  the License, or (at your option) any later version.
00015 //
00016 //  The Computational Morphometry Toolkit is distributed in the hope that it
00017 //  will be useful, but WITHOUT ANY WARRANTY; without even the implied
00018 //  warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019 //  GNU General Public License for more details.
00020 //
00021 //  You should have received a copy of the GNU General Public License along
00022 //  with the Computational Morphometry Toolkit.  If not, see
00023 //  <http://www.gnu.org/licenses/>.
00024 //
00025 //  $Revision: 2398 $
00026 //
00027 //  $LastChangedDate: 2010-10-05 14:54:37 -0700 (Tue, 05 Oct 2010) $
00028 //
00029 //  $LastChangedBy: torstenrohlfing $
00030 //
00031 */
00032 
00033 #include "cmtkMakeInitialAffineTransformation.h"
00034 
00035 #include <Base/cmtkAffineXform.h>
00036 
00037 namespace
00038 cmtk
00039 {
00040 
00043 
00044 const std::string 
00045 MakeInitialAffineTransformation
00046 ::GetModeName( const Self::Mode mode )
00047 {
00048   switch ( mode )
00049     {
00050     case Self::NONE:
00051     default:
00052       return std::string( "none" );
00053     case Self::FOV:
00054       return std::string( "FieldsOfView" );
00055     case Self::COM:
00056       return std::string( "CentersOfMass" );
00057     case Self::PAX:
00058       return std::string( "PrincipalAxes" );
00059     case Self::PHYS:
00060       return std::string( "PhysicalCoordinates" );
00061     }
00062   return std::string( "unknown" );
00063 }
00064 
00065 AffineXform* 
00066 MakeInitialAffineTransformation
00067 ::Create( const UniformVolume& referenceImage, const UniformVolume& floatingImage, const Self::Mode mode )
00068 {
00069   switch ( mode )
00070     {
00071     case Self::NONE:
00072     default:
00073       return new AffineXform;
00074     case Self::FOV:
00075       return Self::AlignFieldsOfView( referenceImage, floatingImage );
00076     case Self::COM:
00077       return Self::AlignCentersOfMass( referenceImage, floatingImage );
00078     case Self::PAX:
00079       return Self::AlignPrincipalAxes( referenceImage, floatingImage );
00080     case Self::PHYS:
00081       return Self::AlignDirectionVectors( referenceImage, floatingImage );
00082     }
00083   return new AffineXform;
00084 }
00085 
00086 AffineXform* 
00087 MakeInitialAffineTransformation
00088 ::AlignDirectionVectors( const UniformVolume& referenceImage, const UniformVolume& floatingImage, const bool centerXform )
00089 {
00090   if ( referenceImage.m_MetaInformation[META_SPACE] != floatingImage.m_MetaInformation[META_SPACE] )
00091     {
00092     StdErr << "ERROR: coordinate spaces '" << referenceImage.m_MetaInformation[META_SPACE]
00093               << "' and '" << floatingImage.m_MetaInformation[META_SPACE] << "' do not match.\n";
00094     return NULL;
00095     }
00096   
00097   if ( referenceImage.m_MetaInformation[META_EXTERNAL_SPACE_ID] != floatingImage.m_MetaInformation[META_EXTERNAL_SPACE_ID] )
00098     {
00099     StdErr << "ERROR: semantic coordinate spaces '" << referenceImage.m_MetaInformation[META_EXTERNAL_SPACE_ID]
00100               << "' and '" << floatingImage.m_MetaInformation[META_EXTERNAL_SPACE_ID] << "' do not match.\n";
00101     return NULL;
00102     }
00103   
00104   const AffineXform::MatrixType refMatrix = referenceImage.GetImageToPhysicalMatrix();
00105   AffineXform referenceXform( refMatrix );
00106 
00107   const AffineXform::MatrixType fltMatrix = floatingImage.GetImageToPhysicalMatrix();
00108   AffineXform floatingXform( fltMatrix );
00109   
00110   AffineXform* xform = new AffineXform( referenceXform );
00111   xform->Concat( *floatingXform.GetInverse() );
00112 
00113   if ( centerXform )
00114     {
00115     const Vector3D center = referenceImage.GetCenterCropRegion();
00116     xform->ChangeCenter( center );
00117     }
00118 
00119   return xform;
00120 }
00121 
00122 AffineXform* 
00123 MakeInitialAffineTransformation
00124 ::AlignFieldsOfView( const UniformVolume& referenceImage, const UniformVolume& floatingImage )
00125 {
00126   AffineXform* xform = new AffineXform;
00127   
00128   const Vector3D translation = floatingImage.GetCenterCropRegion() - referenceImage.GetCenterCropRegion();
00129   xform->SetXlate( translation.begin() );
00130   
00131   return xform;
00132 }
00133 
00134 AffineXform* 
00135 MakeInitialAffineTransformation
00136 ::AlignCentersOfMass( const UniformVolume& referenceImage, const UniformVolume& floatingImage )
00137 {
00138   AffineXform* xform = new AffineXform;
00139   
00140   const Vector3D translation = floatingImage.GetCenterOfMass() - referenceImage.GetCenterOfMass();
00141   xform->SetXlate( translation.begin() );
00142 
00143   return xform;
00144 }
00145 
00146 AffineXform* 
00147 MakeInitialAffineTransformation
00148 ::AlignPrincipalAxes( const UniformVolume& referenceImage, const UniformVolume& floatingImage )
00149 {
00150   // get principal axes
00151   Matrix3x3<Types::Coordinate> pAxesRef, pAxesFlt;
00152   Vector3D centerOfMassRef, centerOfMassFlt;
00153 
00154   referenceImage.GetPrincipalAxes( pAxesRef, centerOfMassRef );
00155   floatingImage.GetPrincipalAxes( pAxesFlt, centerOfMassFlt );
00156 
00157   pAxesRef = pAxesRef.GetTranspose();
00158   pAxesFlt = pAxesFlt.GetTranspose();
00159 
00160   // Now compute transformation
00161   pAxesRef.Invert3x3();
00162   Matrix3x3<Types::Coordinate> xform3x3 = (pAxesRef * pAxesFlt);
00163 
00164   Vector3D xlation = centerOfMassRef;
00165   xform3x3.Multiply( xlation );
00166   xlation = centerOfMassFlt - xlation;
00167   
00168   // Assign xform3x3 as a submatrix of a 4x4
00169   Matrix4x4<Types::Coordinate> xform4x4 = xform3x3;
00170   
00171   // Turn xform4x4 into homogenized matrix with xlation as the 4th column.
00172   for ( int i = 0; i < 3; i++ )
00173     {
00174     xform4x4[3][i] = xlation[i];
00175     xform4x4[i][3] = 0;
00176     }
00177   xform4x4[3][3] = 1;
00178   
00179   AffineXform* xform = new AffineXform( xform4x4 );
00180   xform->ChangeCenter( centerOfMassRef );
00181 
00182   Types::Coordinate* angles = xform->RetAngles();
00183   for ( int i = 0; i < 3; ++i )
00184     {
00185     if ( angles[i] > 90 )
00186       angles[i] -= 180;
00187     else if ( angles[i] < -90 )
00188       angles[i] += 180;
00189     }
00190   xform->SetAngles( angles );
00191   
00192   return xform;
00193 }
00194 
00195 } // namespace cmtk
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines