00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
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
00062
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
00246
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
00268
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 }