1 #include <tclap/CmdLine.h> 3 #include <itkMultiplyImageFilter.h> 4 #include <itkAddImageFilter.h> 5 #include <itkExtractImageFilter.h> 6 #include <itkFixedPointInverseDisplacementFieldImageFilter.h> 8 #include <rpiDisplacementFieldTransform.h> 13 itk::Image <double, 4> *geometryImage)
15 typedef itk::Image <double, 4>::DirectionType MatrixType;
16 MatrixType geometry = geometryImage->GetDirection();
19 for (
unsigned int i = 0;i < 3;++i)
20 for (
unsigned int j = 0;j < 3;++j)
21 geometry(i,j) *= geometryImage->GetSpacing()[j];
23 typedef itk::Image <itk::Vector <double,3>, 3> VectorFieldType;
24 itk::ImageRegionIterator <VectorFieldType> vectorFieldItr(vectorField,vectorField->GetLargestPossibleRegion());
26 itk::Vector <double,3> tmpVec, tmpOutVec;
27 while (!vectorFieldItr.IsAtEnd())
29 tmpVec = vectorFieldItr.Get();
31 for (
unsigned int i = 0;i < 3;++i)
34 for (
unsigned int j = 0;j < 3;++j)
35 tmpOutVec[i] += geometry(i,j) * tmpVec[j];
38 vectorFieldItr.Set(tmpOutVec);
43 int main(
int ac,
const char** av)
45 std::string descriptionMessage;
46 descriptionMessage +=
"Resampler tool to apply a distortion correction to one or two 4D volumes\n";
47 descriptionMessage +=
"INRIA / IRISA - VisAGeS/Empenn Team";
49 TCLAP::CmdLine cmd(descriptionMessage,
' ',ANIMA_VERSION);
51 TCLAP::ValueArg<std::string> forwardArg(
"f",
"forward",
"Input forward image (eg A-P, 4D)",
true,
"",
"input forward image",cmd);
52 TCLAP::ValueArg<std::string> backwardArg(
"b",
"backward",
"Input backward image (eg P-A, 3D, or 4D)",
false,
"",
"input backward image",cmd);
53 TCLAP::ValueArg<std::string> trArg(
"t",
"trsf",
"Distortion correction field",
true,
"",
"distortion correction field",cmd);
54 TCLAP::ValueArg<std::string> outArg(
"o",
"output",
"Output corrected image",
true,
"",
"output image",cmd);
55 TCLAP::ValueArg<std::string> outVecArg(
"O",
"out-vec",
"Transformation vector field in real coordinates",
false,
"",
"transformation in real coordinates",cmd);
57 TCLAP::SwitchArg fieldInVoxelCoordinates(
"V",
"voxel",
"If set, the input correction field is assumed to be in voxel coordinates",cmd,
false);
58 TCLAP::SwitchArg reverseFieldArg(
"R",
"reverse",
"If set, apply the opposite of the input field to the forward image",cmd,
false);
59 TCLAP::SwitchArg inverseFieldArg(
"I",
"invert",
"If set, invert the input field (after reverting if R option is on)",cmd,
false);
61 TCLAP::ValueArg<unsigned int> nbpArg(
"T",
"numberofthreads",
"Number of threads to run on (default : all cores)",
false,itk::MultiThreaderBase::GetGlobalDefaultNumberOfThreads(),
"number of threads",cmd);
67 catch (TCLAP::ArgException& e)
69 std::cerr <<
"Error: " << e.error() <<
"for argument " << e.argId() << std::endl;
73 const unsigned int Dimension = 3;
74 typedef double PixelType;
75 typedef double TransformPixelType;
77 typedef itk::Image <PixelType, Dimension> ImageType;
78 typedef itk::Image <PixelType, 4> Image4DType;
80 typedef rpi::DisplacementFieldTransform <TransformPixelType,Dimension> TransformType;
81 typedef TransformType::VectorFieldType VectorFieldType;
82 typedef itk::MultiplyImageFilter <VectorFieldType, itk::Image <double,Dimension>, VectorFieldType> MultiplierFilterType;
84 VectorFieldType::Pointer appliedField = anima::readImage<VectorFieldType>(trArg.getValue());
85 appliedField->DisconnectPipeline();
87 Image4DType::Pointer forwardImage = anima::readImage<Image4DType>(forwardArg.getValue());
89 if (fieldInVoxelCoordinates.isSet())
92 if (reverseFieldArg.isSet())
95 MultiplierFilterType::Pointer vectorMultiplier = MultiplierFilterType::New();
96 vectorMultiplier->SetInput(appliedField);
97 vectorMultiplier->SetConstant(-1.0);
98 vectorMultiplier->SetNumberOfWorkUnits(nbpArg.getValue());
99 vectorMultiplier->Update();
100 vectorMultiplier->InPlaceOn();
102 appliedField = vectorMultiplier->GetOutput();
103 appliedField->DisconnectPipeline();
106 if (inverseFieldArg.isSet())
109 typedef itk::FixedPointInverseDisplacementFieldImageFilter <VectorFieldType, VectorFieldType> InverseFilterType;
110 InverseFilterType::Pointer fieldInverter = InverseFilterType::New();
111 fieldInverter->SetInput(appliedField);
112 fieldInverter->SetSize(appliedField->GetLargestPossibleRegion().GetSize());
113 fieldInverter->SetOutputOrigin(appliedField->GetOrigin());
114 fieldInverter->SetOutputSpacing(appliedField->GetSpacing());
115 fieldInverter->SetNumberOfWorkUnits(nbpArg.getValue());
116 fieldInverter->Update();
118 appliedField = fieldInverter->GetOutput();
119 appliedField->DisconnectPipeline();
122 TransformType::Pointer trsf = TransformType::New();
123 trsf->SetParametersAsVectorField(appliedField);
125 Image4DType::Pointer backwardImage;
126 unsigned int numBackwardImages = 0;
128 if (backwardArg.getValue() !=
"")
130 backwardImage = anima::readImage<Image4DType> (backwardArg.getValue());
131 numBackwardImages = backwardImage->GetLargestPossibleRegion().GetSize()[Dimension];
134 TransformType::Pointer oppositeTransform;
135 if (numBackwardImages > 0)
137 MultiplierFilterType::Pointer vectorMultiplier = MultiplierFilterType::New();
138 vectorMultiplier->SetInput(trsf->GetParametersAsVectorField());
139 vectorMultiplier->SetConstant(-1.0);
140 vectorMultiplier->SetNumberOfWorkUnits(nbpArg.getValue());
141 vectorMultiplier->Update();
143 VectorFieldType::Pointer oppositeField = vectorMultiplier->GetOutput();
144 oppositeField->DisconnectPipeline();
146 oppositeTransform = TransformType::New();
147 oppositeTransform->SetParametersAsVectorField(oppositeField);
150 unsigned int numForwardImages = forwardImage->GetLargestPossibleRegion().GetSize()[Dimension];
152 Image4DType::Pointer outputImage = Image4DType::New();
153 outputImage->Initialize();
154 outputImage->SetRegions(forwardImage->GetLargestPossibleRegion());
155 outputImage->SetSpacing (forwardImage->GetSpacing());
156 outputImage->SetOrigin (forwardImage->GetOrigin());
157 outputImage->SetDirection (forwardImage->GetDirection());
158 outputImage->Allocate();
162 for (
unsigned int i = 0;i < numForwardImages;++i)
164 std::cout <<
"Applying correction to " << i <<
"-th image..." << std::flush;
167 typedef itk::ExtractImageFilter <Image4DType, ImageType> ExtractFilterType;
168 ExtractFilterType::Pointer forwardExtractor = ExtractFilterType::New();
169 forwardExtractor->SetInput(forwardImage);
171 Image4DType::RegionType extractRegion = forwardImage->GetLargestPossibleRegion();
172 extractRegion.SetIndex(Dimension,i);
173 extractRegion.SetSize(Dimension,0);
174 forwardExtractor->SetExtractionRegion(extractRegion);
175 forwardExtractor->SetDirectionCollapseToGuess();
176 forwardExtractor->Update();
178 ResampleFilterType::Pointer forwardResampler = ResampleFilterType::New();
179 forwardResampler->SetInput(forwardExtractor->GetOutput());
180 forwardResampler->SetNumberOfWorkUnits(nbpArg.getValue());
181 forwardResampler->SetTransform(trsf);
183 forwardResampler->SetSize(forwardExtractor->GetOutput()->GetLargestPossibleRegion().GetSize());
184 forwardResampler->SetOutputOrigin(forwardExtractor->GetOutput()->GetOrigin());
185 forwardResampler->SetOutputSpacing(forwardExtractor->GetOutput()->GetSpacing());
186 forwardResampler->SetOutputDirection(forwardExtractor->GetOutput()->GetDirection());
187 forwardResampler->SetDefaultPixelValue(0);
188 forwardResampler->SetScaleIntensitiesWithJacobian(
true);
189 forwardResampler->Update();
191 ImageType::Pointer outputSingleImage = forwardResampler->GetOutput();
193 if (i < numBackwardImages)
195 ExtractFilterType::Pointer backwardExtractor = ExtractFilterType::New();
196 backwardExtractor->SetInput(backwardImage);
197 backwardExtractor->SetExtractionRegion(extractRegion);
198 backwardExtractor->SetDirectionCollapseToGuess();
199 backwardExtractor->Update();
201 ResampleFilterType::Pointer backwardResampler = ResampleFilterType::New();
202 backwardResampler->SetInput(backwardExtractor->GetOutput());
203 backwardResampler->SetNumberOfWorkUnits(nbpArg.getValue());
204 backwardResampler->SetTransform(oppositeTransform);
206 backwardResampler->SetSize(backwardExtractor->GetOutput()->GetLargestPossibleRegion().GetSize());
207 backwardResampler->SetOutputOrigin(backwardExtractor->GetOutput()->GetOrigin());
208 backwardResampler->SetOutputSpacing(backwardExtractor->GetOutput()->GetSpacing());
209 backwardResampler->SetOutputDirection(backwardExtractor->GetOutput()->GetDirection());
210 backwardResampler->SetDefaultPixelValue(0);
211 backwardResampler->SetScaleIntensitiesWithJacobian(
true);
212 backwardResampler->Update();
215 typedef itk::AddImageFilter <ImageType,ImageType,ImageType> AddFilterType;
216 AddFilterType::Pointer outputAdder = AddFilterType::New();
217 outputAdder->SetInput1(outputSingleImage);
218 outputAdder->SetInput2(backwardResampler->GetOutput());
219 outputAdder->SetNumberOfWorkUnits(nbpArg.getValue());
220 outputAdder->Update();
221 outputAdder->InPlaceOn();
223 typedef itk::MultiplyImageFilter <ImageType, itk::Image <double,Dimension>, ImageType> MultiplierFilterType;
224 MultiplierFilterType::Pointer outputMultiplier = MultiplierFilterType::New();
225 outputMultiplier->SetInput(outputAdder->GetOutput());
226 outputMultiplier->SetConstant(0.5);
227 outputMultiplier->SetNumberOfWorkUnits(nbpArg.getValue());
228 outputMultiplier->Update();
229 outputMultiplier->InPlaceOn();
231 outputSingleImage = outputMultiplier->GetOutput();
232 outputSingleImage->DisconnectPipeline();
235 itk::ImageRegionConstIterator <ImageType> singleOutputIterator(outputSingleImage,outputSingleImage->GetLargestPossibleRegion());
236 extractRegion.SetSize(Dimension,1);
237 itk::ImageRegionIterator <Image4DType> globalOutputIterator(outputImage,extractRegion);
239 while (!singleOutputIterator.IsAtEnd())
241 globalOutputIterator.Set(singleOutputIterator.Get());
243 ++singleOutputIterator;
244 ++globalOutputIterator;
247 std::cout <<
" Done" << std::endl;
250 anima::writeImage<Image4DType> (outArg.getValue(),outputImage);
252 if (outVecArg.getValue() !=
"")
253 anima::writeImage<VectorFieldType>(outVecArg.getValue(), const_cast <VectorFieldType *> (trsf->GetParametersAsVectorField()));
void ApplyGeometryToVectorField(itk::Image< itk::Vector< double, 3 >, 3 > *vectorField, itk::Image< double, 4 > *geometryImage)
int main(int ac, const char **av)