├── README.md ├── AbstractValidationMetric.h ├── MultipleBinaryImageMetricsCalculator.h ├── SensitivityImageToImageMetric.txx ├── DiceOverlapImageToImageMetric.txx ├── PositivePredictiveValueImageToImageMetric.txx ├── ImageToImageValidator.h ├── AbsoluteVolumeErrorImageToImageMetric.txx ├── DiceOverlapImageToImageMetric.h ├── SensitivityImageToImageMetric.h ├── ImageToImageValidator.txx ├── PositivePredictiveValueImageToImageMetric.h ├── AbsoluteVolumeErrorImageToImageMetric.h ├── AverageDistanceImageToImageMetric.h ├── HausdorffDistanceImageToImageMetric.h ├── MultipleBinaryImageMetricsCalculator.txx ├── AverageDistanceImageToImageMetric.txx ├── HausdorffDistanceImageToImageMetric.txx ├── CMakeLists.txt └── validateLabelImages-ISLES.cxx /README.md: -------------------------------------------------------------------------------- 1 | ############### 2 | ISLESevaluation 3 | ############### 4 | 5 | Evaluation script for the ISLES 2015 and 2016 challenges (www.isles-challenge.org). 6 | 7 | Background libarary 8 | ------------------- 9 | Covalic: https://github.com/InsightSoftwareConsortium/covalic/ 10 | 11 | Requirements 12 | ------------ 13 | ITK: http://www.itk.org/ 14 | 15 | Compilation 16 | ----------- 17 | ``` 18 | cmake . 19 | make 20 | ``` 21 | 22 | Usage 23 | ----- 24 | ``` 25 | LINUX and MAC 26 | ./validateLabelImages-ISLES truth.nii[.gz] test.nii[.gz] evaluationresults.json (optional) 27 | 28 | WINDOWS 29 | validateLabelImages-ISLES.exe truth.nii[.gz] test.nii[.gz] evaluationresults.json (optional) 30 | 31 | ``` 32 | -------------------------------------------------------------------------------- /AbstractValidationMetric.h: -------------------------------------------------------------------------------- 1 | 2 | /******************************************************************************** 3 | 4 | Abstract class that defines properties of image metrics: 5 | whether it requires binary input images, the best and worst scores, etc 6 | 7 | ********************************************************************************/ 8 | 9 | #ifndef _AbstractValidationMetric_h 10 | #define _AbstractValidationMetric_h 11 | 12 | class AbstractValidationMetric 13 | { 14 | public: 15 | 16 | // Defines whether input contains binary data 17 | virtual bool IsInputBinary() = 0; 18 | 19 | // Defines whether metric is symmetric f(A,B) = f(B,A) 20 | virtual bool IsSymmetric() = 0; 21 | 22 | // Value returned when the match is best 23 | // Ex: 1 for Dice, 0 for surface distance 24 | virtual double GetBestScore() = 0; 25 | 26 | // Value returned when the match is worst 27 | // Ex: 0 for Dice, Inf for surface distance 28 | virtual double GetWorstScore() = 0; 29 | 30 | }; 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /MultipleBinaryImageMetricsCalculator.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef _MultipleBinaryImageMetricsCalculator_h 3 | #define _MultipleBinaryImageMetricsCalculator_h 4 | 5 | #include "itkObject.h" 6 | 7 | #include 8 | 9 | template 10 | class MultipleBinaryImageMetricsCalculator: 11 | public itk::Object 12 | { 13 | 14 | public: 15 | 16 | /** Standard class typedefs. */ 17 | typedef MultipleBinaryImageMetricsCalculator Self; 18 | typedef itk::Object Superclass; 19 | typedef itk::SmartPointer Pointer; 20 | typedef itk::SmartPointer ConstPointer; 21 | 22 | typedef TFixedImage FixedImageType; 23 | typedef TMovingImage MovingImageType; 24 | 25 | typedef typename FixedImageType::Pointer FixedImagePointer; 26 | typedef typename MovingImageType::Pointer MovingImagePointer; 27 | 28 | /** Method for creation through the object factory. */ 29 | itkNewMacro(Self); 30 | 31 | //typedef TMetric MetricType; 32 | typedef TMetric MetricType; 33 | 34 | void SetFixedImage(FixedImageType* img); 35 | void SetMovingImage(MovingImageType* img); 36 | 37 | void Update(); 38 | 39 | unsigned int GetNumberOfValues() const; 40 | 41 | double GetValue(unsigned int i); 42 | 43 | protected: 44 | 45 | MultipleBinaryImageMetricsCalculator(); 46 | ~MultipleBinaryImageMetricsCalculator(); 47 | 48 | FixedImagePointer m_FixedImage; 49 | MovingImagePointer m_MovingImage; 50 | 51 | std::vector m_MetricValues; 52 | 53 | 54 | }; 55 | 56 | #ifndef ITK_MANUAL_INSTANTIATION 57 | #include "MultipleBinaryImageMetricsCalculator.txx" 58 | #endif 59 | 60 | 61 | #endif 62 | -------------------------------------------------------------------------------- /SensitivityImageToImageMetric.txx: -------------------------------------------------------------------------------- 1 | 2 | #ifndef _SensitivityImageToImageMetric_txx 3 | #define _SensitivityImageToImageMetric_txx 4 | 5 | #include "SensitivityImageToImageMetric.h" 6 | 7 | #include "itkImageRegionIterator.h" 8 | 9 | template 10 | SensitivityImageToImageMetric 11 | ::SensitivityImageToImageMetric() 12 | { 13 | 14 | } 15 | 16 | template 17 | SensitivityImageToImageMetric 18 | ::~SensitivityImageToImageMetric() 19 | { 20 | 21 | } 22 | 23 | template 24 | typename SensitivityImageToImageMetric::MeasureType 25 | SensitivityImageToImageMetric 26 | ::GetValue() const 27 | { 28 | if (Superclass::m_FixedImage.IsNull() || Superclass::m_MovingImage.IsNull()) 29 | itkExceptionMacro(<< "Need two input classification images"); 30 | 31 | // Define iterators 32 | typedef itk::ImageRegionConstIterator FixedIteratorType; 33 | typedef itk::ImageRegionConstIterator MovingIteratorType; 34 | 35 | FixedIteratorType fixedIt(Superclass::m_FixedImage, Superclass::m_FixedImage->GetRequestedRegion()); 36 | MovingIteratorType movingIt(Superclass::m_MovingImage, Superclass::m_MovingImage->GetRequestedRegion()); 37 | 38 | // Get count of true negatives and false positives 39 | unsigned int numTruePositives = 0; 40 | unsigned int numFalseNegatives = 0; 41 | 42 | fixedIt.GoToBegin(); 43 | movingIt.GoToBegin(); 44 | while (!fixedIt.IsAtEnd() && !movingIt.IsAtEnd()) 45 | { 46 | unsigned int r = (unsigned int)fixedIt.Get(); 47 | unsigned int c = (unsigned int)movingIt.Get(); 48 | 49 | bool a = (r != 0); 50 | bool b = (c != 0); 51 | 52 | if (a && b) 53 | numTruePositives++; 54 | 55 | if (a && !b) 56 | numFalseNegatives++; 57 | 58 | ++fixedIt; 59 | ++movingIt; 60 | } 61 | 62 | return numTruePositives / (numTruePositives + numFalseNegatives + 1e-20); 63 | } 64 | 65 | #endif 66 | -------------------------------------------------------------------------------- /DiceOverlapImageToImageMetric.txx: -------------------------------------------------------------------------------- 1 | 2 | #ifndef _DiceOverlapImageToImageMetric_txx 3 | #define _DiceOverlapImageToImageMetric_txx 4 | 5 | #include "DiceOverlapImageToImageMetric.h" 6 | 7 | #include "itkImageRegionIterator.h" 8 | 9 | template 10 | DiceOverlapImageToImageMetric 11 | ::DiceOverlapImageToImageMetric() 12 | { 13 | 14 | } 15 | 16 | template 17 | DiceOverlapImageToImageMetric 18 | ::~DiceOverlapImageToImageMetric() 19 | { 20 | 21 | } 22 | 23 | template 24 | typename DiceOverlapImageToImageMetric::MeasureType 25 | DiceOverlapImageToImageMetric 26 | ::GetValue() const 27 | { 28 | if (Superclass::m_FixedImage.IsNull() || Superclass::m_MovingImage.IsNull()) 29 | itkExceptionMacro(<< "Need two input classification images"); 30 | 31 | // Define iterators 32 | typedef itk::ImageRegionConstIterator FixedIteratorType; 33 | typedef itk::ImageRegionConstIterator MovingIteratorType; 34 | 35 | FixedIteratorType fixedIt(Superclass::m_FixedImage, Superclass::m_FixedImage->GetRequestedRegion()); 36 | MovingIteratorType movingIt(Superclass::m_MovingImage, Superclass::m_MovingImage->GetRequestedRegion()); 37 | 38 | // Get intersection and individual set sizes 39 | unsigned int numIntersect = 0; 40 | unsigned int numA = 0; 41 | unsigned int numB = 0; 42 | 43 | fixedIt.GoToBegin(); 44 | movingIt.GoToBegin(); 45 | while (!fixedIt.IsAtEnd() && !movingIt.IsAtEnd()) 46 | { 47 | unsigned int r = (unsigned int)fixedIt.Get(); 48 | unsigned int c = (unsigned int)movingIt.Get(); 49 | 50 | bool a = (r != 0); 51 | bool b = (c != 0); 52 | 53 | if (a && b) 54 | numIntersect++; 55 | 56 | if (a) 57 | numA++; 58 | 59 | if (b) 60 | numB++; 61 | 62 | ++fixedIt; 63 | ++movingIt; 64 | } 65 | 66 | // Overlap or similarity coeff is intersect / average 67 | double avgSize = (numA + numB) / 2.0 + 1e-20; 68 | 69 | return (double)numIntersect / avgSize; 70 | } 71 | 72 | #endif 73 | -------------------------------------------------------------------------------- /PositivePredictiveValueImageToImageMetric.txx: -------------------------------------------------------------------------------- 1 | 2 | #ifndef _PositivePredictiveValueImageToImageMetric_txx 3 | #define _PositivePredictiveValueImageToImageMetric_txx 4 | 5 | #include "PositivePredictiveValueImageToImageMetric.h" 6 | 7 | #include "itkImageRegionIterator.h" 8 | 9 | template 10 | PositivePredictiveValueImageToImageMetric 11 | ::PositivePredictiveValueImageToImageMetric() 12 | { 13 | 14 | } 15 | 16 | template 17 | PositivePredictiveValueImageToImageMetric 18 | ::~PositivePredictiveValueImageToImageMetric() 19 | { 20 | 21 | } 22 | 23 | template 24 | typename PositivePredictiveValueImageToImageMetric::MeasureType 25 | PositivePredictiveValueImageToImageMetric 26 | ::GetValue() const 27 | { 28 | if (Superclass::m_FixedImage.IsNull() || Superclass::m_MovingImage.IsNull()) 29 | itkExceptionMacro(<< "Need two input classification images"); 30 | 31 | // Define iterators 32 | typedef itk::ImageRegionConstIterator FixedIteratorType; 33 | typedef itk::ImageRegionConstIterator MovingIteratorType; 34 | 35 | FixedIteratorType fixedIt(Superclass::m_FixedImage, Superclass::m_FixedImage->GetRequestedRegion()); 36 | MovingIteratorType movingIt(Superclass::m_MovingImage, Superclass::m_MovingImage->GetRequestedRegion()); 37 | 38 | // Get count of true negatives and false positives 39 | unsigned int numTruePositives = 0; 40 | unsigned int numFalsePositives = 0; 41 | 42 | fixedIt.GoToBegin(); 43 | movingIt.GoToBegin(); 44 | while (!fixedIt.IsAtEnd() && !movingIt.IsAtEnd()) 45 | { 46 | unsigned int r = (unsigned int)fixedIt.Get(); 47 | unsigned int c = (unsigned int)movingIt.Get(); 48 | 49 | bool a = (r != 0); 50 | bool b = (c != 0); 51 | 52 | if (a && b) 53 | numTruePositives++; 54 | 55 | if (!a && b) 56 | numFalsePositives++; 57 | 58 | ++fixedIt; 59 | ++movingIt; 60 | } 61 | 62 | return numTruePositives / (numTruePositives + numFalsePositives + 1e-20); 63 | } 64 | 65 | #endif 66 | -------------------------------------------------------------------------------- /ImageToImageValidator.h: -------------------------------------------------------------------------------- 1 | 2 | // Checks that two images are comparable in origin, spacing, direction. 3 | // Input: binary images, where fixed image denotes truth 4 | 5 | #ifndef _ImageToImageValidator_h 6 | #define _ImageToImageValidator_h 7 | 8 | #include "AbstractValidationMetric.h" 9 | 10 | #include "itkImageToImageMetric.h" 11 | #include "itkSmartPointer.h" 12 | 13 | template 14 | class ITK_EXPORT ImageToImageValidator : 15 | public itk::ImageToImageMetric, public AbstractValidationMetric 16 | { 17 | 18 | public: 19 | 20 | // Validation metric properties 21 | bool IsInputBinary() { return true; } 22 | bool IsSymmetric() { return false; } 23 | double GetBestScore() { return 0.0; } 24 | double GetWorstScore() { return 1.0; } 25 | 26 | /** Standard class typedefs. */ 27 | typedef ImageToImageValidator Self; 28 | typedef itk::ImageToImageMetric Superclass; 29 | typedef itk::SmartPointer Pointer; 30 | typedef itk::SmartPointer ConstPointer; 31 | 32 | typedef TFixedImage FixedImageType; 33 | typedef TMovingImage MovingImageType; 34 | 35 | /** Method for creation through the object factory. */ 36 | itkNewMacro(Self); 37 | 38 | /** Run-time type information (and related methods). */ 39 | itkTypeMacro(ImageToImageValidator, 40 | itk::ImageToImageMetric); 41 | 42 | typedef typename Superclass::MeasureType MeasureType; 43 | typedef typename Superclass::TransformParametersType TransformParametersType; 44 | typedef typename Superclass::DerivativeType DerivativeType; 45 | 46 | /** Get the value for single valued optimizers. */ 47 | MeasureType GetValue() const; 48 | 49 | MeasureType GetValue(const TransformParametersType& p) const 50 | { // TODO: apply transform with nearest neighbor interpolation 51 | return this->GetValue(); } 52 | 53 | void GetDerivative(const TransformParametersType& p, DerivativeType& dp) const 54 | { itkExceptionMacro(<< "Not implemented"); } 55 | 56 | void GetValueAndDerivative(const TransformParametersType& p, MeasureType& v, DerivativeType& dp) const 57 | { itkExceptionMacro(<< "Not implemented"); } 58 | 59 | protected: 60 | 61 | ImageToImageValidator(); 62 | virtual ~ImageToImageValidator(); 63 | 64 | 65 | }; 66 | 67 | #ifndef ITK_MANUAL_INSTANTIATION 68 | #include "ImageToImageValidator.txx" 69 | #endif 70 | 71 | #endif 72 | -------------------------------------------------------------------------------- /AbsoluteVolumeErrorImageToImageMetric.txx: -------------------------------------------------------------------------------- 1 | 2 | #ifndef _AbsoluteVolumeErrorImageToImageMetric_txx 3 | #define _AbsoluteVolumeErrorImageToImageMetric_txx 4 | 5 | #include "AbsoluteVolumeErrorImageToImageMetric.h" 6 | 7 | #include "itkImageRegionIterator.h" 8 | 9 | template 10 | AbsoluteVolumeErrorImageToImageMetric 11 | ::AbsoluteVolumeErrorImageToImageMetric() 12 | { 13 | 14 | } 15 | 16 | template 17 | AbsoluteVolumeErrorImageToImageMetric 18 | ::~AbsoluteVolumeErrorImageToImageMetric() 19 | { 20 | 21 | } 22 | 23 | template 24 | typename AbsoluteVolumeErrorImageToImageMetric::MeasureType 25 | AbsoluteVolumeErrorImageToImageMetric 26 | ::GetValue() const 27 | { 28 | if (Superclass::m_FixedImage.IsNull() || Superclass::m_MovingImage.IsNull()) 29 | itkExceptionMacro(<< "Need two input classification images"); 30 | 31 | // Define iterators 32 | typedef itk::ImageRegionConstIterator FixedIteratorType; 33 | typedef itk::ImageRegionConstIterator MovingIteratorType; 34 | 35 | FixedIteratorType fixedIt(Superclass::m_FixedImage, Superclass::m_FixedImage->GetRequestedRegion()); 36 | MovingIteratorType movingIt(Superclass::m_MovingImage, Superclass::m_MovingImage->GetRequestedRegion()); 37 | 38 | // Get intersection and individual set sizes 39 | unsigned int numA = 0; 40 | unsigned int numB = 0; 41 | 42 | fixedIt.GoToBegin(); 43 | movingIt.GoToBegin(); 44 | while (!fixedIt.IsAtEnd() && !movingIt.IsAtEnd()) 45 | { 46 | unsigned int r = (unsigned int)fixedIt.Get(); 47 | unsigned int c = (unsigned int)movingIt.Get(); 48 | 49 | bool a = (r != 0); 50 | bool b = (c != 0); 51 | 52 | if (a) 53 | numA++; 54 | 55 | if (b) 56 | numB++; 57 | 58 | ++fixedIt; 59 | ++movingIt; 60 | } 61 | 62 | float spacing[3]; 63 | 64 | spacing[0] = Superclass::m_FixedImage->GetSpacing()[0]; 65 | spacing[1] = Superclass::m_FixedImage->GetSpacing()[1]; 66 | spacing[2] = Superclass::m_FixedImage->GetSpacing()[2]; 67 | 68 | float volumeFixed; 69 | float volumeMoving; 70 | 71 | volumeFixed = numA * spacing[0]*spacing[1]*spacing[2]; 72 | volumeMoving = numB * spacing[0]*spacing[1]*spacing[2]; 73 | 74 | double absVolErr = volumeMoving - volumeFixed; 75 | 76 | return absVolErr; 77 | } 78 | 79 | #endif 80 | -------------------------------------------------------------------------------- /DiceOverlapImageToImageMetric.h: -------------------------------------------------------------------------------- 1 | 2 | // Dice similarity coefficient 3 | // Input: binary images 4 | // 2 * intersect(A, B) / (|A| + |B|) 5 | 6 | #ifndef _DiceOverlapImageToImageMetric_h 7 | #define _DiceOverlapImageToImageMetric_h 8 | 9 | #include "AbstractValidationMetric.h" 10 | 11 | #include "itkImageToImageMetric.h" 12 | #include "itkSmartPointer.h" 13 | 14 | template 15 | class ITK_EXPORT DiceOverlapImageToImageMetric : 16 | public itk::ImageToImageMetric, public AbstractValidationMetric 17 | { 18 | 19 | public: 20 | 21 | // Validation metric properties 22 | bool IsInputBinary() { return true; } 23 | bool IsSymmetric() { return true; } 24 | double GetBestScore() { return 1.0; } 25 | double GetWorstScore() { return 0.0; } 26 | 27 | /** Standard class typedefs. */ 28 | typedef DiceOverlapImageToImageMetric Self; 29 | typedef itk::ImageToImageMetric Superclass; 30 | typedef itk::SmartPointer Pointer; 31 | typedef itk::SmartPointer ConstPointer; 32 | 33 | typedef TFixedImage FixedImageType; 34 | typedef TMovingImage MovingImageType; 35 | 36 | /** Method for creation through the object factory. */ 37 | itkNewMacro(Self); 38 | 39 | /** Run-time type information (and related methods). */ 40 | itkTypeMacro(DiceOverlapImageToImageMetric, 41 | itk::ImageToImageMetric); 42 | 43 | typedef typename Superclass::MeasureType MeasureType; 44 | typedef typename Superclass::TransformParametersType TransformParametersType; 45 | typedef typename Superclass::DerivativeType DerivativeType; 46 | 47 | /** Get the value for single valued optimizers. */ 48 | MeasureType GetValue() const; 49 | 50 | MeasureType GetValue(const TransformParametersType& p) const 51 | { // TODO: apply transform with nearest neighbor interpolation 52 | return this->GetValue(); } 53 | 54 | void GetDerivative(const TransformParametersType& p, DerivativeType& dp) const 55 | { itkExceptionMacro(<< "Not implemented"); } 56 | 57 | void GetValueAndDerivative(const TransformParametersType& p, MeasureType& v, DerivativeType& dp) const 58 | { itkExceptionMacro(<< "Not implemented"); } 59 | 60 | protected: 61 | 62 | DiceOverlapImageToImageMetric(); 63 | virtual ~DiceOverlapImageToImageMetric(); 64 | 65 | // TODO: transform member, default to identity 66 | 67 | }; 68 | 69 | #ifndef ITK_MANUAL_INSTANTIATION 70 | #include "DiceOverlapImageToImageMetric.txx" 71 | #endif 72 | 73 | #endif 74 | -------------------------------------------------------------------------------- /SensitivityImageToImageMetric.h: -------------------------------------------------------------------------------- 1 | 2 | // Measures sensitivity or true positive rate 3 | // Input: binary images, where fixed image denotes truth 4 | // #true positives / (#true positives + #false negatives) 5 | 6 | #ifndef _SensitivityImageToImageMetric_h 7 | #define _SensitivityImageToImageMetric_h 8 | 9 | #include "AbstractValidationMetric.h" 10 | 11 | #include "itkImageToImageMetric.h" 12 | #include "itkSmartPointer.h" 13 | 14 | template 15 | class ITK_EXPORT SensitivityImageToImageMetric : 16 | public itk::ImageToImageMetric, public AbstractValidationMetric 17 | { 18 | 19 | public: 20 | 21 | // Validation metric properties 22 | bool IsInputBinary() { return true; } 23 | bool IsSymmetric() { return false; } 24 | double GetBestScore() { return 1.0; } 25 | double GetWorstScore() { return 0.0; } 26 | 27 | /** Standard class typedefs. */ 28 | typedef SensitivityImageToImageMetric Self; 29 | typedef itk::ImageToImageMetric Superclass; 30 | typedef itk::SmartPointer Pointer; 31 | typedef itk::SmartPointer ConstPointer; 32 | 33 | typedef TFixedImage FixedImageType; 34 | typedef TMovingImage MovingImageType; 35 | 36 | /** Method for creation through the object factory. */ 37 | itkNewMacro(Self); 38 | 39 | /** Run-time type information (and related methods). */ 40 | itkTypeMacro(SensitivityImageToImageMetric, 41 | itk::ImageToImageMetric); 42 | 43 | typedef typename Superclass::MeasureType MeasureType; 44 | typedef typename Superclass::TransformParametersType TransformParametersType; 45 | typedef typename Superclass::DerivativeType DerivativeType; 46 | 47 | /** Get the value for single valued optimizers. */ 48 | MeasureType GetValue() const; 49 | 50 | MeasureType GetValue(const TransformParametersType& p) const 51 | { // TODO: apply transform with nearest neighbor interpolation 52 | return this->GetValue(); } 53 | 54 | void GetDerivative(const TransformParametersType& p, DerivativeType& dp) const 55 | { itkExceptionMacro(<< "Not implemented"); } 56 | 57 | void GetValueAndDerivative(const TransformParametersType& p, MeasureType& v, DerivativeType& dp) const 58 | { itkExceptionMacro(<< "Not implemented"); } 59 | 60 | protected: 61 | 62 | SensitivityImageToImageMetric(); 63 | virtual ~SensitivityImageToImageMetric(); 64 | 65 | // TODO: transform member, default to identity 66 | 67 | }; 68 | 69 | #ifndef ITK_MANUAL_INSTANTIATION 70 | #include "SensitivityImageToImageMetric.txx" 71 | #endif 72 | 73 | #endif 74 | -------------------------------------------------------------------------------- /ImageToImageValidator.txx: -------------------------------------------------------------------------------- 1 | 2 | #ifndef _ImageToImageValidator_txx 3 | #define _ImageToImageValidator_txx 4 | 5 | #include "ImageToImageValidator.h" 6 | 7 | #include "itkImageRegionIterator.h" 8 | 9 | #include "itkPoint.h" 10 | 11 | template 12 | ImageToImageValidator 13 | ::ImageToImageValidator() 14 | { 15 | 16 | } 17 | 18 | template 19 | ImageToImageValidator 20 | ::~ImageToImageValidator() 21 | { 22 | 23 | } 24 | 25 | template 26 | typename ImageToImageValidator::MeasureType 27 | ImageToImageValidator 28 | ::GetValue() const 29 | { 30 | if (Superclass::m_FixedImage.IsNull() || Superclass::m_MovingImage.IsNull()) 31 | itkExceptionMacro(<< "Need two input classification images"); 32 | 33 | /* 34 | std::cout << "Truth Origin" << std::endl; 35 | std::cout << Superclass::m_FixedImage->GetOrigin() << std::endl; 36 | std::cout << "Result Origin" << std::endl; 37 | std::cout << Superclass::m_MovingImage->GetOrigin() << std::endl; 38 | std::cout << std::endl; 39 | 40 | std::cout << "Truth Spacing" << std::endl; 41 | std::cout << Superclass::m_FixedImage->GetSpacing() << std::endl; 42 | std::cout << "Result Spacing" << std::endl; 43 | std::cout << Superclass::m_MovingImage->GetSpacing() << std::endl; 44 | std::cout << std::endl; 45 | 46 | std::cout << "Truth Direction" << std::endl; 47 | std::cout << Superclass::m_FixedImage->GetDirection() << std::endl; 48 | std::cout << "Result Direction" << std::endl; 49 | std::cout << Superclass::m_MovingImage->GetDirection() << std::endl; 50 | std::cout << std::endl; 51 | 52 | std::cout << "Truth LargestPossibleRegionSize" << std::endl; 53 | std::cout << Superclass::m_FixedImage->GetLargestPossibleRegion().GetSize() << std::endl; 54 | std::cout << "Result LargestPossibleRegionSize" << std::endl; 55 | std::cout << Superclass::m_MovingImage->GetLargestPossibleRegion().GetSize() << std::endl; 56 | std::cout << std::endl; 57 | */ 58 | 59 | if (Superclass::m_FixedImage->GetOrigin() != Superclass::m_MovingImage->GetOrigin()) 60 | return -1.0; 61 | if (Superclass::m_FixedImage->GetSpacing() != Superclass::m_MovingImage->GetSpacing()) 62 | return -1.0; 63 | if (Superclass::m_FixedImage->GetDirection() != Superclass::m_MovingImage->GetDirection()) 64 | return -1.0; 65 | if (Superclass::m_FixedImage->GetLargestPossibleRegion().GetSize() 66 | != Superclass::m_MovingImage->GetLargestPossibleRegion().GetSize()) 67 | return -1.0; 68 | 69 | return 0; 70 | } 71 | 72 | #endif 73 | -------------------------------------------------------------------------------- /PositivePredictiveValueImageToImageMetric.h: -------------------------------------------------------------------------------- 1 | 2 | // Measures positive predictive value (PPV) or precision 3 | // Input: binary images, where fixed image denotes truth 4 | // #true positives / (#true positives + #false negatives) 5 | 6 | #ifndef _PositivePredictiveValueImageToImageMetric_h 7 | #define _PositivePredictiveValueImageToImageMetric_h 8 | 9 | #include "AbstractValidationMetric.h" 10 | 11 | #include "itkImageToImageMetric.h" 12 | #include "itkSmartPointer.h" 13 | 14 | template 15 | class ITK_EXPORT PositivePredictiveValueImageToImageMetric : 16 | public itk::ImageToImageMetric, public AbstractValidationMetric 17 | { 18 | 19 | public: 20 | 21 | // Validation metric properties 22 | bool IsInputBinary() { return true; } 23 | bool IsSymmetric() { return false; } 24 | double GetBestScore() { return 1.0; } 25 | double GetWorstScore() { return 0.0; } 26 | 27 | /** Standard class typedefs. */ 28 | typedef PositivePredictiveValueImageToImageMetric Self; 29 | typedef itk::ImageToImageMetric Superclass; 30 | typedef itk::SmartPointer Pointer; 31 | typedef itk::SmartPointer ConstPointer; 32 | 33 | typedef TFixedImage FixedImageType; 34 | typedef TMovingImage MovingImageType; 35 | 36 | /** Method for creation through the object factory. */ 37 | itkNewMacro(Self); 38 | 39 | /** Run-time type information (and related methods). */ 40 | itkTypeMacro(PositivePredictiveValueImageToImageMetric, 41 | itk::ImageToImageMetric); 42 | 43 | typedef typename Superclass::MeasureType MeasureType; 44 | typedef typename Superclass::TransformParametersType TransformParametersType; 45 | typedef typename Superclass::DerivativeType DerivativeType; 46 | 47 | /** Get the value for single valued optimizers. */ 48 | MeasureType GetValue() const; 49 | 50 | MeasureType GetValue(const TransformParametersType& p) const 51 | { // TODO: apply transform with nearest neighbor interpolation 52 | return this->GetValue(); } 53 | 54 | void GetDerivative(const TransformParametersType& p, DerivativeType& dp) const 55 | { itkExceptionMacro(<< "Not implemented"); } 56 | 57 | void GetValueAndDerivative(const TransformParametersType& p, MeasureType& v, DerivativeType& dp) const 58 | { itkExceptionMacro(<< "Not implemented"); } 59 | 60 | protected: 61 | 62 | PositivePredictiveValueImageToImageMetric(); 63 | virtual ~PositivePredictiveValueImageToImageMetric(); 64 | 65 | // TODO: transform member, default to identity 66 | 67 | }; 68 | 69 | #ifndef ITK_MANUAL_INSTANTIATION 70 | #include "PositivePredictiveValueImageToImageMetric.txx" 71 | #endif 72 | 73 | #endif 74 | -------------------------------------------------------------------------------- /AbsoluteVolumeErrorImageToImageMetric.h: -------------------------------------------------------------------------------- 1 | 2 | // absolute volume error 3 | // Input: binary images 4 | 5 | #ifndef _AbsoluteVolumeErrorImageToImageMetric_h 6 | #define _AbsoluteVolumeErrorImageToImageMetric_h 7 | 8 | #include "AbstractValidationMetric.h" 9 | 10 | #include "itkImageToImageMetric.h" 11 | #include "itkSmartPointer.h" 12 | 13 | template 14 | class ITK_EXPORT AbsoluteVolumeErrorImageToImageMetric : 15 | public itk::ImageToImageMetric, public AbstractValidationMetric 16 | { 17 | 18 | public: 19 | 20 | // Validation metric properties 21 | bool IsInputBinary() { return true; } 22 | bool IsSymmetric() { return true; } 23 | double GetBestScore() { return 1.0; } 24 | double GetWorstScore() { return 0.0; } 25 | 26 | /** Standard class typedefs. */ 27 | typedef AbsoluteVolumeErrorImageToImageMetric Self; 28 | typedef itk::ImageToImageMetric Superclass; 29 | typedef itk::SmartPointer Pointer; 30 | typedef itk::SmartPointer ConstPointer; 31 | 32 | typedef TFixedImage FixedImageType; 33 | typedef TMovingImage MovingImageType; 34 | 35 | /** Method for creation through the object factory. */ 36 | itkNewMacro(Self); 37 | 38 | /** Run-time type information (and related methods). */ 39 | itkTypeMacro(AbsoluteVolumeErrorImageToImageMetric, 40 | itk::ImageToImageMetric); 41 | 42 | typedef typename Superclass::MeasureType MeasureType; 43 | typedef typename Superclass::TransformParametersType TransformParametersType; 44 | typedef typename Superclass::DerivativeType DerivativeType; 45 | 46 | /** Get the value for single valued optimizers. */ 47 | MeasureType GetValue() const; 48 | 49 | MeasureType GetValue(const TransformParametersType& p) const 50 | { // TODO: apply transform with nearest neighbor interpolation 51 | TransformParametersType pp = p;pp = TransformParametersType(); 52 | return this->GetValue(); } 53 | 54 | void GetDerivative(const TransformParametersType& p, DerivativeType& dp) const 55 | { 56 | TransformParametersType pp = p;pp = TransformParametersType();dp.rms(); 57 | itkExceptionMacro(<< "Not implemented"); } 58 | 59 | void GetValueAndDerivative(const TransformParametersType& p, MeasureType& v, DerivativeType& dp) const 60 | { 61 | TransformParametersType pp = p;pp = TransformParametersType();v=0;dp.rms(); 62 | itkExceptionMacro(<< "Not implemented"); } 63 | 64 | protected: 65 | 66 | AbsoluteVolumeErrorImageToImageMetric(); 67 | virtual ~AbsoluteVolumeErrorImageToImageMetric(); 68 | 69 | // TODO: transform member, default to identity 70 | 71 | }; 72 | 73 | #ifndef ITK_MANUAL_INSTANTIATION 74 | #include "AbsoluteVolumeErrorImageToImageMetric.txx" 75 | #endif 76 | 77 | #endif 78 | -------------------------------------------------------------------------------- /AverageDistanceImageToImageMetric.h: -------------------------------------------------------------------------------- 1 | 2 | // Average boundary distances, given two binary image masks 3 | // 4 | // Both fixed and moving images should have the same unsigned type 5 | // Only handles 3D images 6 | 7 | #ifndef _AverageDistanceImageToImageMetric_h 8 | #define _AverageDistanceImageToImageMetric_h 9 | 10 | #include "AbstractValidationMetric.h" 11 | 12 | #include "itkImageToImageMetric.h" 13 | 14 | #include "vnl/vnl_math.h" 15 | 16 | template 17 | class AverageDistanceImageToImageMetric : 18 | public itk::ImageToImageMetric, public AbstractValidationMetric 19 | { 20 | 21 | public: 22 | 23 | // Validation metric properties 24 | bool IsInputBinary() { return true; } 25 | bool IsSymmetric() { return true; } 26 | double GetBestScore() { return 0; } 27 | double GetWorstScore() { return vnl_huge_val(1.0); } 28 | 29 | /** Standard class typedefs. */ 30 | typedef AverageDistanceImageToImageMetric Self; 31 | typedef itk::ImageToImageMetric Superclass; 32 | typedef itk::SmartPointer Pointer; 33 | typedef itk::SmartPointer ConstPointer; 34 | 35 | typedef TFixedImage FixedImageType; 36 | typedef TMovingImage MovingImageType; 37 | 38 | /** Method for creation through the object factory. */ 39 | itkNewMacro(Self); 40 | 41 | /** Run-time type information (and related methods). */ 42 | itkTypeMacro(AverageDistanceImageToImageMetric, 43 | itk::ImageToImageMetric); 44 | 45 | typedef typename Superclass::MeasureType MeasureType; 46 | typedef typename Superclass::TransformParametersType TransformParametersType; 47 | typedef typename Superclass::DerivativeType DerivativeType; 48 | 49 | typedef typename TFixedImage::Pointer FixedImagePointer; 50 | typedef typename TFixedImage::IndexType FixedImageIndexType; 51 | typedef typename TFixedImage::PixelType FixedImagePixelType; 52 | typedef typename TFixedImage::PointType FixedImagePointType; 53 | typedef typename TFixedImage::SizeType FixedImageSizeType; 54 | typedef typename TFixedImage::SpacingType FixedImageSpacingType; 55 | 56 | MeasureType GetValue() const; 57 | 58 | MeasureType GetValue(const TransformParametersType& p) const 59 | { // TODO: apply transform with nearest neighbor interpolation 60 | return this->GetValue(); } 61 | 62 | void GetDerivative(const TransformParametersType& p, DerivativeType& dp) const 63 | { itkExceptionMacro(<< "Not implemented"); } 64 | 65 | void GetValueAndDerivative(const TransformParametersType& p, MeasureType& v, DerivativeType& dp) const 66 | { itkExceptionMacro(<< "Not implemented"); } 67 | 68 | void BlurringOn() { m_DoBlurring = true; } 69 | void BlurringOff() { m_DoBlurring = false; } 70 | 71 | protected: 72 | 73 | AverageDistanceImageToImageMetric(); 74 | ~AverageDistanceImageToImageMetric(); 75 | 76 | double ComputeNonSymmetricDistance(const FixedImageType*, const MovingImageType*) const; 77 | 78 | private: 79 | 80 | bool m_DoBlurring; 81 | 82 | }; 83 | 84 | #ifndef MU_MANUAL_INSTANTIATION 85 | #include "AverageDistanceImageToImageMetric.txx" 86 | #endif 87 | 88 | #endif 89 | -------------------------------------------------------------------------------- /HausdorffDistanceImageToImageMetric.h: -------------------------------------------------------------------------------- 1 | 2 | // Hausdorff boundary distances, given two binary image masks 3 | // 4 | // Both fixed and moving images should have the same unsigned type 5 | // Only handles 3D images 6 | 7 | #ifndef _HausdorffDistanceImageToImageMetric_h 8 | #define _HausdorffDistanceImageToImageMetric_h 9 | 10 | #include "AbstractValidationMetric.h" 11 | 12 | #include "itkImageToImageMetric.h" 13 | 14 | #include "vnl/vnl_math.h" 15 | 16 | template 17 | class HausdorffDistanceImageToImageMetric : 18 | public itk::ImageToImageMetric, public AbstractValidationMetric 19 | { 20 | 21 | public: 22 | 23 | // Validation metric properties 24 | bool IsInputBinary() { return true; } 25 | bool IsSymmetric() { return false; } 26 | double GetBestScore() { return 0; } 27 | double GetWorstScore() { return vnl_huge_val(1.0); } 28 | 29 | /** Standard class typedefs. */ 30 | typedef HausdorffDistanceImageToImageMetric Self; 31 | typedef itk::ImageToImageMetric Superclass; 32 | typedef itk::SmartPointer Pointer; 33 | typedef itk::SmartPointer ConstPointer; 34 | 35 | typedef TFixedImage FixedImageType; 36 | typedef TMovingImage MovingImageType; 37 | 38 | /** Method for creation through the object factory. */ 39 | itkNewMacro(Self); 40 | 41 | /** Run-time type information (and related methods). */ 42 | itkTypeMacro(HausdorffDistanceImageToImageMetric, 43 | itk::ImageToImageMetric); 44 | 45 | typedef typename Superclass::MeasureType MeasureType; 46 | typedef typename Superclass::TransformParametersType TransformParametersType; 47 | typedef typename Superclass::DerivativeType DerivativeType; 48 | 49 | typedef typename TFixedImage::Pointer FixedImagePointer; 50 | typedef typename TFixedImage::IndexType FixedImageIndexType; 51 | typedef typename TFixedImage::PixelType FixedImagePixelType; 52 | typedef typename TFixedImage::PointType FixedImagePointType; 53 | typedef typename TFixedImage::SizeType FixedImageSizeType; 54 | typedef typename TFixedImage::SpacingType FixedImageSpacingType; 55 | 56 | void SetPercentile(double p); 57 | 58 | MeasureType GetValue() const; 59 | 60 | MeasureType GetValue(const TransformParametersType& p) const 61 | { // TODO: apply transform with nearest neighbor interpolation 62 | return this->GetValue(); } 63 | 64 | void GetDerivative(const TransformParametersType& p, DerivativeType& dp) const 65 | { itkExceptionMacro(<< "Not implemented"); } 66 | 67 | void GetValueAndDerivative(const TransformParametersType& p, MeasureType& v, DerivativeType& dp) const 68 | { itkExceptionMacro(<< "Not implemented"); } 69 | 70 | void BlurringOn() { m_DoBlurring = true; } 71 | void BlurringOff() { m_DoBlurring = false; } 72 | 73 | protected: 74 | 75 | HausdorffDistanceImageToImageMetric(); 76 | ~HausdorffDistanceImageToImageMetric(); 77 | 78 | double ComputeMaxDistance(const FixedImageType*, const MovingImageType*) const; 79 | 80 | private: 81 | 82 | bool m_DoBlurring; 83 | 84 | double m_Percentile; 85 | 86 | }; 87 | 88 | #ifndef MU_MANUAL_INSTANTIATION 89 | #include "HausdorffDistanceImageToImageMetric.txx" 90 | #endif 91 | 92 | #endif 93 | -------------------------------------------------------------------------------- /MultipleBinaryImageMetricsCalculator.txx: -------------------------------------------------------------------------------- 1 | 2 | #ifndef _MultipleBinaryImageMetricsCalculator_txx 3 | #define _MultipleBinaryImageMetricsCalculator_txx 4 | 5 | #include "MultipleBinaryImageMetricsCalculator.h" 6 | 7 | #include "itkBinaryThresholdImageFilter.h" 8 | #include "itkMinimumMaximumImageCalculator.h" 9 | 10 | #include "itkImageRegionIterator.h" 11 | 12 | template 13 | MultipleBinaryImageMetricsCalculator 14 | ::MultipleBinaryImageMetricsCalculator() 15 | { 16 | 17 | } 18 | 19 | template 20 | MultipleBinaryImageMetricsCalculator 21 | ::~MultipleBinaryImageMetricsCalculator() 22 | { 23 | 24 | } 25 | 26 | template 27 | void 28 | MultipleBinaryImageMetricsCalculator 29 | ::SetFixedImage(FixedImageType* img) 30 | { 31 | m_FixedImage = img; 32 | } 33 | 34 | template 35 | void 36 | MultipleBinaryImageMetricsCalculator 37 | ::SetMovingImage(MovingImageType* img) 38 | { 39 | m_MovingImage = img; 40 | } 41 | 42 | template 43 | unsigned int 44 | MultipleBinaryImageMetricsCalculator 45 | ::GetNumberOfValues() const 46 | { 47 | return m_MetricValues.size(); 48 | } 49 | 50 | template 51 | double 52 | MultipleBinaryImageMetricsCalculator 53 | ::GetValue(unsigned int i) 54 | { 55 | return m_MetricValues[i]; 56 | } 57 | 58 | template 59 | void 60 | MultipleBinaryImageMetricsCalculator 61 | ::Update() 62 | { 63 | if (m_FixedImage.IsNull()) 64 | itkExceptionMacro(<< "Fixed image undefined"); 65 | 66 | if (m_MovingImage.IsNull()) 67 | itkExceptionMacro(<< "Moving image undefined"); 68 | 69 | typedef itk::MinimumMaximumImageCalculator FixedMinMaxCalculator; 70 | typename FixedMinMaxCalculator::Pointer fminmax = FixedMinMaxCalculator::New(); 71 | fminmax->SetImage(m_FixedImage); 72 | fminmax->ComputeMaximum(); 73 | 74 | unsigned int maxLabel = fminmax->GetMaximum(); 75 | 76 | typedef itk::MinimumMaximumImageCalculator MovingMinMaxCalculator; 77 | typename MovingMinMaxCalculator::Pointer mminmax = MovingMinMaxCalculator::New(); 78 | mminmax->SetImage(m_MovingImage); 79 | mminmax->ComputeMaximum(); 80 | 81 | if (mminmax->GetMaximum() > maxLabel) 82 | maxLabel = mminmax->GetMaximum(); 83 | 84 | m_MetricValues.clear(); 85 | 86 | for (unsigned int label = 1; label <= maxLabel; label++) 87 | { 88 | itkDebugMacro(<< "Computing metric for label " << label << "\n"); 89 | 90 | typedef itk::BinaryThresholdImageFilter 91 | FixedThresholderType; 92 | typename FixedThresholderType::Pointer thresf = FixedThresholderType::New(); 93 | thresf->SetInput(m_FixedImage); 94 | thresf->SetLowerThreshold(label); 95 | thresf->SetUpperThreshold(label); 96 | thresf->Update(); 97 | 98 | typedef itk::BinaryThresholdImageFilter 99 | MovingThresholderType; 100 | typename MovingThresholderType::Pointer thresm = MovingThresholderType::New(); 101 | thresm->SetInput(m_MovingImage); 102 | thresm->SetLowerThreshold(label); 103 | thresm->SetUpperThreshold(label); 104 | thresm->Update(); 105 | 106 | typename MetricType::Pointer metric = MetricType::New(); 107 | metric->SetFixedImage(thresf->GetOutput()); 108 | metric->SetMovingImage(thresm->GetOutput()); 109 | 110 | m_MetricValues.push_back(metric->GetValue()); 111 | } 112 | 113 | 114 | } 115 | 116 | 117 | #endif 118 | -------------------------------------------------------------------------------- /AverageDistanceImageToImageMetric.txx: -------------------------------------------------------------------------------- 1 | 2 | #ifndef _AverageDistanceImageToImageMetric_txx 3 | #define _AverageDistanceImageToImageMetric_txx 4 | 5 | #include "itkBSplineInterpolateImageFunction.h" 6 | #include "itkDiscreteGaussianImageFilter.h" 7 | #include "itkImageRegionConstIteratorWithIndex.h" 8 | #include "itkLinearInterpolateImageFunction.h" 9 | #include "itkSignedMaurerDistanceMapImageFilter.h" 10 | 11 | #include "itkBinaryBallStructuringElement.h" 12 | #include "itkMorphologicalGradientImageFilter.h" 13 | 14 | #include "vnl/vnl_math.h" 15 | 16 | #include "AverageDistanceImageToImageMetric.h" 17 | 18 | 19 | template 20 | AverageDistanceImageToImageMetric 21 | ::AverageDistanceImageToImageMetric() 22 | { 23 | m_DoBlurring = false; 24 | } 25 | 26 | template 27 | AverageDistanceImageToImageMetric 28 | ::~AverageDistanceImageToImageMetric() 29 | { 30 | 31 | } 32 | 33 | template 34 | double 35 | AverageDistanceImageToImageMetric 36 | ::ComputeNonSymmetricDistance( 37 | const TFixedImage* img1, const TMovingImage* img2) const 38 | { 39 | typedef itk::Image FloatImageType; 40 | 41 | typedef itk::SignedMaurerDistanceMapImageFilter< 42 | FixedImageType, FloatImageType> DistanceMapFilterType; 43 | 44 | typedef itk::DiscreteGaussianImageFilter< 45 | FloatImageType, FloatImageType> BlurFilterType; 46 | 47 | // Compute distance transform 48 | typename FloatImageType::Pointer distMap2; 49 | { 50 | typename DistanceMapFilterType::Pointer distanceMapFilter = 51 | DistanceMapFilterType::New(); 52 | 53 | distanceMapFilter->InsideIsPositiveOff(); 54 | distanceMapFilter->SetInput(img2); 55 | distanceMapFilter->SquaredDistanceOff(); 56 | distanceMapFilter->UseImageSpacingOn(); 57 | 58 | distanceMapFilter->Update(); 59 | 60 | if (!m_DoBlurring) 61 | { 62 | distMap2 = distanceMapFilter->GetOutput(); 63 | } 64 | else 65 | { 66 | typename FloatImageType::SpacingType spacing = img1->GetSpacing(); 67 | 68 | double minSpacing = spacing[0]; 69 | for (unsigned int dim = 0; dim < FixedImageType::ImageDimension; dim++) 70 | if (spacing[dim] < minSpacing) 71 | minSpacing = spacing[dim]; 72 | 73 | typename BlurFilterType::Pointer blurf = BlurFilterType::New(); 74 | blurf->SetInput(distanceMapFilter->GetOutput()); 75 | blurf->SetVariance(1.5 * minSpacing); 76 | blurf->Update(); 77 | 78 | distMap2 = blurf->GetOutput(); 79 | } 80 | } 81 | 82 | //typedef itk::LinearInterpolateImageFunction 83 | typedef itk::BSplineInterpolateImageFunction 84 | InterpolatorType; 85 | typename InterpolatorType::Pointer distInterp2 = InterpolatorType::New(); 86 | distInterp2->SetInputImage(distMap2); 87 | distInterp2->SetSplineOrder(3); 88 | 89 | // Detect boundary via morphological gradient 90 | typedef itk::BinaryBallStructuringElement 91 | StructElementType; 92 | typedef 93 | itk::MorphologicalGradientImageFilter EdgeFilterType; 95 | 96 | StructElementType structel; 97 | structel.SetRadius(1); 98 | structel.CreateStructuringElement(); 99 | 100 | typename EdgeFilterType::Pointer edgef = EdgeFilterType::New(); 101 | edgef->SetInput(img1); 102 | edgef->SetKernel(structel); 103 | edgef->Update(); 104 | 105 | FixedImagePointer edgeImg1 = edgef->GetOutput(); 106 | 107 | double sumD = 0; 108 | double numV = 0; 109 | 110 | typedef itk::ImageRegionConstIteratorWithIndex 111 | FixedIteratorType; 112 | FixedIteratorType it(edgeImg1, edgeImg1->GetLargestPossibleRegion()); 113 | 114 | for (it.GoToBegin(); !it.IsAtEnd(); ++it) 115 | { 116 | FixedImageIndexType ind = it.GetIndex(); 117 | 118 | if (it.Get() == 0 || img1->GetPixel(ind) == 0) 119 | continue; 120 | 121 | FixedImagePointType p; 122 | img1->TransformIndexToPhysicalPoint(ind, p); 123 | 124 | if (!distInterp2->IsInsideBuffer(p)) 125 | continue; 126 | 127 | sumD += vnl_math_abs(distInterp2->Evaluate(p)); 128 | numV += 1.0; 129 | } 130 | 131 | if (numV == 0) 132 | return vnl_huge_val(1.0); 133 | 134 | 135 | return sumD / numV; 136 | 137 | } 138 | 139 | template 140 | typename AverageDistanceImageToImageMetric::MeasureType 141 | AverageDistanceImageToImageMetric 142 | ::GetValue() const 143 | { 144 | if (Superclass::m_FixedImage.IsNull() || Superclass::m_MovingImage.IsNull()) 145 | itkExceptionMacro(<< "Need two input classification images"); 146 | 147 | // Handle special case where inputs are zeros 148 | typedef itk::ImageRegionConstIteratorWithIndex 149 | FixedIteratorType; 150 | FixedIteratorType it(Superclass::m_FixedImage, Superclass::m_FixedImage->GetLargestPossibleRegion()); 151 | 152 | double sumFixed = 0; 153 | double sumMoving = 0; 154 | for (it.GoToBegin(); !it.IsAtEnd(); ++it) 155 | { 156 | sumFixed += it.Get(); 157 | sumMoving += Superclass::m_MovingImage->GetPixel(it.GetIndex()); 158 | } 159 | 160 | if (sumFixed == 0 || sumMoving == 0) 161 | { 162 | if (sumFixed == sumMoving) 163 | return 0.0; 164 | else 165 | return vnl_huge_val(1.0); 166 | } 167 | 168 | double d12 = this->ComputeNonSymmetricDistance( 169 | Superclass::m_FixedImage, Superclass::m_MovingImage); 170 | 171 | if (vnl_math_isinf(d12)) 172 | return vnl_huge_val(1.0); 173 | 174 | double d21 = this->ComputeNonSymmetricDistance( 175 | Superclass::m_MovingImage, Superclass::m_FixedImage); 176 | 177 | if (vnl_math_isinf(d21)) 178 | return vnl_huge_val(1.0); 179 | 180 | return 0.5 * (d12 + d21); 181 | 182 | } 183 | 184 | #endif 185 | -------------------------------------------------------------------------------- /HausdorffDistanceImageToImageMetric.txx: -------------------------------------------------------------------------------- 1 | 2 | #ifndef _HausdorffDistanceImageToImageMetric_txx 3 | #define _HausdorffDistanceImageToImageMetric_txx 4 | 5 | #include "itkBSplineInterpolateImageFunction.h" 6 | #include "itkDiscreteGaussianImageFilter.h" 7 | #include "itkImageRegionConstIteratorWithIndex.h" 8 | #include "itkLinearInterpolateImageFunction.h" 9 | #include "itkSignedMaurerDistanceMapImageFilter.h" 10 | 11 | #include "itkBinaryBallStructuringElement.h" 12 | #include "itkMorphologicalGradientImageFilter.h" 13 | 14 | #include "vnl/vnl_math.h" 15 | 16 | #include "HausdorffDistanceImageToImageMetric.h" 17 | 18 | #include 19 | #include 20 | #include 21 | 22 | 23 | template 24 | HausdorffDistanceImageToImageMetric 25 | ::HausdorffDistanceImageToImageMetric() 26 | { 27 | m_DoBlurring = false; 28 | 29 | m_Percentile = 0.95; 30 | } 31 | 32 | template 33 | HausdorffDistanceImageToImageMetric 34 | ::~HausdorffDistanceImageToImageMetric() 35 | { 36 | 37 | } 38 | 39 | template 40 | void 41 | HausdorffDistanceImageToImageMetric 42 | ::SetPercentile(double p) 43 | { 44 | if (p < 0.0 || p > 1.0) 45 | itkExceptionMacro(<< "Percentile needs to be in [0, 1]"); 46 | 47 | m_Percentile = p; 48 | } 49 | 50 | template 51 | double 52 | HausdorffDistanceImageToImageMetric 53 | ::ComputeMaxDistance( 54 | const TFixedImage* img1, const TMovingImage* img2) const 55 | { 56 | typedef itk::Image FloatImageType; 57 | 58 | typedef itk::SignedMaurerDistanceMapImageFilter< 59 | FixedImageType, FloatImageType> DistanceMapFilterType; 60 | 61 | typedef itk::DiscreteGaussianImageFilter< 62 | FloatImageType, FloatImageType> BlurFilterType; 63 | 64 | // Compute distance transform 65 | typename FloatImageType::Pointer distMap2; 66 | { 67 | typename DistanceMapFilterType::Pointer distanceMapFilter = 68 | DistanceMapFilterType::New(); 69 | 70 | distanceMapFilter->InsideIsPositiveOff(); 71 | distanceMapFilter->SetInput(img2); 72 | distanceMapFilter->SquaredDistanceOff(); 73 | distanceMapFilter->UseImageSpacingOn(); 74 | 75 | distanceMapFilter->Update(); 76 | 77 | if (!m_DoBlurring) 78 | { 79 | distMap2 = distanceMapFilter->GetOutput(); 80 | } 81 | else 82 | { 83 | typename FloatImageType::SpacingType spacing = img1->GetSpacing(); 84 | 85 | double minSpacing = spacing[0]; 86 | for (unsigned int dim = 0; dim < FixedImageType::ImageDimension; dim++) 87 | if (spacing[dim] < minSpacing) 88 | minSpacing = spacing[dim]; 89 | 90 | typename BlurFilterType::Pointer blurf = BlurFilterType::New(); 91 | blurf->SetInput(distanceMapFilter->GetOutput()); 92 | blurf->SetVariance(1.5 * minSpacing); 93 | blurf->Update(); 94 | 95 | distMap2 = blurf->GetOutput(); 96 | } 97 | } 98 | 99 | //typedef itk::LinearInterpolateImageFunction 100 | typedef itk::BSplineInterpolateImageFunction 101 | InterpolatorType; 102 | typename InterpolatorType::Pointer distInterp2 = InterpolatorType::New(); 103 | distInterp2->SetInputImage(distMap2); 104 | distInterp2->SetSplineOrder(3); 105 | 106 | // Detect boundary via morphological gradient 107 | typedef itk::BinaryBallStructuringElement 108 | StructElementType; 109 | typedef 110 | itk::MorphologicalGradientImageFilter EdgeFilterType; 112 | 113 | StructElementType structel; 114 | structel.SetRadius(1); 115 | structel.CreateStructuringElement(); 116 | 117 | typename EdgeFilterType::Pointer edgef = EdgeFilterType::New(); 118 | edgef->SetInput(img1); 119 | edgef->SetKernel(structel); 120 | edgef->Update(); 121 | 122 | FixedImagePointer edgeImg1 = edgef->GetOutput(); 123 | 124 | std::vector distances; 125 | 126 | typedef itk::ImageRegionConstIteratorWithIndex 127 | FixedIteratorType; 128 | FixedIteratorType it(edgeImg1, edgeImg1->GetLargestPossibleRegion()); 129 | 130 | for (it.GoToBegin(); !it.IsAtEnd(); ++it) 131 | { 132 | FixedImageIndexType ind = it.GetIndex(); 133 | 134 | if (it.Get() == 0 || img1->GetPixel(ind) == 0) 135 | continue; 136 | 137 | FixedImagePointType p; 138 | img1->TransformIndexToPhysicalPoint(ind, p); 139 | 140 | if (!distInterp2->IsInsideBuffer(p)) 141 | continue; 142 | 143 | distances.push_back(vnl_math_abs(distInterp2->Evaluate(p))); 144 | } 145 | 146 | if (distances.size() == 0) 147 | return vnl_huge_val(1.0); 148 | 149 | std::sort(distances.begin(), distances.end()); 150 | 151 | return distances[(int)(m_Percentile*(distances.size() - 1))]; 152 | } 153 | 154 | template 155 | typename HausdorffDistanceImageToImageMetric::MeasureType 156 | HausdorffDistanceImageToImageMetric 157 | ::GetValue() const 158 | { 159 | if (Superclass::m_FixedImage.IsNull() || Superclass::m_MovingImage.IsNull()) 160 | itkExceptionMacro(<< "Need two input classification images"); 161 | 162 | // Handle special case where inputs are zeros 163 | typedef itk::ImageRegionConstIteratorWithIndex 164 | FixedIteratorType; 165 | FixedIteratorType it(Superclass::m_FixedImage, Superclass::m_FixedImage->GetLargestPossibleRegion()); 166 | 167 | double sumFixed = 0; 168 | double sumMoving = 0; 169 | for (it.GoToBegin(); !it.IsAtEnd(); ++it) 170 | { 171 | sumFixed += it.Get(); 172 | sumMoving += Superclass::m_MovingImage->GetPixel(it.GetIndex()); 173 | } 174 | 175 | if (sumFixed == 0 || sumMoving == 0) 176 | { 177 | if (sumFixed == sumMoving) 178 | return 0.0; 179 | else 180 | return vnl_huge_val(1.0); 181 | } 182 | 183 | // Compute max distances at specified percentile 184 | double d12 = this->ComputeMaxDistance( 185 | Superclass::m_FixedImage, Superclass::m_MovingImage); 186 | double d21 = this->ComputeMaxDistance( 187 | Superclass::m_MovingImage, Superclass::m_FixedImage); 188 | 189 | if (d12 > d21) 190 | return d12; 191 | else 192 | return d21; 193 | 194 | } 195 | 196 | #endif 197 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | MACRO(LISTLIBNAMES result curdir) 3 | FILE(GLOB children RELATIVE ${curdir} ${curdir}/*) 4 | SET(listnames "") 5 | FOREACH(child ${children}) 6 | IF(IS_DIRECTORY ${curdir}/${child}) 7 | ELSE() 8 | LIST(APPEND listnames ${child}) 9 | ENDIF() 10 | ENDFOREACH() 11 | SET(${result} ${listnames}) 12 | ENDMACRO() 13 | 14 | if(POLICY CMP0020) 15 | cmake_policy(SET CMP0020 NEW) 16 | endif() 17 | if(POLICY CMP0043) 18 | cmake_policy(SET CMP0043 NEW) 19 | endif() 20 | if(POLICY CMP0042) 21 | cmake_policy(SET CMP0042 NEW) 22 | endif() 23 | if(POLICY CMP0043) 24 | cmake_policy(SET CMP0043 NEW) 25 | endif() 26 | # ====================================================================== 27 | # ====================================================================== 28 | PROJECT(ImageValidationISLES) 29 | # ====================================================================== 30 | # ====================================================================== 31 | if(CMAKE_COMPILER_IS_GNUCXX) 32 | add_definitions(-std=c++11) 33 | endif() 34 | 35 | GET_FILENAME_COMPONENT(PARENT_DIR ${CMAKE_SOURCE_DIR} DIRECTORY) 36 | 37 | IF(APPLE) 38 | 39 | ELSEIF(WIN32) 40 | # this optional you have to provide to the program where are your dll lib of ITK 41 | LINK_DIRECTORIES(C:/Developer/ITKs/InsightToolkit-4.7.1/build/bin/Release/) 42 | LINK_DIRECTORIES(C:/Developer/ITKs/InsightToolkit-4.7.1/build/lib/Release/) 43 | ELSEIF(UNIX AND NOT APPLE) 44 | SET(CMAKE_INSTALL_PREFIX ${PARENT_DIR}/install/linux) 45 | ENDIF(APPLE) 46 | 47 | 48 | FIND_PACKAGE(OpenGL) 49 | 50 | FIND_PACKAGE(ITK REQUIRED) 51 | INCLUDE(${ITK_USE_FILE}) 52 | 53 | # Find includes in corresponding build directories 54 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 55 | 56 | add_executable(${PROJECT_NAME} MACOSX_BUNDLE validateLabelImages-ISLES.cxx) 57 | target_link_libraries(${PROJECT_NAME} ${ITK_LIBRARIES}) 58 | 59 | # > --------------------------------------------------------------------------'' 60 | SET(APPS \$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/bin/${PROJECT_NAME}) 61 | 62 | SET(APP_DESTINY bin) 63 | 64 | IF(APPLE) 65 | SET(APPS "${APPS}.app") 66 | SET(APP_DESTINY bin/${PROJECT_NAME}.app/Contents/MacOS) 67 | 68 | SET(ITK_LIBRARY_DIRS ${ITK_INSTALL_PREFIX}/lib) 69 | SET(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH}) 70 | SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) 71 | ELSEIF(WIN32) 72 | SET(APPS "${APPS}.exe") 73 | SET(ITK_LIBRARY_DIRS C:/Developer/ITKs/InsightToolkit-4.7.1/build/bin/Release) 74 | ELSEIF(UNIX AND NOT APPLE) 75 | SET(ITK_LIBRARY_DIRS ${ITK_DIR}) 76 | ENDIF(APPLE) 77 | #-------------------------------------------------------------------------------- 78 | 79 | INSTALL(TARGETS ${PROJECT_NAME} 80 | BUNDLE DESTINATION bin COMPONENT bin 81 | RUNTIME DESTINATION bin COMPONENT bin) 82 | 83 | #-------------------------------------------------------------------------------- 84 | # Use BundleUtilities to get all other dependencies for the application to work. 85 | 86 | IF(NOT CMAKE_CFG_INTDIR) 87 | SET(CMAKE_CFG_INTDIR "Release") 88 | ENDIF(NOT CMAKE_CFG_INTDIR) 89 | 90 | MESSAGE("\nProject: ${PROJECT_NAME}, Source path: ${CMAKE_CURRENT_SOURCE_DIR}") 91 | MESSAGE("Project: ${PROJECT_NAME}, Install path: ${CMAKE_CURRENT_BINARY_DIR}") 92 | MESSAGE("Project: ${PROJECT_NAME}, INTDIR path: ${CMAKE_CFG_INTDIR}") 93 | MESSAGE("Project: ${PROJECT_NAME}, ITK Directories path: ${ITK_LIBRARY_DIRS}") 94 | 95 | 96 | SET(DIRS ${ITK_LIBRARY_DIRS}) 97 | 98 | IF(APPLE) 99 | SET(DIRS ${DIRS} /opt/local/lib) 100 | INSTALL(FILES 101 | "/opt/local/lib/libxslt.1.dylib" 102 | DESTINATION ${APP_DESTINY} 103 | COMPONENT bin) 104 | # ELSEIF(WIN32) 105 | # 106 | ELSEIF(UNIX AND NOT APPLE) 107 | SET(DIRS ${DIRS} /opt/local/lib) 108 | ENDIF(APPLE) 109 | 110 | # Now the work of copying dependencies into the bundle/package 111 | MESSAGE("${APPS}") 112 | 113 | INSTALL(CODE " 114 | include(BundleUtilities) 115 | fixup_bundle(\"${APPS}\" \"\${QTPLUGINS}\" \"${DIRS}\") 116 | " COMPONENT bin) 117 | 118 | 119 | # To Create a package, one can run "cpack -G DragNDrop CPackConfig.cmake" on Mac OS X 120 | # where CPackConfig.cmake is created by including CPack 121 | # And then there's ways to customize this as well 122 | INCLUDE(InstallRequiredSystemLibraries) 123 | 124 | IF(APPLE) 125 | # SET(CPACK_BUNDLE_NAME ${PROJECT_NAME}) 126 | ELSEIF(WIN32) 127 | set(CPACK_GENERATOR NSIS) 128 | set(CPACK_NSIS_EXTRA_INSTALL_COMMANDS " 129 | CreateShortCut \\\"$DESKTOP\\\\ImageValidationISLES.lnk\\\" \\\"$INSTDIR\\\\bin\\\\ImageValidationISLES.exe\\\"") 130 | SET(CPACK_NSIS_MODIFY_PATH ON) 131 | install(FILES ${LIBS_EXTERNALS} 132 | DESTINATION bin 133 | COMPONENT ${PROJECT_NAME}) 134 | MESSAGE("Project: ${LIBNAMES}") 135 | # By default, do not warn when built on machines using only VS Express: 136 | if(NOT DEFINED CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_NO_WARNINGS) 137 | SET(CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_NO_WARNINGS ON) 138 | endif() 139 | ELSEIF(UNIX AND NOT APPLE) 140 | SET(CPACK_SOURCE_INSTALLED_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR};/" ) 141 | SET(CPACK_STRIP_FILES "bin/${PROJECT_NAME}") 142 | SET(CPACK_SOURCE_STRIP_FILES "") 143 | SET(CPACK_SOURCE_PACKAGE_FILE_NAME "${PROJECT_NAME}-${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}") 144 | 145 | SET(CPACK_PACKAGING_INSTALL_PREFIX "/tmp") 146 | 147 | SET(CPACK_GENERATOR "TGZ;DEB") 148 | # Use dkpg-shlibdeps to generate dependency list 149 | SET( CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON ) 150 | # Enable debug message 151 | SET( CPACK_DEBIAN_PACKAGE_DEBUG 1 ) 152 | 153 | SET(CPACK_DEBIAN_ARCHITECTURE ${CMAKE_SYSTEM_PROCESSOR}) 154 | SET(CPACK_DEB_COMPONENT_INSTALL 1) 155 | SET(CPACK_DEBIAN_PACKAGE_MAINTAINER "Waldo Valenzuela") #required 156 | SET(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6 (>= 2.3.1-6), libgcc1 (>= 1:3.4.2-12)") 157 | 158 | #Control files 159 | SET( CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA 160 | "${CMAKE_CURRENT_SOURCE_DIR}/build/packaging/debian/postinst" 161 | "${CMAKE_CURRENT_SOURCE_DIR}/build/packaging/debian/postrm" 162 | "${CMAKE_CURRENT_SOURCE_DIR}/build/packaging/debian/preinst" 163 | "${CMAKE_CURRENT_SOURCE_DIR}/build/packaging/debian/prerm" 164 | "${CMAKE_CURRENT_SOURCE_DIR}/build/packaging/debian/conffiles" 165 | ) 166 | ENDIF(APPLE) 167 | 168 | include(CPack) 169 | 170 | -------------------------------------------------------------------------------- /validateLabelImages-ISLES.cxx: -------------------------------------------------------------------------------- 1 | 2 | // Executable for computing image metrics 3 | // Usage: truth.nii[.gz] test.nii[.gz] evaluation.json (optional) 4 | // 5 | // Metrics returned (semicolon-separated): 6 | // 1. Average symmetric surface distance (ASSD) 7 | // 2. Dice's Coefficient (DC) 8 | // 3. Hausdorff Distance (HD) 9 | // 4. Precision = positive predictive value (precision) 10 | // 5. Recall = true positive rate = sensitivity (recall) 11 | // 6. Volume overlapping error 12 | // 13 | // Error return codes: 14 | // 0: success 15 | // -1: wrong number of input parameters 16 | // -2: failed to read input image(s) 17 | // -3: incompatible input images 18 | // -4: exception thrown during metric computation 19 | // 20 | // prastawa@sci.utah.edu 21 | // modified stefan.bauer@istb.unibe.ch 22 | // adapted for www.isles-challenge.org by maier@imi.uni-luebeck.de 23 | // modified for www.isles-challenge.org by waldo.valenzuela@istb.unibe.ch 24 | 25 | #include "itkImage.h" 26 | #include "itkImageFileReader.h" 27 | 28 | #include "ImageToImageValidator.h" 29 | 30 | #include "AverageDistanceImageToImageMetric.h" 31 | #include "HausdorffDistanceImageToImageMetric.h" 32 | #include "DiceOverlapImageToImageMetric.h" 33 | #include "SensitivityImageToImageMetric.h" 34 | #include "PositivePredictiveValueImageToImageMetric.h" 35 | #include "AbsoluteVolumeErrorImageToImageMetric.h" 36 | #include "MultipleBinaryImageMetricsCalculator.h" 37 | 38 | #include 39 | #include 40 | #include 41 | #include 42 | 43 | typedef itk::Image ImageType; 44 | 45 | typedef struct { 46 | double assd; 47 | double dice; 48 | double hausdorff; 49 | double precision; 50 | double sensitivity; 51 | double volumeerror; 52 | }Evaluation; 53 | 54 | 55 | Evaluation 56 | validateLabelImage(ImageType::Pointer fixedImage, ImageType::Pointer movingImage) 57 | { 58 | // input assumes to be binary and valid 59 | Evaluation evaluation; 60 | // Metrics for binary data 61 | typedef AverageDistanceImageToImageMetric 62 | AverageDistanceMetricType; 63 | typedef DiceOverlapImageToImageMetric 64 | DiceMetricType; 65 | typedef HausdorffDistanceImageToImageMetric 66 | HausdorffDistanceMetricType; 67 | typedef SensitivityImageToImageMetric 68 | SensitivityMetricType; 69 | typedef PositivePredictiveValueImageToImageMetric 70 | PPVMetricType; 71 | 72 | AverageDistanceMetricType::Pointer assd = AverageDistanceMetricType::New(); 73 | assd->SetFixedImage(fixedImage); 74 | assd->SetMovingImage(movingImage); 75 | std::cout << assd->GetValue() << ";"; 76 | evaluation.assd = assd->GetValue(); 77 | 78 | DiceMetricType::Pointer dc = DiceMetricType::New(); 79 | dc->SetFixedImage(fixedImage); 80 | dc->SetMovingImage(movingImage); 81 | std::cout << dc->GetValue() << ";"; 82 | evaluation.dice = dc->GetValue(); 83 | 84 | HausdorffDistanceMetricType::Pointer hd = HausdorffDistanceMetricType::New(); 85 | hd->SetFixedImage(fixedImage); 86 | hd->SetMovingImage(movingImage); 87 | hd->SetPercentile(1.0); 88 | std::cout << hd->GetValue() << ";"; 89 | evaluation.hausdorff = hd->GetValue(); 90 | 91 | 92 | PPVMetricType::Pointer precision = PPVMetricType::New(); 93 | precision->SetFixedImage(fixedImage); 94 | precision->SetMovingImage(movingImage); 95 | std::cout << precision->GetValue() << ";"; 96 | evaluation.precision = precision->GetValue(); 97 | 98 | SensitivityMetricType::Pointer recall = SensitivityMetricType::New(); 99 | recall->SetFixedImage(fixedImage); 100 | recall->SetMovingImage(movingImage); 101 | std::cout << recall->GetValue() << std::endl; 102 | evaluation.sensitivity = recall->GetValue(); 103 | 104 | //================================================ 105 | typedef AbsoluteVolumeErrorImageToImageMetric AbsVolErrMetricType; 106 | typedef MultipleBinaryImageMetricsCalculator AbsVolErrCalculatorType; 107 | { 108 | AbsVolErrCalculatorType::Pointer calc = AbsVolErrCalculatorType::New(); 109 | calc->SetFixedImage(fixedImage); 110 | calc->SetMovingImage(movingImage); 111 | calc->Update(); 112 | for (unsigned int i = 0; i < calc->GetNumberOfValues(); i++) 113 | std::cout << "AbsoluteVolumeError(" << "A_" << i+1 << ", B_" << i+1 << ") = " << calc->GetValue(i) << std::endl; 114 | evaluation.volumeerror = calc->GetValue(0); 115 | } 116 | return evaluation; 117 | } 118 | void writeJson(Evaluation evaluation, std::string path) 119 | { 120 | std::ofstream myfile; 121 | myfile.open (path.c_str()); 122 | myfile << "[{"; 123 | myfile << "\"ASSD\":" << evaluation.assd << ","; 124 | myfile << "\"DICE\":" << evaluation.dice << ","; 125 | myfile << "\"HD\":" << evaluation.hausdorff << ","; 126 | myfile << "\"PRECISION\":" << evaluation.precision << ","; 127 | myfile << "\"RECALL\":" << evaluation.sensitivity << ","; 128 | myfile << "\"VOLUMEERROR\":" << evaluation.volumeerror; 129 | myfile << "}]"; 130 | myfile.close(); 131 | } 132 | int 133 | main(int argc, char** argv) 134 | { 135 | if (argc < 3) 136 | { 137 | std::cerr << "computes assd, dc, hd, precision and recall between two binary images" << std::endl; 138 | std::cerr << "usage: " << argv[0] << " truth-image test-image" << std::endl; 139 | return -1; 140 | } 141 | std::string pathdestiny = "evaluation.json"; 142 | if (argc == 4) 143 | { 144 | pathdestiny = std::string(argv[3]); 145 | } 146 | 147 | 148 | // read images 149 | typedef itk::ImageFileReader ReaderType; 150 | 151 | // read truth image 152 | ReaderType::Pointer freader = ReaderType::New(); 153 | freader->SetFileName(argv[1]); 154 | try 155 | { 156 | freader->Update(); 157 | } 158 | catch ( itk::ExceptionObject &exception ) 159 | { 160 | std::cerr << "Exception caught while reading truth-image!" << std::endl; 161 | std::cerr << &exception << std::endl; 162 | return -2; 163 | } 164 | ImageType::Pointer truthImage = freader->GetOutput(); 165 | 166 | // read test image 167 | ReaderType::Pointer mreader = ReaderType::New(); 168 | mreader->SetFileName(argv[2]); 169 | try 170 | { 171 | mreader->Update(); 172 | } 173 | catch ( itk::ExceptionObject &exception ) 174 | { 175 | std::cerr << "Exception caught while reading!" << std::endl; 176 | std::cerr << &exception << std::endl; 177 | return -2; 178 | } 179 | ImageType::Pointer testImage = mreader->GetOutput(); 180 | 181 | // validate image compatibility 182 | typedef ImageToImageValidator 183 | ImageToImageValidatorType; 184 | ImageToImageValidatorType::Pointer validator = ImageToImageValidatorType::New(); 185 | validator->SetFixedImage(truthImage); 186 | validator->SetMovingImage(testImage); 187 | if (!(0 == validator->GetValue())) 188 | { 189 | std::cerr << "Incompatible input images (according to origin, spacing, direction or largest possible region)! " << std::endl; 190 | return -3; 191 | } 192 | 193 | // compute metrics 194 | Evaluation evaluation; 195 | try 196 | { 197 | evaluation = validateLabelImage(truthImage, testImage); 198 | writeJson(evaluation,pathdestiny); 199 | } 200 | catch ( itk::ExceptionObject& e ) 201 | { 202 | std::cerr << e << std::endl; 203 | return -4; 204 | } 205 | catch ( std::exception& e ) 206 | { 207 | std::cerr << "Exception: " << e.what() << std::endl; 208 | return -4; 209 | } 210 | catch ( std::string& s ) 211 | { 212 | std::cerr << "Exception: " << s << std::endl; 213 | return -4; 214 | } 215 | catch (...) 216 | { 217 | std::cerr << "Unknown exception" << std::endl; 218 | return -4; 219 | } 220 | 221 | return 0; 222 | } 223 | --------------------------------------------------------------------------------