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 ===========================================================================**/
18 #ifndef __clitkMultipleBSplineDeformableTransformInitializer_txx
19 #define __clitkMultipleBSplineDeformableTransformInitializer_txx
20 #include "clitkMultipleBSplineDeformableTransformInitializer.h"
25 template < class TTransform, class TImage >
26 MultipleBSplineDeformableTransformInitializer<TTransform, TImage >
27 ::MultipleBSplineDeformableTransformInitializer()
29 this->m_NumberOfControlPointsInsideTheImage.Fill( 5 );
30 this->m_ControlPointSpacing.Fill(64.);
31 this->m_ChosenSpacing.Fill(64.);
32 m_NumberOfControlPointsIsGiven=false;
33 m_ControlPointSpacingIsGiven=false;
34 m_TransformRegionIsGiven=false;
35 m_SamplingFactorIsGiven=false;
36 m_SplineOrders.Fill(3);
40 template < class TTransform, class TImage >
42 MultipleBSplineDeformableTransformInitializer<TTransform, TImage >
43 ::InitializeTransform()
46 // The image is required for the region and spacing
49 itkExceptionMacro( "Reference Image has not been set" );
53 // A pointer to the transform is required
54 if( ! this->m_Transform )
56 itkExceptionMacro( "Transform has not been set" );
60 // If the image come from a filter, then update that filter.
61 if( this->m_Image->GetSource() )
63 this->m_Image->GetSource()->Update();
67 //--------------------------------------
68 // Spacing & Size on image
69 //--------------------------------------
70 SpacingType fixedImageSpacing = m_Image->GetSpacing();
71 SizeType fixedImageSize=m_Image->GetLargestPossibleRegion().GetSize();
72 typename RegionType::SizeType gridBorderSize;
73 typename RegionType::SizeType totalGridSize;
75 // Only spacing given: adjust if necessary
76 if (m_ControlPointSpacingIsGiven && !m_NumberOfControlPointsIsGiven)
78 for(unsigned int r=0; r<InputDimension; r++)
81 m_ChosenSpacing[r]= m_ControlPointSpacing[r];
82 m_ControlPointSpacing[r]= ( itk::Math::Round<double>(m_ChosenSpacing[r]/fixedImageSpacing[r]) *fixedImageSpacing[r] ) ;
83 m_NumberOfControlPointsInsideTheImage[r] = ceil( (double)fixedImageSize[r]*fixedImageSpacing[r]/ m_ControlPointSpacing[r] );
84 if ( ( ceil( (double)fixedImageSize[r]*fixedImageSpacing[r]/ m_ControlPointSpacing[r] ) )
85 == ( (double)fixedImageSize[r]*fixedImageSpacing[r]/ m_ControlPointSpacing[r] ) )
87 m_NumberOfControlPointsInsideTheImage[r] +=1;
88 DD("Adding control point");
93 // Only number of CP given: adjust if necessary
95 else if (!m_ControlPointSpacingIsGiven && m_NumberOfControlPointsIsGiven)
97 for(unsigned int r=0; r<InputDimension; r++)
99 m_ChosenSpacing[r]=fixedImageSpacing[r]*( (double)(fixedImageSize[r]) /
100 (double)(m_NumberOfControlPointsInsideTheImage[r]) );
101 m_ControlPointSpacing[r]= fixedImageSpacing[r]* ceil( (double)(fixedImageSize[r] - 1) /
102 (double)(m_NumberOfControlPointsInsideTheImage[r] - 1) );
106 // Both or none of Spacing and number of CP given: no adjustment adjust, just warnings
109 for(unsigned int r=0; r<InputDimension; r++)
111 m_ChosenSpacing[r]= m_ControlPointSpacing[r];
112 if (m_NumberOfControlPointsInsideTheImage[r]*m_ControlPointSpacing[r]< fixedImageSize[r]*fixedImageSpacing[r])
114 std::cout<<"WARNING: Specified control point region ("<<m_NumberOfControlPointsInsideTheImage[r]*m_ControlPointSpacing[r]
115 <<"mm) does not cover the fixed image region ("<< fixedImageSize[r]*fixedImageSpacing[r]
116 <<"mm) for dimension "<<r<<"!" <<std::endl
117 <<"Specify only --spacing or --control for automatic adjustment..."<<std::endl;
119 if ( fmod(m_ControlPointSpacing[r], fixedImageSpacing[r]) )
121 std::cout<<"WARNING: Specified control point spacing for dimension "<<r
122 <<" does not allow exact representation of BLUT FFD!"<<std::endl
123 <<"Spacing ratio is non-integer: "<<m_ControlPointSpacing[r]/ fixedImageSpacing[r]<<std::endl
124 <<"Specify only --spacing or --control for automatic adjustment..."<<std::endl;
129 if (m_Verbose) std::cout<<"The chosen control point spacing "<<m_ChosenSpacing<<"..."<<std::endl;
130 if (m_Verbose) std::cout<<"The control points spacing was adapted to "<<m_ControlPointSpacing<<"..."<<std::endl;
131 if (m_Verbose) std::cout<<"The number of (internal) control points is "<<m_NumberOfControlPointsInsideTheImage<<"..."<<std::endl;
134 //--------------------------------------
136 //--------------------------------------
137 for(unsigned int r=0; r<InputDimension; r++) gridBorderSize[r]=m_SplineOrders[r]; // Border for spline order = 3 ( 1 lower, 2 upper )
138 totalGridSize = m_NumberOfControlPointsInsideTheImage + gridBorderSize;
139 if (m_Verbose) std::cout<<"The total control point grid size was set to "<<totalGridSize<<"..."<<std::endl;
140 RegionType gridRegion;
141 gridRegion.SetSize(totalGridSize);
144 //--------------------------------------
146 //--------------------------------------
147 typedef typename TransformType::OriginType OriginType;
148 OriginType fixedImageOrigin, gridOrigin;
150 // In case of non-zero index
151 m_Image->TransformIndexToPhysicalPoint(m_Image->GetLargestPossibleRegion().GetIndex(),fixedImageOrigin);
152 typename ImageType::DirectionType gridDirection = m_Image->GetDirection();
155 // Shift depends on order
156 for(unsigned int r=0; r<InputDimension; r++)
158 orderShift[r] = m_SplineOrders[r] / 2;
159 gridOrigin[r] = fixedImageOrigin[r]- (double) orderShift[r]* m_ControlPointSpacing[r];
161 if (m_Verbose) std::cout<<"The control point grid origin was set to "<<gridOrigin<<"..."<<std::endl;
164 //--------------------------------------
165 // LUT sampling factors
166 //--------------------------------------
167 for (unsigned int i=0; i< InputDimension; i++)
169 if (m_Verbose) std::cout<<"For dimension "<<i<<", the ideal sampling factor (if integer) is a multitude of "
170 << m_ControlPointSpacing[i]/ fixedImageSpacing[i]<<"..."<<std::endl;
171 if ( !m_SamplingFactorIsGiven) m_SamplingFactors[i]= (int) ( m_ControlPointSpacing[i]/ fixedImageSpacing[i]);
172 if (m_Verbose) std::cout<<"Setting sampling factor "<<i<<" to "<<m_SamplingFactors[i]<<"..."<<std::endl;
176 //--------------------------------------
178 //--------------------------------------
179 this->m_Transform->SetSplineOrders(m_SplineOrders);
180 this->m_Transform->SetGridRegion( gridRegion );
181 this->m_Transform->SetGridOrigin( gridOrigin );
182 this->m_Transform->SetGridSpacing( m_ControlPointSpacing );
183 this->m_Transform->SetGridDirection( gridDirection );
184 this->m_Transform->SetLUTSamplingFactors(m_SamplingFactors);
188 template < class TTransform, class TImage >
190 MultipleBSplineDeformableTransformInitializer<TTransform, TImage >
191 ::SetInitialParameters( const std::string& s, ParametersType& params)
193 //---------------------------------------
194 // Read Initial parameters
195 //---------------------------------------
196 typedef itk::ImageFileReader<CoefficientImageType> CoefficientReaderType;
197 typename CoefficientReaderType::Pointer coeffReader = CoefficientReaderType::New();
198 std::vector<typename CoefficientImageType::Pointer> coefficientImages;
199 unsigned nLabels = m_Transform->GetnLabels();
200 coefficientImages.resize(nLabels);
202 int dotpos = s.length() - 1;
203 while (dotpos >= 0 && s[dotpos] != '.')
206 for (unsigned i = 0; i < nLabels; ++i)
208 std::ostringstream osfname;
209 osfname << s.substr(0, dotpos) << '_' << i << s.substr(dotpos);
210 coeffReader->SetFileName(osfname.str());
212 std::cout << "Reading initial coefficients from file: " << osfname.str() << "..." << std::endl;
213 coeffReader->Update();
214 coefficientImages[i] = coeffReader->GetOutput();
216 this->SetInitialParameters(coefficientImages, params);
219 template < class TTransform, class TImage >
221 MultipleBSplineDeformableTransformInitializer<TTransform, TImage >
222 ::SetInitialParameters(std::vector<typename CoefficientImageType::Pointer> coefficientImages, ParametersType& params)
225 m_Parameters=¶ms;
228 typedef ResampleBSplineDeformableTransformImageFilter<CoefficientImageType,CoefficientImageType> ResamplerType;
229 typename ResamplerType::Pointer resampler;
231 for (unsigned l = 0; l < coefficientImages.size(); ++l)
233 typename ResamplerType::Pointer resampler = ResamplerType::New();
234 resampler->SetInput(coefficientImages[l]);
235 resampler->SetOutputParametersFromImage(m_Transform->GetCoefficientImages()[l]);
237 std::cout << "Resampling initial coefficients..." << std::endl;
240 // Copy parameters into the existing array, I know its crappy
241 typedef itk::ImageRegionConstIterator<CoefficientImageType> Iterator;
242 Iterator it(resampler->GetOutput(), resampler->GetOutput()->GetLargestPossibleRegion());
244 while (!it.IsAtEnd())
246 for (unsigned int j = 0; j < InputDimension; ++j)
247 params[i + j] = it.Get()[j];
253 // JV pass the reference to the array !!
254 this->m_Transform->SetParameters(params);