Commit 8bddcd54 authored by hjohnson's avatar hjohnson
Browse files

ENH: Adding in test suite of tools to svn.

git-svn-id: http://svn.slicer.org/Slicer4/trunk@13133 3bd1e089-480b-0410-8dfb-8563597acbee
parent 20adb047
##The start of a test program for this filter.
## HACK-- This still needs to be finalized, and tests written.
set(TestName TestLargestForegroundFilledMaskImageFilter)
add_executable(${TestName} ${TestName}.cxx)
target_link_libraries(${TestName})${ITK_LIBRARIES}
#include "itkLargestForegroundFilledMaskImageFilter.h"
#include "itkIO.h"
#include <string>
int
main(int argc, char **argv)
{
if(argc < 3)
{
std::cerr << "TestLargestForegrounFilledMaskImageFilter <input image> <output image>"
<< std::endl;
exit(1);
}
typedef itk::Image<float,3> ImageType;
typedef itk::LargestForegroundFilledMaskImageFilter<ImageType>
FilterType;
std::string inputname(argv[1]);
std::string outputname(argv[2]);
ImageType::Pointer image = itkUtil::ReadImage<ImageType>(inputname);
FilterType::Pointer filter = FilterType::New();
filter->SetInput(image);
filter->Update();
ImageType::Pointer outputImage = filter->GetOutput();
itkUtil::WriteImage<ImageType>(outputImage,outputname);
return 0;
}
#
# This is rather a problem: FindCenterOfBrainFilter is included in more than one
# NITRC based BRAINS Project, which means that BRAINSFit_SOURCE_DIR is not always
# defined.
#
# In practice, this is only a problem if programs other than BRAINSFit actually
# add FindCenterOfBrainFilter as a subdirectory, rather than just using it for the
# include files.
#
# But if a build fails because someone added it to a non-brainsfit application, I
# hope they look at this file and read this comment, and CUT THAT BUSINESS RIGHT OUT.
# Unless this is a subdirectory of BRAINSFit, there's NO USE adding it as a subdirectory
# in the CMakeLists.txt. It will just end in tears.
#
INCLUDE_DIRECTORIES(${BRAINSFit_SOURCE_DIR}/BRAINSFit_Common)
INCLUDE_DIRECTORIES(${BRAINSFit_SOURCE_DIR}/LargestForegroundFilledMaskImageFilter)
INCLUDE_DIRECTORIES(${BRAINSFit_SOURCE_DIR}/FindCenterOfBrainFilter)
ENABLE_TESTING()
include(Dart)
SET(FindCenterOfBrain_SRC
FindCenterOfBrainCLP.cxx)
generateclp(FindCenterOfBrain_SRC FindCenterOfBrain.xml)
ADD_EXECUTABLE(FindCenterOfBrain ${FindCenterOfBrain_SRC})
TARGET_LINK_LIBRARIES(FindCenterOfBrain
ITKAlgorithms
ITKStatistics
ITKIO
ITKBasicFilters
ITKCommon
ITKNumerics)
IF(NOT BRAINS_BUILD)
ADD_EXECUTABLE(ImageCompare ImageCompare.cxx)
TARGET_LINK_LIBRARIES(ImageCompare ITKIO ITKNumerics ITKStatistics)
ENDIF(NOT BRAINS_BUILD)
set(FINDCENTER_PROG ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/FindCenterOfBrain)
ADD_TEST(RudimentaryFindCenterOfBrainTest tclsh ${CMAKE_CURRENT_SOURCE_DIR}}/TestData/FindCenterOfBrainFilter/Test/TestFCOB.tcl
${CMAKE_RUNTIME_OUTPUT_DIRECTORY}
${BRAINSFit_SOURCE_DIR}/TestData
${BRAINSFit_BINARY_DIR}/Testing
${BRAINSFit_SOURCE_DIR}/TestData/ANON0006_20_T1_dbg_splayed.nii.gz
)
<?xml version="1.0" encoding="utf-8"?>
<executable>
<category>Utility</category>
<title>FindCenterOfBrain</title>
<description>Finds the center point of a brain</description>
<documentation-url></documentation-url>
<license>https://www.nitrc.org/svn/brains/BuildScripts/trunk/License.txt </license>
<contributor>Hans J. Johnson, hans-johnson -at- uiowa.edu, http://wwww.psychiatry.uiowa.edu</contributor>
<acknowledgements>Hans Johnson(1,3,4); Kent Williams(1); Gregory Harris(1), Vincent Magnotta(1,2,3); Andriy Fedorov(5), fedorov -at- bwh.harvard.edu (Slicer integration); (1=University of Iowa Department of Psychiatry, 2=University of Iowa Department of Radiology, 3=University of Iowa Department of Biomedical Engineering, 4=University of Iowa Department of Electrical and Computer Engineering, 5=Surgical Planning Lab, Harvard) </acknowledgements>
<version>3.0.0</version>
<parameters advanced="false">
<label>Required Input Parameters</label>
<image>
<name>InputVolume</name>
<longflag>--inputVolume</longflag>
<label>Input Image Volume</label>
<description>The image in which to find the center.</description>
<channel>input</channel>
<default></default>
</image>
<image>
<name>ImageMask</name>
<longflag>--imageMask</longflag>
<label>Image Mask</label>
<description></description>
<channel>input</channel>
<default></default>
</image>
<image>
<name>ClippedImageMask</name>
<longflag>--clippedImageMask</longflag>
<label>Clipped Image Mask</label>
<description></description>
<channel>output</channel>
<default></default>
</image>
</parameters>
<!-- -->
<parameters advanced="false">
<label>Algorith Configuration Parameters</label>
<boolean>
<name>Maximize</name>
<longflag>--maximize</longflag>
<label>Maximize</label>
<description></description>
<default>true</default>
</boolean>
<integer>
<name>Axis</name>
<longflag>--axis</longflag>
<label>Axis</label>
<description></description>
<default>2</default>
</integer>
<double>
<name>OtsuPercentileThreshold</name>
<longflag>--otsuPercentileThreshold</longflag>
<label>Otsu Percentile Threshold</label>
<description></description>
<default>0.001</default>
</double>
<integer>
<name>ClosingSize</name>
<longflag>--closingSize</longflag>
<label>Closing Size</label>
<description></description>
<default>7</default>
</integer>
<double>
<name>HeadSizeLimit</name>
<longflag>--headSizeLimit</longflag>
<label>Head Size Limit</label>
<description></description>
<default>1000</default>
</double>
<double>
<name>HeadSizeEstimate</name>
<longflag>--headSizeEstimate</longflag>
<label>Head Size Estimate</label>
<description></description>
<default>0</default>
</double>
<integer>
<name>BackgroundValue</name>
<longflag>--backgroundValue</longflag>
<label>Background Value</label>
<description></description>
<default>0</default>
</integer>
</parameters>
<parameters advanced="false">
<label>Debug Parameters</label>
<boolean>
<name>GenerateDebugImages</name>
<longflag>--generateDebugImages</longflag>
<label>GenerateDebugImages</label>
<description></description>
<default>false</default>
</boolean>
<image>
<name>DebugDistanceImage</name>
<longflag>--debugDistanceImage</longflag>
<label>Debug Distance Image</label>
<description></description>
<channel>output</channel>
<default></default>
</image>
<image>
<name>DebugGridImage</name>
<longflag>--debugGridImage</longflag>
<label>Debug Grid Image</label>
<description></description>
<channel>output</channel>
<default></default>
</image>
<image>
<name>DebugAfterGridComputationsForegroundImage</name>
<longflag>--debugAfterGridComputationsForegroundImage</longflag>
<label>Foreground Image After Grid Computations</label>
<description></description>
<channel>output</channel>
<default></default>
</image>
<image>
<name>DebugClippedImageMask</name>
<longflag>--debugClippedImageMask</longflag>
<label>Clipped Image Mask</label>
<description></description>
<channel>output</channel>
<default></default>
</image>
<image>
<name>DebugTrimmedImage</name>
<longflag>--debugTrimmedImage</longflag>
<label>Trimmed Image</label>
<description></description>
<channel>output</channel>
<default></default>
</image>
</parameters>
</executable>
/* KENT -- This CLP Wrapped test program needs to exercise
* the itkFindCenterOfBrainCLP.h class.
*
* As part of this testing, please move as many of the hard-coded
* debuggging images out of the txx files, and make it so that this
* test program will create those images from the command line.
*
* You will have to make some more member variables of the class for
* some of the intermediate images like "AfterGridComputationsForeground.nii.gz"
* so that the class can expose them to the test program.
*
* Please also write an ADD_TEST section to the CMakeLists.txt file that will execute this test program.
*/
#include "itkFindCenterOfBrainFilter.h"
#include "itkIO.h"
#include <FindCenterOfBrainCLP.h>
int main(int argc, char **argv)
{
PARSE_ARGS;
if(InputVolume == "")
{
std::cerr << "FindCenterOfBrain: missing input image name" << std::endl;
exit(1);
}
typedef itk::Image<unsigned char,3> ImageType;
typedef itk::FindCenterOfBrainFilter<ImageType> FindCenterFilterType;
typedef FindCenterFilterType::MaskImageType MaskImageType;
ImageType::Pointer inputImage = itkUtil::ReadImage<ImageType>(InputVolume);
if(inputImage.IsNull())
{
std::cerr << "FindCenterOfBrain: Can't read input image "
<< InputVolume << std::endl;
exit(2);
}
FindCenterFilterType::Pointer filter = FindCenterFilterType::New();
filter->SetInput(inputImage);
MaskImageType::Pointer imageMask;
if(ImageMask != "")
{
imageMask = itkUtil::ReadImage<MaskImageType>(ImageMask);
if(imageMask.IsNull())
{
std::cerr << "FindCenterOfBrain: Can't read mask "
<< ImageMask << std::endl;
exit(3);
}
filter->SetImageMask(imageMask);
}
filter->SetMaximize(Maximize);
filter->SetAxis(Axis);
filter->SetOtsuPercentileThreshold(OtsuPercentileThreshold);
filter->SetClosingSize(ClosingSize);
filter->SetHeadSizeLimit(HeadSizeLimit);
filter->SetHeadSizeEstimate(HeadSizeEstimate);
filter->SetBackgroundValue(BackgroundValue);
filter->SetGenerateDebugImages(GenerateDebugImages);
try
{
filter->Update();
}
catch( itk::ExceptionObject &err)
{
std::cerr << "ExceptionObject caught !" << std::endl;
std::cerr << err << std::endl;
exit(4);
}
FindCenterFilterType::PointType center =
filter->GetCenterOfBrain();
std::cout << "Center Of Brain:"
<< " " << center[0]
<< " " << center[1]
<< " " << center[2]
<< std::endl;
if(ClippedImageMask != "")
{
MaskImageType::Pointer clippedMask =
filter->GetClippedImageMask();
itkUtil::WriteImage<MaskImageType>(clippedMask,
ClippedImageMask);
}
if(!GenerateDebugImages)
{
exit(0);
}
if(DebugDistanceImage != "")
{
FindCenterFilterType::DistanceImagePointer distImage =
filter->GetDebugDistanceImage();
itkUtil::WriteImage<FindCenterFilterType::DistanceImageType>(distImage,
DebugDistanceImage);
}
if(DebugGridImage != "")
{
FindCenterFilterType::InputImagePointer gridImage =
filter->GetDebugGridImage();
itkUtil::WriteImage<ImageType>(gridImage,DebugGridImage);
}
if(DebugAfterGridComputationsForegroundImage != "")
{
MaskImageType::Pointer afterImage =
filter->GetDebugAfterGridComputationsForegroundImage();
itkUtil::WriteImage<MaskImageType>(afterImage,
DebugAfterGridComputationsForegroundImage);
}
if(DebugClippedImageMask != "")
{
MaskImageType::Pointer clippedMask =
filter->GetDebugClippedImageMask();
itkUtil::WriteImage<MaskImageType>(clippedMask,
DebugClippedImageMask);
}
if(DebugTrimmedImage != "")
{
ImageType::Pointer trimmedImage =
filter->GetDebugTrimmedImage();
itkUtil::WriteImage<ImageType>(trimmedImage,
DebugTrimmedImage);
}
exit(0);
}
#include "itkWin32Header.h"
#include <iostream>
#include <fstream>
#include "itkNumericTraits.h"
#include "itkImage.h"
#include "itkImageFileReader.h"
#include "itkImageFileWriter.h"
#include "itkRescaleIntensityImageFilter.h"
#include "itkExtractImageFilter.h"
#include "itkDifferenceImageFilter.h"
using namespace std;
#define ITK_TEST_DIMENSION_MAX 6
int RegressionTestImage (const char *, const char *, int, bool);
int main(int argc, char **argv)
{
if(argc < 3)
{
cerr << "Usage:" << endl;
cerr << "testImage, baselineImage1, [baselineImage2, baselineImage3, ...]" << endl;
cerr << "Note that if you supply more than one baselineImage, this test will pass if any" << endl;
cerr << "of them match the testImage" << endl;
return -1;
}
int bestBaselineStatus = 2001;
int bestBaseline = 2;
try
{
if(argc == 3)
{
bestBaselineStatus = RegressionTestImage(argv[1], argv[2], 0, false);
}
else
{
int currentStatus = 2001;
for(int i=2;i<argc;i++)
{
currentStatus = RegressionTestImage(argv[1], argv[i], 0, false);
if(currentStatus < bestBaselineStatus)
{
bestBaselineStatus = currentStatus;
bestBaseline = i;
}
if(bestBaselineStatus == 0)
{
break;
}
}
}
// generate images of our closest match
if(bestBaselineStatus == 0)
{
RegressionTestImage(argv[1], argv[bestBaseline], 1, false);
}
else
{
RegressionTestImage(argv[1], argv[bestBaseline], 1, true);
}
}
catch(const itk::ExceptionObject& e)
{
std::cerr << "ITK test driver caught an ITK exception:\n";
std::cerr << e.GetFile() << ":" << e.GetLine() << ":\n"
<< e.GetDescription() << "\n";
bestBaselineStatus = -1;
}
catch(const std::exception& e)
{
std::cerr << "ITK test driver caught an exception:\n";
std::cerr << e.what() << "\n";
bestBaselineStatus = -1;
}
catch(...)
{
std::cerr << "ITK test driver caught an unknown exception!!!\n";
bestBaselineStatus = -1;
}
cout << bestBaselineStatus << endl;
return bestBaselineStatus;
}
// Regression Testing Code
int RegressionTestImage (const char *testImageFilename, const char *baselineImageFilename,
int reportErrors, bool differences)
{
// Use the factory mechanism to read the test and baseline files and convert them to double
typedef itk::Image<double,ITK_TEST_DIMENSION_MAX> ImageType;
typedef itk::Image<unsigned char,ITK_TEST_DIMENSION_MAX> OutputType;
typedef itk::Image<unsigned char,2> DiffOutputType;
typedef itk::ImageFileReader<ImageType> ReaderType;
// Read the baseline file
ReaderType::Pointer baselineReader = ReaderType::New();
baselineReader->SetFileName(baselineImageFilename);
try
{
baselineReader->UpdateLargestPossibleRegion();
}
catch (itk::ExceptionObject& e)
{
std::cerr << "Exception detected while reading " << baselineImageFilename << " : " << e.GetDescription();
return 1000;
}
// Read the file generated by the test
ReaderType::Pointer testReader = ReaderType::New();
testReader->SetFileName(testImageFilename);
try
{
testReader->UpdateLargestPossibleRegion();
}
catch (itk::ExceptionObject& e)
{
std::cerr << "Exception detected while reading " << testImageFilename << " : " << e.GetDescription() << std::endl;
return 1000;
}
// The sizes of the baseline and test image must match
ImageType::SizeType baselineSize;
baselineSize = baselineReader->GetOutput()->GetLargestPossibleRegion().GetSize();
ImageType::SizeType testSize;
testSize = testReader->GetOutput()->GetLargestPossibleRegion().GetSize();
if (baselineSize != testSize)
{
std::cerr << "The size of the Baseline image and Test image do not match!" << std::endl;
std::cerr << "Baseline image: " << baselineImageFilename
<< " has size " << baselineSize << std::endl;
std::cerr << "Test image: " << testImageFilename
<< " has size " << testSize << std::endl;
return 1;
}
// Now compare the two images
typedef itk::DifferenceImageFilter<ImageType,ImageType> DiffType;
DiffType::Pointer diff = DiffType::New();
diff->SetValidInput(baselineReader->GetOutput());
diff->SetTestInput(testReader->GetOutput());
diff->SetDifferenceThreshold(2.0);
diff->UpdateLargestPossibleRegion();
double status = diff->GetTotalDifference();
if (reportErrors)
{
typedef itk::RescaleIntensityImageFilter<ImageType,OutputType> RescaleType;
typedef itk::ExtractImageFilter<OutputType,DiffOutputType> ExtractType;
typedef itk::ImageFileWriter<DiffOutputType> WriterType;
typedef itk::ImageRegion<ITK_TEST_DIMENSION_MAX> RegionType;
OutputType::IndexType index; index.Fill(0);
OutputType::SizeType size; size.Fill(0);
RescaleType::Pointer rescale = RescaleType::New();
rescale->SetOutputMinimum(itk::NumericTraits<unsigned char>::NonpositiveMin());
rescale->SetOutputMaximum(itk::NumericTraits<unsigned char>::max());
rescale->SetInput(diff->GetOutput());
rescale->UpdateLargestPossibleRegion();
RegionType region;
region.SetIndex(index);
size = rescale->GetOutput()->GetLargestPossibleRegion().GetSize();
for (unsigned int i = 2; i < ITK_TEST_DIMENSION_MAX; i++)
{
size[i] = 0;
}
region.SetSize(size);
ExtractType::Pointer extract = ExtractType::New();
extract->SetInput(rescale->GetOutput());
extract->SetExtractionRegion(region);
WriterType::Pointer writer = WriterType::New();
writer->SetInput(extract->GetOutput());
if(differences)
{
// if there are discrepencies, create an diff image
std::cout << "<DartMeasurement name=\"ImageError\" type=\"numeric/double\">";
std::cout << status;
std::cout << "</DartMeasurement>" << std::endl;
::itk::OStringStream diffName;
diffName << testImageFilename << ".diff.png";
try
{
rescale->SetInput(diff->GetOutput());
rescale->Update();
}
catch (...)
{
std::cerr << "Error during rescale of " << diffName.str() << std::endl;
}
writer->SetFileName(diffName.str().c_str());