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