]> Creatis software - clitk.git/blob - registration/itkOptMeanSquaresImageToImageMetricFor3DBLUTFFD.txx
Merge branch 'master' into extentSimon
[clitk.git] / registration / itkOptMeanSquaresImageToImageMetricFor3DBLUTFFD.txx
1 /*=========================================================================
2   Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
3
4   Authors belong to:
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
8
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.
12
13   It is distributed under dual licence
14
15   - BSD        See included LICENSE.txt file
16   - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
17 ===========================================================================**/
18
19 /*=========================================================================
20
21   Program:   Insight Segmentation & Registration Toolkit
22   Module:    $RCSfile: itkOptMeanSquaresImageToImageMetricFor3DBLUTFFD.txx,v $
23   Language:  C++
24   Date:      $Date: 2010/06/14 17:32:07 $
25   Version:   $Revision: 1.1 $
26
27   Copyright (c) Insight Software Consortium. All rights reserved.
28   See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.
29
30      This software is distributed WITHOUT ANY WARRANTY; without even
31      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
32      PURPOSE.  See the above copyright notices for more information.
33
34 =========================================================================*/
35 #ifndef __itkOptMeanSquaresImageToImageMetricFor3DBLUTFFD_txx
36 #define __itkOptMeanSquaresImageToImageMetricFor3DBLUTFFD_txx
37
38 #include "itkOptMeanSquaresImageToImageMetricFor3DBLUTFFD.h"
39 #include "itkCovariantVector.h"
40 #include "itkImageRandomConstIteratorWithIndex.h"
41 #include "itkImageRegionConstIterator.h"
42 #include "itkImageRegionIterator.h"
43 #include "itkImageIterator.h"
44 #include "vnl/vnl_math.h"
45
46 namespace itk
47 {
48
49 /**
50  * Constructor
51  */
52 template < class TFixedImage, class TMovingImage >
53 MeanSquaresImageToImageMetricFor3DBLUTFFD<TFixedImage,TMovingImage>
54 ::MeanSquaresImageToImageMetricFor3DBLUTFFD()
55 {
56   this->SetComputeGradient(true);
57
58   m_ThreaderMSE = NULL;
59   m_ThreaderMSEDerivatives = NULL;
60   this->m_WithinThreadPreProcess = false;
61   this->m_WithinThreadPostProcess = false;
62
63   //  For backward compatibility, the default behavior is to use all the pixels
64   //  in the fixed image.
65   this->UseAllPixelsOn();
66 }
67
68 template < class TFixedImage, class TMovingImage >
69 MeanSquaresImageToImageMetricFor3DBLUTFFD<TFixedImage,TMovingImage>
70 ::~MeanSquaresImageToImageMetricFor3DBLUTFFD()
71 {
72   if(m_ThreaderMSE != NULL) {
73     delete [] m_ThreaderMSE;
74   }
75   m_ThreaderMSE = NULL;
76
77   if(m_ThreaderMSEDerivatives != NULL) {
78     delete [] m_ThreaderMSEDerivatives;
79   }
80   m_ThreaderMSEDerivatives = NULL;
81 }
82
83 /**
84  * Print out internal information about this class
85  */
86 template < class TFixedImage, class TMovingImage  >
87 void
88 MeanSquaresImageToImageMetricFor3DBLUTFFD<TFixedImage,TMovingImage>
89 ::PrintSelf(std::ostream& os, Indent indent) const
90 {
91
92   Superclass::PrintSelf(os, indent);
93
94 }
95
96
97 /**
98  * Initialize
99  */
100 template <class TFixedImage, class TMovingImage>
101 void
102 MeanSquaresImageToImageMetricFor3DBLUTFFD<TFixedImage,TMovingImage>
103 ::Initialize(void) throw ( ExceptionObject )
104 {
105
106   this->Superclass::Initialize();
107   this->Superclass::MultiThreadingInitialize();
108
109   if(m_ThreaderMSE != NULL) {
110     delete [] m_ThreaderMSE;
111   }
112   m_ThreaderMSE = new double[this->m_NumberOfThreads];
113
114   if(m_ThreaderMSEDerivatives != NULL) {
115     delete [] m_ThreaderMSEDerivatives;
116   }
117   m_ThreaderMSEDerivatives = new DerivativeType[this->m_NumberOfThreads];
118   for(unsigned int threadID=0; threadID<this->m_NumberOfThreads; threadID++) {
119     m_ThreaderMSEDerivatives[threadID].SetSize( this->m_NumberOfParameters );
120   }
121 }
122
123 template < class TFixedImage, class TMovingImage  >
124 inline bool
125 MeanSquaresImageToImageMetricFor3DBLUTFFD<TFixedImage,TMovingImage>
126 ::GetValueThreadProcessSample( unsigned int threadID,
127                                unsigned long fixedImageSample,
128                                const MovingImagePointType & itkNotUsed(mappedPoint),
129                                double movingImageValue) const
130 {
131   double diff = movingImageValue - this->m_FixedImageSamples[fixedImageSample].value;
132
133   m_ThreaderMSE[threadID] += diff*diff;
134
135   return true;
136 }
137
138 template < class TFixedImage, class TMovingImage  >
139 typename MeanSquaresImageToImageMetricFor3DBLUTFFD<TFixedImage,TMovingImage>
140 ::MeasureType
141 MeanSquaresImageToImageMetricFor3DBLUTFFD<TFixedImage,TMovingImage>
142 ::GetValue( const ParametersType & parameters ) const
143 {
144   itkDebugMacro("GetValue( " << parameters << " ) ");
145
146   if( !this->m_FixedImage ) {
147     itkExceptionMacro( << "Fixed image has not been assigned" );
148   }
149
150   memset( m_ThreaderMSE,
151           0,
152           this->m_NumberOfThreads * sizeof(MeasureType) );
153
154   // Set up the parameters in the transform
155   this->m_Transform->SetParameters( parameters );
156
157   // MUST BE CALLED TO INITIATE PROCESSING
158   this->GetValueMultiThreadedInitiate();
159
160   itkDebugMacro( "Ratio of voxels mapping into moving image buffer: "
161                  << this->m_NumberOfPixelsCounted << " / "
162                  << this->m_NumberOfFixedImageSamples
163                  << std::endl );
164
165   if( this->m_NumberOfPixelsCounted <
166       this->m_NumberOfFixedImageSamples / 4 ) {
167     itkExceptionMacro( "Too many samples map outside moving image buffer: "
168                        << this->m_NumberOfPixelsCounted << " / "
169                        << this->m_NumberOfFixedImageSamples
170                        << std::endl );
171   }
172
173   double mse = m_ThreaderMSE[0];
174   for(unsigned int t=1; t<this->m_NumberOfThreads; t++) {
175     mse += m_ThreaderMSE[t];
176   }
177   mse /= this->m_NumberOfPixelsCounted;
178
179   return mse;
180 }
181
182
183 template < class TFixedImage, class TMovingImage  >
184 inline bool
185 MeanSquaresImageToImageMetricFor3DBLUTFFD<TFixedImage,TMovingImage>
186 ::GetValueAndDerivativeThreadProcessSample( unsigned int threadID,
187     unsigned long fixedImageSample,
188     const MovingImagePointType & itkNotUsed(mappedPoint),
189     double movingImageValue,
190     const ImageDerivativesType &
191     movingImageGradientValue ) const
192 {
193   double diff = movingImageValue - this->m_FixedImageSamples[fixedImageSample].value;
194
195   m_ThreaderMSE[threadID] += diff*diff;
196
197   //JV
198   //FixedImagePointType fixedImagePoint = this->m_FixedImageSamples[fixedImageSample].point;
199
200   // Need to use one of the threader transforms if we're
201   // not in thread 0.
202   //
203   // Use a raw pointer here to avoid the overhead of smart pointers.
204   // For instance, Register and UnRegister have mutex locks around
205   // the reference counts.
206   TransformType* transform;
207
208   if (threadID > 0) {
209     transform = this->m_ThreaderTransform[threadID - 1];
210   } else {
211     transform = this->m_Transform;
212   }
213
214   // Jacobian should be evaluated at the unmapped (fixed image) point.
215   TransformJacobianType jacobian;
216   transform->ComputeJacobianWithRespectToParameters(this->m_FixedImageSamples[fixedImageSample].point, jacobian);
217   //double sum;
218   unsigned int par, dim;
219   for( par=0; par<this->m_NumberOfParameters; par+=3) {
220     //     double sum = 0.0;
221     //     for(unsigned int dim=0; dim<MovingImageDimension; dim++)
222     //       {
223     //       sum += 2.0 * diff * jacobian( dim, par ) * movingImageGradientValue[dim];
224     //       }
225     //     m_ThreaderMSEDerivatives[threadID][par] += sum;
226
227     // JV only for 3D BLUT FFD
228     if (jacobian( 0, par ) )
229       for( dim=0; dim<3; dim++)
230         m_ThreaderMSEDerivatives[threadID][par+dim  ]  += 2.0 * diff* jacobian( dim, par+dim   ) * movingImageGradientValue[dim];
231
232   }
233   return true;
234 }
235
236 /**
237  * Get the both Value and Derivative Measure
238  */
239 template < class TFixedImage, class TMovingImage  >
240 void
241 MeanSquaresImageToImageMetricFor3DBLUTFFD<TFixedImage,TMovingImage>
242 ::GetValueAndDerivative( const ParametersType & parameters,
243                          MeasureType & value,
244                          DerivativeType & derivative) const
245 {
246
247   if( !this->m_FixedImage ) {
248     itkExceptionMacro( << "Fixed image has not been assigned" );
249   }
250
251   // Set up the parameters in the transform
252   this->m_Transform->SetParameters( parameters );
253
254   // Reset the joint pdfs to zero
255   memset( m_ThreaderMSE,
256           0,
257           this->m_NumberOfThreads * sizeof(MeasureType) );
258
259   // Set output values to zero
260   if(derivative.GetSize() != this->m_NumberOfParameters) {
261     derivative = DerivativeType( this->m_NumberOfParameters );
262   }
263   memset( derivative.data_block(),
264           0,
265           this->m_NumberOfParameters * sizeof(double) );
266
267   for( unsigned int threadID = 0; threadID<this->m_NumberOfThreads; threadID++ ) {
268     memset( m_ThreaderMSEDerivatives[threadID].data_block(),
269             0,
270             this->m_NumberOfParameters * sizeof(double) );
271   }
272
273   // MUST BE CALLED TO INITIATE PROCESSING
274   this->GetValueAndDerivativeMultiThreadedInitiate();
275
276   itkDebugMacro( "Ratio of voxels mapping into moving image buffer: "
277                  << this->m_NumberOfPixelsCounted << " / "
278                  << this->m_NumberOfFixedImageSamples
279                  << std::endl );
280
281   if( this->m_NumberOfPixelsCounted <
282       this->m_NumberOfFixedImageSamples / 4 ) {
283     itkExceptionMacro( "Too many samples map outside moving image buffer: "
284                        << this->m_NumberOfPixelsCounted << " / "
285                        << this->m_NumberOfFixedImageSamples
286                        << std::endl );
287   }
288
289   value = 0;
290   for(unsigned int t=0; t<this->m_NumberOfThreads; t++) {
291     value += m_ThreaderMSE[t];
292     for(unsigned int parameter = 0; parameter < this->m_NumberOfParameters;
293         parameter++) {
294       derivative[parameter] += m_ThreaderMSEDerivatives[t][parameter];
295     }
296   }
297
298   value /= this->m_NumberOfPixelsCounted;
299   for(unsigned int parameter = 0; parameter < this->m_NumberOfParameters;
300       parameter++) {
301     derivative[parameter] /= this->m_NumberOfPixelsCounted;
302     // JV
303     //DD(parameter<<"\t"<<derivative[parameter]);
304   }
305
306 }
307
308
309 /**
310  * Get the match measure derivative
311  */
312 template < class TFixedImage, class TMovingImage  >
313 void
314 MeanSquaresImageToImageMetricFor3DBLUTFFD<TFixedImage,TMovingImage>
315 ::GetDerivative( const ParametersType & parameters,
316                  DerivativeType & derivative ) const
317 {
318   if( !this->m_FixedImage ) {
319     itkExceptionMacro( << "Fixed image has not been assigned" );
320   }
321
322   MeasureType value;
323   // call the combined version
324   this->GetValueAndDerivative( parameters, value, derivative );
325 }
326
327 } // end namespace itk
328
329
330 #endif