histogram.hh
Go to the documentation of this file.
1 /* -*- mia-c++ -*-
2  *
3  * This file is part of MIA - a toolbox for medical image analysis
4  * Copyright (c) Leipzig, Madrid 1999-2017 Gert Wollny
5  *
6  * MIA is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with MIA; if not, see <http://www.gnu.org/licenses/>.
18  *
19  */
20 
21 #ifndef mia_core_histogram_hh
22 #define mia_core_histogram_hh
23 
24 #include <mia/core/defines.hh>
25 
26 #include <cmath>
27 #include <cassert>
28 #include <vector>
29 #include <mia/core/defines.hh>
30 #include <mia/core/msgstream.hh>
31 #include <boost/type_traits.hpp>
32 
36 
48 template <typename T>
50 public:
52  typedef T value_type;
53 
61  THistogramFeeder(T min, T max, size_t bins);
62 
64  size_t size() const;
65 
72  size_t index(T x) const;
73 
79  T value(size_t k) const;
80 private:
81  T m_min;
82  T m_max;
83  size_t m_bins;
84  double m_step;
85  double m_inv_step;
86 };
87 
98 template <>
99 class THistogramFeeder<unsigned char> {
100 public:
102  typedef unsigned char value_type;
103 
105  THistogramFeeder(unsigned char min, unsigned char max, size_t bins);
106 
108  size_t size() const;
109 
111  size_t index(unsigned char x) const;
112 
114  unsigned char value(size_t k) const;
115 };
116 
119 
131 template <typename Feeder>
132 class THistogram {
133 public:
134 
136  typedef std::vector<size_t>::const_iterator const_iterator;
137 
139  typedef std::pair<typename Feeder::value_type, size_t> value_type;
140 
141  typedef std::pair<typename Feeder::value_type, typename Feeder::value_type> range_type;
142 
146  THistogram(const Feeder& f);
147 
157  THistogram(const THistogram<Feeder>& org, double perc);
158 
163  void push(typename Feeder::value_type x);
164 
170  void push(typename Feeder::value_type x, size_t count);
171 
178  template <typename Iterator>
179  void push_range(Iterator begin, Iterator end);
180 
182  size_t size() const;
183 
185  const_iterator begin() const;
186 
188  const_iterator end() const;
189 
191  size_t operator [] (size_t idx) const;
192 
198  const value_type at(size_t idx) const;
199 
200 
202  typename Feeder::value_type median() const;
203 
205  typename Feeder::value_type MAD() const;
206 
208  double average() const;
209 
211  double deviation() const;
212 
214  double excess_kurtosis() const;
215 
217  double skewness() const;
218 
225  range_type get_reduced_range(double remove) const;
226 private:
227  Feeder m_feeder;
228  std::vector<size_t> m_histogram;
229  size_t m_n;
230 };
231 
232 // inline inplementation
233 template <typename T>
234 THistogramFeeder<T>::THistogramFeeder(T min, T max, size_t bins):
235  m_min(min),
236  m_max(max),
237  m_bins(bins),
238  m_step(( double(max) - double(min) ) / double(bins - 1)),
239  m_inv_step(double(bins - 1) / (double(max) - double(min)))
240 {
241 }
242 
243 template <typename T>
245 {
246  return m_bins;
247 }
248 
249 template <typename T>
250 inline size_t THistogramFeeder<T>::index(T x) const
251 {
252  double val = floor(m_inv_step * (x - m_min) + 0.5);
253  if (val < 0)
254  return 0;
255  if (val < m_bins)
256  return val;
257  return m_bins - 1;
258 }
259 
260 template <typename T>
261 T THistogramFeeder<T>::value(size_t k) const
262 {
263  return k * m_step + m_min;
264 }
265 
266 inline THistogramFeeder<unsigned char>::THistogramFeeder(unsigned char /*min*/, unsigned char /*max*/, size_t /*bins*/)
267 {
268 }
269 
271 {
272  return 256;
273 }
274 
275 inline
276 size_t THistogramFeeder<unsigned char>::index(unsigned char x) const
277 {
278  return x;
279 }
280 
281 inline
282 unsigned char THistogramFeeder<unsigned char>::value(size_t k) const
283 {
284  return k;
285 }
286 
287 template <typename Feeder>
289  m_feeder(f),
290  m_histogram(f.size()),
291  m_n(0)
292 {
293 }
294 
295 template <typename Feeder>
297  m_feeder(org.m_feeder),
298  m_histogram(m_feeder.size()),
299  m_n(0)
300 {
301  size_t n = (size_t)(org.m_n * (1.0 - perc));
302 
303  size_t i = 0;
304  while (n > m_n && i < m_histogram.size()) {
305  m_n += org.m_histogram[i];
306  m_histogram[i] = org.m_histogram[i];
307  ++i;
308  }
309 }
310 
311 
312 template <typename Feeder>
314 {
315  return m_histogram.size();
316 }
317 
318 template <typename Feeder>
319 void THistogram<Feeder>::push(typename Feeder::value_type x)
320 {
321  ++m_n;
322  ++m_histogram[m_feeder.index(x)];
323 }
324 
325 template <typename Feeder>
326 template <typename Iterator>
327 void THistogram<Feeder>::push_range(Iterator begin, Iterator end)
328 {
329  while (begin != end)
330  push(*begin++);
331 }
332 
333 
334 
335 template <typename Feeder>
336 void THistogram<Feeder>::push(typename Feeder::value_type x, size_t count)
337 {
338  m_n += count;
339  m_histogram[m_feeder.index(x)] += count;
340 }
341 
342 template <typename Feeder>
344 {
345  return m_histogram.begin();
346 }
347 
348 template <typename Feeder>
350 {
351  return m_histogram.end();
352 }
353 
354 template <typename Feeder>
355 size_t THistogram<Feeder>::operator [] (size_t idx) const
356 {
357  assert(idx < m_histogram.size());
358  return m_histogram[idx];
359 }
360 
361 template <typename Feeder>
362 typename Feeder::value_type THistogram<Feeder>::median() const
363 {
364  float n_2 = m_n / 2.0f;
365  float sum = 0;
366  size_t k = 0;
367  while ( sum < n_2 )
368  sum += m_histogram[k++];
369 
370  return m_feeder.value(k > 0 ? k-1 : k);
371 }
372 
373 template <typename Feeder>
374 typename Feeder::value_type THistogram<Feeder>::MAD() const
375 {
376  typedef typename Feeder::value_type T;
377  T m = median();
378 
379  THistogram<Feeder> help(m_feeder);
380 
381  ;
382  for (size_t k = 0; k < size(); ++k) {
383  T v = m_feeder.value(k);
384  help.push(v > m ? v - m : m -v, m_histogram[k]);
385  }
386  return help.median();
387 }
388 
389 
390 template <typename Feeder>
392 {
393  if (idx < m_histogram.size())
394  return value_type(m_feeder.value(idx), m_histogram[idx]);
395  else
396  return value_type(m_feeder.value(idx), 0);
397 }
398 
399 template <typename Feeder>
401 {
402  if (m_n < 1)
403  return 0.0;
404  double sum = 0.0;
405  for (size_t i = 0; i < size(); ++i) {
406  const typename THistogram<Feeder>::value_type value = at(i);
407  sum += value.first * value.second;
408  }
409  return sum / m_n;
410 }
411 
412 template <typename Feeder>
414 {
415  double mu = average();
416  double sum1 = 0.0;
417  double sum2 = 0.0;
418  double sum3 = 0.0;
419 
420  for (size_t i = 0; i < size(); ++i) {
421  const auto value = at(i);
422  sum1 += value.first * value.second;
423  sum2 += value.first * value.first * value.second;
424  double h = (value.first - mu);
425  h *= h;
426  h *= h;
427  sum3 += h * value.second;
428  }
429 
430  double sigma2 = (sum2 - sum1 * sum1 / m_n) / m_n;
431  double mu4 = sum3 / m_n;
432  return mu4 / (sigma2 * sigma2) - 3;
433 }
434 
435 template <typename Feeder>
437 {
438  double mu = average();
439  double sum1 = 0.0;
440  double sum2 = 0.0;
441  double sum3 = 0.0;
442 
443  for (size_t i = 0; i < size(); ++i) {
444  const auto value = at(i);
445  sum1 += value.first * value.second;
446  sum2 += value.first * value.first * value.second;
447  double h = (value.first - mu);
448  sum3 += h * h * h * value.second;
449  }
450 
451  double sigma2 = (sum2 - sum1 * sum1 / m_n) / m_n;
452  double mu4 = sum3 / m_n;
453  return mu4 / (sigma2 * sqrt(sigma2));
454 }
455 
456 template <typename Feeder>
458 {
459  if (m_n < 2)
460  return 0.0;
461  double sum = 0.0;
462  double sum2 = 0.0;
463  for (size_t i = 0; i < size(); ++i) {
464  const typename THistogram<Feeder>::value_type value = at(i);
465  sum += value.first * value.second;
466  sum2 += value.first * value.first * value.second;
467  }
468  return sqrt((sum2 - sum * sum / m_n) / (m_n - 1));
469 }
470 
471 template <typename Feeder>
474 {
475  assert(remove >= 0.0 && remove < 49.0);
476  long remove_count = static_cast<long>(remove * m_n / 100.0);
477 
478  range_type result(m_feeder.value(0), m_feeder.value(m_histogram.size() - 1));
479 
480  if (remove_count > 0) {
481  long low_end = -1;
482  long counted_pixels_low = 0;
483 
484  while (counted_pixels_low < remove_count && low_end < (long)m_histogram.size())
485  counted_pixels_low += m_histogram[++low_end];
486 
487  result.first = m_feeder.value(low_end);
488 
489  long high_end = m_histogram.size();
490  long counted_pixels_high = 0;
491  while (counted_pixels_high <= remove_count && high_end > 0)
492  counted_pixels_high += m_histogram[--high_end];
493  cvdebug() << " int range = " << low_end << ", " << high_end << " removing " << remove_count << " pixels at each end\n";
494  result.second = m_feeder.value(high_end);
495  }
496  return result;
497 }
498 
500 
501 #endif
502 
503 
THistogram(const Feeder &f)
Definition: histogram.hh:288
CDebugSink & cvdebug()
Definition: msgstream.hh:216
specialization of the THistogramFeeder for unsigned byte input data
Definition: histogram.hh:99
size_t size() const
Definition: histogram.hh:244
range_type get_reduced_range(double remove) const
Definition: histogram.hh:473
const_iterator begin() const
Definition: histogram.hh:343
double excess_kurtosis() const
Definition: histogram.hh:413
#define NS_MIA_BEGIN
conveniance define to start the mia namespace
Definition: defines.hh:33
T value_type
typedef for generic programming
Definition: histogram.hh:52
std::pair< typename Feeder::value_type, size_t > value_type
A type for the value-index pair.
Definition: histogram.hh:139
a simple histogram that uses an instance of THistogramFeeder as input converter
Definition: histogram.hh:132
THistogramFeeder(T min, T max, size_t bins)
Definition: histogram.hh:234
THistogramFeeder< unsigned char > CUBHistogramFeeder
typedef for the unsigned byte histogram feeder specialization
Definition: histogram.hh:118
A class to normalize and quantizize input data to a given histogram range with its given number of bi...
Definition: histogram.hh:49
std::vector< size_t >::const_iterator const_iterator
STL iterator.
Definition: histogram.hh:136
const_iterator end() const
Definition: histogram.hh:349
double average() const
Definition: histogram.hh:400
size_t operator[](size_t idx) const
Definition: histogram.hh:355
Feeder::value_type MAD() const
Definition: histogram.hh:374
const value_type at(size_t idx) const
Definition: histogram.hh:391
std::pair< typename Feeder::value_type, typename Feeder::value_type > range_type
Definition: histogram.hh:141
size_t size() const
Definition: histogram.hh:313
double skewness() const
Definition: histogram.hh:436
void push(typename Feeder::value_type x)
Definition: histogram.hh:319
size_t index(T x) const
Definition: histogram.hh:250
void push_range(Iterator begin, Iterator end)
Definition: histogram.hh:327
double deviation() const
Definition: histogram.hh:457
T value(size_t k) const
Definition: histogram.hh:261
unsigned char value_type
typedef for generic programming
Definition: histogram.hh:102
Feeder::value_type median() const
Definition: histogram.hh:362
#define NS_MIA_END
conveniance define to end the mia namespace
Definition: defines.hh:36