00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef __freAccuracySOMetricThread_txx
00023 #define __freAccuracySOMetricThread_txx
00024
00025 #include "freAccuracySOMetricThread.h"
00026
00027 #include "freVectorToNormImageFilter.h"
00028 #include "freImageSampleCharacteristicsCalculator.h"
00029 #include "freSessionProcessor.h"
00030
00031 #include "itkNumericTraits.h"
00032 #include "itkSubtractImageFilter.h"
00033 #include "itkImageAdaptor.h"
00034 #include "itkPointSet.h"
00035 #include "itkListSample.h"
00036
00037 namespace FREE
00038 {
00039
00040 template <unsigned int VImageDimension>
00041 void
00042 AccuracySOMetricThread<VImageDimension>::
00043 SetResultFieldPath(const IDPath& path)
00044 {
00045 this->LockExecutionMutex();
00046 this->m_ResultFieldPath = path;
00047 this->UnlockExecutionMutex();
00048 };
00049
00050 template <unsigned int VImageDimension>
00051 const IDPath&
00052 AccuracySOMetricThread<VImageDimension>::
00053 GetResultFieldPath() const {return m_ResultFieldPath;};
00054
00055 template <unsigned int VImageDimension>
00056 void
00057 AccuracySOMetricThread<VImageDimension>::
00058 SetReferenceFieldPath(const IDPath& path)
00059 {
00060 this->LockExecutionMutex();
00061 this->m_ReferenceFieldPath = path;
00062 this->UnlockExecutionMutex();
00063 };
00064
00065 template <unsigned int VImageDimension>
00066 const IDPath&
00067 AccuracySOMetricThread<VImageDimension>::
00068 GetReferenceFieldPath() const {return m_ReferenceFieldPath;};
00069
00070 template <unsigned int VImageDimension>
00071 void
00072 AccuracySOMetricThread<VImageDimension>::
00073 SetReferencePointsPath(const IDPath& path)
00074 {
00075 this->LockExecutionMutex();
00076 this->m_ReferencePointsPath = path;
00077 this->UnlockExecutionMutex();
00078 };
00079
00080 template <unsigned int VImageDimension>
00081 const IDPath&
00082 AccuracySOMetricThread<VImageDimension>::
00083 GetReferencePointsPath() const {return m_ReferencePointsPath;};
00084
00085 template <unsigned int VImageDimension>
00086 void
00087 AccuracySOMetricThread<VImageDimension>::
00088 SetMovingPointsPath(const IDPath& path)
00089 {
00090 this->LockExecutionMutex();
00091 this->m_MovingPointsPath = path;
00092 this->UnlockExecutionMutex();
00093 };
00094
00095 template <unsigned int VImageDimension>
00096 const IDPath&
00097 AccuracySOMetricThread<VImageDimension>::
00098 GetMovingPointsPath() const {return m_MovingPointsPath;};
00099
00100 template <unsigned int VImageDimension>
00101 void
00102 AccuracySOMetricThread<VImageDimension>::
00103 SetUseField(const bool& bUseField)
00104 {
00105 this->LockExecutionMutex();
00106 this->m_UseField = bUseField;
00107 this->UnlockExecutionMutex();
00108 };
00109
00110 template <unsigned int VImageDimension>
00111 bool
00112 AccuracySOMetricThread<VImageDimension>::
00113 GetUseField() const {return m_UseField;};
00114
00115 template <unsigned int VImageDimension>
00116 AccuracySOMetricThread<VImageDimension>::
00117 AccuracySOMetricThread()
00118 {
00119 m_UseField = true;
00120 m_ReferenceFieldPath.Reset();
00121 m_ReferencePointsPath.Reset();
00122 m_MovingPointsPath.Reset();
00123 m_ResultFieldPath.Reset();
00124 };
00125
00126 template <unsigned int VImageDimension>
00127 AccuracySOMetricThread<VImageDimension>::
00128 ~AccuracySOMetricThread() {};
00129
00130 template <unsigned int VImageDimension>
00131 bool
00132 AccuracySOMetricThread<VImageDimension>::
00133 ProcessSetup(Setup* pAdaptationSetup) throw()
00134 {
00135 bool result = false;
00136
00137 ControllerCentral::AddOnProgressEvent(this->m_EvaluatedSessionProgressEvent);
00138
00139 try
00140 {
00141 SessionProcessor processor;
00142
00143 processor.SetSetup(pAdaptationSetup);
00144 processor.DefineOutput("resultField", this->m_ResultFieldPath);
00145
00146 processor.InitializeSession();
00147
00148 this->m_EvaluatedSessionProgressEvent->SetACR(processor.GetSessionInfo()->GetSessionCache());
00149
00150 clock_t start = clock();
00151
00152 typename TransformationFieldType::Pointer smpResult = processor.GetCastedOutput<TransformationFieldType>("resultField");
00153
00154 clock_t stop = clock();
00155 double dDuration = (stop-start) / (CLOCKS_PER_SEC/10);
00156
00157
00158 if (m_UseField)
00159 {
00160 EvaluateField(smpResult, processor.GetSessionInfo());
00161 }
00162 else
00163 {
00164 EvaluatePoints(smpResult, processor.GetSessionInfo());
00165 }
00166
00167 m_Results.SetDuration((unsigned long)dDuration);
00168
00169 result = true;
00170 }
00171 catch( FREE::ExceptionBase & err )
00172 {
00173 this->m_FailureComment = std::string(err.what());
00174 }
00175 catch(...)
00176 {
00177 this->m_FailureComment = "unkown error";
00178 }
00179
00180 ControllerCentral::RemoveOnProgressEvent(m_EvaluatedSessionProgressEvent);
00181
00182 return result;
00183 };
00184
00185 template <unsigned int VImageDimension>
00186 void
00187 AccuracySOMetricThread<VImageDimension>::
00188 EvaluateField(TransformationFieldType* pResultField, SessionInfo* pSessionInfo)
00189 {
00190 typename TransformationFieldType::Pointer smpRefField = NULL;
00191
00192 if (m_ReferenceFieldPath.IsEmpty()) throwExceptionMacro("Error: Reference field path is null, but should be used to measure registration. Ensure correct initialisation of the metric.");
00193
00194 try
00195 {
00196 SessionAccessor::GenericMediaPointer smpFieldReference = SessionAccessor::GetMedia(m_ReferenceFieldPath,pSessionInfo);
00197 smpRefField = dynamic_cast<TransformationFieldType*>(smpFieldReference.GetPointer());
00198 }
00199 catchAllNPassMacro("Error: cannot retrieve reference field. Ensure correct IDPath. Used path: "<<m_ReferenceFieldPath.ToStr());
00200 if (smpRefField.IsNull()) throwExceptionMacro("Error: Reference field is of wrong type. Ensure correct initialisation of the metric. Field class name: "<<smpRefField->GetNameOfClass());
00201
00202
00203 typedef itk::SubtractImageFilter< TransformationFieldType, TransformationFieldType, TransformationFieldType > SubtractFilterType;
00204 typename SubtractFilterType::Pointer smpSubFilter = SubtractFilterType::New();
00205
00206
00207 typedef itk::Image<double,VImageDimension> NormImageType;
00208 typedef VectorToNormImageFilter<TransformationFieldType, NormImageType > NormImageFilterType;
00209 typedef ImageSampleCharacteristicsCalculator<NormImageType> CharCalculator;
00210 typename NormImageFilterType::Pointer smpNormFilter = NormImageFilterType::New();
00211
00212 smpSubFilter->SetInput1(pResultField);
00213 smpSubFilter->SetInput2(smpRefField);
00214 smpNormFilter->SetInput(smpSubFilter->GetOutput());
00215 smpNormFilter->Update();
00216 typename NormImageType::Pointer smpNormImage = smpNormFilter->GetOutput();
00217
00218 CharCalculator calculator;
00219 calculator.SetImage(smpNormImage);
00220 calculator.Compute();
00221
00222 this->m_Results.SetError(calculator.GetMean());
00223 this->m_Results.SetVariance(calculator.GetVariance());
00224 this->m_Results.SetSamplesize(pResultField->GetLargestPossibleRegion().GetNumberOfPixels());
00225
00226
00227 typedef itk::ImageRegionConstIterator<NormImageType> NormIterator;
00228
00229 double dMin = itk::NumericTraits< double >::max();
00230 double dMax = 0.0;
00231
00232 NormIterator it(smpNormImage,pResultField->GetBufferedRegion());
00233 for ( it.GoToBegin(); !it.IsAtEnd(); ++it )
00234 {
00235 if (it.Get()<dMin) dMin = it.Get();
00236 if (it.Get()>dMax) dMax = it.Get();
00237 }
00238
00239 this->m_Results.SetMinError(dMin);
00240 this->m_Results.SetMaxError(dMax);
00241 };
00242
00243 template <unsigned int VImageDimension>
00244 void
00245 AccuracySOMetricThread<VImageDimension>::
00246 EvaluatePoints(TransformationFieldType* pResultField, SessionInfo* pSessionInfo)
00247 {
00248 typedef TransformationFieldType FieldType;
00249 typedef typename TransformationFieldType::Pointer FieldPointer;
00250
00251 typedef typename ImageTypes<VImageDimension>::PointSetType PointSetType;
00252 typedef typename PointSetType::Pointer PointSetPointer;
00253
00254 PointSetPointer smpRefPoints = 0;
00255 PointSetPointer smpMovingPoints = 0;
00256
00257 if (m_ReferencePointsPath.IsEmpty()) throwExceptionMacro("Error: Reference points path is null, but should be used to measure registration. Ensure correct initialisation of the metric.");
00258 try
00259 {
00260 typename SessionAccessor::GenericMediaPointer genPoints = SessionAccessor::GetMedia(m_ReferencePointsPath,pSessionInfo);
00261 smpRefPoints = dynamic_cast<PointSetType*>(genPoints.GetPointer());
00262 }
00263 catchAllNPassMacro("Error: cannot retrieve reference point set Ensure correct IDPath. Used path: "<<m_ReferenceFieldPath.ToStr());
00264
00265 if (m_MovingPointsPath.IsEmpty()) throwExceptionMacro("Error: Reference points path is null, but should be used to measure registration. Ensure correct initialisation of the metric.");
00266 try
00267 {
00268 SessionAccessor::GenericMediaPointer genPoints = SessionAccessor::GetMedia(m_MovingPointsPath,pSessionInfo);
00269 smpMovingPoints = dynamic_cast<PointSetType*>(genPoints.GetPointer());
00270 }
00271 catchAllNPassMacro("Error: cannot retrieve reference point set Ensure correct IDPath. Used path: "<<m_ReferenceFieldPath.ToStr());
00272
00273 if (smpRefPoints->GetNumberOfPoints() != smpMovingPoints->GetNumberOfPoints()) throwExceptionMacro("Error: reference point set and moving point set must have same number of points. Reference count: " << smpRefPoints->GetNumberOfPoints() << "; moving count: " << smpMovingPoints->GetNumberOfPoints());
00274
00275
00276
00277 typename PointSetType::PointsContainer::Iterator refIter = smpRefPoints->GetPoints()->Begin();
00278 typename PointSetType::PointsContainer::Iterator movingIter = smpMovingPoints->GetPoints()->Begin();
00279
00280 typename PointSetType::PointsContainer::Iterator endOfPoints = smpRefPoints->GetPoints()->End();
00281
00282 const unsigned int iMeasurementVectorSize = 1;
00283 typedef itk::Vector<double,iMeasurementVectorSize> MeasurementVectorType;
00284 typedef itk::Statistics::ListSample< MeasurementVectorType > SampleType;
00285
00286 typename SampleType::Pointer smpSample = SampleType::New();
00287 smpSample->SetMeasurementVectorSize(iMeasurementVectorSize);
00288
00289 double dMin = itk::NumericTraits< double >::max();
00290 double dMax = 0.0;
00291
00292 while (refIter != endOfPoints)
00293 {
00294 typename PointSetType::PointType refPoint = refIter.Value();
00295 typename PointSetType::PointType movingPoint = movingIter.Value();
00296
00297 typename FieldType::PixelType translation;
00298 translation.Fill(0.0);
00299
00300 typename FieldType::IndexType index;
00301 bool bInField = pResultField->TransformPhysicalPointToIndex(refPoint, index);
00302
00303 if (bInField)
00304 {
00305 translation = pResultField->GetPixel(index);
00306 refPoint += translation;
00307
00308 MeasurementVectorType mv;
00309
00310 typename PointSetType::PointType::VectorType difVector = movingPoint - refPoint;
00311 mv[0] = difVector.GetNorm();
00312
00313 this->m_Results.GetPointErrors().push_back(mv[0]);
00314 smpSample->PushBack(mv);
00315
00316 if (mv[0]<dMin) dMin = mv[0];
00317 if (mv[0]>dMax) dMax = mv[0];
00318 }
00319 else
00320 {
00321 this->m_Results.GetUnevaluatedPoints()++;
00322 }
00323 ++refIter;
00324 ++movingIter;
00325 }
00326
00327
00328 typedef itk::Statistics::CovarianceCalculator< SampleType > CovarianceAlgorithmType;
00329
00330 typename CovarianceAlgorithmType::Pointer covarianceAlgorithm = CovarianceAlgorithmType::New();
00331 covarianceAlgorithm->SetInputSample( smpSample );
00332 covarianceAlgorithm->SetMean( 0 );
00333 covarianceAlgorithm->Update();
00334
00335 double mean = covarianceAlgorithm->GetMean()->GetElement(0);
00336 double var = (*(covarianceAlgorithm->GetOutput()))(0,0);
00337
00338 this->m_Results.SetError(mean);
00339 this->m_Results.SetVariance(var);
00340 this->m_Results.SetMinError(dMin);
00341 this->m_Results.SetMaxError(dMax);
00342 };
00343
00344
00345
00346 }
00347
00348 #endif