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 ======================================================================-====*/
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 #ifdef ITK_USE_OPTIMIZED_REGISTRATION_METHODS
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<ITK_TYPENAME DerivativeType::ValueType>::Zero );
186 DerivativeType derivativeF = DerivativeType( ParametersDimension );
187 derivativeF.Fill( itk::NumericTraits<ITK_TYPENAME DerivativeType::ValueType>::Zero );
189 DerivativeType derivativeM = DerivativeType( ParametersDimension );
190 derivativeM.Fill( itk::NumericTraits<ITK_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 const TransformJacobianType & jacobian =
255 this->m_Transform->GetJacobian( inputPoint );
257 // Get the gradient by NearestNeighboorInterpolation:
258 // which is equivalent to round up the point components.
259 typedef typename OutputPointType::CoordRepType CoordRepType;
260 typedef itk::ContinuousIndex<CoordRepType,MovingImageType::ImageDimension>
261 MovingImageContinuousIndexType;
263 MovingImageContinuousIndexType tempIndex;
264 this->m_MovingImage->TransformPhysicalPointToContinuousIndex( transformedPoint, tempIndex );
266 typename MovingImageType::IndexType mappedIndex;
267 mappedIndex.CopyWithRound( tempIndex );
269 const GradientPixelType gradient =
270 this->GetGradientImage()->GetPixel( mappedIndex );
272 for(unsigned int par=0; par<ParametersDimension; par++) {
273 RealType sumF = itk::NumericTraits< RealType >::Zero;
274 RealType sumM = itk::NumericTraits< RealType >::Zero;
275 for(unsigned int dim=0; dim<dimension; dim++) {
276 const RealType differential = jacobian( dim, par ) * gradient[dim];
277 sumF += fixedValue * differential;
278 sumM += movingValue * differential;
279 if ( this->m_SubtractMean && this->m_NumberOfPixelsCounted > 0 ) {
280 sumF -= differential * sf / this->m_NumberOfPixelsCounted;
281 sumM -= differential * sm / this->m_NumberOfPixelsCounted;
284 derivativeF[par] += sumF;
285 derivativeM[par] += sumM;
292 if ( this->m_SubtractMean && this->m_NumberOfPixelsCounted > 0 ) {
293 sff -= ( sf * sf / this->m_NumberOfPixelsCounted );
294 smm -= ( sm * sm / this->m_NumberOfPixelsCounted );
295 sfm -= ( sf * sm / this->m_NumberOfPixelsCounted );
298 const RealType denom = -1.0 * vcl_sqrt(sff * smm );
300 if( this->m_NumberOfPixelsCounted > 0 && denom != 0.0) {
301 for(unsigned int i=0; i<ParametersDimension; i++) {
302 derivative[i] = ( derivativeF[i] - (sfm/smm)* derivativeM[i] ) / denom;
305 for(unsigned int i=0; i<ParametersDimension; i++) {
306 derivative[i] = itk::NumericTraits< MeasureType >::Zero;
314 * Get both the match Measure and theDerivative Measure
316 template <class TFixedImage, class TMovingImage>
318 NormalizedCorrelationImageToImageMetricFor3DBLUTFFD<TFixedImage,TMovingImage>
319 ::GetValueAndDerivative(const TransformParametersType & parameters,
320 MeasureType & value, DerivativeType & derivative) const
324 if( !this->GetGradientImage() ) {
325 itkExceptionMacro(<<"The gradient image is null, maybe you forgot to call Initialize()");
328 FixedImageConstPointer fixedImage = this->m_FixedImage;
331 itkExceptionMacro( << "Fixed image has not been assigned" );
334 const unsigned int dimension = FixedImageType::ImageDimension;
336 typedef itk::ImageRegionConstIteratorWithIndex<FixedImageType> FixedIteratorType;
338 FixedIteratorType ti( fixedImage, this->GetFixedImageRegion() );
340 typename FixedImageType::IndexType index;
342 this->m_NumberOfPixelsCounted = 0;
344 this->SetTransformParameters( parameters );
346 typedef typename itk::NumericTraits< MeasureType >::AccumulateType AccumulateType;
348 AccumulateType sff = itk::NumericTraits< AccumulateType >::Zero;
349 AccumulateType smm = itk::NumericTraits< AccumulateType >::Zero;
350 AccumulateType sfm = itk::NumericTraits< AccumulateType >::Zero;
351 AccumulateType sf = itk::NumericTraits< AccumulateType >::Zero;
352 AccumulateType sm = itk::NumericTraits< AccumulateType >::Zero;
354 const unsigned int ParametersDimension = this->GetNumberOfParameters();
355 derivative = DerivativeType( ParametersDimension );
356 derivative.Fill( itk::NumericTraits<ITK_TYPENAME DerivativeType::ValueType>::Zero );
358 DerivativeType derivativeF = DerivativeType( ParametersDimension );
359 derivativeF.Fill( itk::NumericTraits<ITK_TYPENAME DerivativeType::ValueType>::Zero );
361 DerivativeType derivativeM = DerivativeType( ParametersDimension );
362 derivativeM.Fill( itk::NumericTraits<ITK_TYPENAME DerivativeType::ValueType>::Zero );
364 DerivativeType derivativeM1 = DerivativeType( ParametersDimension );
365 derivativeM1.Fill( itk::NumericTraits<ITK_TYPENAME DerivativeType::ValueType>::Zero );
368 // First compute the sums
369 while(!ti.IsAtEnd()) {
371 index = ti.GetIndex();
373 InputPointType inputPoint;
374 fixedImage->TransformIndexToPhysicalPoint( index, inputPoint );
376 if( this->m_FixedImageMask && !this->m_FixedImageMask->IsInside( inputPoint ) ) {
381 OutputPointType transformedPoint = this->m_Transform->TransformPoint( inputPoint );
383 if( this->m_MovingImageMask && !this->m_MovingImageMask->IsInside( transformedPoint ) ) {
388 if( this->m_Interpolator->IsInsideBuffer( transformedPoint ) ) {
389 const RealType movingValue = this->m_Interpolator->Evaluate( transformedPoint );
390 const RealType fixedValue = ti.Get();
391 sff += fixedValue * fixedValue;
392 smm += movingValue * movingValue;
393 sfm += fixedValue * movingValue;
394 if ( this->m_SubtractMean ) {
398 this->m_NumberOfPixelsCounted++;
405 // Compute contributions to derivatives
407 while(!ti.IsAtEnd()) {
409 index = ti.GetIndex();
411 InputPointType inputPoint;
412 fixedImage->TransformIndexToPhysicalPoint( index, inputPoint );
414 if( this->m_FixedImageMask && !this->m_FixedImageMask->IsInside( inputPoint ) ) {
419 OutputPointType transformedPoint = this->m_Transform->TransformPoint( inputPoint );
421 if( this->m_MovingImageMask && !this->m_MovingImageMask->IsInside( transformedPoint ) ) {
426 if( this->m_Interpolator->IsInsideBuffer( transformedPoint ) ) {
427 const RealType movingValue = this->m_Interpolator->Evaluate( transformedPoint );
428 const RealType fixedValue = ti.Get();
430 const TransformJacobianType & jacobian =
431 this->m_Transform->GetJacobian( inputPoint );
433 // Get the gradient by NearestNeighboorInterpolation:
434 // which is equivalent to round up the point components.
435 typedef typename OutputPointType::CoordRepType CoordRepType;
436 typedef itk::ContinuousIndex<CoordRepType,MovingImageType::ImageDimension>
437 MovingImageContinuousIndexType;
439 MovingImageContinuousIndexType tempIndex;
440 this->m_MovingImage->TransformPhysicalPointToContinuousIndex( transformedPoint, tempIndex );
442 typename MovingImageType::IndexType mappedIndex;
443 mappedIndex.CopyWithRound( tempIndex );
445 const GradientPixelType gradient =
446 this->GetGradientImage()->GetPixel( mappedIndex );
448 for(unsigned int par=0; par<ParametersDimension; par++) {
449 RealType sumF = itk::NumericTraits< RealType >::Zero;
450 RealType sumM = itk::NumericTraits< RealType >::Zero;
451 for(unsigned int dim=0; dim<dimension; dim++) {
452 const RealType differential = jacobian( dim, par ) * gradient[dim];
453 sumF += fixedValue * differential;
454 sumM += movingValue * differential;
455 if ( this->m_SubtractMean && this->m_NumberOfPixelsCounted > 0 ) {
456 sumF -= differential * sf / this->m_NumberOfPixelsCounted;
457 sumM -= differential * sm / this->m_NumberOfPixelsCounted;
460 derivativeF[par] += sumF;
461 derivativeM[par] += sumM;
467 if ( this->m_SubtractMean && this->m_NumberOfPixelsCounted > 0 ) {
468 sff -= ( sf * sf / this->m_NumberOfPixelsCounted );
469 smm -= ( sm * sm / this->m_NumberOfPixelsCounted );
470 sfm -= ( sf * sm / this->m_NumberOfPixelsCounted );
473 const RealType denom = -1.0 * vcl_sqrt(sff * smm );
475 if( this->m_NumberOfPixelsCounted > 0 && denom != 0.0) {
476 for(unsigned int i=0; i<ParametersDimension; i++) {
477 derivative[i] = ( derivativeF[i] - (sfm/smm)* derivativeM[i] ) / denom;
481 for(unsigned int i=0; i<ParametersDimension; i++) {
482 derivative[i] = itk::NumericTraits< MeasureType >::Zero;
484 value = itk::NumericTraits< MeasureType >::Zero;
491 template < class TFixedImage, class TMovingImage>
493 NormalizedCorrelationImageToImageMetricFor3DBLUTFFD<TFixedImage,TMovingImage>
494 ::PrintSelf(std::ostream& os, itk::Indent indent) const
496 Superclass::PrintSelf(os, indent);
497 os << indent << "SubtractMean: " << m_SubtractMean << std::endl;
500 } // end namespace itk
505 #endif // _clitkNormalizedCorrelationImageToImageMetricFor3DBLUTFFD.txx