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 _clitkNormalizedCorrelationImageToImageMetricFor3DBLUTFFD_txx
20 #define _clitkNormalizedCorrelationImageToImageMetricFor3DBLUTFFD_txx
22 // First make sure that the configuration is available.
23 // This line can be removed once the optimized versions
24 // gets integrated into the main directories.
25 #include "itkConfigure.h"
27 #if defined(ITK_USE_OPTIMIZED_REGISTRATION_METHODS) || ITK_VERSION_MAJOR >= 4
28 #include "clitkOptNormalizedCorrelationImageToImageMetricFor3DBLUTFFD.txx"
32 #include "clitkNormalizedCorrelationImageToImageMetricFor3DBLUTFFD.h"
34 #include "itkImageRegionConstIteratorWithIndex.h"
43 template <class TFixedImage, class TMovingImage>
44 NormalizedCorrelationImageToImageMetricFor3DBLUTFFD<TFixedImage,TMovingImage>
45 ::NormalizedCorrelationImageToImageMetricFor3DBLUTFFD()
47 m_SubtractMean = false;
51 * Get the match Measure
53 template <class TFixedImage, class TMovingImage>
54 typename NormalizedCorrelationImageToImageMetricFor3DBLUTFFD<TFixedImage,TMovingImage>::MeasureType
55 NormalizedCorrelationImageToImageMetricFor3DBLUTFFD<TFixedImage,TMovingImage>
56 ::GetValue( const TransformParametersType & parameters ) const
59 FixedImageConstPointer fixedImage = this->m_FixedImage;
62 itkExceptionMacro( << "Fixed image has not been assigned" );
65 typedef itk::ImageRegionConstIteratorWithIndex<FixedImageType> FixedIteratorType;
67 FixedIteratorType ti( fixedImage, this->GetFixedImageRegion() );
69 typename FixedImageType::IndexType index;
73 this->m_NumberOfPixelsCounted = 0;
75 this->SetTransformParameters( parameters );
77 typedef typename itk::NumericTraits< MeasureType >::AccumulateType AccumulateType;
79 AccumulateType sff = itk::NumericTraits< AccumulateType >::Zero;
80 AccumulateType smm = itk::NumericTraits< AccumulateType >::Zero;
81 AccumulateType sfm = itk::NumericTraits< AccumulateType >::Zero;
82 AccumulateType sf = itk::NumericTraits< AccumulateType >::Zero;
83 AccumulateType sm = itk::NumericTraits< AccumulateType >::Zero;
85 while(!ti.IsAtEnd()) {
87 index = ti.GetIndex();
89 InputPointType inputPoint;
90 fixedImage->TransformIndexToPhysicalPoint( index, inputPoint );
92 if( this->m_FixedImageMask && !this->m_FixedImageMask->IsInside( inputPoint ) ) {
97 OutputPointType transformedPoint = this->m_Transform->TransformPoint( inputPoint );
99 if( this->m_MovingImageMask && !this->m_MovingImageMask->IsInside( transformedPoint ) ) {
104 if( this->m_Interpolator->IsInsideBuffer( transformedPoint ) ) {
105 const RealType movingValue = this->m_Interpolator->Evaluate( transformedPoint );
106 const RealType fixedValue = ti.Get();
107 sff += fixedValue * fixedValue;
108 smm += movingValue * movingValue;
109 sfm += fixedValue * movingValue;
110 if ( this->m_SubtractMean ) {
114 this->m_NumberOfPixelsCounted++;
120 if ( this->m_SubtractMean && this->m_NumberOfPixelsCounted > 0 ) {
121 sff -= ( sf * sf / this->m_NumberOfPixelsCounted );
122 smm -= ( sm * sm / this->m_NumberOfPixelsCounted );
123 sfm -= ( sf * sm / this->m_NumberOfPixelsCounted );
126 const RealType denom = -1.0 * vcl_sqrt(sff * smm );
128 if( this->m_NumberOfPixelsCounted > 0 && denom != 0.0) {
129 measure = sfm / denom;
131 measure = itk::NumericTraits< MeasureType >::Zero;
143 * Get the Derivative Measure
145 template < class TFixedImage, class TMovingImage>
147 NormalizedCorrelationImageToImageMetricFor3DBLUTFFD<TFixedImage,TMovingImage>
148 ::GetDerivative( const TransformParametersType & parameters,
149 DerivativeType & derivative ) const
152 if( !this->GetGradientImage() ) {
153 itkExceptionMacro(<<"The gradient image is null, maybe you forgot to call Initialize()");
156 FixedImageConstPointer fixedImage = this->m_FixedImage;
159 itkExceptionMacro( << "Fixed image has not been assigned" );
162 const unsigned int dimension = FixedImageType::ImageDimension;
164 typedef itk::ImageRegionConstIteratorWithIndex<FixedImageType> FixedIteratorType;
166 FixedIteratorType ti( fixedImage, this->GetFixedImageRegion() );
168 typename FixedImageType::IndexType index;
170 this->m_NumberOfPixelsCounted = 0;
172 this->SetTransformParameters( parameters );
174 typedef typename itk::NumericTraits< MeasureType >::AccumulateType AccumulateType;
176 AccumulateType sff = itk::NumericTraits< AccumulateType >::Zero;
177 AccumulateType smm = itk::NumericTraits< AccumulateType >::Zero;
178 AccumulateType sfm = itk::NumericTraits< AccumulateType >::Zero;
179 AccumulateType sf = itk::NumericTraits< AccumulateType >::Zero;
180 AccumulateType sm = itk::NumericTraits< AccumulateType >::Zero;
182 const unsigned int ParametersDimension = this->GetNumberOfParameters();
183 derivative = DerivativeType( ParametersDimension );
184 derivative.Fill( itk::NumericTraits<typename DerivativeType::ValueType>::Zero );
186 DerivativeType derivativeF = DerivativeType( ParametersDimension );
187 derivativeF.Fill( itk::NumericTraits<typename DerivativeType::ValueType>::Zero );
189 DerivativeType derivativeM = DerivativeType( ParametersDimension );
190 derivativeM.Fill( itk::NumericTraits<typename DerivativeType::ValueType>::Zero );
193 // First compute the sums
194 while(!ti.IsAtEnd()) {
196 index = ti.GetIndex();
198 InputPointType inputPoint;
199 fixedImage->TransformIndexToPhysicalPoint( index, inputPoint );
201 if( this->m_FixedImageMask && !this->m_FixedImageMask->IsInside( inputPoint ) ) {
206 OutputPointType transformedPoint = this->m_Transform->TransformPoint( inputPoint );
208 if( this->m_MovingImageMask && !this->m_MovingImageMask->IsInside( transformedPoint ) ) {
213 if( this->m_Interpolator->IsInsideBuffer( transformedPoint ) ) {
214 const RealType movingValue = this->m_Interpolator->Evaluate( transformedPoint );
215 const RealType fixedValue = ti.Get();
216 sff += fixedValue * fixedValue;
217 smm += movingValue * movingValue;
218 sfm += fixedValue * movingValue;
219 if ( this->m_SubtractMean ) {
223 this->m_NumberOfPixelsCounted++;
229 // Compute contributions to derivatives
231 while(!ti.IsAtEnd()) {
233 index = ti.GetIndex();
235 InputPointType inputPoint;
236 fixedImage->TransformIndexToPhysicalPoint( index, inputPoint );
238 if ( this->m_FixedImageMask && !this->m_FixedImageMask->IsInside( inputPoint ) ) {
243 OutputPointType transformedPoint = this->m_Transform->TransformPoint( inputPoint );
245 if ( this->m_MovingImageMask && !this->m_MovingImageMask->IsInside( transformedPoint ) ) {
250 if( this->m_Interpolator->IsInsideBuffer( transformedPoint ) ) {
251 const RealType movingValue = this->m_Interpolator->Evaluate( transformedPoint );
252 const RealType fixedValue = ti.Get();
254 #if ITK_VERSION_MAJOR >= 4
255 TransformJacobianType jacobian;
256 this->m_Transform->ComputeJacobianWithRespectToParameters( inputPoint, jacobian );
258 const TransformJacobianType & jacobian =
259 this->m_Transform->GetJacobian( inputPoint );
262 // Get the gradient by NearestNeighboorInterpolation:
263 // which is equivalent to round up the point components.
264 typedef typename OutputPointType::CoordRepType CoordRepType;
265 typedef itk::ContinuousIndex<CoordRepType,MovingImageType::ImageDimension>
266 MovingImageContinuousIndexType;
268 MovingImageContinuousIndexType tempIndex;
269 this->m_MovingImage->TransformPhysicalPointToContinuousIndex( transformedPoint, tempIndex );
271 typename MovingImageType::IndexType mappedIndex;
272 mappedIndex.CopyWithRound( tempIndex );
274 const GradientPixelType gradient =
275 this->GetGradientImage()->GetPixel( mappedIndex );
277 for(unsigned int par=0; par<ParametersDimension; par++) {
278 RealType sumF = itk::NumericTraits< RealType >::Zero;
279 RealType sumM = itk::NumericTraits< RealType >::Zero;
280 for(unsigned int dim=0; dim<dimension; dim++) {
281 const RealType differential = jacobian( dim, par ) * gradient[dim];
282 sumF += fixedValue * differential;
283 sumM += movingValue * differential;
284 if ( this->m_SubtractMean && this->m_NumberOfPixelsCounted > 0 ) {
285 sumF -= differential * sf / this->m_NumberOfPixelsCounted;
286 sumM -= differential * sm / this->m_NumberOfPixelsCounted;
289 derivativeF[par] += sumF;
290 derivativeM[par] += sumM;
297 if ( this->m_SubtractMean && this->m_NumberOfPixelsCounted > 0 ) {
298 sff -= ( sf * sf / this->m_NumberOfPixelsCounted );
299 smm -= ( sm * sm / this->m_NumberOfPixelsCounted );
300 sfm -= ( sf * sm / this->m_NumberOfPixelsCounted );
303 const RealType denom = -1.0 * vcl_sqrt(sff * smm );
305 if( this->m_NumberOfPixelsCounted > 0 && denom != 0.0) {
306 for(unsigned int i=0; i<ParametersDimension; i++) {
307 derivative[i] = ( derivativeF[i] - (sfm/smm)* derivativeM[i] ) / denom;
310 for(unsigned int i=0; i<ParametersDimension; i++) {
311 derivative[i] = itk::NumericTraits< MeasureType >::Zero;
319 * Get both the match Measure and theDerivative Measure
321 template <class TFixedImage, class TMovingImage>
323 NormalizedCorrelationImageToImageMetricFor3DBLUTFFD<TFixedImage,TMovingImage>
324 ::GetValueAndDerivative(const TransformParametersType & parameters,
325 MeasureType & value, DerivativeType & derivative) const
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 dimension = FixedImageType::ImageDimension;
341 typedef itk::ImageRegionConstIteratorWithIndex<FixedImageType> FixedIteratorType;
343 FixedIteratorType ti( fixedImage, this->GetFixedImageRegion() );
345 typename FixedImageType::IndexType index;
347 this->m_NumberOfPixelsCounted = 0;
349 this->SetTransformParameters( parameters );
351 typedef typename itk::NumericTraits< MeasureType >::AccumulateType AccumulateType;
353 AccumulateType sff = itk::NumericTraits< AccumulateType >::Zero;
354 AccumulateType smm = itk::NumericTraits< AccumulateType >::Zero;
355 AccumulateType sfm = itk::NumericTraits< AccumulateType >::Zero;
356 AccumulateType sf = itk::NumericTraits< AccumulateType >::Zero;
357 AccumulateType sm = itk::NumericTraits< AccumulateType >::Zero;
359 const unsigned int ParametersDimension = this->GetNumberOfParameters();
360 derivative = DerivativeType( ParametersDimension );
361 derivative.Fill( itk::NumericTraits<typename DerivativeType::ValueType>::Zero );
363 DerivativeType derivativeF = DerivativeType( ParametersDimension );
364 derivativeF.Fill( itk::NumericTraits<typename DerivativeType::ValueType>::Zero );
366 DerivativeType derivativeM = DerivativeType( ParametersDimension );
367 derivativeM.Fill( itk::NumericTraits<typename DerivativeType::ValueType>::Zero );
369 DerivativeType derivativeM1 = DerivativeType( ParametersDimension );
370 derivativeM1.Fill( itk::NumericTraits<typename DerivativeType::ValueType>::Zero );
373 // First compute the sums
374 while(!ti.IsAtEnd()) {
376 index = ti.GetIndex();
378 InputPointType inputPoint;
379 fixedImage->TransformIndexToPhysicalPoint( index, inputPoint );
381 if( this->m_FixedImageMask && !this->m_FixedImageMask->IsInside( inputPoint ) ) {
386 OutputPointType transformedPoint = this->m_Transform->TransformPoint( inputPoint );
388 if( this->m_MovingImageMask && !this->m_MovingImageMask->IsInside( transformedPoint ) ) {
393 if( this->m_Interpolator->IsInsideBuffer( transformedPoint ) ) {
394 const RealType movingValue = this->m_Interpolator->Evaluate( transformedPoint );
395 const RealType fixedValue = ti.Get();
396 sff += fixedValue * fixedValue;
397 smm += movingValue * movingValue;
398 sfm += fixedValue * movingValue;
399 if ( this->m_SubtractMean ) {
403 this->m_NumberOfPixelsCounted++;
410 // Compute contributions to derivatives
412 while(!ti.IsAtEnd()) {
414 index = ti.GetIndex();
416 InputPointType inputPoint;
417 fixedImage->TransformIndexToPhysicalPoint( index, inputPoint );
419 if( this->m_FixedImageMask && !this->m_FixedImageMask->IsInside( inputPoint ) ) {
424 OutputPointType transformedPoint = this->m_Transform->TransformPoint( inputPoint );
426 if( this->m_MovingImageMask && !this->m_MovingImageMask->IsInside( transformedPoint ) ) {
431 if( this->m_Interpolator->IsInsideBuffer( transformedPoint ) ) {
432 const RealType movingValue = this->m_Interpolator->Evaluate( transformedPoint );
433 const RealType fixedValue = ti.Get();
435 #if ITK_VERSION_MAJOR >= 4
436 TransformJacobianType jacobian;
437 this->m_Transform->ComputeJacobianWithRespectToParameters( inputPoint, jacobian );
439 const TransformJacobianType & jacobian =
440 this->m_Transform->GetJacobian( inputPoint );
443 // Get the gradient by NearestNeighboorInterpolation:
444 // which is equivalent to round up the point components.
445 typedef typename OutputPointType::CoordRepType CoordRepType;
446 typedef itk::ContinuousIndex<CoordRepType,MovingImageType::ImageDimension>
447 MovingImageContinuousIndexType;
449 MovingImageContinuousIndexType tempIndex;
450 this->m_MovingImage->TransformPhysicalPointToContinuousIndex( transformedPoint, tempIndex );
452 typename MovingImageType::IndexType mappedIndex;
453 mappedIndex.CopyWithRound( tempIndex );
455 const GradientPixelType gradient =
456 this->GetGradientImage()->GetPixel( mappedIndex );
458 for(unsigned int par=0; par<ParametersDimension; par++) {
459 RealType sumF = itk::NumericTraits< RealType >::Zero;
460 RealType sumM = itk::NumericTraits< RealType >::Zero;
461 for(unsigned int dim=0; dim<dimension; dim++) {
462 const RealType differential = jacobian( dim, par ) * gradient[dim];
463 sumF += fixedValue * differential;
464 sumM += movingValue * differential;
465 if ( this->m_SubtractMean && this->m_NumberOfPixelsCounted > 0 ) {
466 sumF -= differential * sf / this->m_NumberOfPixelsCounted;
467 sumM -= differential * sm / this->m_NumberOfPixelsCounted;
470 derivativeF[par] += sumF;
471 derivativeM[par] += sumM;
477 if ( this->m_SubtractMean && this->m_NumberOfPixelsCounted > 0 ) {
478 sff -= ( sf * sf / this->m_NumberOfPixelsCounted );
479 smm -= ( sm * sm / this->m_NumberOfPixelsCounted );
480 sfm -= ( sf * sm / this->m_NumberOfPixelsCounted );
483 const RealType denom = -1.0 * vcl_sqrt(sff * smm );
485 if( this->m_NumberOfPixelsCounted > 0 && denom != 0.0) {
486 for(unsigned int i=0; i<ParametersDimension; i++) {
487 derivative[i] = ( derivativeF[i] - (sfm/smm)* derivativeM[i] ) / denom;
491 for(unsigned int i=0; i<ParametersDimension; i++) {
492 derivative[i] = itk::NumericTraits< MeasureType >::Zero;
494 value = itk::NumericTraits< MeasureType >::Zero;
501 template < class TFixedImage, class TMovingImage>
503 NormalizedCorrelationImageToImageMetricFor3DBLUTFFD<TFixedImage,TMovingImage>
504 ::PrintSelf(std::ostream& os, itk::Indent indent) const
506 Superclass::PrintSelf(os, indent);
507 os << indent << "SubtractMean: " << m_SubtractMean << std::endl;
510 } // end namespace itk
515 #endif // _clitkNormalizedCorrelationImageToImageMetricFor3DBLUTFFD.txx