Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
mitkSimpleHistogram.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 "mitkSimpleHistogram.h"
18 
19 #include "mitkImageReadAccessor.h"
21 #include "mitkUnstructuredGrid.h"
22 
23 namespace mitk
24 {
26  {
27  valid = false;
28 
29  // check if input is valid
30  if (src == nullptr)
31  return;
32  Image *source = dynamic_cast<Image *>(src);
33  if (source == nullptr)
34  return;
35  else if (source->IsEmpty())
36  return;
37 
38  // dummy histogram
39  {
40  min = 0;
41  max = 1;
42  first = 0;
43  last = 1;
44  }
45 
46  {
47  int typInt = 0;
48  {
49  const int typ = source->GetPixelType().GetComponentType();
50  if (typ == itk::ImageIOBase::UCHAR)
51  typInt = 0;
52  else if (typ == itk::ImageIOBase::CHAR)
53  typInt = 1;
54  else if (typ == itk::ImageIOBase::USHORT)
55  typInt = 2;
56  else if (typ == itk::ImageIOBase::SHORT)
57  typInt = 3;
58  else if (typ == itk::ImageIOBase::INT)
59  typInt = 4;
60  else if (typ == itk::ImageIOBase::UINT)
61  typInt = 5;
62  else if (typ == itk::ImageIOBase::LONG)
63  typInt = 6;
64  else if (typ == itk::ImageIOBase::ULONG)
65  typInt = 7;
66  else if (typ == itk::ImageIOBase::FLOAT)
67  typInt = 8;
68  else if (typ == itk::ImageIOBase::DOUBLE)
69  typInt = 9;
70  else
71  {
72  MITK_WARN << "Pixel type not supported by SimpleImageHistogram";
73  return;
74  }
75  }
76 
77  first = -32768;
78  last = 65535; // support at least full signed and unsigned short range
79 
80  if (histogram)
81  delete histogram;
82 
83  histogram = new CountType[last - first + 1];
84  memset(histogram, 0, sizeof(CountType) * (last - first + 1));
85  highest = 0;
86  max = first - 1;
87  min = last + 1;
88 
89  unsigned int num = 1;
90  for (unsigned int r = 0; r < source->GetDimension(); r++)
91  num *= source->GetDimension(r);
92 
93  // MITK_INFO << "building histogramm of integer image: 0=" << source->GetDimension(0) << " 1=" <<
94  // source->GetDimension(1) << " 2=" << source->GetDimension(2) << " 3=" << source->GetDimension(3);
95 
96  ImageReadAccessor sourceAcc(source);
97  const void *src = sourceAcc.GetData();
98 
99  do
100  {
101  int value = 0;
102 
103  switch (typInt)
104  {
105  case 0:
106  {
107  unsigned char *t = (unsigned char *)src;
108  value = *t++;
109  src = (void *)t;
110  }
111  break;
112  case 1:
113  {
114  signed char *t = (signed char *)src;
115  value = *t++;
116  src = (void *)t;
117  }
118  break;
119  case 2:
120  {
121  unsigned short *t = (unsigned short *)src;
122  value = *t++;
123  src = (void *)t;
124  }
125  break;
126  case 3:
127  {
128  signed short *t = (signed short *)src;
129  value = *t++;
130  src = (void *)t;
131  }
132  break;
133  case 4:
134  {
135  signed int *t = (signed int *)src;
136  value = *t++;
137  src = (void *)t;
138  }
139  break;
140  case 5:
141  {
142  unsigned int *t = (unsigned int *)src;
143  value = *t++;
144  src = (void *)t;
145  }
146  break;
147  case 6:
148  {
149  signed long *t = (signed long *)src;
150  value = *t++;
151  src = (void *)t;
152  }
153  break;
154  case 7:
155  {
156  unsigned long *t = (unsigned long *)src;
157  value = *t++;
158  src = (void *)t;
159  }
160  break;
161  case 8:
162  {
163  float *t = (float *)src;
164  value = *t++;
165  src = (void *)t;
166  }
167  break;
168  case 9:
169  {
170  double *t = (double *)src;
171  value = *t++;
172  src = (void *)t;
173  }
174  break;
175  }
176 
177  if (value >= first && value <= last)
178  {
179  if (value < min)
180  min = value;
181  if (value > max)
182  max = value;
183  CountType tmp = ++histogram[value - first];
184  if (tmp > highest)
185  highest = tmp;
186  }
187  } while (--num);
188 
189  MITK_INFO << "histogramm computed: min=" << min << " max=" << max << " highestBin=" << highest
190  << " samples=" << num;
191  }
192 
193  invLogHighest = 1.0 / log(double(highest));
194  valid = true;
195  }
196 
198  float SimpleImageHistogram::GetRelativeBin(double left, double right) const
199  {
200  if (!valid)
201  return 0.0f;
202 
203  int iLeft = floorf(left);
204  int iRight = ceilf(right);
205 
206  /*
207  double sum = 0;
208 
209  for( int r = 0 ; r < 256 ; r++)
210  {
211  int pos = left + (right-left) * r/255.0;
212  int posInArray = floorf(pos+0.5f) - first;
213  sum += float(log(double(histogram[posInArray])));
214  }
215 
216  sum /= 256.0;
217  return float(sum*invLogHighest);
218  */
219 
220  CountType maximum = 0;
221 
222  for (int i = iLeft; i <= iRight; i++)
223  {
224  int posInArray = i - first;
225  if (histogram[posInArray] > maximum)
226  maximum = histogram[posInArray];
227  }
228 
229  return float(log(double(maximum)) * invLogHighest);
230  }
231 
232  class ImageHistogramCacheElement : public SimpleHistogramCache::Element
233  {
234  public:
235  void ComputeFromBaseData(BaseData *baseData) override { histogram.ComputeFromBaseData(baseData); }
236  SimpleHistogram *GetHistogram() override { return &histogram; }
237  SimpleImageHistogram histogram;
238  };
239 
240  class UnstructuredGridHistogramCacheElement : public SimpleHistogramCache::Element
241  {
242  public:
243  void ComputeFromBaseData(BaseData *baseData) override { histogram.ComputeFromBaseData(baseData); }
244  SimpleHistogram *GetHistogram() override { return &histogram; }
245  SimpleUnstructuredGridHistogram histogram;
246  };
247 
249  {
250  BaseData *p_BaseData = sp_BaseData.GetPointer();
251 
252  if (!p_BaseData)
253  {
254  MITK_WARN << "SimpleHistogramCache::operator[] with null base data called";
255  return nullptr;
256  }
257 
258  Element *elementToUpdate = nullptr;
259 
260  bool first = true;
261 
262  for (auto iter = cache.begin(); iter != cache.end(); iter++)
263  {
264  Element *e = *iter;
265  BaseData *p_tmp = e->baseData.GetPointer();
266 
267  if (p_tmp == p_BaseData)
268  {
269  if (!first)
270  {
271  cache.erase(iter);
272  cache.push_front(e);
273  }
274  if (p_BaseData->GetMTime() > e->m_LastUpdateTime.GetMTime())
275  {
276  elementToUpdate = e;
277  goto recomputeElement;
278  }
279 
280  // MITK_INFO << "using a cached histogram";
281 
282  return e->GetHistogram();
283  }
284 
285  first = false;
286  }
287 
288  if (dynamic_cast<Image *>(p_BaseData))
289  {
290  elementToUpdate = new ImageHistogramCacheElement();
291  }
292  else if (dynamic_cast<UnstructuredGrid *>(p_BaseData))
293  {
294  elementToUpdate = new UnstructuredGridHistogramCacheElement();
295  }
296  else
297  {
298  MITK_WARN << "not supported: " << p_BaseData->GetNameOfClass();
299  }
300 
301  elementToUpdate->baseData = p_BaseData;
302  cache.push_front(elementToUpdate);
303  TrimCache();
304 
305  recomputeElement:
306 
307  // MITK_INFO << "computing a new histogram";
308 
309  elementToUpdate->ComputeFromBaseData(p_BaseData);
310  elementToUpdate->m_LastUpdateTime.Modified();
311  return elementToUpdate->GetHistogram();
312  }
313 
315 }
SimpleHistogram * operator[](BaseData::Pointer sp_BaseData)
#define MITK_INFO
Definition: mitkLogMacros.h:22
mitk::WeakPointer< BaseData > baseData
Base of all data objects.
Definition: mitkBaseData.h:39
virtual void ComputeFromBaseData(BaseData *baseData)=0
float GetRelativeBin(double start, double end) const override
TODO: (What should this method do?)
const void * GetData() const
Gives const access to the data.
DataCollection - Class to facilitate loading/accessing structured data.
void ComputeFromBaseData(BaseData *source) override
Creates a new histogram out the source which must be an image. Method does nothing if the image is in...
#define MITK_WARN
Definition: mitkLogMacros.h:23
void TrimCache(bool full=false)
Abstract superclass for histograms with double values. Classes which are deriving from this class can...
Image class for storing images.
Definition: mitkImage.h:76
int GetComponentType() const
Get the component type (the scalar (!) type). Each element may contain m_NumberOfComponents (more tha...
const mitk::PixelType GetPixelType(int n=0) const
Returns the PixelType of channel n.
Definition: mitkImage.cpp:105
virtual unsigned long GetMTime() const override
Get the modified time of the last change of the contents this data object or its geometry.
virtual bool IsEmpty() const
Check whether object contains data (at least at one point in time), e.g., a set of points may be empt...
virtual SimpleHistogram * GetHistogram()=0
unsigned int GetDimension() const
Get dimension of the image.
Definition: mitkImage.cpp:110
ImageReadAccessor class to get locked read access for a particular image part.