]> Creatis software - clitk.git/blob - registration/itkOptMeanSquaresImageToImageMetricFor3DBLUTFFD.txx
af1c98645af36d2b0483d6fc5226eafad1e49a67
[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)
104 {
105
106   this->Superclass::Initialize();
107   this->Superclass::MultiThreadingInitialize();
108
109   if(m_ThreaderMSE != NULL) {
110     delete [] m_ThreaderMSE;
111   }
112 #if ITK_VERSION_MAJOR <= 4
113   m_ThreaderMSE = new double[this->m_NumberOfThreads];
114 #else
115   m_ThreaderMSE = new double[this->m_NumberOfWorkUnits];
116 #endif
117
118   if(m_ThreaderMSEDerivatives != NULL) {
119     delete [] m_ThreaderMSEDerivatives;
120   }
121 #if ITK_VERSION_MAJOR <= 4
122   m_ThreaderMSEDerivatives = new DerivativeType[this->m_NumberOfThreads];
123   for(unsigned int threadID=0; threadID<this->m_NumberOfThreads; threadID++) {
124 #else
125   m_ThreaderMSEDerivatives = new DerivativeType[this->m_NumberOfWorkUnits];
126   for(unsigned int threadID=0; threadID<this->m_NumberOfWorkUnits; threadID++) {
127 #endif
128     m_ThreaderMSEDerivatives[threadID].SetSize( this->m_NumberOfParameters );
129   }
130 }
131
132 template < class TFixedImage, class TMovingImage  >
133 inline bool
134 MeanSquaresImageToImageMetricFor3DBLUTFFD<TFixedImage,TMovingImage>
135 ::GetValueThreadProcessSample( unsigned int threadID,
136                                unsigned long fixedImageSample,
137                                const MovingImagePointType & itkNotUsed(mappedPoint),
138                                double movingImageValue) const
139 {
140   double diff = movingImageValue - this->m_FixedImageSamples[fixedImageSample].value;
141
142   m_ThreaderMSE[threadID] += diff*diff;
143
144   return true;
145 }
146
147 template < class TFixedImage, class TMovingImage  >
148 typename MeanSquaresImageToImageMetricFor3DBLUTFFD<TFixedImage,TMovingImage>
149 ::MeasureType
150 MeanSquaresImageToImageMetricFor3DBLUTFFD<TFixedImage,TMovingImage>
151 ::GetValue( const ParametersType & parameters ) const
152 {
153   itkDebugMacro("GetValue( " << parameters << " ) ");
154
155   if( !this->m_FixedImage ) {
156     itkExceptionMacro( << "Fixed image has not been assigned" );
157   }
158
159 #if ITK_VERSION_MAJOR <= 4
160   memset( m_ThreaderMSE, 0, this->m_NumberOfThreads * sizeof(MeasureType) );
161 #else
162   memset( m_ThreaderMSE, 0, this->m_NumberOfWorkUnits * sizeof(MeasureType) );
163 #endif
164
165   // Set up the parameters in the transform
166   this->m_Transform->SetParameters( parameters );
167
168   // MUST BE CALLED TO INITIATE PROCESSING
169   this->GetValueMultiThreadedInitiate();
170
171   itkDebugMacro( "Ratio of voxels mapping into moving image buffer: "
172                  << this->m_NumberOfPixelsCounted << " / "
173                  << this->m_NumberOfFixedImageSamples
174                  << std::endl );
175
176   if( this->m_NumberOfPixelsCounted <
177       this->m_NumberOfFixedImageSamples / 4 ) {
178     itkExceptionMacro( "Too many samples map outside moving image buffer: "
179                        << this->m_NumberOfPixelsCounted << " / "
180                        << this->m_NumberOfFixedImageSamples
181                        << std::endl );
182   }
183
184   double mse = m_ThreaderMSE[0];
185 #if ITK_VERSION_MAJOR <= 4
186   for(unsigned int t=1; t<this->m_NumberOfThreads; t++) {
187 #else
188   for(unsigned int t=1; t<this->m_NumberOfWorkUnits; t++) {
189 #endif
190     mse += m_ThreaderMSE[t];
191   }
192   mse /= this->m_NumberOfPixelsCounted;
193
194   return mse;
195 }
196
197
198 template < class TFixedImage, class TMovingImage  >
199 inline bool
200 MeanSquaresImageToImageMetricFor3DBLUTFFD<TFixedImage,TMovingImage>
201 ::GetValueAndDerivativeThreadProcessSample( unsigned int threadID,
202     unsigned long fixedImageSample,
203     const MovingImagePointType & itkNotUsed(mappedPoint),
204     double movingImageValue,
205     const ImageDerivativesType &
206     movingImageGradientValue ) const
207 {
208   double diff = movingImageValue - this->m_FixedImageSamples[fixedImageSample].value;
209
210   m_ThreaderMSE[threadID] += diff*diff;
211
212   //JV
213   //FixedImagePointType fixedImagePoint = this->m_FixedImageSamples[fixedImageSample].point;
214
215   // Need to use one of the threader transforms if we're
216   // not in thread 0.
217   //
218   // Use a raw pointer here to avoid the overhead of smart pointers.
219   // For instance, Register and UnRegister have mutex locks around
220   // the reference counts.
221   TransformType* transform;
222
223   if (threadID > 0) {
224     transform = this->m_ThreaderTransform[threadID - 1];
225   } else {
226     transform = this->m_Transform;
227   }
228
229   // Jacobian should be evaluated at the unmapped (fixed image) point.
230   TransformJacobianType jacobian;
231   transform->ComputeJacobianWithRespectToParameters(this->m_FixedImageSamples[fixedImageSample].point, jacobian);
232   //double sum;
233   unsigned int par, dim;
234   for( par=0; par<this->m_NumberOfParameters; par+=3) {
235     //     double sum = 0.0;
236     //     for(unsigned int dim=0; dim<MovingImageDimension; dim++)
237     //       {
238     //       sum += 2.0 * diff * jacobian( dim, par ) * movingImageGradientValue[dim];
239     //       }
240     //     m_ThreaderMSEDerivatives[threadID][par] += sum;
241
242     // JV only for 3D BLUT FFD
243     if (jacobian( 0, par ) )
244       for( dim=0; dim<3; dim++)
245         m_ThreaderMSEDerivatives[threadID][par+dim  ]  += 2.0 * diff* jacobian( dim, par+dim   ) * movingImageGradientValue[dim];
246
247   }
248   return true;
249 }
250
251 /**
252  * Get the both Value and Derivative Measure
253  */
254 template < class TFixedImage, class TMovingImage  >
255 void
256 MeanSquaresImageToImageMetricFor3DBLUTFFD<TFixedImage,TMovingImage>
257 ::GetValueAndDerivative( const ParametersType & parameters,
258                          MeasureType & value,
259                          DerivativeType & derivative) const
260 {
261
262   if( !this->m_FixedImage ) {
263     itkExceptionMacro( << "Fixed image has not been assigned" );
264   }
265
266   // Set up the parameters in the transform
267   this->m_Transform->SetParameters( parameters );
268
269   // Reset the joint pdfs to zero
270 #if ITK_VERSION_MAJOR <= 4
271   memset( m_ThreaderMSE, 0, this->m_NumberOfThreads * sizeof(MeasureType) );
272 #else
273   memset( m_ThreaderMSE, 0, this->m_NumberOfWorkUnits * sizeof(MeasureType) );
274 #endif
275
276   // Set output values to zero
277   if(derivative.GetSize() != this->m_NumberOfParameters) {
278     derivative = DerivativeType( this->m_NumberOfParameters );
279   }
280   memset( derivative.data_block(),
281           0,
282           this->m_NumberOfParameters * sizeof(double) );
283
284 #if ITK_VERSION_MAJOR <= 4
285   for( unsigned int threadID = 0; threadID<this->m_NumberOfThreads; threadID++ ) {
286 #else
287   for( unsigned int threadID = 0; threadID<this->m_NumberOfWorkUnits; threadID++ ) {
288 #endif
289     memset( m_ThreaderMSEDerivatives[threadID].data_block(),
290             0,
291             this->m_NumberOfParameters * sizeof(double) );
292   }
293
294   // MUST BE CALLED TO INITIATE PROCESSING
295   this->GetValueAndDerivativeMultiThreadedInitiate();
296
297   itkDebugMacro( "Ratio of voxels mapping into moving image buffer: "
298                  << this->m_NumberOfPixelsCounted << " / "
299                  << this->m_NumberOfFixedImageSamples
300                  << std::endl );
301
302   if( this->m_NumberOfPixelsCounted <
303       this->m_NumberOfFixedImageSamples / 4 ) {
304     itkExceptionMacro( "Too many samples map outside moving image buffer: "
305                        << this->m_NumberOfPixelsCounted << " / "
306                        << this->m_NumberOfFixedImageSamples
307                        << std::endl );
308   }
309
310   value = 0;
311 #if ITK_VERSION_MAJOR <= 4
312   for(unsigned int t=0; t<this->m_NumberOfThreads; t++) {
313 #else
314   for(unsigned int t=0; t<this->m_NumberOfWorkUnits; t++) {
315 #endif
316     value += m_ThreaderMSE[t];
317     for(unsigned int parameter = 0; parameter < this->m_NumberOfParameters;
318         parameter++) {
319       derivative[parameter] += m_ThreaderMSEDerivatives[t][parameter];
320     }
321   }
322
323   value /= this->m_NumberOfPixelsCounted;
324   for(unsigned int parameter = 0; parameter < this->m_NumberOfParameters;
325       parameter++) {
326     derivative[parameter] /= this->m_NumberOfPixelsCounted;
327     // JV
328     //DD(parameter<<"\t"<<derivative[parameter]);
329   }
330
331 }
332
333
334 /**
335  * Get the match measure derivative
336  */
337 template < class TFixedImage, class TMovingImage  >
338 void
339 MeanSquaresImageToImageMetricFor3DBLUTFFD<TFixedImage,TMovingImage>
340 ::GetDerivative( const ParametersType & parameters,
341                  DerivativeType & derivative ) const
342 {
343   if( !this->m_FixedImage ) {
344     itkExceptionMacro( << "Fixed image has not been assigned" );
345   }
346
347   MeasureType value;
348   // call the combined version
349   this->GetValueAndDerivative( parameters, value, derivative );
350 }
351
352 } // end namespace itk
353
354
355 #endif