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 clitkAffineTransformGenericFilter_txx
19 #define clitkAffineTransformGenericFilter_txx
24 #include <itkCenteredEuler3DTransform.h>
25 #include <itkRecursiveGaussianImageFilter.h>
26 #include "clitkElastix.h"
27 #include "clitkResampleImageWithOptionsFilter.h"
32 //-----------------------------------------------------------
34 //-----------------------------------------------------------
35 template<class args_info_type>
36 AffineTransformGenericFilter<args_info_type>::AffineTransformGenericFilter()
41 //-------------------------------------------------------------------
44 //-----------------------------------------------------------
46 //-----------------------------------------------------------
47 template<class args_info_type>
48 void AffineTransformGenericFilter<args_info_type>::Update()
50 // Read the Dimension and PixelType
51 int Dimension, Components;
52 std::string PixelType;
53 ReadImageDimensionAndPixelType(m_InputFileName, Dimension, PixelType, Components);
56 if(Dimension==2) UpdateWithDim<2>(PixelType, Components);
58 if(Dimension==3) UpdateWithDim<3>(PixelType, Components);
59 else if (Dimension==4)UpdateWithDim<4>(PixelType, Components);
61 std::cout<<"Error, Only for 2, 3 or 4 Dimensions!!!"<<std::endl ;
65 //-------------------------------------------------------------------
68 //-------------------------------------------------------------------
69 // Update with the number of dimensions
70 //-------------------------------------------------------------------
71 template<class args_info_type>
72 template<unsigned int Dimension>
74 AffineTransformGenericFilter<args_info_type>::UpdateWithDim(std::string PixelType, int Components)
76 if (m_Verbose) std::cout << "Image was detected to be "<<Dimension<<"D and "<<Components<<" component(s) of "<< PixelType<<"..."<<std::endl;
79 if(PixelType == "short") {
80 if (m_Verbose) std::cout << "Launching filter in "<< Dimension <<"D and signed short..." << std::endl;
81 UpdateWithDimAndPixelType<Dimension, signed short>();
83 else if(PixelType == "unsigned_short"){
84 if (m_Verbose) std::cout << "Launching filter in "<< Dimension <<"D and unsigned_short..." << std::endl;
85 UpdateWithDimAndPixelType<Dimension, unsigned short>();
88 else if (PixelType == "unsigned_char") {
89 if (m_Verbose) std::cout << "Launching filter in "<< Dimension <<"D and unsigned_char..." << std::endl;
90 UpdateWithDimAndPixelType<Dimension, unsigned char>();
93 // else if (PixelType == "char"){
94 // if (m_Verbose) std::cout << "Launching filter in "<< Dimension <<"D and signed_char..." << std::endl;
95 // UpdateWithDimAndPixelType<Dimension, signed char>();
98 if (m_Verbose) std::cout << "Launching filter in "<< Dimension <<"D and float..." << std::endl;
99 UpdateWithDimAndPixelType<Dimension, float>();
103 else if (Components==3) {
104 if (m_Verbose) std::cout << "Launching transform in "<< Dimension <<"D and 3D float (DVF)" << std::endl;
105 UpdateWithDimAndVectorType<Dimension, itk::Vector<float, Dimension> >();
108 else std::cerr<<"Number of components is "<<Components<<", not supported!"<<std::endl;
111 //-------------------------------------------------------------------
114 //-------------------------------------------------------------------
115 // Compute updated bounding box
116 //-------------------------------------------------------------------
117 template<class args_info_type>
119 AffineTransformGenericFilter<args_info_type>::ComputeSize(vnl_vector<double> inputSize, vnl_matrix<double> transformationMatrix, bool returnMin)
121 //Compute input corners
122 int Dimension = inputSize.size();
123 vnl_matrix<double> vnlOutputSize(std::pow(2, Dimension), Dimension);
124 vnlOutputSize.fill(0);
125 if (Dimension == 2) {
126 for(unsigned int i=0; i< Dimension; i++)
127 vnlOutputSize[3][i] = inputSize[i];
128 vnlOutputSize[1][0] = inputSize[0];
129 vnlOutputSize[2][1] = inputSize[1];
130 } else if (Dimension == 3) {
131 for(unsigned int i=0; i< Dimension; i++)
132 vnlOutputSize[7][i] = inputSize[i];
133 vnlOutputSize[1][0] = inputSize[0];
134 vnlOutputSize[2][1] = inputSize[1];
135 vnlOutputSize[3][2] = inputSize[2];
136 vnlOutputSize[4][0] = inputSize[0];
137 vnlOutputSize[4][1] = inputSize[1];
138 vnlOutputSize[5][1] = inputSize[1];
139 vnlOutputSize[5][2] = inputSize[2];
140 vnlOutputSize[6][0] = inputSize[0];
141 vnlOutputSize[6][2] = inputSize[2];
142 } else { //Dimension ==4
143 for(unsigned int i=0; i< Dimension; i++)
144 vnlOutputSize[15][i] = inputSize[i];
145 vnlOutputSize[1][0] = inputSize[0];
146 vnlOutputSize[2][1] = inputSize[1];
147 vnlOutputSize[3][2] = inputSize[2];
148 vnlOutputSize[4][3] = inputSize[3];
149 vnlOutputSize[5][0] = inputSize[0];
150 vnlOutputSize[5][1] = inputSize[1];
151 vnlOutputSize[6][0] = inputSize[0];
152 vnlOutputSize[6][2] = inputSize[2];
153 vnlOutputSize[7][0] = inputSize[0];
154 vnlOutputSize[7][3] = inputSize[3];
155 vnlOutputSize[8][1] = inputSize[1];
156 vnlOutputSize[8][2] = inputSize[2];
157 vnlOutputSize[9][1] = inputSize[1];
158 vnlOutputSize[9][3] = inputSize[3];
159 vnlOutputSize[10][2] = inputSize[2];
160 vnlOutputSize[10][3] = inputSize[3];
161 vnlOutputSize[11][0] = inputSize[0];
162 vnlOutputSize[11][1] = inputSize[1];
163 vnlOutputSize[11][2] = inputSize[2];
164 vnlOutputSize[12][0] = inputSize[0];
165 vnlOutputSize[12][1] = inputSize[1];
166 vnlOutputSize[12][3] = inputSize[3];
167 vnlOutputSize[13][0] = inputSize[0];
168 vnlOutputSize[13][2] = inputSize[2];
169 vnlOutputSize[13][3] = inputSize[3];
170 vnlOutputSize[14][1] = inputSize[1];
171 vnlOutputSize[14][2] = inputSize[2];
172 vnlOutputSize[14][3] = inputSize[3];
175 //Compute the transformation of all corner
176 for (unsigned int i=0; i< std::pow(2, Dimension); ++i)
177 vnlOutputSize.set_row(i, transformationMatrix*vnlOutputSize.get_row(i));
179 //Compute the bounding box taking the max and the min
180 vnl_vector<double> minBB(vnlOutputSize.get_row(0)), maxBB(vnlOutputSize.get_row(0));
181 for (unsigned int i=0; i< std::pow(2, Dimension); ++i) {
182 for (unsigned int j=0; j< Dimension; ++j) {
183 if (vnlOutputSize[i][j] < minBB[j])
184 minBB[j] = vnlOutputSize[i][j];
185 if (vnlOutputSize[i][j] > maxBB[j])
186 maxBB[j] = vnlOutputSize[i][j];
194 vnl_vector<double> size;
195 size = maxBB - minBB;
200 //-------------------------------------------------------------------
203 //-------------------------------------------------------------------
204 // Update with the number of dimensions and the pixeltype
205 //-------------------------------------------------------------------
206 template<class args_info_type>
207 template <unsigned int Dimension, class PixelType>
209 AffineTransformGenericFilter<args_info_type>::UpdateWithDimAndPixelType()
213 typedef itk::Image<PixelType, Dimension> InputImageType;
214 typedef itk::Image<PixelType, Dimension> OutputImageType;
217 typedef itk::ImageFileReader<InputImageType> InputReaderType;
218 typename InputReaderType::Pointer reader = InputReaderType::New();
219 reader->SetFileName( m_InputFileName);
221 typename InputImageType::Pointer input= reader->GetOutput();
223 //Adaptative size, spacing origin (use previous clitkResampleImage)
224 if (m_ArgsInfo.adaptive_given) {
226 typedef clitk::ResampleImageWithOptionsFilter<InputImageType, OutputImageType> ResampleImageFilterType;
227 typename ResampleImageFilterType::Pointer filter = ResampleImageFilterType::New();
228 filter->SetInput(input);
231 filter->SetVerboseOptions(m_ArgsInfo.verbose_flag);
233 // Set size / spacing
234 static const unsigned int dim = OutputImageType::ImageDimension;
235 typename OutputImageType::SpacingType spacing;
236 typename OutputImageType::SizeType size;
237 typename OutputImageType::PointType origin;
238 typename OutputImageType::DirectionType direction;
240 if (m_ArgsInfo.like_given) {
241 itk::ImageIOBase::Pointer header = clitk::readImageHeader(m_ArgsInfo.like_arg);
243 for(unsigned int i=0; i<dim; i++){
244 spacing[i] = header->GetSpacing(i);
245 size[i] = header->GetDimensions(i);
246 origin[i] = header->GetOrigin(i);
248 for(unsigned int i=0; i<dim; i++) {
249 for(unsigned int j=0;j<dim;j++) {
250 direction(i,j) = header->GetDirection(i)[j];
253 filter->SetOutputSpacing(spacing);
254 filter->SetOutputSize(size);
255 filter->SetOutputOrigin(origin);
256 filter->SetOutputDirection(direction);
259 std::cerr << "*** Warning : I could not read '" << m_ArgsInfo.like_arg << "' ***" << std::endl;
264 if (m_ArgsInfo.spacing_given == 1) {
265 filter->SetOutputIsoSpacing(m_ArgsInfo.spacing_arg[0]);
267 else if ((m_ArgsInfo.spacing_given != 0) && (m_ArgsInfo.size_given != 0)) {
268 std::cerr << "Error: use spacing or size, not both." << std::endl;
271 else if (m_ArgsInfo.spacing_given) {
272 if ((m_ArgsInfo.spacing_given != 0) && (m_ArgsInfo.spacing_given != dim)) {
273 std::cerr << "Error: spacing should have one or " << dim << " values." << std::endl;
276 for(unsigned int i=0; i<dim; i++)
277 spacing[i] = m_ArgsInfo.spacing_arg[i];
278 filter->SetOutputSpacing(spacing);
280 else if (m_ArgsInfo.size_given) {
281 if ((m_ArgsInfo.size_given != 0) && (m_ArgsInfo.size_given != dim)) {
282 std::cerr << "Error: size should have " << dim << " values." << std::endl;
285 for(unsigned int i=0; i<dim; i++)
286 size[i] = m_ArgsInfo.size_arg[i];
287 filter->SetOutputSize(size);
289 for(unsigned int i=0; i<dim; i++){
290 origin[i] = input->GetOrigin()[i];
292 for(unsigned int i=0; i<dim; i++) {
293 for(unsigned int j=0;j<dim;j++) {
294 direction(i,j) = input->GetDirection()[i][j];
297 filter->SetOutputOrigin(origin);
298 filter->SetOutputDirection(direction);
301 // Set temporal dimension
302 //filter->SetLastDimensionIsTime(m_ArgsInfo.time_flag);
305 filter->SetGaussianFilteringEnabled(m_ArgsInfo.autogauss_flag);
306 if (m_ArgsInfo.gauss_given != 0) {
307 typename ResampleImageFilterType::GaussianSigmaType g;
308 for(unsigned int i=0; i<dim; i++) {
309 g[i] = m_ArgsInfo.gauss_arg[i];
311 filter->SetGaussianSigma(g);
315 int interp = m_ArgsInfo.interp_arg;
317 filter->SetInterpolationType(ResampleImageFilterType::NearestNeighbor);
320 filter->SetInterpolationType(ResampleImageFilterType::Linear);
323 filter->SetInterpolationType(ResampleImageFilterType::BSpline);
326 filter->SetInterpolationType(ResampleImageFilterType::B_LUT);
328 std::cerr << "Error. I do not know interpolation '" << m_ArgsInfo.interp_arg
329 << "'. Choose among: nn, linear, bspline, blut, windowed sinc" << std::endl;
336 // Set default pixel value
337 filter->SetDefaultPixelValue(m_ArgsInfo.pad_arg);
340 //if (m_ArgsInfo.thread_given) {
341 // filter->SetNumberOfThreads(m_ArgsInfo.thread_arg);
346 typename OutputImageType::Pointer output = filter->GetOutput();
347 //this->template SetNextOutput<OutputImageType>(outputImage);
350 typedef itk::ImageFileWriter<OutputImageType> WriterType;
351 typename WriterType::Pointer writer = WriterType::New();
352 writer->SetFileName(m_ArgsInfo.output_arg);
353 writer->SetInput(output);
359 //Gaussian pre-filtering
360 typename itk::Vector<double, Dimension> gaussianSigma;
361 gaussianSigma.Fill(0);
362 bool gaussianFilteringEnabled(false);
363 bool autoGaussEnabled(false);
364 if (m_ArgsInfo.autogauss_given) { // Gaussian filter auto
365 autoGaussEnabled = m_ArgsInfo.autogauss_flag;
367 if (m_ArgsInfo.gauss_given) { // Gaussian filter set by user
368 gaussianFilteringEnabled = true;
369 if (m_ArgsInfo.gauss_given == 1)
371 for (unsigned int i=0; i<Dimension; i++)
373 gaussianSigma[i] = m_ArgsInfo.gauss_arg[0];
376 else if (m_ArgsInfo.gauss_given == Dimension)
378 for (unsigned int i=0; i<Dimension; i++)
380 gaussianSigma[i] = m_ArgsInfo.gauss_arg[i];
385 std::cerr << "Gaussian sigma dimension is incorrect" << std::endl;
391 typedef itk::ResampleImageFilter< InputImageType,OutputImageType > ResampleFilterType;
392 typename ResampleFilterType::Pointer resampler = ResampleFilterType::New();
395 typename itk::Matrix<double, Dimension+1, Dimension+1> matrix;
396 if (m_ArgsInfo.rotate_given || m_ArgsInfo.translate_given)
398 if (m_ArgsInfo.matrix_given)
400 std::cerr << "You must use either rotate/translate or matrix options" << std::endl;
403 itk::Array<double> transformParameters(2 * Dimension);
404 transformParameters.Fill(0.0);
405 if (m_ArgsInfo.rotate_given)
408 transformParameters[0] = m_ArgsInfo.rotate_arg[0];
410 for (unsigned int i = 0; i < 3; i++)
411 transformParameters[i] = m_ArgsInfo.rotate_arg[i];
413 if (m_ArgsInfo.translate_given)
418 for (unsigned int i = 0; i < Dimension && i < 3; i++)
419 transformParameters[pos++] = m_ArgsInfo.translate_arg[i];
423 matrix.SetIdentity();
424 itk::Matrix<double, 4, 4> tmp = GetForwardAffineMatrix3D(transformParameters);
425 for (unsigned int i = 0; i < 3; ++i)
426 for (unsigned int j = 0; j < 3; ++j)
427 matrix[i][j] = tmp[i][j];
428 for (unsigned int i = 0; i < 3; ++i)
429 matrix[i][4] = tmp[i][3];
432 matrix = GetForwardAffineMatrix<Dimension>(transformParameters);
436 if (m_ArgsInfo.matrix_given)
438 matrix= clitk::ReadMatrix<Dimension>(m_ArgsInfo.matrix_arg);
439 if (m_Verbose) std::cout << "Reading the matrix..." << std::endl;
442 if (m_ArgsInfo.elastix_given) {
443 std::string filename(m_ArgsInfo.elastix_arg);
444 matrix = createMatrixFromElastixFile<Dimension>(filename, m_Verbose);
447 matrix.SetIdentity();
451 std::cout << "Using the following matrix:" << std::endl
452 << matrix << std::endl;
453 typename itk::Matrix<double, Dimension, Dimension> rotationMatrix = clitk::GetRotationalPartMatrix(matrix);
454 typename itk::Vector<double, Dimension> translationPart = clitk::GetTranslationPartMatrix(matrix);
457 typedef itk::AffineTransform<double, Dimension> AffineTransformType;
458 typename AffineTransformType::Pointer affineTransform=AffineTransformType::New();
459 affineTransform->SetMatrix(rotationMatrix);
460 affineTransform->SetTranslation(translationPart);
463 typedef clitk::GenericInterpolator<args_info_type, InputImageType, double> GenericInterpolatorType;
464 typename GenericInterpolatorType::Pointer genericInterpolator=GenericInterpolatorType::New();
465 genericInterpolator->SetArgsInfo(m_ArgsInfo);
468 if (m_ArgsInfo.like_given) {
469 typename InputReaderType::Pointer likeReader=InputReaderType::New();
470 likeReader->SetFileName(m_ArgsInfo.like_arg);
471 likeReader->Update();
472 resampler->SetOutputParametersFromImage(likeReader->GetOutput());
473 resampler->SetOutputDirection(likeReader->GetOutput()->GetDirection());
474 if (autoGaussEnabled) { // Automated sigma when downsample
475 for(unsigned int i=0; i<Dimension; i++) {
476 if (likeReader->GetOutput()->GetSpacing()[i] > input->GetSpacing()[i]) { // downsample
477 gaussianSigma[i] = 0.5*likeReader->GetOutput()->GetSpacing()[i];// / inputSpacing[i]);
479 else gaussianSigma[i] = 0; // will be ignore after
482 } else if(m_ArgsInfo.transform_grid_flag) {
483 typename itk::Matrix<double, Dimension+1, Dimension+1> invMatrix( matrix.GetInverse() );
484 typename itk::Matrix<double, Dimension, Dimension> invRotMatrix( clitk::GetRotationalPartMatrix(invMatrix) );
485 typename itk::Vector<double,Dimension> invTrans = clitk::GetTranslationPartMatrix(invMatrix);
488 if (m_ArgsInfo.spacing_given)
489 std::cout << "Warning --spacing ignored (because --transform_grid_flag)" << std::endl;
490 if (m_ArgsInfo.origin_given)
491 std::cout << "Warning --origin ignored (because --transform_grid_flag)" << std::endl;
493 // Origin is influenced by translation but not by input direction
494 typename InputImageType::PointType outputOrigin;
495 outputOrigin = invRotMatrix *
499 // Size is influenced by affine transform matrix and input direction
500 // Size is converted to double, transformed and converted back to size type.
501 // Determine the bounding box tranforming all corners
502 vnl_vector<double> vnlOutputSize(Dimension), vnlOutputmmSize(Dimension), vnlOutputOffset(Dimension);
503 typename InputImageType::SpacingType outputSpacing;
504 for(unsigned int i=0; i< Dimension; i++) {
505 vnlOutputSize[i] = input->GetLargestPossibleRegion().GetSize()[i];
506 vnlOutputmmSize[i] = input->GetLargestPossibleRegion().GetSize()[i]*input->GetSpacing()[i];
507 vnlOutputOffset[i] = input->GetLargestPossibleRegion().GetSize()[i]*input->GetSpacing()[i];
509 vnlOutputSize = ComputeSize(vnlOutputSize, invRotMatrix.GetVnlMatrix() * input->GetDirection().GetVnlMatrix(), 0);
510 vnlOutputmmSize = ComputeSize(vnlOutputmmSize, invRotMatrix.GetVnlMatrix() * input->GetDirection().GetVnlMatrix(), 0);
511 vnlOutputOffset = ComputeSize(vnlOutputOffset, invRotMatrix.GetVnlMatrix() * input->GetDirection().GetVnlMatrix(), 1);
512 for(unsigned int i=0; i< Dimension; i++) {
513 outputSpacing[i] = vnlOutputmmSize[i]/lrint(vnlOutputSize[i]);
514 outputOrigin[i] += vnlOutputOffset[i];
516 if (autoGaussEnabled) { // Automated sigma when downsample
517 for(unsigned int i=0; i<Dimension; i++) {
518 if (outputSpacing[i] > input->GetSpacing()[i]) { // downsample
519 gaussianSigma[i] = 0.5*outputSpacing[i];// / inputSpacing[i]);
521 else gaussianSigma[i] = 0; // will be ignore after
525 typename OutputImageType::SizeType outputSize;
526 for(unsigned int i=0; i< Dimension; i++) {
527 // If the size is negative, we have a flip and we must modify
528 // the origin and the spacing accordingly.
529 if(vnlOutputSize[i]<0.) {
530 vnlOutputSize[i] *= -1.;
531 outputOrigin[i] = outputOrigin[i] + outputSpacing[i] * (vnlOutputSize[i]-1);
532 outputSpacing[i] *= -1.;
534 outputSize[i] = lrint(vnlOutputSize[i]);
536 resampler->SetSize( outputSize );
537 resampler->SetOutputSpacing( outputSpacing );
538 resampler->SetOutputOrigin( outputOrigin );
541 typename OutputImageType::SizeType outputSize;
542 if (m_ArgsInfo.size_given) {
543 for(unsigned int i=0; i< Dimension; i++)
544 outputSize[i]=m_ArgsInfo.size_arg[i];
545 } else outputSize=input->GetLargestPossibleRegion().GetSize();
548 typename OutputImageType::SpacingType outputSpacing;
549 if (m_ArgsInfo.spacing_given) {
550 for(unsigned int i=0; i< Dimension; i++)
551 outputSpacing[i]=m_ArgsInfo.spacing_arg[i];
552 } else outputSpacing=input->GetSpacing();
553 if (autoGaussEnabled) { // Automated sigma when downsample
554 for(unsigned int i=0; i<Dimension; i++) {
555 if (outputSpacing[i] > input->GetSpacing()[i]) { // downsample
556 gaussianSigma[i] = 0.5*outputSpacing[i];// / inputSpacing[i]);
558 else gaussianSigma[i] = 0; // will be ignore after
563 typename OutputImageType::PointType outputOrigin;
564 if (m_ArgsInfo.origin_given) {
565 for(unsigned int i=0; i< Dimension; i++)
566 outputOrigin[i]=m_ArgsInfo.origin_arg[i];
567 } else outputOrigin=input->GetOrigin();
570 typename OutputImageType::DirectionType outputDirection;
571 if (m_ArgsInfo.direction_given) {
572 for(unsigned int j=0; j< Dimension; j++)
573 for(unsigned int i=0; i< Dimension; i++)
574 outputDirection[j][i]=m_ArgsInfo.direction_arg[i+Dimension*j];
575 } else outputDirection=input->GetDirection();
578 resampler->SetSize( outputSize );
579 resampler->SetOutputSpacing( outputSpacing );
580 resampler->SetOutputOrigin( outputOrigin );
581 resampler->SetOutputDirection( outputDirection );
585 if (m_ArgsInfo.spacinglike_given) {
586 typename InputReaderType::Pointer likeReader=InputReaderType::New();
587 likeReader->SetFileName(m_ArgsInfo.spacinglike_arg);
588 likeReader->Update();
590 // set the support like the image
591 if (m_ArgsInfo.like_given) {
592 typename OutputImageType::SizeType outputSize;
593 outputSize[0] = ceil(resampler->GetSize()[0]*resampler->GetOutputSpacing()[0]
594 /likeReader->GetOutput()->GetSpacing()[0]);
595 outputSize[1] = ceil(resampler->GetSize()[1]*resampler->GetOutputSpacing()[1]
596 /likeReader->GetOutput()->GetSpacing()[1]);
597 outputSize[2] = ceil(resampler->GetSize()[2]*resampler->GetOutputSpacing()[2]
598 /likeReader->GetOutput()->GetSpacing()[2]);
599 if (m_ArgsInfo.verbose_flag) {
600 std::cout << "Compute the number of pixels such as the support is like " << m_ArgsInfo.like_arg << std::endl;
602 resampler->SetSize( outputSize );
605 resampler->SetOutputSpacing( likeReader->GetOutput()->GetSpacing() );
608 if (m_ArgsInfo.verbose_flag) {
609 std::cout << "Setting the output size to " << resampler->GetSize() << "..." << std::endl;
610 std::cout << "Setting the output spacing to " << resampler->GetOutputSpacing() << "..." << std::endl;
611 std::cout << "Setting the output origin to " << resampler->GetOutputOrigin() << "..." << std::endl;
612 std::cout << "Setting the output direction to " << resampler->GetOutputDirection() << "..." << std::endl;
615 typedef itk::RecursiveGaussianImageFilter<InputImageType, InputImageType> GaussianFilterType;
616 std::vector<typename GaussianFilterType::Pointer> gaussianFilters;
617 if (gaussianFilteringEnabled || autoGaussEnabled) {
618 for(unsigned int i=0; i<Dimension; i++) {
619 if (gaussianSigma[i] != 0) {
620 gaussianFilters.push_back(GaussianFilterType::New());
621 gaussianFilters[i]->SetDirection(i);
622 gaussianFilters[i]->SetOrder(GaussianFilterType::ZeroOrder);
623 gaussianFilters[i]->SetNormalizeAcrossScale(false);
624 gaussianFilters[i]->SetSigma(gaussianSigma[i]); // in millimeter !
625 if (gaussianFilters.size() == 1) { // first
626 gaussianFilters[0]->SetInput(input);
628 gaussianFilters[i]->SetInput(gaussianFilters[i-1]->GetOutput());
632 if (gaussianFilters.size() > 0) {
633 resampler->SetInput(gaussianFilters[gaussianFilters.size()-1]->GetOutput());
634 } else resampler->SetInput(input);
635 } else resampler->SetInput(input);
637 resampler->SetTransform( affineTransform );
638 resampler->SetInterpolator( genericInterpolator->GetInterpolatorPointer());
639 resampler->SetDefaultPixelValue( static_cast<PixelType>(m_ArgsInfo.pad_arg) );
643 } catch(itk::ExceptionObject) {
644 std::cerr<<"Error resampling the image"<<std::endl;
647 typename OutputImageType::Pointer output = resampler->GetOutput();
650 typedef itk::ImageFileWriter<OutputImageType> WriterType;
651 typename WriterType::Pointer writer = WriterType::New();
652 writer->SetFileName(m_ArgsInfo.output_arg);
653 writer->SetInput(output);
657 //-------------------------------------------------------------------
660 //-------------------------------------------------------------------
661 // Update with the number of dimensions and the pixeltype (components)
662 //-------------------------------------------------------------------
663 template<class args_info_type>
664 template<unsigned int Dimension, class PixelType>
665 void AffineTransformGenericFilter<args_info_type>::UpdateWithDimAndVectorType()
668 typedef itk::Image<PixelType, Dimension> InputImageType;
669 typedef itk::Image<PixelType, Dimension> OutputImageType;
672 typedef itk::ImageFileReader<InputImageType> InputReaderType;
673 typename InputReaderType::Pointer reader = InputReaderType::New();
674 reader->SetFileName( m_InputFileName);
676 typename InputImageType::Pointer input= reader->GetOutput();
678 //Gaussian pre-filtering
679 typename itk::Vector<double, Dimension> gaussianSigma;
680 gaussianSigma.Fill(0);
681 bool gaussianFilteringEnabled(false);
682 bool autoGaussEnabled(false);
683 if (m_ArgsInfo.autogauss_given) { // Gaussian filter auto
684 autoGaussEnabled = m_ArgsInfo.autogauss_flag;
686 if (m_ArgsInfo.gauss_given) { // Gaussian filter set by user
687 gaussianFilteringEnabled = true;
688 if (m_ArgsInfo.gauss_given == 1)
690 for (unsigned int i=0; i<Dimension; i++)
692 gaussianSigma[i] = m_ArgsInfo.gauss_arg[0];
695 else if (m_ArgsInfo.gauss_given == Dimension)
697 for (unsigned int i=0; i<Dimension; i++)
699 gaussianSigma[i] = m_ArgsInfo.gauss_arg[i];
704 std::cerr << "Gaussian sigma dimension is incorrect" << std::endl;
710 typedef itk::VectorResampleImageFilter< InputImageType,OutputImageType, double > ResampleFilterType;
711 typename ResampleFilterType::Pointer resampler = ResampleFilterType::New();
714 typename itk::Matrix<double, Dimension+1, Dimension+1> matrix;
715 if (m_ArgsInfo.rotate_given || m_ArgsInfo.translate_given)
717 if (m_ArgsInfo.matrix_given)
719 std::cerr << "You must use either rotate/translate or matrix options" << std::endl;
722 itk::Array<double> transformParameters(2 * Dimension);
723 transformParameters.Fill(0.0);
724 if (m_ArgsInfo.rotate_given)
727 transformParameters[0] = m_ArgsInfo.rotate_arg[0];
729 for (unsigned int i = 0; i < 3; i++)
730 transformParameters[i] = m_ArgsInfo.rotate_arg[i];
732 if (m_ArgsInfo.translate_given)
737 for (unsigned int i = 0; i < Dimension && i < 3; i++)
738 transformParameters[pos++] = m_ArgsInfo.translate_arg[i];
742 matrix.SetIdentity();
743 itk::Matrix<double, 4, 4> tmp = GetForwardAffineMatrix3D(transformParameters);
744 for (unsigned int i = 0; i < 3; ++i)
745 for (unsigned int j = 0; j < 3; ++j)
746 matrix[i][j] = tmp[i][j];
747 for (unsigned int i = 0; i < 3; ++i)
748 matrix[i][4] = tmp[i][3];
751 matrix = GetForwardAffineMatrix<Dimension>(transformParameters);
755 if (m_ArgsInfo.matrix_given)
757 matrix= clitk::ReadMatrix<Dimension>(m_ArgsInfo.matrix_arg);
758 if (m_Verbose) std::cout << "Reading the matrix..." << std::endl;
761 matrix.SetIdentity();
764 std::cout << "Using the following matrix:" << std::endl
765 << matrix << std::endl;
766 typename itk::Matrix<double, Dimension, Dimension> rotationMatrix = clitk::GetRotationalPartMatrix(matrix);
767 typename itk::Vector<double, Dimension> translationPart = clitk::GetTranslationPartMatrix(matrix);
770 typedef itk::AffineTransform<double, Dimension> AffineTransformType;
771 typename AffineTransformType::Pointer affineTransform=AffineTransformType::New();
772 affineTransform->SetMatrix(rotationMatrix);
773 affineTransform->SetTranslation(translationPart);
776 typedef clitk::GenericVectorInterpolator<args_info_type, InputImageType, double> GenericInterpolatorType;
777 typename GenericInterpolatorType::Pointer genericInterpolator=GenericInterpolatorType::New();
778 genericInterpolator->SetArgsInfo(m_ArgsInfo);
781 if (m_ArgsInfo.like_given) {
782 typename InputReaderType::Pointer likeReader=InputReaderType::New();
783 likeReader->SetFileName(m_ArgsInfo.like_arg);
784 likeReader->Update();
785 resampler->SetSize( likeReader->GetOutput()->GetLargestPossibleRegion().GetSize() );
786 resampler->SetOutputSpacing( likeReader->GetOutput()->GetSpacing() );
787 resampler->SetOutputOrigin( likeReader->GetOutput()->GetOrigin() );
788 resampler->SetOutputDirection( likeReader->GetOutput()->GetDirection() );
789 if (autoGaussEnabled) { // Automated sigma when downsample
790 for(unsigned int i=0; i<Dimension; i++) {
791 if (likeReader->GetOutput()->GetSpacing()[i] > input->GetSpacing()[i]) { // downsample
792 gaussianSigma[i] = 0.5*likeReader->GetOutput()->GetSpacing()[i];// / inputSpacing[i]);
794 else gaussianSigma[i] = 0; // will be ignore after
799 typename OutputImageType::SizeType outputSize;
800 if (m_ArgsInfo.size_given) {
801 for(unsigned int i=0; i< Dimension; i++)
802 outputSize[i]=m_ArgsInfo.size_arg[i];
803 } else outputSize=input->GetLargestPossibleRegion().GetSize();
804 std::cout<<"Setting the size to "<<outputSize<<"..."<<std::endl;
807 typename OutputImageType::SpacingType outputSpacing;
808 if (m_ArgsInfo.spacing_given) {
809 for(unsigned int i=0; i< Dimension; i++)
810 outputSpacing[i]=m_ArgsInfo.spacing_arg[i];
811 } else outputSpacing=input->GetSpacing();
812 if (autoGaussEnabled) { // Automated sigma when downsample
813 for(unsigned int i=0; i<Dimension; i++) {
814 if (outputSpacing[i] > input->GetSpacing()[i]) { // downsample
815 gaussianSigma[i] = 0.5*outputSpacing[i];// / inputSpacing[i]);
817 else gaussianSigma[i] = 0; // will be ignore after
820 std::cout<<"Setting the spacing to "<<outputSpacing<<"..."<<std::endl;
823 typename OutputImageType::PointType outputOrigin;
824 if (m_ArgsInfo.origin_given) {
825 for(unsigned int i=0; i< Dimension; i++)
826 outputOrigin[i]=m_ArgsInfo.origin_arg[i];
827 } else outputOrigin=input->GetOrigin();
828 std::cout<<"Setting the origin to "<<outputOrigin<<"..."<<std::endl;
831 typename OutputImageType::DirectionType outputDirection;
832 if (m_ArgsInfo.direction_given) {
833 for(unsigned int j=0; j< Dimension; j++)
834 for(unsigned int i=0; i< Dimension; i++)
835 outputDirection[j][i]=m_ArgsInfo.direction_arg[i+Dimension*j];
836 } else outputDirection=input->GetDirection();
837 std::cout<<"Setting the direction to "<<outputDirection<<"..."<<std::endl;
840 resampler->SetSize( outputSize );
841 resampler->SetOutputSpacing( outputSpacing );
842 resampler->SetOutputOrigin( outputOrigin );
843 resampler->SetOutputDirection( outputDirection );
847 typedef itk::RecursiveGaussianImageFilter<InputImageType, InputImageType> GaussianFilterType;
848 std::vector<typename GaussianFilterType::Pointer> gaussianFilters;
849 if (gaussianFilteringEnabled || autoGaussEnabled) {
850 for(unsigned int i=0; i<Dimension; i++) {
851 if (gaussianSigma[i] != 0) {
852 gaussianFilters.push_back(GaussianFilterType::New());
853 gaussianFilters[i]->SetDirection(i);
854 gaussianFilters[i]->SetOrder(GaussianFilterType::ZeroOrder);
855 gaussianFilters[i]->SetNormalizeAcrossScale(false);
856 gaussianFilters[i]->SetSigma(gaussianSigma[i]); // in millimeter !
857 if (gaussianFilters.size() == 1) { // first
858 gaussianFilters[0]->SetInput(input);
860 gaussianFilters[i]->SetInput(gaussianFilters[i-1]->GetOutput());
864 if (gaussianFilters.size() > 0) {
865 resampler->SetInput(gaussianFilters[gaussianFilters.size()-1]->GetOutput());
866 } else resampler->SetInput(input);
867 } else resampler->SetInput(input);
869 resampler->SetInput( input );
870 resampler->SetTransform( affineTransform );
871 resampler->SetInterpolator( genericInterpolator->GetInterpolatorPointer());
872 resampler->SetDefaultPixelValue( static_cast<PixelType>(m_ArgsInfo.pad_arg) );
876 } catch(itk::ExceptionObject) {
877 std::cerr<<"Error resampling the image"<<std::endl;
880 typename OutputImageType::Pointer output = resampler->GetOutput();
883 typedef itk::ImageFileWriter<OutputImageType> WriterType;
884 typename WriterType::Pointer writer = WriterType::New();
885 writer->SetFileName(m_ArgsInfo.output_arg);
886 writer->SetInput(output);
890 //-------------------------------------------------------------------
894 #endif //#define clitkAffineTransformGenericFilter_txx