00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifndef __freTransformInitializer_h
00025 #define __freTransformInitializer_h
00026
00027 #include "freElementals.h"
00028 #include "freImageTypes.h"
00029 #include "freExceptions.h"
00030
00031 #include "itkImage.h"
00032 #include "itkVector.h"
00033 #include "itkPoint.h"
00034 #include "itkImageMomentsCalculator.h"
00035 #include "itkAffineTransform.h"
00036
00037 namespace FREE
00038 {
00039
00041 enum RotationAxisType
00042 {
00043 RA_X = 0,
00044 RA_Y = 1,
00045 RA_Z = 2,
00046 };
00047
00048
00049 inline RotationAxisType operator++( RotationAxisType &ra, int )
00050 {
00051 return ra = (RotationAxisType)(ra + 1);
00052 }
00053
00054
00055 inline RotationAxisType operator--( RotationAxisType &ra, int )
00056 {
00057 return ra = (RotationAxisType)(ra - 1);
00058 }
00059
00086 template <typename TPixel, int iDimension>
00087 class CenterInitializer
00088 {
00089 public:
00090 typedef itk::Point<ScalarType,iDimension> PointType;
00091 typedef itk::Vector<ScalarType,iDimension> VectorType;
00092 typedef itk::Image<TPixel,iDimension> TImage;
00093
00094 void GeometryOn()
00095 {
00096 if (m_bUseMoments)
00097 {
00098 m_bUseMoments = false;
00099 m_bInitialized = false;
00100 }
00101 };
00102
00103 void MomentsOn()
00104 {
00105 if (!m_bUseMoments)
00106 {
00107 m_bUseMoments = true;
00108 m_bInitialized = false;
00109 }
00110 };
00111
00112 void SetImage(TImage* pImage)
00113 {
00114 m_pImage = pImage;
00115 m_bInitialized = false;
00116 };
00117
00118 void ComputeCenter()
00119 {
00120 if( m_bUseMoments )
00121 {
00122
00123 typedef itk::ImageMomentsCalculator< TImage > ImageCalculatorType;
00124
00125 typename ImageCalculatorType::Pointer calculator = ImageCalculatorType::New();
00126
00127 try
00128 {
00129 calculator->SetImage( m_pImage );
00130 calculator->Compute();
00131
00132 m_Center = calculator->GetCenterOfGravity();
00133 }
00134 catch(...)
00135 {
00136
00137
00138 m_bUseMoments = false;
00139 }
00140 }
00141
00142 if( !m_bUseMoments )
00143 {
00144
00145
00146 const typename TImage::SpacingType& rSpacing = m_pImage->GetSpacing();
00147 const typename TImage::PointType& rOrigin = m_pImage->GetOrigin();
00148
00149 typename TImage::SizeType size = m_pImage->GetLargestPossibleRegion().GetSize();
00150
00151 for( unsigned int iIndex=0; iIndex<iDimension; iIndex++)
00152 {
00153 m_Center[iIndex] = rOrigin[iIndex] + rSpacing[iIndex] * (size[iIndex] /2.0);
00154 }
00155 }
00156 m_bInitialized = true;
00157 };
00158
00159 void GetCenter(VectorType& rVector)
00160 {
00161 if (!m_bInitialized) ComputeCenter();
00162
00163 rVector = m_Center;
00164 };
00165
00166 void GetCenter(ParameterArrayType& rVector)
00167 {
00168 if (!m_bInitialized) ComputeCenter();
00169
00170 rVector.SetSize(iDimension);
00171 for (int iIndex = 0; iIndex<iDimension; iIndex++)
00172 {
00173 rVector.SetElement(iIndex,m_Center[iIndex]);
00174 }
00175 };
00176
00177 CenterInitializer()
00178 {
00179 m_bUseMoments = true;
00180 m_bInitialized = false;
00181 m_pImage = NULL;
00182 };
00183
00184 ~CenterInitializer() {};
00185
00186 private:
00187 bool m_bUseMoments;
00188 bool m_bInitialized;
00189
00190 VectorType m_Center;
00191
00192 TImage* m_pImage;
00193 };
00194
00213 template <int iDimension>
00214 class RotationInitializer
00215 {
00216 public:
00217 typedef itk::Vector<ScalarType,iDimension> VectorType;
00218
00219 void ClearSchedule(bool bToDefault = true)
00220 {
00221 m_Schedule.clear();
00222 if(bToDefault)
00223 {
00224 m_Schedule.push_back(RA_Z);
00225 m_Schedule.push_back(RA_Y);
00226 m_Schedule.push_back(RA_X);
00227 }
00228 m_bInitialized = false;
00229 };
00230
00231 void AddToSchedule(RotationAxisType axis)
00232 {
00233 m_Schedule.push_back(axis);
00234 m_bInitialized = false;
00235 };
00236
00237 void SetMovingCenter(VectorType center)
00238 {
00239 m_MovingCenter.Fill(0.0);
00240 for (int iIndex=0; iIndex<iDimension; iIndex++) m_MovingCenter.SetNthComponent(iIndex,center[iIndex]);
00241 m_bInitialized = false;
00242 };
00243
00244 void SetFixedCenter(VectorType center)
00245 {
00246 m_FixedCenter.Fill(0);
00247 for (int iIndex=0; iIndex<iDimension; iIndex++) m_FixedCenter.SetNthComponent(iIndex,center[iIndex]);
00248 m_bInitialized = false;
00249 };
00250
00251 void SetCenterPair(VectorType movingCenter,VectorType fixedCenter)
00252 {
00253 SetFixedCenter(fixedCenter);
00254 SetMovingCenter(movingCenter);
00255 };
00256
00257 void SetCenterPair(ParameterArrayType movingCenter,ParameterArrayType fixedCenter)
00258 {
00259 VectorType movingCenterVector;
00260 VectorType fixedCenterVector;
00261
00262 for (int iIndex = 0; iIndex<iDimension; iIndex++)
00263 {
00264 movingCenterVector.SetNthComponent(iIndex,movingCenter[iIndex]);
00265 fixedCenterVector.SetNthComponent(iIndex,fixedCenter[iIndex]);
00266 };
00267
00268 SetFixedCenter(fixedCenterVector);
00269 SetMovingCenter(movingCenterVector);
00270 };
00271
00272 void ClearReferences()
00273 {
00274 this->m_FixedReferences.RemoveAll();
00275 this->m_MovingReferences.RemoveAll();
00276 m_bInitialized = false;
00277 };
00278
00279 void AddReferencePair(VectorType movingReference,VectorType fixedReference)
00280 {
00281 Vector3DType movingVector3D;
00282 Vector3DType fixedVector3D;
00283
00284 movingVector3D.Fill(0);
00285 fixedVector3D.Fill(0);
00286
00287 for (int iIndex=0; iIndex<iDimension; iIndex++)
00288 {
00289 movingVector3D.SetNthComponent(iIndex,movingReference[iIndex]);
00290 fixedVector3D.SetNthComponent(iIndex,fixedReference[iIndex]);
00291 }
00292
00293 m_FixedReferences.push_back(fixedVector3D);
00294 m_MovingReferences.push_back(movingVector3D);
00295 m_bInitialized = false;
00296 };
00297
00298 void AddReferencePair(ParameterArrayType movingReference,ParameterArrayType fixedReference)
00299 {
00300 VectorType movingReferenceVector;
00301 VectorType fixedReferenceVector;
00302
00303 for (int iIndex = 0; iIndex<iDimension; iIndex++)
00304 {
00305 movingReferenceVector.SetNthComponent(iIndex,movingReference[iIndex]);
00306 fixedReferenceVector.SetNthComponent(iIndex,fixedReference[iIndex]);
00307 };
00308
00309 AddReferencePair(movingReferenceVector,fixedReferenceVector);
00310 };
00311
00312 void ComputeRotations()
00313 {
00314 typedef std::vector<double> AnglesArrayType;
00315 AnglesArrayType xAngles;
00316 AnglesArrayType yAngles;
00317 AnglesArrayType zAngles;
00318
00319 for (int iIndex=0; iIndex<m_FixedReferences.size(); iIndex++)
00320 {
00321
00322 Vector3DType movingRef = m_MovingReferences[iIndex] - m_MovingCenter;
00323 Vector3DType fixedRef = m_FixedReferences[iIndex] - m_FixedCenter;
00324
00325
00326 Vector3DType::ValueType lengthFixed = fixedRef.GetNorm();
00327 Vector3DType smartRef= fixedRef;
00328
00329
00330 movingRef.Normalize();
00331 fixedRef.Normalize();
00332
00333 for (int iScheduleIndex=0; iScheduleIndex<m_Schedule.size(); iScheduleIndex++)
00334 {
00335 RotationAxisType axis = m_Schedule[iScheduleIndex];
00336
00337 Vector3DType movingTmpRef =movingRef;
00338 Vector3DType fixedTmpRef = fixedRef;
00339 movingTmpRef[axis]=0;
00340 fixedTmpRef[axis]=0;
00341
00342
00343 Vector3DType smartTmpRef = smartRef;
00344 smartTmpRef[axis]=0;
00345 Vector3DType::ValueType length2DFixed = smartTmpRef.GetNorm();
00346 ScalarType rotationWeight = length2DFixed/lengthFixed;
00347
00348
00349 movingTmpRef.Normalize();
00350 fixedTmpRef.Normalize();
00351
00352 Vector3DType rotationAxis;
00353 rotationAxis.Fill(0);
00354 rotationAxis[axis]=1;
00355
00356
00357 ScalarType dAngel = CalculateRotationAngel(fixedTmpRef,movingTmpRef,rotationAxis);
00358
00359
00360
00361
00362
00363
00364
00365
00366 if (m_bUseRotationWeight) dAngel *= rotationWeight;
00367
00368
00369 typedef itk::AffineTransform<ScalarType,3> CalculateTransformType;
00370 CalculateTransformType::Pointer oneRotation = CalculateTransformType::New();
00371 oneRotation->Rotate3D(rotationAxis,dAngel);
00372
00373
00374 movingRef = oneRotation->TransformVector(movingRef);
00375
00376
00377 smartRef = oneRotation->TransformVector(smartRef);
00378
00379 switch (axis)
00380 {
00381 case RA_X: xAngles.push_back(dAngel); break;
00382 case RA_Y: yAngles.push_back(dAngel); break;
00383 case RA_Z: zAngles.push_back(dAngel); break;
00384 };
00385 };
00386 };
00387
00388 for (int iIndex=0; iIndex<xAngles.size(); iIndex++)
00389 {
00390 m_Angles[RA_X] += xAngles[iIndex];
00391 }
00392
00393 for (int iIndex=0; iIndex<yAngles.size(); iIndex++)
00394 {
00395 m_Angles[RA_Y] += yAngles[iIndex];
00396 }
00397
00398 for (int iIndex=0; iIndex<zAngles.size(); iIndex++)
00399 {
00400 m_Angles[RA_Z] += zAngles[iIndex];
00401 }
00402
00403 if (xAngles.size()>0) m_Angles[RA_X] = m_Angles[RA_X]/ xAngles.size();
00404 if (yAngles.size()>0) m_Angles[RA_Y] = m_Angles[RA_Y]/ yAngles.size();
00405 if (zAngles.size()>0) m_Angles[RA_Z] = m_Angles[RA_Z]/ zAngles.size();
00406
00407 m_bInitialized = true;
00408 };
00409
00410 double GetRotation(RotationAxisType axis)
00411 {
00412 if (!m_bInitialized) ComputeRotations();
00413
00414 return m_Angles[axis];
00415 };
00416
00417 bool GetUseRotationWeight() {return m_bUseRotationWeight;};
00418
00419 void SetUseRotationWeight(bool bUseWeight)
00420 {
00421 m_bUseRotationWeight = bUseWeight;
00422 m_bInitialized = true;
00423 };
00424
00425 RotationInitializer()
00426 {
00427 ClearSchedule();
00428 m_Angles[RA_X] = 0.0;
00429 m_Angles[RA_Y] = 0.0;
00430 m_Angles[RA_Z] = 0.0;
00431
00432 m_bInitialized = false;
00433 m_bUseRotationWeight = false;
00434 };
00435
00436 ~RotationInitializer() {};
00437
00438 private:
00439 double m_Angles[3];
00440 bool m_bInitialized;
00441 bool m_bUseRotationWeight;
00442
00443 typedef std::vector<Vector3DType> VectorArrayType;
00444 VectorArrayType m_FixedReferences;
00445 VectorArrayType m_MovingReferences;
00446
00447 typedef std::vector<RotationAxisType> ScheduleType;
00448
00449 ScheduleType m_Schedule;
00450
00451 Vector3DType m_FixedCenter;
00452 Vector3DType m_MovingCenter;
00453
00456 double CalculateRotationAngel(Vector3DType vector1, Vector3DType vector2,
00457 Vector3DType rotationAxis)
00458 {
00459 vector1.Normalize();
00460 vector2.Normalize();
00461
00462 double dAngel = acos(vector1*vector2);
00463
00464
00465 typedef itk::AffineTransform<ScalarType,3> CalculateTransformType;
00466 CalculateTransformType::Pointer calcTransform = CalculateTransformType::New();
00467
00468 calcTransform->Rotate3D(rotationAxis,dAngel);
00469
00470 double dTestangel = acos((calcTransform->TransformVector(vector2))*vector1);
00471
00472 if (dTestangel>dAngel)
00473 {
00474
00475 dAngel = -1*dAngel;
00476 };
00477
00478 return dAngel;
00479 };
00480 };
00481
00482 }
00483 #endif