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