cmtkWarpXform.cxx

Go to the documentation of this file.
00001 /*
00002 //
00003 //  Copyright 1997-2010 Torsten Rohlfing
00004 //
00005 //  Copyright 2004-2011 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: 2731 $
00026 //
00027 //  $LastChangedDate: 2011-01-13 16:22:47 -0800 (Thu, 13 Jan 2011) $
00028 //
00029 //  $LastChangedBy: torstenrohlfing $
00030 //
00031 */
00032 
00033 #include "cmtkWarpXform.h"
00034 
00035 #include <Base/cmtkMathUtil.h>
00036 #include <Base/cmtkUniformVolume.h>
00037 
00038 #include <string.h>
00039 #include <algorithm>
00040 
00041 namespace
00042 cmtk
00043 {
00044 
00047 
00048 void
00049 WarpXform::InitGrid
00050 ( const FixedVector<3,Types::Coordinate>& domain, const Self::IndexType& dims )
00051 {
00052   this->Domain = domain;
00053   this->m_Dims = dims;
00054   std::fill( this->m_Offset.begin(), this->m_Offset.end(), 0 );
00055   
00056   NumberOfControlPoints = this->m_Dims[0] * this->m_Dims[1] * this->m_Dims[2];
00057   this->AllocateParameterVector( 3 * NumberOfControlPoints );
00058   this->Update();
00059 }
00060 
00061 void 
00062 WarpXform::Update( const bool )
00063 {
00064   nextI = 3;
00065   nextJ = nextI * this->m_Dims[0];
00066   nextK = nextJ * this->m_Dims[1];
00067   nextIJ = nextJ + nextI;
00068   nextIK = nextK + nextI;
00069   nextJK = nextK + nextJ;
00070   nextIJK = nextJK + nextI;
00071 }
00072 
00073 void
00074 WarpXform::GetDerivativeLandmarksMSD
00075 ( double& lowerMSD, double& upperMSD, const MatchedLandmarkList* ll,
00076   const unsigned int idx, const Types::Coordinate step )
00077 {
00078   upperMSD = lowerMSD = 0;
00079 
00080   Types::Coordinate pOld = this->m_Parameters[idx];
00081 
00082   this->m_Parameters[idx] += step;
00083   MatchedLandmarkList::const_iterator it = ll->begin();
00084   while ( it != ll->end() ) 
00085     {
00086     Self::SpaceVectorType source( (*it)->GetLocation() );
00087     Self::SpaceVectorType target( (*it)->GetTargetLocation() );
00088     this->ApplyInPlace( source );
00089     upperMSD += (source - target).SumOfSquares();
00090     ++it;
00091     }
00092   
00093   this->m_Parameters[idx] = pOld - step;
00094   it = ll->begin();
00095   while ( it != ll->end() ) 
00096     {
00097     Self::SpaceVectorType source( (*it)->GetLocation() );
00098     Self::SpaceVectorType target( (*it)->GetTargetLocation() );
00099     this->ApplyInPlace( source );
00100     lowerMSD += (source - target).SumOfSquares();
00101     ++it;
00102     }
00103   this->m_Parameters[idx] = pOld;
00104   
00105   upperMSD /= ll->size();
00106   lowerMSD /= ll->size();
00107 }
00108 
00109 Types::Coordinate
00110 WarpXform::GetInverseConsistencyError
00111 ( const Self* inverse, const UniformVolume* volume, const UniformVolume::RegionType* voi ) const 
00112 {
00113   Self::SpaceVectorType v, vv;
00114   Types::Coordinate result = 0.0;
00115   int count = 0;
00116 
00117   DataGrid::RegionType myVoi;
00118   const DataGrid::RegionType *pVoi = &myVoi;
00119   if ( voi ) 
00120     {
00121     pVoi = voi;
00122     } 
00123   else
00124     {
00125     myVoi = volume->GetWholeImageRegion();
00126     }
00127 
00128   for ( int z = pVoi->From()[2]; z < pVoi->To()[2]; ++z )
00129     for ( int y = pVoi->From()[1]; y < pVoi->To()[1]; ++y )
00130       for ( int x = pVoi->From()[0]; x < pVoi->To()[0]; ++x ) 
00131         {
00132         v = volume->GetGridLocation( x, y, z );
00133         vv = v;
00134         this->ApplyInPlace( vv );
00135         if ( inverse->InDomain( vv ) ) 
00136           {
00137           inverse->ApplyInPlace( vv );
00138           v -= vv;
00139           result += v.RootSumOfSquares();
00140           ++count;
00141           }
00142         }
00143   
00144   return count ? result / count : 0.0;
00145 }
00146 
00147 void
00148 WarpXform::GetDerivativeInverseConsistencyError
00149 ( double& lower, double& upper, const Self* inverse,
00150   const UniformVolume* volume, const UniformVolume::RegionType* voi, 
00151   const unsigned int idx, const Types::Coordinate step )
00152 {
00153   const Types::Coordinate pOld = this->m_Parameters[idx];
00154   upper = lower = (-this->GetInverseConsistencyError( inverse, volume, voi ));
00155 
00156   this->m_Parameters[idx] += step;
00157   upper += this->GetInverseConsistencyError( inverse, volume, voi );
00158 
00159   this->m_Parameters[idx] = pOld - step;
00160   lower+= this->GetInverseConsistencyError( inverse, volume, voi );
00161 
00162   this->m_Parameters[idx] = pOld;
00163 }
00164 
00165 Types::Coordinate 
00166 WarpXform::GetParamStep
00167 ( const size_t idx, const Self::SpaceVectorType&, const Types::Coordinate mmStep ) const
00168 {
00169   if ( this->m_ActiveFlags && ! (*this->m_ActiveFlags)[idx] ) return 0;
00170 
00171   int controlPointIdx = idx / 3;
00172   unsigned short x =  ( controlPointIdx %  this->m_Dims[0] );
00173   unsigned short y = ( (controlPointIdx /  this->m_Dims[0]) % this->m_Dims[1] );
00174   unsigned short z = ( (controlPointIdx /  this->m_Dims[0]) / this->m_Dims[1] );
00175   
00176   if ( (x>=this->m_IgnoreEdge) && (x<(this->m_Dims[0]-this->m_IgnoreEdge)) && 
00177        (y>=this->m_IgnoreEdge) && (y<(this->m_Dims[1]-this->m_IgnoreEdge)) && 
00178        (z>=this->m_IgnoreEdge) && (z<(this->m_Dims[2]-this->m_IgnoreEdge)) ) 
00179     {
00180     return mmStep;
00181     } 
00182   else
00183     {
00184     return 0;
00185     }
00186 }
00187 
00188 void 
00189 WarpXform::SetParametersActive()
00190 {
00191   if ( !this->m_ActiveFlags ) 
00192     {
00193     this->m_ActiveFlags = BitVector::SmartPtr( new BitVector( this->m_NumberOfParameters, true ) );
00194     }
00195   this->m_ActiveFlags->Set();
00196 }
00197 
00198 void
00199 WarpXform::SetParameterActive
00200 ( const size_t index, const bool active )
00201 {
00202   if ( !this->m_ActiveFlags ) 
00203     {
00204     this->m_ActiveFlags = BitVector::SmartPtr( new BitVector( this->m_NumberOfParameters, true ) );
00205     }
00206   this->m_ActiveFlags->Set( index, active );
00207 }
00208 
00209 void 
00210 WarpXform::SetParametersActive( const DataGrid::RegionType& )
00211 {
00212   if ( !this->m_ActiveFlags ) 
00213     {
00214     this->m_ActiveFlags = BitVector::SmartPtr( new BitVector( this->m_NumberOfParameters, true ) );
00215     }
00216 }
00217 
00218 void
00219 WarpXform::SetParametersActive
00220 ( const int axis, const bool active )
00221 {
00222   if ( !this->m_ActiveFlags ) 
00223     {
00224     this->m_ActiveFlags = BitVector::SmartPtr( new BitVector( this->m_NumberOfParameters, true ) );
00225     }
00226   for ( unsigned int idx = (unsigned int)axis; idx < this->m_NumberOfParameters; idx += 3 )
00227     this->m_ActiveFlags->Set( idx, active );
00228 }
00229 
00230 void
00231 WarpXform::SetParametersActive( const char* axes )
00232 {
00233   if ( !this->m_ActiveFlags ) 
00234     {
00235     this->m_ActiveFlags = BitVector::SmartPtr( new BitVector( this->m_NumberOfParameters, false ) );
00236     }
00237   if ( axes ) 
00238     {
00239     if ( strchr( axes, 'x' ) || strchr( axes, 'X' ) )
00240       this->SetParametersActive( AXIS_X );
00241     if ( strchr( axes, 'y' ) || strchr( axes, 'Y' ) )
00242       this->SetParametersActive( AXIS_Y );
00243     if ( strchr( axes, 'z' ) || strchr( axes, 'Z' ) )
00244       this->SetParametersActive( AXIS_Z );
00245     }
00246 }
00247 
00248 void
00249 WarpXform::SetParameterInactive( const size_t index )
00250 {
00251   if ( !this->m_ActiveFlags ) 
00252     {
00253     this->m_ActiveFlags = BitVector::SmartPtr( new BitVector( this->m_NumberOfParameters, true ) );
00254     }
00255   this->m_ActiveFlags->Reset( index );
00256 }
00257 
00258 int
00259 WarpXform::GetParameterActive( const size_t index ) const
00260 {
00261   if ( this->m_ActiveFlags )
00262     return (*this->m_ActiveFlags)[index];
00263   else
00264     return 1;
00265 }
00266 
00267 void
00268 WarpXform::DeleteParameterActiveFlags()
00269 {
00270   this->m_ActiveFlags = BitVector::SmartPtr::Null;
00271 }
00272 
00273 void
00274 WarpXform::ReplaceInitialAffine( const AffineXform* newAffineXform )
00275 {
00276   AffineXform change;
00277 
00278   // first, get inverse of current initial affine transformation
00279   if ( this->m_InitialAffineXform ) 
00280     {
00281     change = *(this->m_InitialAffineXform->GetInverse());
00282     }
00283 
00284   // second, append current initial affine transformation
00285   if ( newAffineXform )
00286     change.Concat( *newAffineXform );
00287 
00288   // apply effective change to all control points.
00289   Types::Coordinate *coeff = this->m_Parameters;
00290   for ( unsigned int idx = 0; idx < NumberOfControlPoints; ++idx, coeff+=3 ) 
00291     {
00292     Self::SpaceVectorType p( coeff );
00293     change.ApplyInPlace( p );
00294     coeff[0] = p[0];
00295     coeff[1] = p[1];
00296     coeff[2] = p[2];
00297     }
00298 
00299   // Finally, copy new transformation. We want to create a new object here
00300   // if the current transformation is linked somewhere else.
00301   if ( newAffineXform )
00302     {
00303     this->m_InitialAffineXform = AffineXform::SmartPtr::DynamicCastFrom( newAffineXform->Clone() );
00304     }
00305   else
00306     {
00307     this->m_InitialAffineXform = AffineXform::SmartPtr( new AffineXform );
00308     }
00309   this->m_InitialAffineXform->m_MetaInformation[META_XFORM_FIXED_IMAGE_PATH] = this->m_MetaInformation[META_XFORM_FIXED_IMAGE_PATH];
00310   this->m_InitialAffineXform->m_MetaInformation[META_XFORM_MOVING_IMAGE_PATH] = this->m_MetaInformation[META_XFORM_MOVING_IMAGE_PATH];
00311 }
00312 
00313 void
00314 WarpXform::ConcatAffine( const AffineXform* affineXform )
00315 {
00316   // apply effective change to all control points.
00317   Types::Coordinate *coeff = this->m_Parameters;
00318   for ( unsigned int idx = 0; idx < NumberOfControlPoints; ++idx, coeff+=3 ) 
00319     {
00320     Self::SpaceVectorType p( coeff );
00321     affineXform->ApplyInPlace( p );
00322     coeff[0] = p[0];
00323     coeff[1] = p[1];
00324     coeff[2] = p[2];
00325     }
00326 
00327   // Finally, generate combined affine transformation. We want to create a new
00328   // object here if the current transformation is linked somewhere else.
00329   if ( this->m_InitialAffineXform.GetReferenceCount() != 1 )
00330     this->m_InitialAffineXform = this->m_InitialAffineXform->Clone();
00331   this->m_InitialAffineXform->Concat( *affineXform );
00332 }
00333 
00334 } // namespace cmtk
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines