1 /*=========================================================================
2 Program: vv http://www.creatis.insa-lyon.fr/rio/vv
5 - University of LYON http://www.universite-lyon.fr/
6 - Léon Bérard cancer center http://www.centreleonberard.fr
7 - CREATIS CNRS laboratory http://www.creatis.insa-lyon.fr
9 This software is distributed WITHOUT ANY WARRANTY; without even
10 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
11 PURPOSE. See the copyright notices for more information.
13 It is distributed under dual licence
15 - BSD See included LICENSE.txt file
16 - CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
17 ===========================================================================**/
19 #ifndef __clitkGenericMetric_txx
20 #define __clitkGenericMetric_txx
22 #include "clitkGenericMetric.h"
23 #include <itkImageMaskSpatialObject.h>
29 //=========================================================================================================================
31 template <class args_info_type, class FixedImageType, class MovingImageType>
32 GenericMetric<args_info_type, FixedImageType, MovingImageType>::GenericMetric()
37 m_FixedImageRegionGiven=false;
38 #if defined(ITK_USE_OPTIMIZED_REGISTRATION_METHODS) || ITK_VERSION_MAJOR >= 4
39 m_FixedImageSamplesIntensityThreshold=0;
40 m_UseFixedImageSamplesIntensityThreshold=false;
42 m_FixedImageMask=NULL;
46 //=========================================================================================================================
48 template <class args_info_type, class FixedImageType, class MovingImageType>
49 typename GenericMetric<args_info_type, FixedImageType, MovingImageType>::MetricPointer
50 GenericMetric<args_info_type,FixedImageType, MovingImageType>::GetMetricPointer()
52 //============================================================================
54 // The image is required for the region and spacing
55 if( ! this->m_FixedImage ) {
56 itkExceptionMacro( "Fixed Image has not been set" );
59 // If the image come from a filter, then update that filter.
60 if( this->m_FixedImage->GetSource() ) {
61 this->m_FixedImage->Update();
65 if( ! m_FixedImageRegionGiven ) {
66 m_FixedImageRegion=m_FixedImage->GetLargestPossibleRegion();
70 //============================================================================
71 //switch on the metric type chosen adn set metric specific members
72 switch (m_ArgsInfo.metric_arg) {
75 typename itk::MeanSquaresImageToImageMetric< FixedImageType, MovingImageType >::Pointer m =
76 itk::MeanSquaresImageToImageMetric< FixedImageType, MovingImageType >::New();
78 //Set Parameters for this metric
80 if (m_Verbose) std::cout<<"Using the mean squares metric..."<<std::endl;
86 typename clitk::NormalizedCorrelationImageToImageMetric< FixedImageType, MovingImageType >::Pointer m
87 =clitk::NormalizedCorrelationImageToImageMetric< FixedImageType, MovingImageType >::New();
89 //Set Parameters for this metric
90 m->SetSubtractMean(m_ArgsInfo.subtractMean_flag);
93 if ( !m_ArgsInfo.subtractMean_flag) std::cout<<"Using the normalized correlation metric without subtracting the mean..."<<std::endl;
94 else std::cout<<"Using the normalized correlation metric with subtraction of mean..."<<std::endl;
101 typename itk::CorrelationCoefficientHistogramImageToImageMetric< FixedImageType, MovingImageType >::Pointer m
102 = itk::CorrelationCoefficientHistogramImageToImageMetric< FixedImageType, MovingImageType >::New();
104 //Set parameters for this metric
105 typename itk::CorrelationCoefficientHistogramImageToImageMetric<FixedImageType, MovingImageType>::HistogramSizeType size;
106 for (unsigned int i=0; i < FixedImageDimension; i++)size[i]=m_ArgsInfo.bins_arg;
107 m->SetHistogramSize(size);
109 if (m_Verbose) std::cout<<"Using the histogram correlation coefficient metric..."<<std::endl;
115 typename itk::GradientDifferenceImageToImageMetric< FixedImageType, MovingImageType >::Pointer m
116 = itk::GradientDifferenceImageToImageMetric< FixedImageType, MovingImageType >::New();
118 //Set parameters for this metric
120 if (m_Verbose) std::cout<<"Using the gradient difference metric..."<<std::endl;
126 typename itk::MutualInformationImageToImageMetric< FixedImageType, MovingImageType >::Pointer m
127 = itk::MutualInformationImageToImageMetric< FixedImageType, MovingImageType >::New();
129 //Set parameters for this metric
130 m->SetFixedImageStandardDeviation( m_ArgsInfo.stdDev_arg );
131 m->SetMovingImageStandardDeviation( m_ArgsInfo.stdDev_arg);
134 //Randomize samples if demanded
135 if (m_ArgsInfo.random_flag ) m->ReinitializeSeed();
136 else m->ReinitializeSeed(0);
137 if (m_Verbose) std::cout<<"Using Viola-Wells MI..."<<std::endl;
143 typename itk::MutualInformationHistogramImageToImageMetric< FixedImageType, MovingImageType >::Pointer m
144 = itk::MutualInformationHistogramImageToImageMetric< FixedImageType, MovingImageType>::New();
146 //Set parameters for this metric
147 typename itk::MutualInformationHistogramImageToImageMetric<FixedImageType, MovingImageType>::HistogramSizeType size;
148 for (unsigned int i=0; i < FixedImageDimension; i++)size[i]=m_ArgsInfo.bins_arg;
149 m->SetHistogramSize(size);
151 if (m_Verbose) std::cout<<"Using the histogram MI with "<<m_ArgsInfo.bins_arg<<" bins..."<<std::endl;
157 typename itk::MattesMutualInformationImageToImageMetric< FixedImageType, MovingImageType >::Pointer m
158 = itk::MattesMutualInformationImageToImageMetric< FixedImageType, MovingImageType >::New();
160 //Set parameters for this metric
162 m->SetNumberOfHistogramBins(m_ArgsInfo.bins_arg);
164 //Randomize samples if demanded
165 if (m_ArgsInfo.random_flag ) m->ReinitializeSeed();
166 else m->ReinitializeSeed(0);
168 // Two ways of calculating the derivatives
169 m->SetUseExplicitPDFDerivatives(m_ArgsInfo.explicitPDFDerivatives_flag);
173 std::cout<<"Using Mattes' MI with "<<m_ArgsInfo.bins_arg<<" bins..."<<std::endl;
174 if (m_ArgsInfo.explicitPDFDerivatives_flag) std::cout<<"Calculating PDFs explicitly..."<<std::endl;
181 typename itk::NormalizedMutualInformationHistogramImageToImageMetric< FixedImageType, MovingImageType >::Pointer m
182 =itk::NormalizedMutualInformationHistogramImageToImageMetric< FixedImageType, MovingImageType >::New();
184 //Set parameters for this metric
185 typename itk::NormalizedMutualInformationHistogramImageToImageMetric<FixedImageType, MovingImageType>::HistogramSizeType size;
186 for (unsigned int i=0; i < FixedImageDimension; i++)size[i]=m_ArgsInfo.bins_arg;
187 m->SetHistogramSize(size);
189 if (m_Verbose) std::cout<<"Using the normalized MI with "<<m_ArgsInfo.bins_arg<<" bins..."<<std::endl;
195 typename clitk::CorrelationRatioImageToImageMetric< FixedImageType, MovingImageType >::Pointer m
196 = clitk::CorrelationRatioImageToImageMetric< FixedImageType, MovingImageType >::New();
198 //Set parameters for this metric
200 m->SetNumberOfBins(m_ArgsInfo.bins_arg);
201 if (m_Verbose) std::cout<<"Using the correlation ratio..."<<std::endl;
207 typename itk::MeanSquaresImageToImageMetricFor3DBLUTFFD< FixedImageType, MovingImageType >::Pointer m
208 = itk::MeanSquaresImageToImageMetricFor3DBLUTFFD< FixedImageType, MovingImageType >::New();
210 //Set Parameters for this metric
212 if (m_Verbose) std::cout<<"Using the mean squares metric for 3D BLUT FFD..."<<std::endl;
218 typename clitk::NormalizedCorrelationImageToImageMetricFor3DBLUTFFD< FixedImageType, MovingImageType >::Pointer m
219 =clitk::NormalizedCorrelationImageToImageMetricFor3DBLUTFFD< FixedImageType, MovingImageType >::New();
221 //Set Parameters for this metric
222 m->SetSubtractMean(m_ArgsInfo.subtractMean_flag);
225 if ( !m_ArgsInfo.subtractMean_flag) std::cout<<"Using the normalized correlation metric for 3D BLUT FFD without subtracting the mean..."<<std::endl;
226 else std::cout<<"Using the normalized correlation metric 3D BLUT FFD with subtraction of mean..."<<std::endl;
233 typename itk::MattesMutualInformationImageToImageMetricFor3DBLUTFFD< FixedImageType, MovingImageType >::Pointer m
234 = itk::MattesMutualInformationImageToImageMetricFor3DBLUTFFD< FixedImageType, MovingImageType >::New();
236 //Set parameters for this metric
238 m->SetNumberOfHistogramBins(m_ArgsInfo.bins_arg);
240 //Randomize samples if demanded
241 if (m_ArgsInfo.random_flag ) m->ReinitializeSeed();
242 else m->ReinitializeSeed(0);
244 // Two ways of calculating the derivatives
245 m->SetUseExplicitPDFDerivatives(m_ArgsInfo.explicitPDFDerivatives_flag);
249 std::cout<<"Using Mattes' MI for 3D BLUT FFD with "<<m_ArgsInfo.bins_arg<<" bins..."<<std::endl;
250 if (m_ArgsInfo.explicitPDFDerivatives_flag) std::cout<<"Calculating PDFs explicitly..."<<std::endl;
259 typedef itk::ImageMaskSpatialObject<itkGetStaticConstMacro(FixedImageDimension)> ImageMaskSpatialObjectType;
260 typename ImageMaskSpatialObjectType::ConstPointer mask = NULL;
261 if (m_FixedImageMask.IsNotNull())
262 mask = dynamic_cast<const ImageMaskSpatialObjectType*>(m_FixedImageMask.GetPointer());
264 typedef typename ImageMaskSpatialObjectType::RegionType ImageMaskRegionType;
265 ImageMaskRegionType mask_region;
266 if (mask.IsNotNull())
267 mask_region = mask->GetAxisAlignedBoundingBoxRegion();
270 if( m_FixedImageMask.IsNotNull() )
271 m_Metric->SetFixedImageMask(m_FixedImageMask);
273 m_Metric->SetFixedImageRegion(m_FixedImageRegion);
274 //m_Metric->SetFixedImageRegion(mask_region);
277 #if defined(ITK_USE_OPTIMIZED_REGISTRATION_METHODS) || ITK_VERSION_MAJOR >= 4
279 //============================================================================
280 // Set the lower intensity threshold
281 if (m_ArgsInfo.intThreshold_given) {
282 m_UseFixedImageSamplesIntensityThreshold=true;
283 m_FixedImageSamplesIntensityThreshold=m_ArgsInfo.intThreshold_arg;
284 m_Metric->SetFixedImageSamplesIntensityThreshold(m_FixedImageSamplesIntensityThreshold);
285 if (m_Verbose) std::cout<<"Setting the fixed image intensity threshold to "<<m_FixedImageSamplesIntensityThreshold<<"..."<<std::endl;
289 //============================================================================
290 // Set the number of samples
293 if ( ( m_ArgsInfo.samples_arg==1.0) && (m_FixedImageMask.IsNull()) && (!m_UseFixedImageSamplesIntensityThreshold ) ) {
294 m_Metric->SetUseAllPixels(true);
295 if (m_Verbose) std::cout<<"Using all pixels (a fraction of "<<m_ArgsInfo.samples_arg<<")..."<<std::endl;
297 // JV the optimized metric will resample points to obtain the number of pixels:
298 // Pass the correct number of spatial samples, with indexes
300 std::vector<typename FixedImageType::IndexType> fiic;// fixedImageindexContainer
301 unsigned int numberOfValidPixels=0;
302 FixedImageIndexType index;
303 FixedImagePointType inputPoint;
305 // Calculate the number
306 const unsigned int totalNumberOfPixels = m_FixedImageRegion.GetNumberOfPixels();
307 const unsigned int totalNumberOfMaskPixels = mask_region.GetNumberOfPixels();
308 const unsigned int numberOfDemandedPixels = static_cast< unsigned int >( (double) totalNumberOfPixels *m_ArgsInfo.samples_arg );
310 // --------------------------------------------------
311 // Sample whole image sequentially and pass the indexes
312 if (m_ArgsInfo.samples_arg==1.0) {
313 if (m_Verbose) std::cout<<"Sequentially scanning the image for valid pixels..."<<std::endl;
315 // Set up a region interator within the user specified fixed image region.
316 typedef ImageRegionConstIteratorWithIndex<FixedImageType> RegionIterator;
317 RegionIterator regionIter( m_FixedImage, m_FixedImageRegion );
318 //RegionIterator regionIter( m_FixedImage, mask_region );
320 // go over the whole region
321 regionIter.GoToBegin();
322 while(!regionIter.IsAtEnd() ) {
325 index = regionIter.GetIndex();
328 if( m_FixedImageMask.IsNotNull() ) {
329 // Check if the Index is inside the mask, translate index to point
330 m_FixedImage->TransformIndexToPhysicalPoint( index, inputPoint );
332 // If not inside the mask, ignore the point
333 if( !m_FixedImageMask->IsInside( inputPoint ) ) {
334 ++regionIter; // jump to next pixel
341 if( m_UseFixedImageSamplesIntensityThreshold &&
342 ( regionIter.Get() < m_FixedImageSamplesIntensityThreshold) ) {
343 ++regionIter; // jump to next pixel
348 // Add point to the numbers
349 fiic.push_back(index);
350 ++numberOfValidPixels;
355 // --------------------------------------------------
358 if (m_Verbose) std::cout<<"Randomly scanning the image for valid pixels..."<<std::endl;
360 // Set up a random interator within the user specified fixed image region.
361 typedef ImageRandomConstIteratorWithIndex<FixedImageType> RandomIterator;
364 RandomIterator randIter( m_FixedImage, m_FixedImageRegion );
365 //RandomIterator randIter( m_FixedImage, mask_region );
367 if (m_Verbose) std::cout << "Search region " << m_FixedImageRegion << std::endl;
368 if (m_Verbose) std::cout << "Mask search region " << mask_region << std::endl;
370 // Randomly sample the image
373 while (att <= natts) {
374 if (m_Verbose) std::cout << "Attempt " << att << std::endl;
377 int count_not_thres = 0;
379 randIter.ReinitializeSeed(c);
380 randIter.SetNumberOfSamples( numberOfDemandedPixels * 1000 );
381 randIter.GoToBegin();
383 while( (!randIter.IsAtEnd()) && (numberOfValidPixels<=numberOfDemandedPixels) ) {
385 index = randIter.GetIndex();
386 //if (m_Verbose) std::cout << "testing pixel " << index << std::endl;
389 if( m_FixedImageMask.IsNotNull() ) {
391 // Check if the Index is inside the mask, translate index to point
392 m_FixedImage->TransformIndexToPhysicalPoint( index, inputPoint );
394 // If not inside the mask, ignore the point
395 if( !m_FixedImageMask->IsInside( inputPoint ) ) {
396 ++randIter; // jump to next pixel
397 //if (m_Verbose) std::cout << "not inside " << inputPoint << std::endl;
405 // if( m_UseFixedImageSamplesIntensityThreshold &&
406 // randIter.Get() < m_FixedImageSamplesIntensityThreshold ) {
408 // //if (m_Verbose) std::cout << "not in threshold" << std::endl;
409 // count_not_thres++;
413 // Add point to the numbers
414 fiic.push_back(index);
415 ++numberOfValidPixels;
419 if (m_Verbose) std::cout << "points outside = " << count_out << std::endl;
420 if (m_Verbose) std::cout << "points not in threshold = " << count_not_thres << std::endl;
430 // Set the indexes of valid samples
431 m_Metric->SetFixedImageIndexes(fiic);
432 // m_Metric->SetNumberOfSpatialSamples( numberOfValidPixels);
433 if (m_Verbose) std::cout<<"A fraction of "<<m_ArgsInfo.samples_arg<<" spatial samples was requested..."<<std::endl;
434 double fraction=(double)numberOfValidPixels/ (double) totalNumberOfPixels;
435 if (m_Verbose) std::cout<<"Found "<<numberOfValidPixels <<" valid pixels for a total of "<<totalNumberOfPixels<<" (a fraction of "<<fraction<<")..."<<std::endl;
436 if (m_Verbose) std::cout<<"number of mask pixels "<<totalNumberOfMaskPixels<<std::endl;
441 if (m_Verbose) std::cout<<"Not setting the fixed image intensity threshold or the fraction of samples to use (not compiled with USE_OPTIMIZED_REGISTRATION_METHODS)..."<<std::endl;
445 //============================================================================