cmtkSplineWarpXform_Rigidity.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: 2676 $
00026 //
00027 //  $LastChangedDate: 2010-12-15 14:50:13 -0800 (Wed, 15 Dec 2010) $
00028 //
00029 //  $LastChangedBy: torstenrohlfing $
00030 //
00031 */
00032 
00033 #include "cmtkSplineWarpXform.h"
00034 
00035 #include <Base/cmtkQRDecomposition.h>
00036 
00037 #include <vector>
00038 
00039 namespace
00040 cmtk
00041 {
00042 
00045 
00046 Types::Coordinate
00047 SplineWarpXform::GetRigidityConstraintSparse () const
00048 {
00049   double Constraint = 0;
00050   CoordinateMatrix3x3 J;
00051 
00052   const Types::Coordinate* coeff = this->m_Parameters + nextI + nextJ + nextK;
00053   for ( int z = 1; z<this->m_Dims[2]-1; ++z, coeff+=2*nextJ )
00054     for ( int y = 1; y<this->m_Dims[1]-1; ++y, coeff+=2*nextI )
00055       for ( int x = 1; x<this->m_Dims[0]-1; ++x, coeff+=nextI )
00056         {
00057         this->GetJacobian( Self::SpaceVectorType( coeff ), J );
00058         Constraint += this->GetRigidityConstraint( J );
00059         }
00060   
00061   // Divide by number of control points to normalize with respect to the
00062   // number of local Jacobians in the computation.
00063   return (Types::Coordinate)(Constraint / this->NumberOfControlPoints);
00064 }
00065 
00066 void 
00067 SplineWarpXform::GetRigidityConstraintDerivative
00068 ( double& lower, double& upper, const int param, const DataGrid::RegionType& voi, const Types::Coordinate step ) const
00069 {
00070   const int pixelsPerRow = voi.To()[0] - voi.From()[0];
00071   std::vector<CoordinateMatrix3x3> arrayJ( pixelsPerRow );
00072   
00073   double ground = 0;
00074 
00075   for ( int k = voi.From()[2]; k < voi.To()[2]; ++k )
00076     for ( int j = voi.From()[1]; j < voi.To()[1]; ++j ) 
00077       {
00078       this->GetJacobianRow( &(arrayJ[0]), voi.From()[0], j, k, pixelsPerRow );
00079       for ( int i = 0; i < pixelsPerRow; ++i ) 
00080         {
00081         ground += this->GetRigidityConstraint( arrayJ[i] );
00082         }
00083       }
00084   
00085   upper = -ground;
00086   lower = -ground;
00087   
00088   const Types::Coordinate oldCoeff = this->m_Parameters[param];
00089   this->m_Parameters[param] += step;
00090   for ( int k = voi.From()[2]; k < voi.To()[2]; ++k )
00091     for ( int j = voi.From()[1]; j < voi.To()[1]; ++j ) 
00092       {
00093       this->GetJacobianRow( &(arrayJ[0]), voi.From()[0], j, k, pixelsPerRow );
00094       for ( int i = 0; i < pixelsPerRow; ++i ) 
00095         {
00096         upper += this->GetRigidityConstraint( arrayJ[i] );
00097         }
00098       }
00099   
00100   this->m_Parameters[param] = oldCoeff - step;
00101   for ( int k = voi.From()[2]; k < voi.To()[2]; ++k )
00102     for ( int j = voi.From()[1]; j < voi.To()[1]; ++j ) 
00103       {
00104       this->GetJacobianRow( &(arrayJ[0]), voi.From()[0], j, k, pixelsPerRow );
00105       for ( int i = 0; i < pixelsPerRow; ++i ) 
00106         {
00107         lower += this->GetRigidityConstraint( arrayJ[i] );
00108         }
00109       }
00110   this->m_Parameters[param] = oldCoeff;
00111 
00112   const double invVolume = 1.0 / ((voi.To()[0]-voi.From()[0])*(voi.To()[1]-voi.From()[1])*(voi.To()[2]-voi.From()[2]));
00113   upper *= invVolume;
00114   lower *= invVolume;
00115 }
00116 
00117 void 
00118 SplineWarpXform::GetRigidityConstraintDerivative
00119 ( double& lower, double& upper, const int param, const DataGrid::RegionType& voi, const Types::Coordinate step, const DataGrid* weightMap ) const
00120 {
00121   const int pixelsPerRow = voi.To()[0] - voi.From()[0];
00122   std::vector<CoordinateMatrix3x3> arrayJ( pixelsPerRow );
00123   
00124   double ground = 0;
00125 
00126   for ( int k = voi.From()[2]; k < voi.To()[2]; ++k )
00127     for ( int j = voi.From()[1]; j < voi.To()[1]; ++j ) 
00128       {
00129       this->GetJacobianRow( &(arrayJ[0]), voi.From()[0], j, k, pixelsPerRow );
00130       for ( int i = 0; i < pixelsPerRow; ++i ) 
00131         {
00132         ground += weightMap->GetDataAt( voi.From()[0] + i, j, k ) * this->GetRigidityConstraint( arrayJ[i] );
00133         }
00134       }
00135   
00136   upper = -ground;
00137   lower = -ground;
00138   
00139   const Types::Coordinate oldCoeff = this->m_Parameters[param];
00140   this->m_Parameters[param] += step;
00141   for ( int k = voi.From()[2]; k < voi.To()[2]; ++k )
00142     for ( int j = voi.From()[1]; j < voi.To()[1]; ++j ) 
00143       {
00144       this->GetJacobianRow( &(arrayJ[0]), voi.From()[0], j, k, pixelsPerRow );
00145       for ( int i = 0; i < pixelsPerRow; ++i ) 
00146         {
00147         upper += weightMap->GetDataAt( voi.From()[0] + i, j, k ) *
00148           this->GetRigidityConstraint( arrayJ[i] );
00149         }
00150       }
00151   
00152   this->m_Parameters[param] = oldCoeff - step;
00153   for ( int k = voi.From()[2]; k < voi.To()[2]; ++k )
00154     for ( int j = voi.From()[1]; j < voi.To()[1]; ++j ) 
00155       {
00156       this->GetJacobianRow( &(arrayJ[0]), voi.From()[0], j, k, pixelsPerRow );
00157       for ( int i = 0; i < pixelsPerRow; ++i ) 
00158         {
00159         lower += weightMap->GetDataAt( voi.From()[0] + i, j, k ) * this->GetRigidityConstraint( arrayJ[i] );
00160         }
00161       }
00162   this->m_Parameters[param] = oldCoeff;
00163 
00164   const double invVolume = 1.0 / voi.Size();
00165   upper *= invVolume;
00166   lower *= invVolume;
00167 }
00168 
00169 void 
00170 SplineWarpXform::GetRigidityConstraintDerivative
00171 ( double& lower, double& upper, const int param, const Types::Coordinate step )
00172   const
00173 {
00174   const int controlPointIdx = param / nextI;
00175   const unsigned short x =  ( controlPointIdx %  this->m_Dims[0] );
00176   const unsigned short y = ( (controlPointIdx /  this->m_Dims[0]) % this->m_Dims[1] );
00177   const unsigned short z = ( (controlPointIdx /  this->m_Dims[0]) / this->m_Dims[1] );
00178   
00179   const int thisDim = param % nextI;
00180   const Types::Coordinate* coeff = this->m_Parameters + param - thisDim;
00181   
00182   double ground = 0;
00183 
00184   const int iFrom = std::max( -1, 1-x );
00185   const int jFrom = std::max( -1, 1-y );
00186   const int kFrom = std::max( -1, 1-z );
00187 
00188   const int iTo = std::min( 1, this->m_Dims[0]-2-x );
00189   const int jTo = std::min( 1, this->m_Dims[1]-2-y );
00190   const int kTo = std::min( 1, this->m_Dims[2]-2-z );
00191 
00192   CoordinateMatrix3x3 J;
00193   for ( int k = kFrom; k < kTo; ++k )
00194     for ( int j = jFrom; j < jTo; ++j )
00195       for ( int i = iFrom; i < iTo; ++i )
00196         {
00197         this->GetJacobianAtControlPoint( coeff + i*nextI + j*nextJ + k*nextK, J );
00198         ground += this->GetRigidityConstraint( J );
00199         }
00200   
00201   upper = -ground;
00202   lower = -ground;
00203   
00204   const Types::Coordinate oldCoeff = this->m_Parameters[param];
00205   this->m_Parameters[param] += step;
00206   for ( int k = kFrom; k < kTo; ++k )
00207     for ( int j = jFrom; j < jTo; ++j )
00208       for ( int i = iFrom; i < iTo; ++i )
00209         {
00210         this->GetJacobianAtControlPoint( coeff + i*nextI + j*nextJ + k*nextK, J );
00211         upper += this->GetRigidityConstraint( J );
00212         }
00213 
00214   this->m_Parameters[param] = oldCoeff - step;
00215   for ( int k = kFrom; k < kTo; ++k )
00216     for ( int j = jFrom; j < jTo; ++j )
00217       for ( int i = iFrom; i < iTo; ++i )
00218         {
00219         this->GetJacobianAtControlPoint( coeff + i*nextI + j*nextJ + k*nextK, J );
00220         lower += this->GetRigidityConstraint( J );
00221         }
00222   this->m_Parameters[param] = oldCoeff;
00223 
00224   upper /= this->NumberOfControlPoints;
00225   lower /= this->NumberOfControlPoints;
00226 }
00227 
00228 Types::Coordinate
00229 SplineWarpXform::GetRigidityConstraint () const
00230 {
00231   const int pixelsPerRow = VolumeDims[0];
00232   std::vector<CoordinateMatrix3x3> arrayJ( pixelsPerRow );
00233 
00234   double constraint = 0;
00235   for ( int z = 0; z < VolumeDims[2]; ++z )
00236     for ( int y = 0; y < VolumeDims[1]; ++y ) 
00237       {
00238       this->GetJacobianRow( &(arrayJ[0]), 0, y, z, pixelsPerRow );
00239       for ( int x = 0; x < pixelsPerRow; ++x ) 
00240         {
00241         constraint += this->GetRigidityConstraint( arrayJ[x] );
00242         }
00243       }
00244   
00245   // Divide by number of control points to normalize with respect to the
00246   // number of local Jacobians in the computation.
00247   return constraint / ( VolumeDims[0] * VolumeDims[1] * VolumeDims[2] );
00248 }
00249 
00250 Types::Coordinate
00251 SplineWarpXform::GetRigidityConstraint( const DataGrid* weightMap ) const
00252 {
00253   const int pixelsPerRow = VolumeDims[0];
00254   std::vector<CoordinateMatrix3x3> arrayJ( pixelsPerRow );
00255 
00256   double constraint = 0;
00257   for ( int z = 0; z < VolumeDims[2]; ++z )
00258     for ( int y = 0; y < VolumeDims[1]; ++y ) 
00259       {
00260       this->GetJacobianRow( &(arrayJ[0]), 0, y, z, pixelsPerRow );
00261       for ( int x = 0; x < pixelsPerRow; ++x ) 
00262         {
00263         constraint += weightMap->GetDataAt( x, y, z ) * this->GetRigidityConstraint( arrayJ[x] );
00264         }
00265       }
00266   
00267   // Divide by number of control points to normalize with respect to the
00268   // number of local Jacobians in the computation.
00269   return constraint / ( VolumeDims[0] * VolumeDims[1] * VolumeDims[2] );
00270 }
00271 
00272 Types::Coordinate
00273 SplineWarpXform::GetRigidityConstraint( const CoordinateMatrix3x3& J ) 
00274   const
00275 {
00276   Matrix2D<Types::Coordinate> matrix2d( 3, 3 );
00277   for ( int i = 0; i < 3; ++i )
00278     for ( int j = 0; j < 3; ++j )
00279       matrix2d[i][j] = J[i][j];
00280 
00281   QRDecomposition<Types::Coordinate> qr( matrix2d );
00282   const Matrix2D<Types::Coordinate> R = qr.GetR();
00283   
00284   return MathUtil::Square( R[0][1] / R[0][0] ) + MathUtil::Square( R[0][2] / R[0][0] ) + MathUtil::Square( R[1][2] / R[1][1] );
00285 }
00286 
00287 } // namespace cmtk
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines