4 #include <itkImageFileWriter.h> 9 #include <itkIdentityTransform.h> 14 template <
class TInputImage,
class TOutputImage>
22 template <
class TInputImage,
class TOutputImage>
27 double meanVals, sumVals = 0, resVal;
29 unsigned int numDirs = 0;
30 for (
unsigned int i = 0;i < sp.Size();++i)
32 if (changeableSizes[i])
39 meanVals = sumVals / numDirs;
42 for (
unsigned int i = 0;i < sp.Size();++i)
44 if (changeableSizes[i])
45 resVal += (sp[i] - meanVals) * (sp[i] - meanVals);
48 resVal = std::sqrt(0.5 * resVal) / sumVals;
53 template <
class TInputImage,
class TOutputImage>
58 const unsigned int minSize = 16;
60 std::vector <RegionType> tmpSizes;
61 std::vector <SpacingType> tmpSpacings;
63 tmpSizes.push_back(this->GetInput()->GetLargestPossibleRegion());
64 tmpSpacings.push_back(this->GetInput()->GetSpacing());
67 std::vector <bool> changeableSizes(InputImageType::ImageDimension,
false);
69 for (
unsigned int j = 0;j < InputImageType::ImageDimension;++j)
71 if ((tmpSizes[0].GetSize()[j] > minSize))
72 changeableSizes[j] =
true;
76 SpacingType previousSpacing, newSpacing, testSpacing;
77 bool allAboveMinSize =
true;
79 unsigned int numPermutations = 1;
80 numPermutations <<= InputImageType::ImageDimension;
82 while (allAboveMinSize && (tmpSizes.size() < m_NumberOfLevels))
84 previousRegion = tmpSizes.back();
85 previousSpacing = tmpSpacings.back();
86 newRegion = previousRegion;
87 newSpacing = previousSpacing;
88 for (
unsigned int j = 0;j < InputImageType::ImageDimension;++j)
90 if (changeableSizes[j])
92 unsigned int oldSize = newRegion.GetSize()[j];
93 unsigned int tmpSize = (
unsigned int)ceil(std::max(oldSize / 2.0, (
double)minSize));
94 newRegion.SetSize(j,tmpSize);
96 newSpacing[j] = newSpacing[j] * oldSize / newRegion.GetSize()[j];
100 double bestAnisotropy = 1.0;
101 unsigned int bestIndex = 0;
103 for (
unsigned int counter = 1; counter < numPermutations; ++counter)
105 testSpacing = previousSpacing;
106 unsigned int upper = counter;
107 bool usefulConfiguration =
false;
108 for (
unsigned int dim = 0; dim < InputImageType::ImageDimension; ++dim)
110 if ((upper & 1) && changeableSizes[dim])
112 usefulConfiguration =
true;
119 if (!usefulConfiguration)
123 for(
unsigned int dim = 0; dim < InputImageType::ImageDimension; ++dim)
126 testSpacing[dim] = newSpacing[dim];
131 double testAnisotropy = this->AnisotropyMeasure(testSpacing,changeableSizes);
134 if (testAnisotropy <= bestAnisotropy)
137 bestAnisotropy = testAnisotropy;
142 unsigned int upper = bestIndex;
143 for(
unsigned int dim = 0; dim < InputImageType::ImageDimension; ++dim)
147 newSpacing[dim] = previousSpacing[dim];
148 newRegion.SetSize(dim,previousRegion.GetSize()[dim]);
154 allAboveMinSize =
true;
155 for (
unsigned int j = 0;j < InputImageType::ImageDimension;++j)
157 if ((newRegion.GetSize()[j] <= minSize)&&(changeableSizes[j]))
159 allAboveMinSize =
false;
160 newRegion.SetSize(j,minSize);
161 newSpacing[j] = previousSpacing[j] * previousRegion.GetSize()[j] / minSize;
165 tmpSizes.push_back(newRegion);
166 tmpSpacings.push_back(newSpacing);
169 if (tmpSpacings.size() < m_NumberOfLevels)
170 m_NumberOfLevels = tmpSpacings.size();
172 m_LevelSpacings.clear();
173 m_LevelRegions.clear();
175 for (
unsigned int i = m_NumberOfLevels;i > 0;--i)
177 m_LevelSpacings.push_back(tmpSpacings[i-1]);
178 m_LevelRegions.push_back(tmpSizes[i-1]);
182 template <
class TInputImage,
class TOutputImage>
187 if (!m_ImageResampler)
188 itkExceptionMacro(
"Image resampler for pyramid filter not provided");
190 this->CheckNumberOfLevels();
192 this->SetNumberOfRequiredOutputs(m_NumberOfLevels);
193 for (
unsigned int i = 0;i < m_NumberOfLevels;++i)
194 this->SetNthOutput(i,this->MakeOutput(i));
198 for (
unsigned int i = m_NumberOfLevels;i > 0;--i)
200 if (vectorInputImages)
201 this->CreateLevelVectorImage(i-1);
203 this->CreateLevelImage(i-1);
207 template <
class TInputImage,
class TOutputImage>
213 if (level == (
unsigned int)(m_NumberOfLevels - 1))
214 previousLevelImage = this->GetInput();
216 previousLevelImage = this->GetOutput(level+1);
220 typedef itk::MatrixOffsetTransformBase <double,InputImageType::ImageDimension> MatrixTrsfType;
221 typedef itk::Transform <double,InputImageType::ImageDimension,InputImageType::ImageDimension> BaseTrsfType;
222 typename MatrixTrsfType::Pointer idTrsf = MatrixTrsfType::New();
223 idTrsf->SetIdentity();
225 typename BaseTrsfType::Pointer baseTrsf = idTrsf.GetPointer();
229 typename ResamplerType::Pointer resample = dynamic_cast <ResamplerType *> (m_ImageResampler->Clone().GetPointer());
230 resample->SetNumberOfWorkUnits(this->GetNumberOfWorkUnits());
233 itk::ContinuousIndex <double,TInputImage::ImageDimension> borderOrigin;
234 borderOrigin.Fill(-0.5);
236 typename TInputImage::PointType borderPoint;
237 previousLevelImage->TransformContinuousIndexToPhysicalPoint(borderOrigin,borderPoint);
239 typename TInputImage::DirectionType newDirectionMatrix = previousLevelImage->GetDirection();
240 typename TInputImage::DirectionType newScaleMatrix;
241 newScaleMatrix.SetIdentity();
243 for (
unsigned int i = 0;i < TInputImage::ImageDimension;++i)
244 newScaleMatrix(i,i) = m_LevelSpacings[level][i];
246 newDirectionMatrix *= newScaleMatrix;
248 for (
unsigned int i = 0;i < TInputImage::ImageDimension;++i)
249 for (
unsigned int j = 0;j < TInputImage::ImageDimension;++j)
250 borderPoint[i] += newDirectionMatrix(i,j) * 0.5;
254 resample->SetOutputLargestPossibleRegion(m_LevelRegions[level]);
255 resample->SetOutputSpacing(m_LevelSpacings[level]);
256 resample->SetOutputDirection(this->GetInput()->GetDirection());
258 resample->SetInput(previousLevelImage);
260 resample->SetTransform(baseTrsf);
264 levelImage = resample->GetOutput();
265 levelImage->DisconnectPipeline();
267 this->GraftNthOutput(level, levelImage);
270 template <
class TInputImage,
class TOutputImage>
276 if (level == (
unsigned int)(m_NumberOfLevels - 1))
283 typedef itk::IdentityTransform<double,InputImageType::ImageDimension> IdTrsfType;
284 typename IdTrsfType::Pointer idTrsf = IdTrsfType::New();
285 idTrsf->SetIdentity();
289 typename ResamplerType::Pointer resample = dynamic_cast <ResamplerType *> (m_ImageResampler->Clone().GetPointer());
292 resample->SetNumberOfWorkUnits(this->GetNumberOfWorkUnits());
295 itk::ContinuousIndex <double,TInputImage::ImageDimension> borderOrigin;
296 borderOrigin.Fill(-0.5);
298 typename TInputImage::PointType borderPoint;
299 previousLevelImage->TransformContinuousIndexToPhysicalPoint(borderOrigin,borderPoint);
301 typename TInputImage::DirectionType newDirectionMatrix = previousLevelImage->GetDirection();
302 typename TInputImage::DirectionType newScaleMatrix;
303 newScaleMatrix.SetIdentity();
305 for (
unsigned int i = 0;i < TInputImage::ImageDimension;++i)
306 newScaleMatrix(i,i) = m_LevelSpacings[level][i];
308 newDirectionMatrix *= newScaleMatrix;
310 for (
unsigned int i = 0;i < TInputImage::ImageDimension;++i)
311 for (
unsigned int j = 0;j < TInputImage::ImageDimension;++j)
312 borderPoint[i] += newDirectionMatrix(i,j) * 0.5;
314 resample->SetOutputOrigin(borderPoint);
316 resample->SetSize(m_LevelRegions[level].GetSize());
317 resample->SetOutputSpacing(m_LevelSpacings[level]);
318 resample->SetOutputDirection(previousLevelImage->GetDirection());
320 resample->SetInput(previousLevelImage);
323 levelImage = resample->GetOutput();
324 levelImage->DisconnectPipeline();
326 this->SetNthOutput(level, levelImage);
void GenerateData() ITK_OVERRIDE
virtual void SetOutputOrigin(OriginPointType _arg)
InputImageType::RegionType RegionType
void CreateLevelVectorImage(unsigned int level)
void CheckNumberOfLevels()
itk::Image< typename TInputImage::IOPixelType, TInputImage::ImageDimension > ScalarInputImageType
itk::VectorImage< typename TInputImage::IOPixelType, TInputImage::ImageDimension > VectorInputImageType
TInputImage InputImageType
double AnisotropyMeasure(SpacingType &sp, std::vector< bool > &changeableSizes)
ScalarOutputImageType::Pointer ScalarOutputImagePointer
void SetTransform(TransformType *transform)
void CreateLevelImage(unsigned int level)
InputImageType::SpacingType SpacingType
OutputImageType::Pointer OutputImagePointer