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 /*=========================================================================
21 Program: Insight Segmentation & Registration Toolkit
22 Module: $RCSfile: itkOptMeanSquaresImageToImageMetricFor3DBLUTFFD.txx,v $
24 Date: $Date: 2010/06/14 17:32:07 $
25 Version: $Revision: 1.1 $
27 Copyright (c) Insight Software Consortium. All rights reserved.
28 See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.
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.
34 =========================================================================*/
35 #ifndef __itkOptMeanSquaresImageToImageMetricFor3DBLUTFFD_txx
36 #define __itkOptMeanSquaresImageToImageMetricFor3DBLUTFFD_txx
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"
52 template < class TFixedImage, class TMovingImage >
53 MeanSquaresImageToImageMetricFor3DBLUTFFD<TFixedImage,TMovingImage>
54 ::MeanSquaresImageToImageMetricFor3DBLUTFFD()
56 this->SetComputeGradient(true);
59 m_ThreaderMSEDerivatives = NULL;
60 this->m_WithinThreadPreProcess = false;
61 this->m_WithinThreadPostProcess = false;
63 // For backward compatibility, the default behavior is to use all the pixels
64 // in the fixed image.
65 this->UseAllPixelsOn();
68 template < class TFixedImage, class TMovingImage >
69 MeanSquaresImageToImageMetricFor3DBLUTFFD<TFixedImage,TMovingImage>
70 ::~MeanSquaresImageToImageMetricFor3DBLUTFFD()
72 if(m_ThreaderMSE != NULL) {
73 delete [] m_ThreaderMSE;
77 if(m_ThreaderMSEDerivatives != NULL) {
78 delete [] m_ThreaderMSEDerivatives;
80 m_ThreaderMSEDerivatives = NULL;
84 * Print out internal information about this class
86 template < class TFixedImage, class TMovingImage >
88 MeanSquaresImageToImageMetricFor3DBLUTFFD<TFixedImage,TMovingImage>
89 ::PrintSelf(std::ostream& os, Indent indent) const
92 Superclass::PrintSelf(os, indent);
100 template <class TFixedImage, class TMovingImage>
102 MeanSquaresImageToImageMetricFor3DBLUTFFD<TFixedImage,TMovingImage>
103 ::Initialize(void) throw ( ExceptionObject )
106 this->Superclass::Initialize();
107 this->Superclass::MultiThreadingInitialize();
109 if(m_ThreaderMSE != NULL) {
110 delete [] m_ThreaderMSE;
112 m_ThreaderMSE = new double[this->m_NumberOfThreads];
114 if(m_ThreaderMSEDerivatives != NULL) {
115 delete [] m_ThreaderMSEDerivatives;
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 );
123 template < class TFixedImage, class TMovingImage >
125 MeanSquaresImageToImageMetricFor3DBLUTFFD<TFixedImage,TMovingImage>
126 ::GetValueThreadProcessSample( unsigned int threadID,
127 unsigned long fixedImageSample,
128 const MovingImagePointType & itkNotUsed(mappedPoint),
129 double movingImageValue) const
131 double diff = movingImageValue - this->m_FixedImageSamples[fixedImageSample].value;
133 m_ThreaderMSE[threadID] += diff*diff;
138 template < class TFixedImage, class TMovingImage >
139 typename MeanSquaresImageToImageMetricFor3DBLUTFFD<TFixedImage,TMovingImage>
141 MeanSquaresImageToImageMetricFor3DBLUTFFD<TFixedImage,TMovingImage>
142 ::GetValue( const ParametersType & parameters ) const
144 itkDebugMacro("GetValue( " << parameters << " ) ");
146 if( !this->m_FixedImage ) {
147 itkExceptionMacro( << "Fixed image has not been assigned" );
150 memset( m_ThreaderMSE,
152 this->m_NumberOfThreads * sizeof(MeasureType) );
154 // Set up the parameters in the transform
155 this->m_Transform->SetParameters( parameters );
156 #if ITK_VERSION_MAJOR < 4
157 this->m_Parameters = parameters;
160 // MUST BE CALLED TO INITIATE PROCESSING
161 this->GetValueMultiThreadedInitiate();
163 itkDebugMacro( "Ratio of voxels mapping into moving image buffer: "
164 << this->m_NumberOfPixelsCounted << " / "
165 << this->m_NumberOfFixedImageSamples
168 if( this->m_NumberOfPixelsCounted <
169 this->m_NumberOfFixedImageSamples / 4 ) {
170 itkExceptionMacro( "Too many samples map outside moving image buffer: "
171 << this->m_NumberOfPixelsCounted << " / "
172 << this->m_NumberOfFixedImageSamples
176 double mse = m_ThreaderMSE[0];
177 for(unsigned int t=1; t<this->m_NumberOfThreads; t++) {
178 mse += m_ThreaderMSE[t];
180 mse /= this->m_NumberOfPixelsCounted;
186 template < class TFixedImage, class TMovingImage >
188 MeanSquaresImageToImageMetricFor3DBLUTFFD<TFixedImage,TMovingImage>
189 ::GetValueAndDerivativeThreadProcessSample( unsigned int threadID,
190 unsigned long fixedImageSample,
191 const MovingImagePointType & itkNotUsed(mappedPoint),
192 double movingImageValue,
193 const ImageDerivativesType &
194 movingImageGradientValue ) const
196 double diff = movingImageValue - this->m_FixedImageSamples[fixedImageSample].value;
198 m_ThreaderMSE[threadID] += diff*diff;
201 //FixedImagePointType fixedImagePoint = this->m_FixedImageSamples[fixedImageSample].point;
203 // Need to use one of the threader transforms if we're
206 // Use a raw pointer here to avoid the overhead of smart pointers.
207 // For instance, Register and UnRegister have mutex locks around
208 // the reference counts.
209 TransformType* transform;
212 transform = this->m_ThreaderTransform[threadID - 1];
214 transform = this->m_Transform;
217 // Jacobian should be evaluated at the unmapped (fixed image) point.
218 #if ITK_VERSION_MAJOR >= 4
219 TransformJacobianType jacobian;
220 transform->ComputeJacobianWithRespectToParameters(this->m_FixedImageSamples[fixedImageSample].point, jacobian);
222 const TransformJacobianType & jacobian = transform ->GetJacobian( this->m_FixedImageSamples[fixedImageSample].point );
225 unsigned int par, dim;
226 for( par=0; par<this->m_NumberOfParameters; par+=3) {
228 // for(unsigned int dim=0; dim<MovingImageDimension; dim++)
230 // sum += 2.0 * diff * jacobian( dim, par ) * movingImageGradientValue[dim];
232 // m_ThreaderMSEDerivatives[threadID][par] += sum;
234 // JV only for 3D BLUT FFD
235 if (jacobian( 0, par ) )
236 for( dim=0; dim<3; dim++)
237 m_ThreaderMSEDerivatives[threadID][par+dim ] += 2.0 * diff* jacobian( dim, par+dim ) * movingImageGradientValue[dim];
244 * Get the both Value and Derivative Measure
246 template < class TFixedImage, class TMovingImage >
248 MeanSquaresImageToImageMetricFor3DBLUTFFD<TFixedImage,TMovingImage>
249 ::GetValueAndDerivative( const ParametersType & parameters,
251 DerivativeType & derivative) const
254 if( !this->m_FixedImage ) {
255 itkExceptionMacro( << "Fixed image has not been assigned" );
258 // Set up the parameters in the transform
259 this->m_Transform->SetParameters( parameters );
260 #if ITK_VERSION_MAJOR < 4
261 this->m_Parameters = parameters;
264 // Reset the joint pdfs to zero
265 memset( m_ThreaderMSE,
267 this->m_NumberOfThreads * sizeof(MeasureType) );
269 // Set output values to zero
270 if(derivative.GetSize() != this->m_NumberOfParameters) {
271 derivative = DerivativeType( this->m_NumberOfParameters );
273 memset( derivative.data_block(),
275 this->m_NumberOfParameters * sizeof(double) );
277 for( unsigned int threadID = 0; threadID<this->m_NumberOfThreads; threadID++ ) {
278 memset( m_ThreaderMSEDerivatives[threadID].data_block(),
280 this->m_NumberOfParameters * sizeof(double) );
283 // MUST BE CALLED TO INITIATE PROCESSING
284 this->GetValueAndDerivativeMultiThreadedInitiate();
286 itkDebugMacro( "Ratio of voxels mapping into moving image buffer: "
287 << this->m_NumberOfPixelsCounted << " / "
288 << this->m_NumberOfFixedImageSamples
291 if( this->m_NumberOfPixelsCounted <
292 this->m_NumberOfFixedImageSamples / 4 ) {
293 itkExceptionMacro( "Too many samples map outside moving image buffer: "
294 << this->m_NumberOfPixelsCounted << " / "
295 << this->m_NumberOfFixedImageSamples
300 for(unsigned int t=0; t<this->m_NumberOfThreads; t++) {
301 value += m_ThreaderMSE[t];
302 for(unsigned int parameter = 0; parameter < this->m_NumberOfParameters;
304 derivative[parameter] += m_ThreaderMSEDerivatives[t][parameter];
308 value /= this->m_NumberOfPixelsCounted;
309 for(unsigned int parameter = 0; parameter < this->m_NumberOfParameters;
311 derivative[parameter] /= this->m_NumberOfPixelsCounted;
313 //DD(parameter<<"\t"<<derivative[parameter]);
320 * Get the match measure derivative
322 template < class TFixedImage, class TMovingImage >
324 MeanSquaresImageToImageMetricFor3DBLUTFFD<TFixedImage,TMovingImage>
325 ::GetDerivative( const ParametersType & parameters,
326 DerivativeType & derivative ) const
328 if( !this->m_FixedImage ) {
329 itkExceptionMacro( << "Fixed image has not been assigned" );
333 // call the combined version
334 this->GetValueAndDerivative( parameters, value, derivative );
337 } // end namespace itk