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
mitkImageStatisticsHolder.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 ===================================================================*/
17 
18 #include "mitkHistogramGenerator.h"
19 //#include "mitkImageTimeSelector.h"
20 #include <mitkProperties.h>
21 
23  : m_Image(image) /*, m_TimeSelectorForExtremaObject(NULL)*/
24 {
25  m_CountOfMinValuedVoxels.resize(1, 0);
26  m_CountOfMaxValuedVoxels.resize(1, 0);
28  m_ScalarMax.resize(1, itk::NumericTraits<ScalarType>::NonpositiveMin());
30  m_Scalar2ndMax.resize(1, itk::NumericTraits<ScalarType>::NonpositiveMin());
31 
33  m_HistogramGeneratorObject = generator;
34 
35  // m_Image = image;
36 
37  // create time selector
38  // this->GetTimeSelector();
39 }
40 
42 {
43  m_HistogramGeneratorObject = nullptr;
44  // m_TimeSelectorForExtremaObject = NULL;
45  // m_Image = NULL;
46 }
47 
49  int t, unsigned int /*component*/)
50 {
51  mitk::ImageTimeSelector *timeSelector = this->GetTimeSelector();
52  if (timeSelector != nullptr)
53  {
54  timeSelector->SetTimeNr(t);
55  timeSelector->UpdateLargestPossibleRegion();
56 
57  mitk::HistogramGenerator *generator =
58  static_cast<mitk::HistogramGenerator *>(m_HistogramGeneratorObject.GetPointer());
59  generator->SetImage(timeSelector->GetOutput());
60  generator->ComputeHistogram();
61  return static_cast<const mitk::ImageStatisticsHolder::HistogramType *>(generator->GetHistogram());
62  }
63  return nullptr;
64 }
65 
67 {
68  return m_Image->IsValidTimeStep(t);
69 }
70 
72 {
73  // if(m_TimeSelectorForExtremaObject.IsNull())
74  //{
75  // m_TimeSelectorForExtremaObject = ImageTimeSelector::New();
76 
77  ImageTimeSelector::Pointer timeSelector =
78  ImageTimeSelector::New(); // static_cast<mitk::ImageTimeSelector*>( m_TimeSelectorForExtremaObject.GetPointer() );
79  timeSelector->SetInput(m_Image);
80  //}
81 
82  return timeSelector; // static_cast<ImageTimeSelector*>( m_TimeSelectorForExtremaObject.GetPointer() );
83 }
84 
85 void mitk::ImageStatisticsHolder::Expand(unsigned int timeSteps)
86 {
87  if (!m_Image->IsValidTimeStep(timeSteps - 1))
88  return;
89 
90  // The BaseData needs to be expanded, call the mitk::Image::Expand() method
91  m_Image->Expand(timeSteps);
92 
93  if (timeSteps > m_ScalarMin.size())
94  {
95  m_ScalarMin.resize(timeSteps, itk::NumericTraits<ScalarType>::max());
96  m_ScalarMax.resize(timeSteps, itk::NumericTraits<ScalarType>::NonpositiveMin());
97  m_Scalar2ndMin.resize(timeSteps, itk::NumericTraits<ScalarType>::max());
98  m_Scalar2ndMax.resize(timeSteps, itk::NumericTraits<ScalarType>::NonpositiveMin());
99  m_CountOfMinValuedVoxels.resize(timeSteps, 0);
100  m_CountOfMaxValuedVoxels.resize(timeSteps, 0);
101  }
102 }
103 
105 {
106  m_ScalarMin.assign(1, itk::NumericTraits<ScalarType>::max());
107  m_ScalarMax.assign(1, itk::NumericTraits<ScalarType>::NonpositiveMin());
108  m_Scalar2ndMin.assign(1, itk::NumericTraits<ScalarType>::max());
109  m_Scalar2ndMax.assign(1, itk::NumericTraits<ScalarType>::NonpositiveMin());
110  m_CountOfMinValuedVoxels.assign(1, 0);
111  m_CountOfMaxValuedVoxels.assign(1, 0);
112 }
113 
114 #include "mitkImageAccessByItk.h"
115 
116 //#define BOUNDINGOBJECT_IGNORE
117 
118 template <typename ItkImageType>
119 void mitk::_ComputeExtremaInItkImage(const ItkImageType *itkImage, mitk::ImageStatisticsHolder *statisticsHolder, int t)
120 {
121  typename ItkImageType::RegionType region;
122  region = itkImage->GetBufferedRegion();
123  if (region.Crop(itkImage->GetRequestedRegion()) == false)
124  return;
125  if (region != itkImage->GetRequestedRegion())
126  return;
127 
128  itk::ImageRegionConstIterator<ItkImageType> it(itkImage, region);
129  typedef typename ItkImageType::PixelType TPixel;
130  TPixel value = 0;
131 
132  if (statisticsHolder == nullptr || !statisticsHolder->IsValidTimeStep(t))
133  return;
134  statisticsHolder->Expand(t + 1); // make sure we have initialized all arrays
135  statisticsHolder->m_CountOfMinValuedVoxels[t] = 0;
136  statisticsHolder->m_CountOfMaxValuedVoxels[t] = 0;
137 
138  statisticsHolder->m_Scalar2ndMin[t] = statisticsHolder->m_ScalarMin[t] = itk::NumericTraits<ScalarType>::max();
139  statisticsHolder->m_Scalar2ndMax[t] = statisticsHolder->m_ScalarMax[t] =
140  itk::NumericTraits<ScalarType>::NonpositiveMin();
141 
142  while (!it.IsAtEnd())
143  {
144  value = it.Get();
145 // if ( (value > mitkImage->m_ScalarMin) && (value < mitkImage->m_Scalar2ndMin) ) mitkImage->m_Scalar2ndMin =
146 // value;
147 // else if ( (value < mitkImage->m_ScalarMax) && (value > mitkImage->m_Scalar2ndMax) ) mitkImage->m_Scalar2ndMax =
148 // value;
149 // else if (value > mitkImage->m_ScalarMax) mitkImage->m_ScalarMax =
150 // value;
151 // else if (value < mitkImage->m_ScalarMin) mitkImage->m_ScalarMin =
152 // value;
153 
154 // if numbers start with 2ndMin or 2ndMax and never have that value again, the previous above logic failed
155 #ifdef BOUNDINGOBJECT_IGNORE
156  if (value > -32765)
157  {
158 #endif
159  // update min
160  if (value < statisticsHolder->m_ScalarMin[t])
161  {
162  statisticsHolder->m_Scalar2ndMin[t] = statisticsHolder->m_ScalarMin[t];
163  statisticsHolder->m_ScalarMin[t] = value;
164  statisticsHolder->m_CountOfMinValuedVoxels[t] = 1;
165  }
166  else if (value == statisticsHolder->m_ScalarMin[t])
167  {
168  ++statisticsHolder->m_CountOfMinValuedVoxels[t];
169  }
170  else if (value < statisticsHolder->m_Scalar2ndMin[t])
171  {
172  statisticsHolder->m_Scalar2ndMin[t] = value;
173  }
174 
175  // update max
176  if (value > statisticsHolder->m_ScalarMax[t])
177  {
178  statisticsHolder->m_Scalar2ndMax[t] = statisticsHolder->m_ScalarMax[t];
179  statisticsHolder->m_ScalarMax[t] = value;
180  statisticsHolder->m_CountOfMaxValuedVoxels[t] = 1;
181  }
182  else if (value == statisticsHolder->m_ScalarMax[t])
183  {
184  ++statisticsHolder->m_CountOfMaxValuedVoxels[t];
185  }
186  else if (value > statisticsHolder->m_Scalar2ndMax[t])
187  {
188  statisticsHolder->m_Scalar2ndMax[t] = value;
189  }
190 #ifdef BOUNDINGOBJECT_IGNORE
191  }
192 #endif
193 
194  ++it;
195  }
196 
198  if (statisticsHolder->m_ScalarMax[t] == statisticsHolder->m_ScalarMin[t])
199  {
200  statisticsHolder->m_Scalar2ndMax[t] = statisticsHolder->m_Scalar2ndMin[t] = statisticsHolder->m_ScalarMax[t];
201  }
202  statisticsHolder->m_LastRecomputeTimeStamp.Modified();
203  // MITK_DEBUG <<"extrema "<<itk::NumericTraits<TPixel>::NonpositiveMin()<<" "<<mitkImage->m_ScalarMin<<"
204  // "<<mitkImage->m_Scalar2ndMin<<" "<<mitkImage->m_Scalar2ndMax<<" "<<mitkImage->m_ScalarMax<<"
205  // "<<itk::NumericTraits<TPixel>::max();
206 }
207 
208 template <typename ItkImageType>
209 void mitk::_ComputeExtremaInItkVectorImage(const ItkImageType *itkImage,
210  mitk::ImageStatisticsHolder *statisticsHolder,
211  int t,
212  unsigned int component)
213 {
214  typename ItkImageType::RegionType region;
215  region = itkImage->GetBufferedRegion();
216  if (region.Crop(itkImage->GetRequestedRegion()) == false)
217  return;
218  if (region != itkImage->GetRequestedRegion())
219  return;
220 
221  itk::ImageRegionConstIterator<ItkImageType> it(itkImage, region);
222 
223  if (statisticsHolder == nullptr || !statisticsHolder->IsValidTimeStep(t))
224  return;
225  statisticsHolder->Expand(t + 1); // make sure we have initialized all arrays
226  statisticsHolder->m_CountOfMinValuedVoxels[t] = 0;
227  statisticsHolder->m_CountOfMaxValuedVoxels[t] = 0;
228 
229  statisticsHolder->m_Scalar2ndMin[t] = statisticsHolder->m_ScalarMin[t] = itk::NumericTraits<ScalarType>::max();
230  statisticsHolder->m_Scalar2ndMax[t] = statisticsHolder->m_ScalarMax[t] =
231  itk::NumericTraits<ScalarType>::NonpositiveMin();
232 
233  while (!it.IsAtEnd())
234  {
235  double value = it.Get()[component];
236 // if ( (value > mitkImage->m_ScalarMin) && (value < mitkImage->m_Scalar2ndMin) ) mitkImage->m_Scalar2ndMin =
237 // value;
238 // else if ( (value < mitkImage->m_ScalarMax) && (value > mitkImage->m_Scalar2ndMax) ) mitkImage->m_Scalar2ndMax =
239 // value;
240 // else if (value > mitkImage->m_ScalarMax) mitkImage->m_ScalarMax =
241 // value;
242 // else if (value < mitkImage->m_ScalarMin) mitkImage->m_ScalarMin =
243 // value;
244 
245 // if numbers start with 2ndMin or 2ndMax and never have that value again, the previous above logic failed
246 #ifdef BOUNDINGOBJECT_IGNORE
247  if (value > -32765)
248  {
249 #endif
250  // update min
251  if (value < statisticsHolder->m_ScalarMin[t])
252  {
253  statisticsHolder->m_Scalar2ndMin[t] = statisticsHolder->m_ScalarMin[t];
254  statisticsHolder->m_ScalarMin[t] = value;
255  statisticsHolder->m_CountOfMinValuedVoxels[t] = 1;
256  }
257  else if (value == statisticsHolder->m_ScalarMin[t])
258  {
259  ++statisticsHolder->m_CountOfMinValuedVoxels[t];
260  }
261  else if (value < statisticsHolder->m_Scalar2ndMin[t])
262  {
263  statisticsHolder->m_Scalar2ndMin[t] = value;
264  }
265 
266  // update max
267  if (value > statisticsHolder->m_ScalarMax[t])
268  {
269  statisticsHolder->m_Scalar2ndMax[t] = statisticsHolder->m_ScalarMax[t];
270  statisticsHolder->m_ScalarMax[t] = value;
271  statisticsHolder->m_CountOfMaxValuedVoxels[t] = 1;
272  }
273  else if (value == statisticsHolder->m_ScalarMax[t])
274  {
275  ++statisticsHolder->m_CountOfMaxValuedVoxels[t];
276  }
277  else if (value > statisticsHolder->m_Scalar2ndMax[t])
278  {
279  statisticsHolder->m_Scalar2ndMax[t] = value;
280  }
281 #ifdef BOUNDINGOBJECT_IGNORE
282  }
283 #endif
284 
285  ++it;
286  }
287 
289  if (statisticsHolder->m_ScalarMax[t] == statisticsHolder->m_ScalarMin[t])
290  {
291  statisticsHolder->m_Scalar2ndMax[t] = statisticsHolder->m_Scalar2ndMin[t] = statisticsHolder->m_ScalarMax[t];
292  }
293  statisticsHolder->m_LastRecomputeTimeStamp.Modified();
294  // MITK_DEBUG <<"extrema "<<itk::NumericTraits<TPixel>::NonpositiveMin()<<" "<<mitkImage->m_ScalarMin<<"
295  // "<<mitkImage->m_Scalar2ndMin<<" "<<mitkImage->m_Scalar2ndMax<<" "<<mitkImage->m_ScalarMax<<"
296  // "<<itk::NumericTraits<TPixel>::max();
297 }
298 
299 void mitk::ImageStatisticsHolder::ComputeImageStatistics(int t, unsigned int component)
300 {
301  // timestep valid?
302  if (!m_Image->IsValidTimeStep(t))
303  return;
304 
305  // image modified?
306  if (this->m_Image->GetMTime() > m_LastRecomputeTimeStamp.GetMTime())
307  this->ResetImageStatistics();
308 
309  Expand(t + 1);
310 
311  // do we have valid information already?
312  if (m_ScalarMin[t] != itk::NumericTraits<ScalarType>::max() ||
313  m_Scalar2ndMin[t] != itk::NumericTraits<ScalarType>::max())
314  return; // Values already calculated before...
315 
316  // used to avoid statistics calculation on qball images. property will be replaced as soons as bug 17928 is merged and
317  // the diffusion image refactoring is complete.
318  mitk::BoolProperty *isqball = dynamic_cast<mitk::BoolProperty *>(m_Image->GetProperty("IsQballImage").GetPointer());
319  const mitk::PixelType pType = m_Image->GetPixelType(0);
320  if (pType.GetNumberOfComponents() == 1 && (pType.GetPixelType() != itk::ImageIOBase::UNKNOWNPIXELTYPE) &&
321  (pType.GetPixelType() != itk::ImageIOBase::VECTOR))
322  {
323  // recompute
324  mitk::ImageTimeSelector::Pointer timeSelector = this->GetTimeSelector();
325  if (timeSelector.IsNotNull())
326  {
327  timeSelector->SetTimeNr(t);
328  timeSelector->UpdateLargestPossibleRegion();
329  const mitk::Image *image = timeSelector->GetOutput();
330  AccessByItk_2(image, _ComputeExtremaInItkImage, this, t);
331  }
332  }
333  else if (pType.GetPixelType() == itk::ImageIOBase::VECTOR &&
334  (!isqball || !isqball->GetValue())) // we have a vector image
335  {
336  // recompute
337  mitk::ImageTimeSelector::Pointer timeSelector = this->GetTimeSelector();
338  if (timeSelector.IsNotNull())
339  {
340  timeSelector->SetTimeNr(t);
341  timeSelector->UpdateLargestPossibleRegion();
342  const mitk::Image *image = timeSelector->GetOutput();
343  AccessVectorPixelTypeByItk_n(image, _ComputeExtremaInItkVectorImage, (this, t, component));
344  }
345  }
346  else
347  {
348  m_ScalarMin[t] = 0;
349  m_ScalarMax[t] = 255;
350  m_Scalar2ndMin[t] = 0;
351  m_Scalar2ndMax[t] = 255;
352  }
353 }
354 
356 {
357  ComputeImageStatistics(t, component);
358  return m_ScalarMin[t];
359 }
360 
362 {
363  ComputeImageStatistics(t, component);
364  return m_ScalarMax[t];
365 }
366 
368 {
369  ComputeImageStatistics(t, component);
370  return m_Scalar2ndMin[t];
371 }
372 
374 {
375  ComputeImageStatistics(t, component);
376  return m_Scalar2ndMax[t];
377 }
378 
380 {
381  ComputeImageStatistics(t, component);
382  return m_CountOfMinValuedVoxels[t];
383 }
384 
386 {
387  ComputeImageStatistics(t, component);
388  return m_CountOfMaxValuedVoxels[t];
389 }
virtual ScalarType GetScalarValue2ndMin(int t=0, unsigned int component=0)
Get the second smallest value for scalar images. Recomputation performed only when necessary...
double ScalarType
virtual ScalarType GetScalarValue2ndMax(int t=0, unsigned int component=0)
Get the second largest value for scalar images.
itk::Object::Pointer m_HistogramGeneratorObject
std::vector< unsigned int > m_CountOfMaxValuedVoxels
std::vector< unsigned int > m_CountOfMinValuedVoxels
virtual void ComputeImageStatistics(int t=0, unsigned int component=0)
itk::ImageIOBase::IOPixelType GetPixelType() const
virtual void Expand(unsigned int timeSteps)
virtual ScalarType GetScalarValueMin(int t=0, unsigned int component=0)
Get the minimum for scalar images. Recomputation performed only when necessary.
virtual void SetTimeNr(int _arg)
#define AccessVectorPixelTypeByItk_n(mitkImage, itkImageTypeFunction, va_tuple)
Access a vector mitk::Image by an ITK vector image with one or more parameters.
virtual ScalarType GetScalarValueMax(int t=0, unsigned int component=0)
Get the maximum for scalar images. Recomputation performed only when necessary.
static Pointer New()
Image class for storing images.
Definition: mitkImage.h:76
Provides access to a volume at a specific time of the input image.
static T max(T x, T y)
Definition: svm.cpp:70
virtual void SetImage(mitk::Image::ConstPointer _arg)
Class holding the statistics informations about a single mitk::Image.
ImageTimeSelector::Pointer GetTimeSelector()
vcl_size_t GetNumberOfComponents() const
Get the number of components of which each element consists.
std::vector< ScalarType > m_ScalarMax
unsigned short PixelType
OutputType * GetOutput()
Get the output data of this image source object.
#define AccessByItk_2(mitkImage, itkImageTypeFunction, arg1, arg2)
itk::Statistics::Histogram< double > HistogramType
Provides an easy way to calculate an itk::Histogram for a mitk::Image.
std::vector< ScalarType > m_Scalar2ndMin
mitk::ScalarType GetCountOfMinValuedVoxels(int t=0, unsigned int component=0)
Get the count of voxels with the smallest scalar value in the dataset.
virtual const HistogramType * GetHistogram()
mitk::ScalarType GetCountOfMaxValuedVoxels(int t=0, unsigned int component=0)
Get the count of voxels with the largest scalar value in the dataset.
std::vector< ScalarType > m_Scalar2ndMax
static Pointer New()
Class for defining the data type of pixels.
Definition: mitkPixelType.h:55
std::vector< ScalarType > m_ScalarMin
virtual T GetValue() const
virtual const HistogramType * GetScalarHistogram(int t=0, unsigned int=0)