Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
CLUtilities/test/mitkGlobalFeaturesTest.cpp
Go to the documentation of this file.
1 /*===================================================================
2 
3 The Medical Imaging Interaction Toolkit (MITK)
4 
5 Copyright (c) German Cancer Research Center,
6 Division of Medical and Biological Informatics.
7 All rights reserved.
8 
9 This software is distributed WITHOUT ANY WARRANTY; without
10 even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE.
12 
13 See LICENSE.txt or http://www.mitk.org for details.
14 
15 ===================================================================*/
16 
17 #include <mitkTestingMacros.h>
18 #include <mitkTestFixture.h>
19 #include "mitkIOUtil.h"
20 
21 #include <mitkImageCast.h>
25 #include <math.h>
26 
27 #include <mitkImageGenerator.h>
28 
29 template <typename TPixelType>
30 static mitk::Image::Pointer GenerateMaskImage(unsigned int dimX,
31  unsigned int dimY,
32  unsigned int dimZ,
33  float spacingX = 1,
34  float spacingY = 1,
35  float spacingZ = 1)
36 {
37  typedef itk::Image< TPixelType, 3 > ImageType;
38  typename ImageType::RegionType imageRegion;
39  imageRegion.SetSize(0, dimX);
40  imageRegion.SetSize(1, dimY);
41  imageRegion.SetSize(2, dimZ);
42  typename ImageType::SpacingType spacing;
43  spacing[0] = spacingX;
44  spacing[1] = spacingY;
45  spacing[2] = spacingZ;
46 
47  mitk::Point3D origin; origin.Fill(0.0);
48  itk::Matrix<double, 3, 3> directionMatrix; directionMatrix.SetIdentity();
49 
50  typename ImageType::Pointer image = ImageType::New();
51  image->SetSpacing( spacing );
52  image->SetOrigin( origin );
53  image->SetDirection( directionMatrix );
54  image->SetLargestPossibleRegion( imageRegion );
55  image->SetBufferedRegion( imageRegion );
56  image->SetRequestedRegion( imageRegion );
57  image->Allocate();
58  image->FillBuffer(1);
59 
61  mitkImage->InitializeByItk( image.GetPointer() );
62  mitkImage->SetVolume( image->GetBufferPointer() );
63  return mitkImage;
64 }
65 
66 template <typename TPixelType>
68  unsigned int dimY,
69  unsigned int dimZ,
70  float spacingX = 1,
71  float spacingY = 1,
72  float spacingZ = 1)
73 {
74  typedef itk::Image< TPixelType, 3 > ImageType;
75  typename ImageType::RegionType imageRegion;
76  imageRegion.SetSize(0, dimX);
77  imageRegion.SetSize(1, dimY);
78  imageRegion.SetSize(2, dimZ);
79  typename ImageType::SpacingType spacing;
80  spacing[0] = spacingX;
81  spacing[1] = spacingY;
82  spacing[2] = spacingZ;
83 
84  mitk::Point3D origin; origin.Fill(0.0);
85  itk::Matrix<double, 3, 3> directionMatrix; directionMatrix.SetIdentity();
86 
87  typename ImageType::Pointer image = ImageType::New();
88  image->SetSpacing( spacing );
89  image->SetOrigin( origin );
90  image->SetDirection( directionMatrix );
91  image->SetLargestPossibleRegion( imageRegion );
92  image->SetBufferedRegion( imageRegion );
93  image->SetRequestedRegion( imageRegion );
94  image->Allocate();
95  image->FillBuffer(0.0);
96 
97  typedef itk::ImageRegionIterator<ImageType> IteratorOutputType;
98  IteratorOutputType it(image, imageRegion);
99  it.GoToBegin();
100 
101  TPixelType val = 0;
102  while(!it.IsAtEnd())
103  {
104  it.Set(val % dimX);
105  val++;
106  ++it;
107  }
108 
110  mitkImage->InitializeByItk( image.GetPointer() );
111  mitkImage->SetVolume( image->GetBufferPointer() );
112  return mitkImage;
113 }
114 
115 class mitkGlobalFeaturesTestSuite : public mitk::TestFixture
116 {
117  CPPUNIT_TEST_SUITE(mitkGlobalFeaturesTestSuite );
118 
119  MITK_TEST(FirstOrder_SinglePoint);
120  MITK_TEST(FirstOrder_QubicArea);
121  //MITK_TEST(RunLenght_QubicArea);
122  MITK_TEST(Coocurrence_QubicArea);
123  //MITK_TEST(TestFirstOrderStatistic);
124  // MITK_TEST(TestThreadedDecisionForest);
125 
126  CPPUNIT_TEST_SUITE_END();
127 
128 private:
129 
130  typedef itk::Image<double,3> ImageType;
131  typedef itk::Image<unsigned char,3> MaskType;
132 
133  mitk::Image::Pointer m_Image,m_Mask,m_Mask1;
134  ImageType::Pointer m_ItkImage;
135  MaskType::Pointer m_ItkMask,m_ItkMask1;
136 
137  mitk::Image::Pointer m_GradientImage, m_GradientMask;
138 
139 public:
140 
141  void setUp(void)
142  {
143  // Load Image Data
144  m_Image = mitk::IOUtil::LoadImage(GetTestDataFilePath("Pic3D.nrrd"));
145  mitk::CastToItkImage(m_Image,m_ItkImage);
146 
147  // Create a single mask with only one pixel within the regions
149  mitk::CastToItkImage(mask1,m_ItkMask);
150  m_ItkMask->FillBuffer(0);
151  MaskType::IndexType index;
152  index[0]=88;index[1]=81;index[2]=13;
153  m_ItkMask->SetPixel(index, 1);
154  MITK_INFO << "Pixel Value: "<<m_ItkImage->GetPixel(index);
155  mitk::CastToMitkImage(m_ItkMask, m_Mask);
156 
157  // Create a mask with a covered region
159  mitk::CastToItkImage(lmask1,m_ItkMask1);
160  m_ItkMask1->FillBuffer(0);
161  int range=2;
162  for (int x = 88-range;x < 88+range+1;++x)
163  {
164  for (int y=81-range;y<81+range+1;++y)
165  {
166  for (int z=13-range;z<13+range+1;++z)
167  {
168  index[0] = x;
169  index[1] = y;
170  index[2] = z;
171  //MITK_INFO << "Pixel: " <<m_ItkImage->GetPixel(index);
172  m_ItkMask1->SetPixel(index, 1);
173  }
174  }
175  }
176  mitk::CastToMitkImage(m_ItkMask1, m_Mask1);
177 
178  m_GradientImage=GenerateGradientWithDimXImage<unsigned char>(5,5,5);
179  m_GradientMask = GenerateMaskImage<unsigned char>(5,5,5);
180  }
181 
182  void FirstOrder_SinglePoint()
183  {
185  calculator->SetHistogramSize(4096);
186  calculator->SetUseCtRange(true);
187  auto features = calculator->CalculateFeatures(m_Image, m_Mask);
188 
189  std::map<std::string, double> results;
190  for (auto iter=features.begin(); iter!=features.end();++iter)
191  {
192  results[(*iter).first]=(*iter).second;
193  MITK_INFO << (*iter).first << " : " << (*iter).second;
194  }
195 
196  CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The range of a single pixel should be 0",0.0, results["FirstOrder Range"], 0);
197  CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The uniformity of a single pixel should be 1",1.0, results["FirstOrder Uniformity"], 0);
198  CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The entropy of a single pixel should be 0",0.0, results["FirstOrder Entropy"], 0);
199  CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Root-Means-Square of a single pixel with (-352) should be 352",352.0, results["FirstOrder RMS"], 0.01);
200  CPPUNIT_ASSERT_EQUAL_MESSAGE("The Kurtosis of a single pixel should be undefined",results["FirstOrder Kurtosis"]==results["FirstOrder Kurtosis"], false);
201  CPPUNIT_ASSERT_EQUAL_MESSAGE("The Skewness of a single pixel should be undefined",results["FirstOrder Skewness"]==results["FirstOrder Skewness"], false);
202  CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Mean absolute deviation of a single pixel with (-352) should be 0",0, results["FirstOrder Mean absolute deviation"], 0.0);
203  CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Covered image intensity range of a single pixel with (-352) should be 0",0, results["FirstOrder Covered Image Intensity Range"], 0.0);
204  CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Minimum of a single pixel with (-352) should be -352",-352, results["FirstOrder Minimum"], 0.0);
205  CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Maximum of a single pixel with (-352) should be -352",-352, results["FirstOrder Maximum"], 0.0);
206  CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Mean of a single pixel with (-352) should be -352",-352, results["FirstOrder Mean"], 0.0);
207  CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Variance (corrected) of a single pixel with (-352) should be 0",0, results["FirstOrder Variance"], 0.0);
208  CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Sum of a single pixel with (-352) should be -352",-352, results["FirstOrder Sum"], 0.0);
209  CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Median of a single pixel with (-352) should be -352",-352, results["FirstOrder Median"], 0.0);
210  CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Standard deviation (corrected) of a single pixel with (-352) should be -352",0, results["FirstOrder Standard deviation"], 0.0);
211  CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The number of voxels of a single pixel should be 1",1, results["FirstOrder No. of Voxel"], 0.0);
212  CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Energy of a single pixel should be 352*352",352*352, results["FirstOrder Energy"], 0.0);
213  // MITK_ASSERT_EQUAL(results["FirstOrder Range"]==0.0,true,"The range of a single pixel should be 0");
214  }
215 
216  void FirstOrder_QubicArea()
217  {
219  calculator->SetHistogramSize(4096);
220  calculator->SetUseCtRange(true);
221  auto features = calculator->CalculateFeatures(m_Image, m_Mask1);
222 
223  std::map<std::string, double> results;
224  for (auto iter=features.begin(); iter!=features.end();++iter)
225  {
226  results[(*iter).first]=(*iter).second;
227  MITK_INFO << (*iter).first << " : " << (*iter).second;
228  }
229 
230  CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The range should be 981",981, results["FirstOrder Range"], 0);
231  CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Root-Means-Square of a single pixel with (-352) should be 352",402.895778, results["FirstOrder RMS"], 0.01);
232  CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Minimum of a single pixel with (-352) should be -352",-937, results["FirstOrder Minimum"], 0.0);
233  CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Maximum of a single pixel with (-352) should be -352",44, results["FirstOrder Maximum"], 0.0);
234  CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Mean of a single pixel with (-352) should be -352",-304.448, results["FirstOrder Mean"], 0.0);
235  CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Sum of a single pixel with (-352) should be -352",-38056, results["FirstOrder Sum"], 0.0);
236  CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Median of a single pixel with (-352) should be -352",-202, results["FirstOrder Median"], 0.0);
237  CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The number of voxels of a single pixel should be 1",125, results["FirstOrder No. of Voxel"], 0.0);
238  CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Standard deviation (corrected) of a single pixel with (-352) should be -352",264.949066, results["FirstOrder Standard deviation"], 0.000001);
239  CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Energy of a single pixel should be 352*352",20290626, results["FirstOrder Energy"], 0.0);
240  CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The uniformity of a single pixel should be 1",0.0088960, results["FirstOrder Uniformity"], 0.0000001);
241  CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The entropy of a single pixel should be 0",-6.853784285, results["FirstOrder Entropy"], 0.000000005);
242  CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Variance (corrected) of a single pixel with (-352) should be 0",70198.0074, results["FirstOrder Variance"], 0.0001);
243  CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Kurtosis of a single pixel should be 0",2.63480121, results["FirstOrder Kurtosis"], 0.0001);
244  CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Skewness of a single pixel should be 0",-0.91817318, results["FirstOrder Skewness"], 0.00001);
245  CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Mean absolute deviation of a single pixel with (-352) should be 0",219.348608, results["FirstOrder Mean absolute deviation"], 0.000001);
246  CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Covered image intensity range of a single pixel with (-352) should be 0",0.41149329, results["FirstOrder Covered Image Intensity Range"], 0.000001);
247  }
248 
249  void RunLenght_QubicArea()
250  {
252  //calculator->SetHistogramSize(4096);
253  calculator->SetUseCtRange(true);
254  calculator->SetRange(981);
255  auto features = calculator->CalculateFeatures(m_Image, m_Mask1);
256 
257  std::map<std::string, double> results;
258  for (auto iter=features.begin(); iter!=features.end();++iter)
259  {
260  results[(*iter).first]=(*iter).second;
261  MITK_INFO << (*iter).first << " : " << (*iter).second;
262  }
263  }
264 
265  void Coocurrence_QubicArea()
266  {
267  /*
268  * Expected Matrix: (Direction 0,0,1)
269  * |------------------------|
270  * | 20 | 0 | 0 | 0 | 0 |
271  * |------------------------|
272  * | 0 | 20 | 0 | 0 | 0 |
273  * |------------------------|
274  * | 0 | 0 | 20 | 0 | 0 |
275  * |------------------------|
276  * | 0 | 0 | 0 | 20 | 0 |
277  * |------------------------|
278  * | 0 | 0 | 0 | 0 | 20 |
279  * |------------------------|
280 
281  * Expected Matrix: (Direction (1,0,0),(0,1,0))
282  * |------------------------|
283  * | 20 | 0 | 0 | 0 | 0 |
284  * |------------------------|
285  * | 20 | 0 | 0 | 0 | 0 |
286  * |------------------------|
287  * | 20 | 0 | 0 | 0 | 0 |
288  * |------------------------|
289  * | 20 | 0 | 0 | 0 | 0 |
290  * |------------------------|
291  * | 20 | 0 | 0 | 0 | 0 |
292  * |------------------------|
293  */
294 
296  //calculator->SetHistogramSize(4096);
297  //calculator->SetUseCtRange(true);
298  //calculator->SetRange(981);
299  calculator->SetDirection(1);
300  auto features = calculator->CalculateFeatures(m_GradientImage, m_GradientMask);
301 
302  std::map<std::string, double> results;
303  for (auto iter=features.begin(); iter!=features.end();++iter)
304  {
305  results[(*iter).first]=(*iter).second;
306  MITK_INFO << (*iter).first << " : " << (*iter).second;
307  }
308  CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The mean energy value should be 0.2",0.2, results["co-occ. (1) Energy Means"], mitk::eps);
309  CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The mean entropy value should be 0.2",2.321928, results["co-occ. (1) Entropy Means"], 0.000001);
310  CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The mean contrast value should be 0.0",0, results["co-occ. (1) Contrast Means"], mitk::eps);
311  CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The mean dissimilarity value should be 0.0",0, results["co-occ. (1) Dissimilarity Means"], mitk::eps);
312  CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The mean homogenity1 value should be 1.0",1, results["co-occ. (1) Homogeneity1 Means"], mitk::eps);
313  CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The mean InverseDifferenceMoment value should be 1.0",1, results["co-occ. (1) InverseDifferenceMoment Means"], mitk::eps);
314  }
315 };
316 
317 MITK_TEST_SUITE_REGISTRATION(mitkGlobalFeatures)
static mitk::Image::Pointer GenerateMaskImage(unsigned int dimX, unsigned int dimY, unsigned int dimZ, float spacingX=1, float spacingY=1, float spacingZ=1)
itk::SmartPointer< Self > Pointer
MITK_TEST_SUITE_REGISTRATION(mitkImageToItk)
#define MITK_INFO
Definition: mitkLogMacros.h:22
itk::Image< unsigned char, 3 > ImageType
#define MITK_TEST(TESTMETHOD)
Adds a test to the current test suite.
static std::string GetTestDataFilePath(const std::string &testData)
Get the absolute path for test data.
static mitk::Image::Pointer GenerateGradientWithDimXImage(unsigned int dimX, unsigned int dimY, unsigned int dimZ, float spacingX=1, float spacingY=1, float spacingZ=1)
map::core::discrete::Elements< 3 >::InternalImageType ImageType
Test fixture for parameterized tests.
static Pointer New()
void CastToMitkImage(const itk::SmartPointer< ItkOutputImageType > &itkimage, itk::SmartPointer< mitk::Image > &mitkoutputimage)
Cast an itk::Image (with a specific type) to an mitk::Image.
Definition: mitkImageCast.h:78
void MITKCORE_EXPORT CastToItkImage(const mitk::Image *mitkImage, itk::SmartPointer< ItkOutputImageType > &itkOutputImage)
Cast an mitk::Image to an itk::Image with a specific type.
const char features[]
MITKCORE_EXPORT const ScalarType eps
static mitk::Image::Pointer LoadImage(const std::string &path)
LoadImage Convenience method to load an arbitrary mitkImage.
Definition: mitkIOUtil.cpp:597
static itkEventMacro(BoundingShapeInteractionEvent, itk::AnyEvent) class MITKBOUNDINGSHAPE_EXPORT BoundingShapeInteractor Pointer New()
Basic interaction methods for mitk::GeometryData.