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://oncora1.lyon.fnclcc.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 ======================================================================-====*/
18 #ifndef _clitkCorrelationRatioImageToImageMetric_txx
19 #define _clitkCorrelationRatioImageToImageMetric_txx
22 * @file clitkCorrelationRatioImageToImageMetric.txx
23 * @author Jef Vandemeulebroucke <jef@creatis.insa-lyon.fr>
24 * @date July 30 18:14:53 2007
26 * @brief Compute the correlation ratio between 2 images
31 #include "clitkCorrelationRatioImageToImageMetric.h"
32 #include "itkImageRegionConstIteratorWithIndex.h"
33 #include "itkImageRegionConstIterator.h"
34 #include "itkImageRegionIterator.h"
42 template <class TFixedImage, class TMovingImage>
43 CorrelationRatioImageToImageMetric<TFixedImage,TMovingImage>
44 ::CorrelationRatioImageToImageMetric()
50 template <class TFixedImage, class TMovingImage>
52 CorrelationRatioImageToImageMetric<TFixedImage,TMovingImage>
53 ::Initialize(void) throw ( ExceptionObject )
56 this->Superclass::Initialize();
58 // Compute the minimum and maximum for the FixedImage over the FixedImageRegion.
59 // We can't use StatisticsImageFilter to do this because the filter computes the min/max for the largest possible region
60 double fixedImageMin = NumericTraits<double>::max();
61 double fixedImageMax = NumericTraits<double>::NonpositiveMin();
63 typedef ImageRegionConstIterator<FixedImageType> FixedIteratorType;
64 FixedIteratorType fixedImageIterator(
65 this->m_FixedImage, this->GetFixedImageRegion() );
67 for ( fixedImageIterator.GoToBegin();
68 !fixedImageIterator.IsAtEnd(); ++fixedImageIterator ) {
70 double sample = static_cast<double>( fixedImageIterator.Get() );
72 if ( sample < fixedImageMin ) {
73 fixedImageMin = sample;
76 if ( sample > fixedImageMax ) {
77 fixedImageMax = sample;
81 // Compute binsize for the fixedImage
82 m_FixedImageBinSize = ( fixedImageMax - fixedImageMin ) / m_NumberOfBins;
83 m_FixedImageMin=fixedImageMin;
84 //Allocate mempry and initialise the fixed image bin
85 m_NumberOfPixelsCountedPerBin.resize( m_NumberOfBins, 0 );
86 m_mMSVPB.resize( m_NumberOfBins, 0.0 );
87 m_mSMVPB.resize( m_NumberOfBins, 0.0 );
92 * Get the match Measure
94 template <class TFixedImage, class TMovingImage>
95 typename CorrelationRatioImageToImageMetric<TFixedImage,TMovingImage>::MeasureType
96 CorrelationRatioImageToImageMetric<TFixedImage,TMovingImage>
97 ::GetValue( const TransformParametersType & parameters ) const
100 itkDebugMacro("GetValue( " << parameters << " ) ");
102 FixedImageConstPointer fixedImage = this->m_FixedImage;
105 itkExceptionMacro( << "Fixed image has not been assigned" );
108 typedef itk::ImageRegionConstIteratorWithIndex<FixedImageType> FixedIteratorType;
111 FixedIteratorType ti( fixedImage, this->GetFixedImageRegion() );
113 typename FixedImageType::IndexType index;
115 MeasureType measure = itk::NumericTraits< MeasureType >::Zero;
117 this->m_NumberOfPixelsCounted = 0;
118 this->SetTransformParameters( parameters );
121 //temporary measures for the calculation
125 while(!ti.IsAtEnd()) {
127 index = ti.GetIndex();
129 typename Superclass::InputPointType inputPoint;
130 fixedImage->TransformIndexToPhysicalPoint( index, inputPoint );
132 // Verify that the point is in the fixed Image Mask
133 if( this->m_FixedImageMask && !this->m_FixedImageMask->IsInside( inputPoint ) ) {
138 typename Superclass::OutputPointType transformedPoint = this->m_Transform->TransformPoint( inputPoint );
140 //Verify that the point is in the moving Image Mask
141 if( this->m_MovingImageMask && !this->m_MovingImageMask->IsInside( transformedPoint ) ) {
146 // Verify is the interpolated value is in the buffer
147 if( this->m_Interpolator->IsInsideBuffer( transformedPoint ) ) {
148 //Accumulate calculations for the correlation ratio
149 //For each pixel the is in both masks and the buffer we adapt the following measures:
150 //movingMeanSquaredValue mMSV; movingSquaredMeanValue mSMV;
151 //movingMeanSquaredValuePerBin[i] mSMVPB; movingSquaredMeanValuePerBin[i] mSMVPB
152 //NumberOfPixelsCounted, NumberOfPixelsCountedPerBin[i]
154 //get the value of the moving image
155 const RealType movingValue = this->m_Interpolator->Evaluate( transformedPoint );
156 // for the variance of the overlapping moving image we accumulate the following measures
157 const RealType movingSquaredValue=movingValue*movingValue;
158 mMSV+=movingSquaredValue;
161 //get the fixed value
162 const RealType fixedValue = ti.Get();
164 //check in which bin the fixed value belongs, get the index
165 const double fixedImageBinTerm = (fixedValue - m_FixedImageMin) / m_FixedImageBinSize;
166 const unsigned int fixedImageBinIndex = static_cast<unsigned int>( vcl_floor(fixedImageBinTerm ) );
167 //adapt the measures per bin
168 this->m_mMSVPB[fixedImageBinIndex]+=movingSquaredValue;
169 this->m_mSMVPB[fixedImageBinIndex]+=movingValue;
170 //increase the fixed image bin and the total pixel count
171 this->m_NumberOfPixelsCountedPerBin[fixedImageBinIndex]+=1;
172 this->m_NumberOfPixelsCounted++;
178 if( !this->m_NumberOfPixelsCounted ) {
179 itkExceptionMacro(<<"All the points mapped to outside of the moving image");
182 //apdapt the measures per bin
183 for (unsigned int i=0; i< m_NumberOfBins; i++ ) {
184 if (this->m_NumberOfPixelsCountedPerBin[i]>0) {
185 measure+=(this->m_mMSVPB[i]-((this->m_mSMVPB[i]*this->m_mSMVPB[i])/this->m_NumberOfPixelsCountedPerBin[i]));
189 //Normalize with the global measures
190 measure /= (mMSV-((mSMV*mSMV)/ this->m_NumberOfPixelsCounted));
201 * Get the Derivative Measure
203 template < class TFixedImage, class TMovingImage>
205 CorrelationRatioImageToImageMetric<TFixedImage,TMovingImage>
206 ::GetDerivative( const TransformParametersType & parameters,
207 DerivativeType & derivative ) const
210 itkDebugMacro("GetDerivative( " << parameters << " ) ");
212 if( !this->GetGradientImage() ) {
213 itkExceptionMacro(<<"The gradient image is null, maybe you forgot to call Initialize()");
216 FixedImageConstPointer fixedImage = this->m_FixedImage;
219 itkExceptionMacro( << "Fixed image has not been assigned" );
222 const unsigned int ImageDimension = FixedImageType::ImageDimension;
225 typedef itk::ImageRegionConstIteratorWithIndex<
226 FixedImageType> FixedIteratorType;
228 typedef itk::ImageRegionConstIteratorWithIndex<
229 ITK_TYPENAME Superclass::GradientImageType> GradientIteratorType;
232 FixedIteratorType ti( fixedImage, this->GetFixedImageRegion() );
234 typename FixedImageType::IndexType index;
236 this->m_NumberOfPixelsCounted = 0;
238 this->SetTransformParameters( parameters );
240 const unsigned int ParametersDimension = this->GetNumberOfParameters();
241 derivative = DerivativeType( ParametersDimension );
242 derivative.Fill( itk::NumericTraits<ITK_TYPENAME DerivativeType::ValueType>::Zero );
246 while(!ti.IsAtEnd()) {
248 index = ti.GetIndex();
250 typename Superclass::InputPointType inputPoint;
251 fixedImage->TransformIndexToPhysicalPoint( index, inputPoint );
253 if( this->m_FixedImageMask && !this->m_FixedImageMask->IsInside( inputPoint ) ) {
258 typename Superclass::OutputPointType transformedPoint = this->m_Transform->TransformPoint( inputPoint );
260 if( this->m_MovingImageMask && !this->m_MovingImageMask->IsInside( transformedPoint ) ) {
265 if( this->m_Interpolator->IsInsideBuffer( transformedPoint ) ) {
266 const RealType movingValue = this->m_Interpolator->Evaluate( transformedPoint );
268 const TransformJacobianType & jacobian =
269 this->m_Transform->GetJacobian( inputPoint );
272 const RealType fixedValue = ti.Value();
273 this->m_NumberOfPixelsCounted++;
274 const RealType diff = movingValue - fixedValue;
276 // Get the gradient by NearestNeighboorInterpolation:
277 // which is equivalent to round up the point components.
278 typedef typename Superclass::OutputPointType OutputPointType;
279 typedef typename OutputPointType::CoordRepType CoordRepType;
280 typedef ContinuousIndex<CoordRepType,MovingImageType::ImageDimension>
281 MovingImageContinuousIndexType;
283 MovingImageContinuousIndexType tempIndex;
284 this->m_MovingImage->TransformPhysicalPointToContinuousIndex( transformedPoint, tempIndex );
286 typename MovingImageType::IndexType mappedIndex;
287 for( unsigned int j = 0; j < MovingImageType::ImageDimension; j++ ) {
288 mappedIndex[j] = static_cast<long>( vnl_math_rnd( tempIndex[j] ) );
291 const GradientPixelType gradient =
292 this->GetGradientImage()->GetPixel( mappedIndex );
294 for(unsigned int par=0; par<ParametersDimension; par++) {
295 RealType sum = NumericTraits< RealType >::Zero;
296 for(unsigned int dim=0; dim<ImageDimension; dim++) {
297 sum += 2.0 * diff * jacobian( dim, par ) * gradient[dim];
299 derivative[par] += sum;
306 if( !this->m_NumberOfPixelsCounted ) {
307 itkExceptionMacro(<<"All the points mapped to outside of the moving image");
309 for(unsigned int i=0; i<ParametersDimension; i++) {
310 derivative[i] /= this->m_NumberOfPixelsCounted;
318 * Get both the match Measure and the Derivative Measure
320 template <class TFixedImage, class TMovingImage>
322 CorrelationRatioImageToImageMetric<TFixedImage,TMovingImage>
323 ::GetValueAndDerivative(const TransformParametersType & parameters,
324 MeasureType & value, DerivativeType & derivative) const
327 itkDebugMacro("GetValueAndDerivative( " << parameters << " ) ");
329 if( !this->GetGradientImage() ) {
330 itkExceptionMacro(<<"The gradient image is null, maybe you forgot to call Initialize()");
333 FixedImageConstPointer fixedImage = this->m_FixedImage;
336 itkExceptionMacro( << "Fixed image has not been assigned" );
339 const unsigned int ImageDimension = FixedImageType::ImageDimension;
341 typedef itk::ImageRegionConstIteratorWithIndex<
342 FixedImageType> FixedIteratorType;
344 typedef itk::ImageRegionConstIteratorWithIndex<
345 ITK_TYPENAME Superclass::GradientImageType> GradientIteratorType;
348 FixedIteratorType ti( fixedImage, this->GetFixedImageRegion() );
350 typename FixedImageType::IndexType index;
352 MeasureType measure = NumericTraits< MeasureType >::Zero;
354 this->m_NumberOfPixelsCounted = 0;
356 this->SetTransformParameters( parameters );
358 const unsigned int ParametersDimension = this->GetNumberOfParameters();
359 derivative = DerivativeType( ParametersDimension );
360 derivative.Fill( NumericTraits<ITK_TYPENAME DerivativeType::ValueType>::Zero );
364 while(!ti.IsAtEnd()) {
366 index = ti.GetIndex();
368 typename Superclass::InputPointType inputPoint;
369 fixedImage->TransformIndexToPhysicalPoint( index, inputPoint );
371 if( this->m_FixedImageMask && !this->m_FixedImageMask->IsInside( inputPoint ) ) {
376 typename Superclass::OutputPointType transformedPoint = this->m_Transform->TransformPoint( inputPoint );
378 if( this->m_MovingImageMask && !this->m_MovingImageMask->IsInside( transformedPoint ) ) {
383 if( this->m_Interpolator->IsInsideBuffer( transformedPoint ) ) {
384 const RealType movingValue = this->m_Interpolator->Evaluate( transformedPoint );
386 const TransformJacobianType & jacobian =
387 this->m_Transform->GetJacobian( inputPoint );
390 const RealType fixedValue = ti.Value();
391 this->m_NumberOfPixelsCounted++;
393 const RealType diff = movingValue - fixedValue;
395 measure += diff * diff;
397 // Get the gradient by NearestNeighboorInterpolation:
398 // which is equivalent to round up the point components.
399 typedef typename Superclass::OutputPointType OutputPointType;
400 typedef typename OutputPointType::CoordRepType CoordRepType;
401 typedef ContinuousIndex<CoordRepType,MovingImageType::ImageDimension>
402 MovingImageContinuousIndexType;
404 MovingImageContinuousIndexType tempIndex;
405 this->m_MovingImage->TransformPhysicalPointToContinuousIndex( transformedPoint, tempIndex );
407 typename MovingImageType::IndexType mappedIndex;
408 for( unsigned int j = 0; j < MovingImageType::ImageDimension; j++ ) {
409 mappedIndex[j] = static_cast<long>( vnl_math_rnd( tempIndex[j] ) );
412 const GradientPixelType gradient =
413 this->GetGradientImage()->GetPixel( mappedIndex );
415 for(unsigned int par=0; par<ParametersDimension; par++) {
416 RealType sum = NumericTraits< RealType >::Zero;
417 for(unsigned int dim=0; dim<ImageDimension; dim++) {
418 sum += 2.0 * diff * jacobian( dim, par ) * gradient[dim];
420 derivative[par] += sum;
427 if( !this->m_NumberOfPixelsCounted ) {
428 itkExceptionMacro(<<"All the points mapped to outside of the moving image");
430 for(unsigned int i=0; i<ParametersDimension; i++) {
431 derivative[i] /= this->m_NumberOfPixelsCounted;
433 measure /= this->m_NumberOfPixelsCounted;
440 } // end namespace itk