Skip to content

Commit

Permalink
BUG: ComputeImageExtremaFilter SameGeometry include Spacing, Direction
Browse files Browse the repository at this point in the history
Fixes issue #1023 "ComputeImageExtremaFilter SameGeometry should include Index, Spacing, and Direction"

Tested that changes of Spacing or Direction of the mask may indeed affect the results of ComputeImageExtremaFilter.
  • Loading branch information
N-Dekker committed Jan 23, 2024
1 parent 5a36e0f commit 47d2242
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 3 deletions.
71 changes: 71 additions & 0 deletions Common/GTesting/itkComputeImageExtremaFilterGTest.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,10 @@
// First include the header file to be tested:
#include "itkComputeImageExtremaFilter.h"
#include "../Core/Main/GTesting/elxCoreMainGTestUtilities.h"
#include "elxDefaultConstruct.h"

#include <itkImage.h>
#include <itkImageBufferRange.h>

#include <gtest/gtest.h>

Expand All @@ -35,6 +37,7 @@ using itk::ComputeImageExtremaFilter;

// Using-declaration:
using elx::CoreMainGTestUtilities::CheckNew;
using elx::CoreMainGTestUtilities::CreateImage;

namespace
{
Expand Down Expand Up @@ -296,3 +299,71 @@ GTEST_TEST(ComputeImageExtremaFilter, OneNonZeroPixelValueMaskedIn)
Expect_one_non_zero_pixel_value_masked_in<itk::Image<short, 3>>({ { 2, 3, 4 } });
Expect_one_non_zero_pixel_value_masked_in<itk::Image<unsigned char, 4>>({ { 2, 3, 4, 5 } });
}


// Changes of the mask Spacing and Direction with respect to the input image may affect the results.
GTEST_TEST(ComputeImageExtremaFilter, MaskSpacingAndDirectionAffectResults)
{
using PixelType = int;
enum
{
Dimension = 2U
};
enum class MaskChange
{
None,
Spacing,
Direction
};

using ImageType = itk::Image<PixelType, Dimension>;
using FilterType = ComputeImageExtremaFilter<ImageType>;
using ImageSpatialMaskType = FilterType::ImageSpatialMaskType;
using MaskImageType = ImageSpatialMaskType::ImageType;

const auto computeMaximum = [](const MaskChange maskChange) {
const auto imageSize = itk::Size<Dimension>::Filled(4);

const auto image = CreateImage<PixelType>(imageSize);
const auto maskImage = CreateImage<MaskPixelType>(imageSize);

// Set specific non-zero values at the first and the last pixel. All other pixels have value zero.
*(itk::ImageBufferRange{ *image }.begin()) = PixelType{ 1 };
*(itk::ImageBufferRange{ *image }.rbegin()) = PixelType{ 2 };

// Include only the first and the last pixel under the mask. All other mask entries are zero (false).
*(itk::ImageBufferRange{ *maskImage }.begin()) = MaskPixelType{ 1 };
*(itk::ImageBufferRange{ *maskImage }.rbegin()) = MaskPixelType{ 1 };

if (maskChange == MaskChange::Spacing)
{
// Change the spacing of the mask, so that the last pixel is no longer "under the mask".
maskImage->SetSpacing(itk::MakeFilled<MaskImageType::SpacingType>(0.5));
}
else
{
if (maskChange == MaskChange::Direction)
{
// Reverse the direction of the mask, so that the last pixel is no longer "under the mask".
maskImage->SetDirection(image->GetDirection() * -1.0);
}
}

const auto maskSpatialObject = ImageSpatialMaskType::New();
maskSpatialObject->SetImage(maskImage);
maskSpatialObject->Update();

elastix::DefaultConstruct<FilterType> filter{};
filter.SetInput(image);
filter.SetImageSpatialMask(maskSpatialObject);
filter.SetUseMask(true);

filter.Update();
return filter.GetMaximum();
};

const auto maximumWithoutMaskChanges = computeMaximum(MaskChange::None);

EXPECT_NE(computeMaximum(MaskChange::Spacing), maximumWithoutMaskChanges);
EXPECT_NE(computeMaximum(MaskChange::Direction), maximumWithoutMaskChanges);
}
9 changes: 6 additions & 3 deletions Common/itkComputeImageExtremaFilter.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,12 @@ template <typename TInputImage>
void
ComputeImageExtremaFilter<TInputImage>::SameGeometry()
{
if (this->GetInput()->GetLargestPossibleRegion().GetSize() ==
this->m_ImageSpatialMask->GetImage()->GetLargestPossibleRegion().GetSize() &&
this->GetInput()->GetOrigin() == this->m_ImageSpatialMask->GetImage()->GetOrigin())
const ImageBase<ImageDimension> & inputImage = *(this->GetInput());
const ImageBase<ImageDimension> & maskImage = *(this->m_ImageSpatialMask->GetImage());

if (inputImage.GetLargestPossibleRegion() == maskImage.GetLargestPossibleRegion() &&
inputImage.GetOrigin() == maskImage.GetOrigin() && inputImage.GetSpacing() == maskImage.GetSpacing() &&
inputImage.GetDirection() == maskImage.GetDirection())
{
this->m_SameGeometry = true;
}
Expand Down

0 comments on commit 47d2242

Please sign in to comment.