Medical Imaging Interaction Toolkit  2018.4.99-ef453c4b
Medical Imaging Interaction Toolkit
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 (DKFZ)
6 All rights reserved.
7 
8 Use of this source code is governed by a 3-clause BSD license that can be
9 found in the LICENSE file.
10 
11 ============================================================================*/
13 
14 #include "mitkHistogramGenerator.h"
15 #include <mitkProperties.h>
16 
18  : m_Image(image)
19 {
20  m_CountOfMinValuedVoxels.resize(1, 0);
21  m_CountOfMaxValuedVoxels.resize(1, 0);
23  m_ScalarMax.resize(1, itk::NumericTraits<ScalarType>::NonpositiveMin());
25  m_Scalar2ndMax.resize(1, itk::NumericTraits<ScalarType>::NonpositiveMin());
26 
28  m_HistogramGeneratorObject = generator;
29 }
30 
32 {
34 }
35 
37  int t, unsigned int /*component*/)
38 {
39  mitk::ImageTimeSelector *timeSelector = this->GetTimeSelector();
40  if (timeSelector != nullptr)
41  {
42  timeSelector->SetTimeNr(t);
43  timeSelector->UpdateLargestPossibleRegion();
44 
45  auto *generator =
46  static_cast<mitk::HistogramGenerator *>(m_HistogramGeneratorObject.GetPointer());
47  generator->SetImage(timeSelector->GetOutput());
48  generator->ComputeHistogram();
49  return static_cast<const mitk::ImageStatisticsHolder::HistogramType *>(generator->GetHistogram());
50  }
51  return nullptr;
52 }
53 
55 {
56  return m_Image->IsValidTimeStep(t);
57 }
58 
60 {
61  ImageTimeSelector::Pointer timeSelector =
63  timeSelector->SetInput(m_Image);
64 
65  return timeSelector;
66 }
67 
68 void mitk::ImageStatisticsHolder::Expand(unsigned int timeSteps)
69 {
70  if (!m_Image->IsValidTimeStep(timeSteps - 1))
71  return;
72 
73  // The BaseData needs to be expanded, call the mitk::Image::Expand() method
74  m_Image->Expand(timeSteps);
75 
76  if (timeSteps > m_ScalarMin.size())
77  {
79  m_ScalarMax.resize(timeSteps, itk::NumericTraits<ScalarType>::NonpositiveMin());
81  m_Scalar2ndMax.resize(timeSteps, itk::NumericTraits<ScalarType>::NonpositiveMin());
82  m_CountOfMinValuedVoxels.resize(timeSteps, 0);
83  m_CountOfMaxValuedVoxels.resize(timeSteps, 0);
84  }
85 }
86 
88 {
90  m_ScalarMax.assign(1, itk::NumericTraits<ScalarType>::NonpositiveMin());
92  m_Scalar2ndMax.assign(1, itk::NumericTraits<ScalarType>::NonpositiveMin());
93  m_CountOfMinValuedVoxels.assign(1, 0);
94  m_CountOfMaxValuedVoxels.assign(1, 0);
95 }
96 
97 #include "mitkImageAccessByItk.h"
98 
99 //#define BOUNDINGOBJECT_IGNORE
100 
101 template <typename ItkImageType>
102 void mitk::_ComputeExtremaInItkImage(const ItkImageType *itkImage, mitk::ImageStatisticsHolder *statisticsHolder, int t)
103 {
104  typename ItkImageType::RegionType region;
105  region = itkImage->GetBufferedRegion();
106  if (region.Crop(itkImage->GetRequestedRegion()) == false)
107  return;
108  if (region != itkImage->GetRequestedRegion())
109  return;
110 
111  itk::ImageRegionConstIterator<ItkImageType> it(itkImage, region);
112  typedef typename ItkImageType::PixelType TPixel;
113  TPixel value = 0;
114 
115  if (statisticsHolder == nullptr || !statisticsHolder->IsValidTimeStep(t))
116  return;
117  statisticsHolder->Expand(t + 1); // make sure we have initialized all arrays
118  statisticsHolder->m_CountOfMinValuedVoxels[t] = 0;
119  statisticsHolder->m_CountOfMaxValuedVoxels[t] = 0;
120 
121  statisticsHolder->m_Scalar2ndMin[t] = statisticsHolder->m_ScalarMin[t] = itk::NumericTraits<ScalarType>::max();
122  statisticsHolder->m_Scalar2ndMax[t] = statisticsHolder->m_ScalarMax[t] =
123  itk::NumericTraits<ScalarType>::NonpositiveMin();
124 
125  while (!it.IsAtEnd())
126  {
127  value = it.Get();
128 #ifdef BOUNDINGOBJECT_IGNORE
129  if (value > -32765)
130  {
131 #endif
132  // update min
133  if (value < statisticsHolder->m_ScalarMin[t])
134  {
135  statisticsHolder->m_Scalar2ndMin[t] = statisticsHolder->m_ScalarMin[t];
136  statisticsHolder->m_ScalarMin[t] = value;
137  statisticsHolder->m_CountOfMinValuedVoxels[t] = 1;
138  }
139  else if (value == statisticsHolder->m_ScalarMin[t])
140  {
141  ++statisticsHolder->m_CountOfMinValuedVoxels[t];
142  }
143  else if (value < statisticsHolder->m_Scalar2ndMin[t])
144  {
145  statisticsHolder->m_Scalar2ndMin[t] = value;
146  }
147 
148  // update max
149  if (value > statisticsHolder->m_ScalarMax[t])
150  {
151  statisticsHolder->m_Scalar2ndMax[t] = statisticsHolder->m_ScalarMax[t];
152  statisticsHolder->m_ScalarMax[t] = value;
153  statisticsHolder->m_CountOfMaxValuedVoxels[t] = 1;
154  }
155  else if (value == statisticsHolder->m_ScalarMax[t])
156  {
157  ++statisticsHolder->m_CountOfMaxValuedVoxels[t];
158  }
159  else if (value > statisticsHolder->m_Scalar2ndMax[t])
160  {
161  statisticsHolder->m_Scalar2ndMax[t] = value;
162  }
163 #ifdef BOUNDINGOBJECT_IGNORE
164  }
165 #endif
166 
167  ++it;
168  }
169 
171  if (statisticsHolder->m_ScalarMax[t] == statisticsHolder->m_ScalarMin[t])
172  {
173  statisticsHolder->m_Scalar2ndMax[t] = statisticsHolder->m_Scalar2ndMin[t] = statisticsHolder->m_ScalarMax[t];
174  }
175  statisticsHolder->m_LastRecomputeTimeStamp.Modified();
176 }
177 
178 template <typename ItkImageType>
179 void mitk::_ComputeExtremaInItkVectorImage(const ItkImageType *itkImage,
180  mitk::ImageStatisticsHolder *statisticsHolder,
181  int t,
182  unsigned int component)
183 {
184  typename ItkImageType::RegionType region;
185  region = itkImage->GetBufferedRegion();
186  if (region.Crop(itkImage->GetRequestedRegion()) == false)
187  return;
188  if (region != itkImage->GetRequestedRegion())
189  return;
190 
191  itk::ImageRegionConstIterator<ItkImageType> it(itkImage, region);
192 
193  if (statisticsHolder == nullptr || !statisticsHolder->IsValidTimeStep(t))
194  return;
195  statisticsHolder->Expand(t + 1); // make sure we have initialized all arrays
196  statisticsHolder->m_CountOfMinValuedVoxels[t] = 0;
197  statisticsHolder->m_CountOfMaxValuedVoxels[t] = 0;
198 
199  statisticsHolder->m_Scalar2ndMin[t] = statisticsHolder->m_ScalarMin[t] = itk::NumericTraits<ScalarType>::max();
200  statisticsHolder->m_Scalar2ndMax[t] = statisticsHolder->m_ScalarMax[t] =
201  itk::NumericTraits<ScalarType>::NonpositiveMin();
202 
203  while (!it.IsAtEnd())
204  {
205  double value = it.Get()[component];
206 #ifdef BOUNDINGOBJECT_IGNORE
207  if (value > -32765)
208  {
209 #endif
210  // update min
211  if (value < statisticsHolder->m_ScalarMin[t])
212  {
213  statisticsHolder->m_Scalar2ndMin[t] = statisticsHolder->m_ScalarMin[t];
214  statisticsHolder->m_ScalarMin[t] = value;
215  statisticsHolder->m_CountOfMinValuedVoxels[t] = 1;
216  }
217  else if (value == statisticsHolder->m_ScalarMin[t])
218  {
219  ++statisticsHolder->m_CountOfMinValuedVoxels[t];
220  }
221  else if (value < statisticsHolder->m_Scalar2ndMin[t])
222  {
223  statisticsHolder->m_Scalar2ndMin[t] = value;
224  }
225 
226  // update max
227  if (value > statisticsHolder->m_ScalarMax[t])
228  {
229  statisticsHolder->m_Scalar2ndMax[t] = statisticsHolder->m_ScalarMax[t];
230  statisticsHolder->m_ScalarMax[t] = value;
231  statisticsHolder->m_CountOfMaxValuedVoxels[t] = 1;
232  }
233  else if (value == statisticsHolder->m_ScalarMax[t])
234  {
235  ++statisticsHolder->m_CountOfMaxValuedVoxels[t];
236  }
237  else if (value > statisticsHolder->m_Scalar2ndMax[t])
238  {
239  statisticsHolder->m_Scalar2ndMax[t] = value;
240  }
241 #ifdef BOUNDINGOBJECT_IGNORE
242  }
243 #endif
244 
245  ++it;
246  }
247 
249  if (statisticsHolder->m_ScalarMax[t] == statisticsHolder->m_ScalarMin[t])
250  {
251  statisticsHolder->m_Scalar2ndMax[t] = statisticsHolder->m_Scalar2ndMin[t] = statisticsHolder->m_ScalarMax[t];
252  }
253  statisticsHolder->m_LastRecomputeTimeStamp.Modified();
254 }
255 
256 void mitk::ImageStatisticsHolder::ComputeImageStatistics(int t, unsigned int component)
257 {
258  // timestep valid?
259  if (!m_Image->IsValidTimeStep(t))
260  return;
261 
262  // image modified?
263  if (this->m_Image->GetMTime() > m_LastRecomputeTimeStamp.GetMTime())
264  this->ResetImageStatistics();
265 
266  Expand(t + 1);
267 
268  // do we have valid information already?
271  return; // Values already calculated before...
272 
273  // used to avoid statistics calculation on Odf images. property will be replaced as soons as bug 17928 is merged and
274  // the diffusion image refactoring is complete.
275  mitk::BoolProperty *isSh = dynamic_cast<mitk::BoolProperty *>(m_Image->GetProperty("IsShImage").GetPointer());
276  mitk::BoolProperty *isOdf = dynamic_cast<mitk::BoolProperty *>(m_Image->GetProperty("IsOdfImage").GetPointer());
277  const mitk::PixelType pType = m_Image->GetPixelType(0);
278  if (pType.GetNumberOfComponents() == 1 && (pType.GetPixelType() != itk::ImageIOBase::UNKNOWNPIXELTYPE) &&
279  (pType.GetPixelType() != itk::ImageIOBase::VECTOR))
280  {
281  // recompute
282  mitk::ImageTimeSelector::Pointer timeSelector = this->GetTimeSelector();
283  if (timeSelector.IsNotNull())
284  {
285  timeSelector->SetTimeNr(t);
286  timeSelector->UpdateLargestPossibleRegion();
287  const mitk::Image *image = timeSelector->GetOutput();
288  AccessByItk_2(image, _ComputeExtremaInItkImage, this, t);
289  }
290  }
291  else if (pType.GetPixelType() == itk::ImageIOBase::VECTOR &&
292  (!isOdf || !isOdf->GetValue()) && (!isSh || !isSh->GetValue())) // we have a vector image
293  {
294  // recompute
295  mitk::ImageTimeSelector::Pointer timeSelector = this->GetTimeSelector();
296  if (timeSelector.IsNotNull())
297  {
298  timeSelector->SetTimeNr(t);
299  timeSelector->UpdateLargestPossibleRegion();
300  const mitk::Image *image = timeSelector->GetOutput();
302  }
303  }
304  else
305  {
306  m_ScalarMin[t] = 0;
307  m_ScalarMax[t] = 255;
308  m_Scalar2ndMin[t] = 0;
309  m_Scalar2ndMax[t] = 255;
310  }
311 }
312 
314 {
315  ComputeImageStatistics(t, component);
316  return m_ScalarMin[t];
317 }
318 
320 {
321  ComputeImageStatistics(t, component);
322  return m_ScalarMax[t];
323 }
324 
326 {
327  ComputeImageStatistics(t, component);
328  return m_Scalar2ndMin[t];
329 }
330 
332 {
333  ComputeImageStatistics(t, component);
334  return m_Scalar2ndMax[t];
335 }
336 
338 {
339  ComputeImageStatistics(t, component);
340  return m_CountOfMinValuedVoxels[t];
341 }
342 
344 {
345  ComputeImageStatistics(t, component);
346  return m_CountOfMaxValuedVoxels[t];
347 }
friend void _ComputeExtremaInItkVectorImage(const ItkImageType *itkImage, mitk::ImageStatisticsHolder *statisticsHolder, int t, unsigned int component)
virtual ScalarType GetScalarValue2ndMin(int t=0, unsigned int component=0)
Get the second smallest value for scalar images. Recomputation performed only when necessary...
const mitk::PixelType GetPixelType(int n=0) const
Returns the PixelType of channel n.
Definition: mitkImage.cpp:101
double ScalarType
vcl_size_t GetNumberOfComponents() const
Get the number of components of which each element consists.
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)
virtual void Expand(unsigned int timeSteps)
virtual T GetValue() const
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.
friend void _ComputeExtremaInItkImage(const ItkImageType *itkImage, mitk::ImageStatisticsHolder *statisticsHolder, int t)
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:72
Provides access to a volume at a specific time of the input image.
itk::ImageIOBase::IOPixelType GetPixelType() const
static T max(T x, T y)
Definition: svm.cpp:56
mitk::Image::Pointer image
unsigned long GetMTime() const override
Get the modified time of the last change of the contents this data object or its geometry.
virtual void SetImage(mitk::Image::ConstPointer _arg)
mitk::BaseProperty::Pointer GetProperty(const char *propertyKey) const
Get the property (instance of BaseProperty) with key propertyKey from the PropertyList, and set it to this, respectively;.
Class holding the statistics informations about a single mitk::Image.
virtual bool IsValidTimeStep(int t) const
Definition: mitkImage.cpp:1143
ImageTimeSelector::Pointer GetTimeSelector()
void Expand(unsigned int timeSteps) override
Expands the TimeGeometry to a number of TimeSteps.
Definition: mitkImage.cpp:1148
std::vector< ScalarType > m_ScalarMax
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.
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:51
std::vector< ScalarType > m_ScalarMin
virtual const HistogramType * GetScalarHistogram(int t=0, unsigned int=0)