Skip to content

Commit

Permalink
BUG: Use GenerateOutputInformation and pipeline isolation
Browse files Browse the repository at this point in the history
The TransformGeometryImageFilter::GenerateData method was refactored
for correct pipeline behavior. The output Image's meta-data is
correctly modifed in the GenerateOutputInformation method, so that
down stream filters can uses the information. The composite pipeline
is not isolated from the inputs and output using the double graft
convention. However, only the bulk data pointer and buffered region
are copied to the output, as not to change the geometry information
previously set.
  • Loading branch information
blowekamp authored and hjmjohnson committed Sep 10, 2021
1 parent 2de73ab commit 374940a
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -142,18 +142,20 @@ class ITK_TEMPLATE_EXPORT TransformGeometryImageFilter : public ImageToImageFilt
using RigidTransformType = VersorRigid3DTransform<double>;
using RigidTransformConstPointer = typename RigidTransformType::ConstPointer;

/** Set/Get rigid transform. The default is an identity transform */
/** Set/Get required rigid transform. */
itkSetGetDecoratedObjectInputMacro(RigidTransform, RigidTransformType);

/** Set/Get required input image. (A wrapper to this->Set/GetInput()) */
itkSetInputMacro(InputImage, InputImageType);

itkGetInputMacro(InputImage, InputImageType);

protected:
TransformGeometryImageFilter();
~TransformGeometryImageFilter() override = default;

void
GenerateOutputInformation() override;

void
GenerateData() override;
};
Expand Down
57 changes: 33 additions & 24 deletions Modules/Core/Transform/include/itkTransformGeometryImageFilter.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -33,51 +33,60 @@ TransformGeometryImageFilter<TInputImage, TOutputImage>::TransformGeometryImageF

// "RigidTransform" required ( not numbered )
Self::AddRequiredInputName("RigidTransform");

// initialize transform
}


template <typename TInputImage, typename TOutputImage>
void
TransformGeometryImageFilter<TInputImage, TOutputImage>::GenerateData()
TransformGeometryImageFilter<TInputImage, TOutputImage>::GenerateOutputInformation()
{
if (!this->GetInput())
{
itkExceptionMacro(<< "Input image has not been connected");
return;
}

typename OutputImageType::Pointer outputPtr;
Superclass::GenerateOutputInformation();

// SEE HEADER FILE FOR MATH DESCRIPTION

{
/** make a cast copied version of the input image **/
using DuplicatorType = CastImageFilter<InputImageType, OutputImageType>;
typename DuplicatorType::Pointer CastFilter = DuplicatorType::New();
CastFilter->SetInput(this->GetInput());
CastFilter->Update();
outputPtr = CastFilter->GetOutput();
}
OutputImageType * outputPtr = this->GetOutput();
const InputImageType * inputPtr = this->GetInputImage();

// SEE HEADER FILE FOR MATH DESCRIPTION
RigidTransformConstPointer FMTxfm = this->GetRigidTransform();
const typename RigidTransformType::MatrixType inverseRotation(FMTxfm->GetMatrix().GetInverse());

// Modify the origin and direction info of the image to reflect the transform.
itk::Vector<double, 3> newOriginVector =
inverseRotation * (this->GetInput()->GetOrigin().GetVectorFromOrigin() - FMTxfm->GetCenter().GetVectorFromOrigin() -
Vector<double, 3> newOriginVector =
inverseRotation * (inputPtr->GetOrigin().GetVectorFromOrigin() - FMTxfm->GetCenter().GetVectorFromOrigin() -
FMTxfm->GetTranslation()) // NewOrigin = [R^-1] * ( O - C - T ) + C
+ FMTxfm->GetCenter().GetVectorFromOrigin();
itk::Point<double, 3> newOriginPoint;
Point<double, 3> newOriginPoint;
for (int i = 0; i < 3; ++i)
{
newOriginPoint[i] = newOriginVector[i];
}
outputPtr->SetOrigin(newOriginPoint);
outputPtr->SetDirection(inverseRotation * this->GetInput()->GetDirection()); // NewDC = [R^-1][DC]
outputPtr->SetDirection(inverseRotation * inputPtr->GetDirection()); // NewDC = [R^-1][DC]
}


template <typename TInputImage, typename TOutputImage>
void
TransformGeometryImageFilter<TInputImage, TOutputImage>::GenerateData()
{
OutputImageType * output = this->GetOutput();

auto input = InputImageType::New();
input->Graft(const_cast<InputImageType *>(this->GetInput()));

// SEE HEADER FILE FOR MATH DESCRIPTION

/** make a cast copied version of the input image **/
using DuplicatorType = CastImageFilter<InputImageType, OutputImageType>;
typename DuplicatorType::Pointer castFilter = DuplicatorType::New();
castFilter->SetInput(input);

castFilter->GraftOutput(this->GetOutput());
castFilter->Update();


this->GraftOutput(outputPtr);
// Can't use graft as it will overwrite the new meta-data
output->SetPixelContainer(castFilter->GetOutput()->GetPixelContainer());
}

} // end namespace itk
Expand Down

0 comments on commit 374940a

Please sign in to comment.