Skip to content

Commit

Permalink
ENH: Improve the Watershed module code coverage.
Browse files Browse the repository at this point in the history
Exercise basic object methods.

Exercise all Set/Get methods using the TEST_SET_GET_VALUE macro. Remove
the calls to print the result of the Get methods.

Refactor the itkIsolatedWatershedImageFilterTest.cxx so that the close
thresholds condition is exercised by specifying the corresponding test
input parameters through the CMakeLists.txt. Use the MD5 hash for the
newly added test baseline comparison.

Move the tests' Baselines from the general ITK
Testing/Data/Baseline/Algorithms and Testing/Data/Baseline/BasicFilters to
the module's Baseline folder. This allows to reduce the data downloaded
depending on the modules activated.

Improve the style of the tests: use of white spaces to be consistent with
the ITK style, indentation, naming of variables, declaration of the image
dimension as a const, etc.

Change-Id: I23da6fb6aef94cfee5d11dd67f7a71a99bc36589
  • Loading branch information
Jon Haitz Legarreta committed Mar 14, 2017
1 parent 1b666d2 commit 3f65599
Show file tree
Hide file tree
Showing 11 changed files with 244 additions and 229 deletions.
@@ -0,0 +1 @@
b19ea6df9f910060bb62fa5e983c59f1
@@ -0,0 +1 @@
edc580d50b7d98d89997423ae7d043bd
@@ -0,0 +1 @@
e51a9e5973dcd8fe01c23495bc46023a
17 changes: 11 additions & 6 deletions Modules/Segmentation/Watersheds/test/CMakeLists.txt
Expand Up @@ -11,14 +11,19 @@ CreateTestDriver(ITKWatersheds "${ITKWatersheds-Test_LIBRARIES}" "${ITKWatershe

itk_add_test(NAME itkTobogganImageFilterTest
COMMAND ITKWatershedsTestDriver
--compare DATA{${ITK_DATA_ROOT}/Baseline/BasicFilters/TobogganImageFilterTest.png}
${ITK_TEST_OUTPUT_DIR}/TobogganImageFilterTest.png
itkTobogganImageFilterTest DATA{${ITK_DATA_ROOT}/Input/cthead1.png} ${ITK_TEST_OUTPUT_DIR}/TobogganImageFilterTest.png)
--compare DATA{Baseline/itkTobogganImageFilterTest.png}
${ITK_TEST_OUTPUT_DIR}/itkTobogganImageFilterTest.png
itkTobogganImageFilterTest DATA{${ITK_DATA_ROOT}/Input/cthead1.png} ${ITK_TEST_OUTPUT_DIR}/itkTobogganImageFilterTest.png)
itk_add_test(NAME itkIsolatedWatershedImageFilterTest
COMMAND ITKWatershedsTestDriver
--compare DATA{${ITK_DATA_ROOT}/Baseline/Algorithms/IsolatedWatershedImageFilterTest.png}
${ITK_TEST_OUTPUT_DIR}/IsolatedWatershedImageFilterTest.png
itkIsolatedWatershedImageFilterTest DATA{${ITK_DATA_ROOT}/Input/cthead1.png} ${ITK_TEST_OUTPUT_DIR}/IsolatedWatershedImageFilterTest.png 113 84 120 99)
--compare DATA{Baseline/itkIsolatedWatershedImageFilterTest.png}
${ITK_TEST_OUTPUT_DIR}/itkIsolatedWatershedImageFilterTest.png
itkIsolatedWatershedImageFilterTest DATA{${ITK_DATA_ROOT}/Input/cthead1.png} ${ITK_TEST_OUTPUT_DIR}/itkIsolatedWatershedImageFilterTest.png 113 84 120 99 0.001 .0001)
itk_add_test(NAME itkIsolatedWatershedImageFilterTestCloseThresholds
COMMAND ITKWatershedsTestDriver
--compare-MD5 DATA{Baseline/itkIsolatedWatershedImageFilterTestCloseThresholds.png}
b53800712fb3b5a376c2f8234e1ebac5
itkIsolatedWatershedImageFilterTest DATA{${ITK_DATA_ROOT}/Input/cthead1.png} ${ITK_TEST_OUTPUT_DIR}/itkIsolatedWatershedImageFilterTestCloseThresholds.png 113 84 120 99 0.1 1.0)
itk_add_test(NAME itkWatershedImageFilterTest
COMMAND ITKWatershedsTestDriver itkWatershedImageFilterTest)

Expand Down
Expand Up @@ -16,131 +16,104 @@
*
*=========================================================================*/

#include <fstream>
#include "itkIsolatedWatershedImageFilter.h"
#include "itkImageFileReader.h"
#include "itkImageFileWriter.h"
#include "itkTestingMacros.h"

int itkIsolatedWatershedImageFilterTest(int ac, char* av[] )
#include <fstream>


int itkIsolatedWatershedImageFilterTest( int argc, char* argv[] )
{
if(ac < 7)
if( argc < 9 )
{
std::cerr << "Usage: " << av[0] << " InputImage OutputImage seed1_x seed1_y seed2_x seed2_y\n";
std::cerr << "Missing parameters" << std::endl;
std::cerr << "Usage: " << argv[0]
<< " InputImage"
<< " OutputImage"
<< " seed1_x"
<< " seed1_y"
<< " seed2_x"
<< " seed2_y"
<< " threshold"
<< " isolatedValueTolerance";
std::cerr << std::endl;
return EXIT_FAILURE;
}

typedef unsigned char PixelType;
typedef itk::Image<PixelType, 2> InputImageType;
const unsigned int Dimension = 2;

typedef unsigned char PixelType;
typedef itk::Image< PixelType, Dimension > ImageType;

itk::ImageFileReader< ImageType >::Pointer reader =
itk::ImageFileReader< ImageType >::New();

reader->SetFileName( argv[1] );

itk::ImageFileReader<InputImageType>::Pointer input =
itk::ImageFileReader<InputImageType>::New();
TRY_EXPECT_NO_EXCEPTION( reader->Update() );

input->SetFileName(av[1]);

// Create a filter
typedef itk::IsolatedWatershedImageFilter<InputImageType, InputImageType> FilterType;
// Create the IsolatedWatershedImageFilter object
typedef itk::IsolatedWatershedImageFilter< ImageType, ImageType > FilterType;

FilterType::Pointer filter = FilterType::New();

EXERCISE_BASIC_OBJECT_METHODS( filter, IsolatedWatershedImageFilter, ImageToImageFilter );

filter->SetInput(input->GetOutput());

FilterType::IndexType seed1;

seed1[0] = atoi(av[3]); seed1[1] = atoi(av[4]);
filter->SetSeed1(seed1);

seed1[0] = atoi(av[5]); seed1[1] = atoi(av[6]);
filter->SetSeed2(seed1);

filter->SetThreshold(0.001);
filter->SetReplaceValue1(255);
filter->SetReplaceValue2(127);
filter->SetUpperValueLimit(1);

// Test SetMacro
filter->SetIsolatedValueTolerance(.0001);

// Test GetMacros
double threshold = filter->GetThreshold();
std::cout << "filter->GetThreshold(): "
<< threshold
<< std::endl;
double isolatedValueTolerance = filter->GetIsolatedValueTolerance();
std::cout << "filter->GetIsolatedValueTolerance(): "
<< isolatedValueTolerance
<< std::endl;
double upperValueLimit = filter->GetUpperValueLimit();
std::cout << "filter->GetUpperValueLimit(): "
<< upperValueLimit
<< std::endl;
PixelType replaceValue1 = filter->GetReplaceValue1();
std::cout << "filter->GetReplaceValue1(): "
<< static_cast<itk::NumericTraits<PixelType>::PrintType>(replaceValue1)
<< std::endl;
PixelType replaceValue2 = filter->GetReplaceValue2();
std::cout << "filter->GetReplaceValue2(): "
<< static_cast<itk::NumericTraits<PixelType>::PrintType>(replaceValue2)
<< std::endl;

try
{
input->Update();
filter->Update();
double isolatedValue = filter->GetIsolatedValue();
std::cout << "filter->GetIsolatedValue(): "
<< isolatedValue
<< std::endl;
}
catch (itk::ExceptionObject& e)
{
std::cerr << "Exception detected: " << e.GetDescription();
return EXIT_FAILURE;
}
EXERCISE_BASIC_OBJECT_METHODS( filter, IsolatedWatershedImageFilter,
ImageToImageFilter );

// Generate test image
itk::ImageFileWriter<InputImageType>::Pointer writer;
writer = itk::ImageFileWriter<InputImageType>::New();
writer->SetInput( filter->GetOutput() );
writer->SetFileName( av[2] );
writer->Update();
FilterType::IndexType seed1, seed2;

//
// Test when lower and upper thresholds are "close", expect the
// filter not to crash, and complete
//
seed1[0] = atoi( argv[3] );
seed1[1] = atoi( argv[4] );
filter->SetSeed1( seed1 );
TEST_SET_GET_VALUE( seed1, filter->GetSeed1() );

filter = FilterType::New();
seed2[0] = atoi( argv[5] );
seed2[1] = atoi( argv[6] );
filter->SetSeed2( seed2 );
TEST_SET_GET_VALUE( seed2, filter->GetSeed2() );

filter->SetInput(input->GetOutput());
double threshold = atof( argv[7] );
filter->SetThreshold( threshold );
TEST_SET_GET_VALUE( threshold, filter->GetThreshold() );

seed1[0] = atoi(av[3]); seed1[1] = atoi(av[4]);
filter->SetSeed1(seed1);
PixelType replaceValue1 = 255;
filter->SetReplaceValue1( replaceValue1 );
TEST_SET_GET_VALUE( replaceValue1, filter->GetReplaceValue1() );

seed1[0] = atoi(av[5]); seed1[1] = atoi(av[6]);
filter->SetSeed2(seed1);
PixelType replaceValue2 = 127;
filter->SetReplaceValue2( replaceValue2 );
TEST_SET_GET_VALUE( replaceValue2, filter->GetReplaceValue2() );

filter->SetThreshold(.1);
filter->SetIsolatedValueTolerance(1.0);
filter->SetReplaceValue1(255);
filter->SetReplaceValue2(127);
filter->SetUpperValueLimit(1);
double upperValueLimit = 1.0;
filter->SetUpperValueLimit( upperValueLimit );
TEST_SET_GET_VALUE( upperValueLimit, filter->GetUpperValueLimit() );

double isolatedValueTolerance = atof( argv[8] );
filter->SetIsolatedValueTolerance( isolatedValueTolerance );
TEST_SET_GET_VALUE( isolatedValueTolerance,
filter->GetIsolatedValueTolerance() );


filter->SetInput( reader->GetOutput() );

TRY_EXPECT_NO_EXCEPTION( filter->Update() );


double isolatedValue = filter->GetIsolatedValue();
std::cout << "IsolatedValue: " << isolatedValue << std::endl;

// Write the filter output
typedef itk::ImageFileWriter< ImageType > WriterType;
WriterType::Pointer writer = WriterType::New();
writer->SetInput( filter->GetOutput() );
writer->SetFileName( argv[2] );

TRY_EXPECT_NO_EXCEPTION( writer->Update() );

try
{
filter->Update();
double isolatedValue = filter->GetIsolatedValue();
std::cout << "filter->GetIsolatedValue(): "
<< isolatedValue
<< std::endl;
}
catch (itk::ExceptionObject& e)
{
std::cerr << "Exception detected: " << e.GetDescription();
return EXIT_FAILURE;
}

std::cout << "Test finished." << std::endl;
return EXIT_SUCCESS;
}
100 changes: 56 additions & 44 deletions Modules/Segmentation/Watersheds/test/itkTobogganImageFilterTest.cxx
Expand Up @@ -22,68 +22,80 @@
#include "itkImageFileReader.h"
#include "itkImageFileWriter.h"
#include "itkTextOutput.h"
#include "itkTestingMacros.h"


int itkTobogganImageFilterTest(int ac, char* av[] )
int itkTobogganImageFilterTest( int argc, char* argv[] )
{
// Comment the following if you want to use the itk text output window
itk::OutputWindow::SetInstance(itk::TextOutput::New());

if(ac < 3)
if( argc < 3 )
{
std::cerr << "Usage: " << av[0] << " InputImage OutputImage\n";
exit ( 1 );
std::cerr << "Missing parameters" << std::endl;
std::cerr << "Usage: " << argv[0] << " InputImage OutputImage" << std::endl;
return EXIT_FAILURE;
}


const unsigned int Dimension = 2;
typedef unsigned char PixelType;
typedef itk::Image<PixelType, Dimension> InputImageType;
typedef itk::Image<float, Dimension> FloatImageType;
typedef itk::Image<PixelType, Dimension> OutputImageType;
typedef itk::Image< itk::IdentifierType, Dimension> LongImageType;

typedef unsigned char PixelType;
typedef float FloatPixelType;
typedef itk::Image< PixelType, Dimension > InputImageType;
typedef itk::Image< FloatPixelType, Dimension > FloatImageType;
typedef itk::Image< PixelType, Dimension > OutputImageType;
typedef itk::Image< itk::IdentifierType, Dimension > LongImageType;


// Create a pipeline
typedef itk::CastImageFilter<InputImageType, FloatImageType>
InCastType;
typedef itk::TobogganImageFilter<FloatImageType>
typedef itk::CastImageFilter< InputImageType, FloatImageType >
InputCastFilterType;
typedef itk::TobogganImageFilter< FloatImageType >
FilterType;
typedef itk::CastImageFilter<LongImageType, OutputImageType>
CastType;
typedef itk::GradientMagnitudeRecursiveGaussianImageFilter<FloatImageType,FloatImageType>
typedef itk::CastImageFilter< LongImageType, OutputImageType >
OutputCastFilterType;
typedef itk::GradientMagnitudeRecursiveGaussianImageFilter< FloatImageType, FloatImageType >
GMGaussianType;


itk::ImageFileReader< InputImageType >::Pointer reader =
itk::ImageFileReader< InputImageType >::New();

reader->SetFileName( argv[1] );

TRY_EXPECT_NO_EXCEPTION( reader->Update() );


FilterType::Pointer toboggan = FilterType::New();
CastType::Pointer cast = CastType::New();
InCastType::Pointer incast = InCastType::New();

EXERCISE_BASIC_OBJECT_METHODS( toboggan, TobogganImageFilter,
ImageToImageFilter );

InputCastFilterType::Pointer inputCaster = InputCastFilterType::New();
GMGaussianType::Pointer gmgaussian = GMGaussianType::New();

itk::ImageFileReader<InputImageType>::Pointer input
= itk::ImageFileReader<InputImageType>::New();
inputCaster->SetInput( reader->GetOutput() );
gmgaussian->SetInput( inputCaster->GetOutput() );
gmgaussian->SetSigma( 15.0 );

input->SetFileName(av[1]);
incast->SetInput ( input->GetOutput() );
gmgaussian->SetInput ( incast->GetOutput() );
gmgaussian->SetSigma ( 15.0 );
toboggan->SetInput ( gmgaussian->GetOutput() );
cast->SetInput ( toboggan->GetOutput() );
try
{
input->Update();
cast->Update();
}
catch (itk::ExceptionObject& e)
{
std::cerr << "Exception detected: " << e.GetDescription();
exit ( 1 );
}
toboggan->SetInput( gmgaussian->GetOutput() );


TRY_EXPECT_NO_EXCEPTION( toboggan->Update() );


// Cast the output of the Toboggan filter
OutputCastFilterType::Pointer outputCaster = OutputCastFilterType::New();
outputCaster->SetInput( toboggan->GetOutput() );

TRY_EXPECT_NO_EXCEPTION( outputCaster->Update() );

// Write the output
typedef itk::ImageFileWriter< OutputImageType > WriterType;
WriterType::Pointer writer = WriterType::New();
writer->SetInput( outputCaster->GetOutput() );
writer->SetFileName( argv[2] );

TRY_EXPECT_NO_EXCEPTION( writer->Update() );

itk::ImageFileWriter<OutputImageType>::Pointer writer;
writer = itk::ImageFileWriter<OutputImageType>::New();
writer->SetInput( cast->GetOutput() );
writer->SetFileName( av[2] );
writer->Update();

std::cout << "Test finished." << std::endl;
return EXIT_SUCCESS;
}

0 comments on commit 3f65599

Please sign in to comment.