Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
mitkCalculateGrayValueStatisticsTool.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 
18 
19 #include "mitkCalculateGrayValueStatisticsTool.xpm"
20 
21 #include "mitkImageAccessByItk.h"
22 #include "mitkImageCast.h"
23 #include "mitkImageTimeSelector.h"
24 #include "mitkProgressBar.h"
25 #include "mitkStatusBar.h"
26 #include "mitkToolManager.h"
27 
28 #include <itkCommand.h>
29 
30 #include <itkHistogram.h>
31 
32 namespace mitk
33 {
35 }
36 
38 {
39 }
40 
42 {
43 }
44 
46 {
47  return mitkCalculateGrayValueStatisticsTool_xpm;
48 }
49 
51 {
52  return "Statistics";
53 }
54 
56 {
57  return "No statistics generated for these segmentations:";
58 }
59 
61 {
62  // clear/prepare report
63  m_CompleteReport.str("");
64 }
65 
67 {
68  if (node)
69  {
70  Image::Pointer image = dynamic_cast<Image *>(node->GetData());
71  if (image.IsNull())
72  return false;
73 
74  DataNode *referencenode = m_ToolManager->GetReferenceData(0);
75  if (!referencenode)
76  return false;
77 
78  try
79  {
81 
82  // add to report
83  std::string nodename("structure");
84  node->GetName(nodename);
85 
86  std::string message = "Calculating statistics for ";
87  message += nodename;
88 
89  StatusBar::GetInstance()->DisplayText(message.c_str());
90 
91  Image::Pointer refImage = dynamic_cast<Image *>(referencenode->GetData());
92  Image::Pointer image = dynamic_cast<Image *>(node->GetData());
93 
94  m_CompleteReport << "======== Gray value analysis of " << nodename << " ========\n";
95 
96  if (image.IsNotNull() && refImage.IsNotNull())
97  {
98  for (unsigned int timeStep = 0; timeStep < image->GetTimeSteps(); ++timeStep)
99  {
101  timeSelector->SetInput(refImage);
102  timeSelector->SetTimeNr(timeStep);
103  timeSelector->UpdateLargestPossibleRegion();
104  Image::Pointer refImage3D = timeSelector->GetOutput();
105 
107  timeSelector2->SetInput(image);
108  timeSelector2->SetTimeNr(timeStep);
109  timeSelector2->UpdateLargestPossibleRegion();
110  Image::Pointer image3D = timeSelector2->GetOutput();
111 
112  if (image3D.IsNotNull() && refImage3D.IsNotNull())
113  {
114  m_CompleteReport << "=== " << nodename << ", time step " << timeStep << " ===\n";
115  AccessFixedDimensionByItk_2(refImage3D, ITKHistogramming, 3, image3D, m_CompleteReport);
116  }
117  }
118  }
119 
120  m_CompleteReport << "======== End of analysis for " << nodename << " ===========\n\n\n";
121 
123  }
124  catch (...)
125  {
126  return false;
127  }
128  }
129 
130  return true;
131 }
132 
134 {
136 
137  // show/send results
138  StatisticsCompleted.Send();
139  // MITK_INFO << m_CompleteReport.str() << std::endl;
140 }
141 
142 #define ROUND_P(x) ((int)((x) + 0.5))
143 
144 template <typename TPixel, unsigned int VImageDimension>
145 void mitk::CalculateGrayValueStatisticsTool::CalculateMinMax(itk::Image<TPixel, VImageDimension> *referenceImage,
146  Image *segmentation,
147  TPixel &minimum,
148  TPixel &maximum)
149 {
150  typedef itk::Image<TPixel, VImageDimension> ImageType;
151  typedef itk::Image<Tool::DefaultSegmentationDataType, VImageDimension> SegmentationType;
152 
153  typename SegmentationType::Pointer segmentationItk;
154  CastToItkImage(segmentation, segmentationItk);
155 
156  typename SegmentationType::RegionType segmentationRegion = segmentationItk->GetLargestPossibleRegion();
157 
158  segmentationRegion.Crop(referenceImage->GetLargestPossibleRegion());
159 
160  itk::ImageRegionConstIteratorWithIndex<SegmentationType> segmentationIterator(segmentationItk, segmentationRegion);
161  itk::ImageRegionConstIteratorWithIndex<ImageType> referenceIterator(referenceImage, segmentationRegion);
162 
163  segmentationIterator.GoToBegin();
164  referenceIterator.GoToBegin();
165 
168 
169  while (!segmentationIterator.IsAtEnd())
170  {
171  itk::Point<float, 3> pt;
172  segmentationItk->TransformIndexToPhysicalPoint(segmentationIterator.GetIndex(), pt);
173 
174  typename ImageType::IndexType ind;
175  itk::ContinuousIndex<float, 3> contInd;
176  if (referenceImage->TransformPhysicalPointToContinuousIndex(pt, contInd))
177  {
178  for (unsigned int i = 0; i < 3; ++i)
179  ind[i] = ROUND_P(contInd[i]);
180 
181  referenceIterator.SetIndex(ind);
182 
183  if (segmentationIterator.Get() > 0)
184  {
185  if (referenceIterator.Get() < minimum)
186  minimum = referenceIterator.Get();
187  if (referenceIterator.Get() > maximum)
188  maximum = referenceIterator.Get();
189  }
190  }
191 
192  ++segmentationIterator;
193  }
194 }
195 
196 template <typename TPixel, unsigned int VImageDimension>
197 void mitk::CalculateGrayValueStatisticsTool::ITKHistogramming(itk::Image<TPixel, VImageDimension> *referenceImage,
198  Image *segmentation,
199  std::stringstream &report)
200 {
201  typedef itk::Image<TPixel, VImageDimension> ImageType;
202  typedef itk::Image<Tool::DefaultSegmentationDataType, VImageDimension> SegmentationType;
203 
204  typename SegmentationType::Pointer segmentationItk;
205  CastToItkImage(segmentation, segmentationItk);
206 
207  // generate histogram
208  typename SegmentationType::RegionType segmentationRegion = segmentationItk->GetLargestPossibleRegion();
209 
210  segmentationRegion.Crop(referenceImage->GetLargestPossibleRegion());
211 
212  itk::ImageRegionConstIteratorWithIndex<SegmentationType> segmentationIterator(segmentationItk, segmentationRegion);
213  itk::ImageRegionConstIteratorWithIndex<ImageType> referenceIterator(referenceImage, segmentationRegion);
214 
215  segmentationIterator.GoToBegin();
216  referenceIterator.GoToBegin();
217 
218  m_ITKHistogram = HistogramType::New();
219 
220  TPixel minimum = std::numeric_limits<TPixel>::max();
221  TPixel maximum = std::numeric_limits<TPixel>::min();
222 
223  CalculateMinMax(referenceImage, segmentation, minimum, maximum);
224 
225  // initialize the histogram to the range of the cropped region
226  HistogramType::SizeType size;
227 #if defined(ITK_USE_REVIEW_STATISTICS)
228  typedef typename HistogramType::SizeType::ValueType HSizeValueType;
229 #else
230  typedef typename HistogramType::SizeType::SizeValueType HSizeValueType;
231 #endif
232  size.Fill(static_cast<HSizeValueType>(maximum - minimum + 1));
233  HistogramType::MeasurementVectorType lowerBound;
234  HistogramType::MeasurementVectorType upperBound;
235  lowerBound[0] = minimum;
236  upperBound[0] = maximum;
237  m_ITKHistogram->Initialize(size, lowerBound, upperBound);
238 
239  double mean(0.0);
240  double sd(0.0);
241  double voxelCount(0.0);
242 
243  // iterate through the cropped region add the values to the histogram
244  while (!segmentationIterator.IsAtEnd())
245  {
246  itk::Point<float, 3> pt;
247  segmentationItk->TransformIndexToPhysicalPoint(segmentationIterator.GetIndex(), pt);
248 
249  typename ImageType::IndexType ind;
250  itk::ContinuousIndex<float, 3> contInd;
251  if (referenceImage->TransformPhysicalPointToContinuousIndex(pt, contInd))
252  {
253  for (unsigned int i = 0; i < 3; ++i)
254  ind[i] = ROUND_P(contInd[i]);
255 
256  referenceIterator.SetIndex(ind);
257 
258  if (segmentationIterator.Get() > 0)
259  {
260  HistogramType::MeasurementVectorType currentMeasurementVector;
261 
262  currentMeasurementVector[0] = static_cast<HistogramType::MeasurementType>(referenceIterator.Get());
263  m_ITKHistogram->IncreaseFrequencyOfMeasurement(currentMeasurementVector, 1);
264 
265  mean = (mean * (static_cast<double>(voxelCount) /
266  static_cast<double>(voxelCount + 1))) // 3 points: old center * 2/3 + currentPoint * 1/3;
267  + static_cast<double>(referenceIterator.Get()) / static_cast<double>(voxelCount + 1);
268 
269  voxelCount += 1.0;
270  }
271  }
272 
273  ++segmentationIterator;
274  }
275 
276  // second pass for SD
277  segmentationIterator.GoToBegin();
278  referenceIterator.GoToBegin();
279  while (!segmentationIterator.IsAtEnd())
280  {
281  itk::Point<float, 3> pt;
282  segmentationItk->TransformIndexToPhysicalPoint(segmentationIterator.GetIndex(), pt);
283 
284  typename ImageType::IndexType ind;
285  itk::ContinuousIndex<float, 3> contInd;
286  if (referenceImage->TransformPhysicalPointToContinuousIndex(pt, contInd))
287  {
288  for (unsigned int i = 0; i < 3; ++i)
289  ind[i] = ROUND_P(contInd[i]);
290 
291  referenceIterator.SetIndex(ind);
292 
293  if (segmentationIterator.Get() > 0)
294  {
295  sd += ((static_cast<double>(referenceIterator.Get()) - mean) *
296  (static_cast<double>(referenceIterator.Get()) - mean));
297  }
298  }
299 
300  ++segmentationIterator;
301  }
302 
303  sd /= static_cast<double>(voxelCount - 1);
304  sd = sqrt(sd);
305 
306  // generate quantiles
307  TPixel histogramQuantileValues[5];
308  histogramQuantileValues[0] = m_ITKHistogram->Quantile(0, 0.05);
309  histogramQuantileValues[1] = m_ITKHistogram->Quantile(0, 0.25);
310  histogramQuantileValues[2] = m_ITKHistogram->Quantile(0, 0.50);
311  histogramQuantileValues[3] = m_ITKHistogram->Quantile(0, 0.75);
312  histogramQuantileValues[4] = m_ITKHistogram->Quantile(0, 0.95);
313 
314  // report histogram values
315  std::locale C("C");
316  std::locale originalLocale = report.getloc();
317  report.imbue(C);
318 
319  report << " Minimum:" << minimum << "\n 5% quantile: " << histogramQuantileValues[0]
320  << "\n 25% quantile: " << histogramQuantileValues[1] << "\n 50% quantile: " << histogramQuantileValues[2]
321  << "\n 75% quantile: " << histogramQuantileValues[3] << "\n 95% quantile: " << histogramQuantileValues[4]
322  << "\n Maximum: " << maximum << "\n Mean: " << mean << "\n SD: " << sd << "\n";
323 
324  report.imbue(originalLocale);
325 }
326 
328 {
329  return m_CompleteReport.str();
330 }
331 
334 {
335  return m_ITKHistogram.GetPointer();
336 }
void Progress(unsigned int steps=1)
Sets the current amount of progress to current progress + steps.
itk::SmartPointer< Self > Pointer
virtual const char ** GetXPM() const override
Returns an icon in the XPM format.
bool GetName(std::string &nodeName, const mitk::BaseRenderer *renderer=nullptr, const char *propertyKey="name") const
Convenience access method for accessing the name of an object (instance of StringProperty with proper...
Definition: mitkDataNode.h:366
#define MITKSEGMENTATION_EXPORT
DataCollection - Class to facilitate loading/accessing structured data.
#define MITK_TOOL_MACRO(EXPORT_SPEC, CLASS_NAME, DESCRIPTION)
BaseData * GetData() const
Get the data object (instance of BaseData, e.g., an Image) managed by this DataNode.
virtual void StartProcessingAllData() override
Subclasses should override this method.
static ProgressBar * GetInstance()
static method to get the GUI dependent ProgressBar-instance so the methods for steps to do and progre...
itk::SmartPointer< const Self > ConstPointer
map::core::discrete::Elements< 3 >::InternalImageType ImageType
void CalculateMinMax(itk::Image< TPixel, VImageDimension > *referenceImage, Image *segmentation, TPixel &minimum, TPixel &maximum)
#define AccessFixedDimensionByItk_2(mitkImage, itkImageTypeFunction, dimension, arg1, arg2)
virtual void FinishProcessingAllData() override
Subclasses should override this method.
virtual const char * GetName() const override
Returns the name of this tool. Make it short!
void DisplayText(const char *t)
Send a string to the applications StatusBar.
ValueType
Type of the value held by a Value object.
Definition: jsoncpp.h:345
virtual std::string GetErrorMessage() override
Describes the error (if one occurred during processing).
Image class for storing images.
Definition: mitkImage.h:76
Calculates some gray value statistics for segmentations.
static T max(T x, T y)
Definition: svm.cpp:70
void ITKHistogramming(itk::Image< TPixel, VImageDimension > *referenceImage, Image *segmentation, std::stringstream &report)
static StatusBar * GetInstance()
static method to get the GUI dependent StatusBar-instance so the methods DisplayText, etc. can be called No reference counting, cause of decentral static use!
static T min(T x, T y)
Definition: svm.cpp:67
void AddStepsToDo(unsigned int steps)
Adds steps to totalSteps.
virtual bool ProcessOneWorkingData(DataNode *node) override
Subclasses should override this method.
void MITKCORE_EXPORT CastToItkImage(const mitk::Image *mitkImage, itk::SmartPointer< ItkOutputImageType > &itkOutputImage)
Cast an mitk::Image to an itk::Image with a specific type.
virtual void FinishProcessingAllData()
Subclasses should override this method.
Class for nodes of the DataTree.
Definition: mitkDataNode.h:66
static Pointer New()
static itkEventMacro(BoundingShapeInteractionEvent, itk::AnyEvent) class MITKBOUNDINGSHAPE_EXPORT BoundingShapeInteractor Pointer New()
Basic interaction methods for mitk::GeometryData.