[ VIGRA Homepage | Function Index | Class Index | Namespaces | File List | Main Page ]

histogram.hxx VIGRA

1 /************************************************************************/
2 /* */
3 /* Copyright 2011-2012 by Ullrich Koethe */
4 /* */
5 /* This file is part of the VIGRA computer vision library. */
6 /* The VIGRA Website is */
7 /* http://hci.iwr.uni-heidelberg.de/vigra/ */
8 /* Please direct questions, bug reports, and contributions to */
9 /* ullrich.koethe@iwr.uni-heidelberg.de or */
10 /* vigra@informatik.uni-hamburg.de */
11 /* */
12 /* Permission is hereby granted, free of charge, to any person */
13 /* obtaining a copy of this software and associated documentation */
14 /* files (the "Software"), to deal in the Software without */
15 /* restriction, including without limitation the rights to use, */
16 /* copy, modify, merge, publish, distribute, sublicense, and/or */
17 /* sell copies of the Software, and to permit persons to whom the */
18 /* Software is furnished to do so, subject to the following */
19 /* conditions: */
20 /* */
21 /* The above copyright notice and this permission notice shall be */
22 /* included in all copies or substantial portions of the */
23 /* Software. */
24 /* */
25 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND */
26 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES */
27 /* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND */
28 /* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT */
29 /* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */
30 /* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */
31 /* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */
32 /* OTHER DEALINGS IN THE SOFTWARE. */
33 /* */
34 /************************************************************************/
35 
36 #ifndef VIGRA_HISTOGRAM_HXX
37 #define VIGRA_HISTOGRAM_HXX
38 
39 #include "config.hxx"
40 #include "array_vector.hxx"
41 #include <algorithm>
42 
43 namespace vigra {
44 
45 /** \brief Set histogram options.
46 
47  HistogramOptions objects are used to pass histogram options to other objects. This \ref acc_hist_options "example" shows how it is is used to pass histogram options to an accumulator chain.
48 */
50 {
51  public:
52 
53  /** \brief Lower bound for linear range mapping from values to indices. */
54  double minimum;
55 
56  /** \brief Upper bound for linear range mapping from values to indices. */
57  double maximum;
58 
59  /** \brief Total number of bins in the histogram. */
60  int binCount;
61 
62  /** \brief If true, range mapping bounds are defined by minimum and maximum of the data. */
64 
65  /** Initialize members with default values:
66 
67  - minimum, maximum = 0.0
68  - binCount = 64
69  - local_auto_init = false
70  */
72  : minimum(0.0), maximum(0.0),
73  binCount(64),
74  local_auto_init(false)
75  {}
76 
77  /** Set minimum = mi and maximum = ma. Requirement: mi < ma.
78  */
79  HistogramOptions & setMinMax(double mi, double ma)
80  {
81  vigra_precondition(mi < ma,
82  "HistogramOptions::setMinMax(): min < max required.");
83  minimum = mi;
84  maximum = ma;
85  return *this;
86  }
87 
88  /** Set binCount = c. Requirement: c > 0.
89  */
91  {
92  vigra_precondition(c > 0,
93  "HistogramOptions::setBinCount(): binCount > 0 required.");
94  binCount = c;
95  return *this;
96  }
97 
98  /** Set local_auto_init = true. Requirement: setMinMax() must not have been called before. */
100  {
101  vigra_precondition(!validMinMax(),
102  "HistogramOptions::regionAutoInit(): you must not call setMinMax() when auto initialization is desired.");
103  local_auto_init = true;
104  return *this;
105  }
106 
107  /** Set local_auto_init = false. Requirement: setMinMax() must not have been called before. */
109  {
110  vigra_precondition(!validMinMax(),
111  "HistogramOptions::globalAutoInit(): you must not call setMinMax() when auto initialization is desired.");
112  local_auto_init = false;
113  return *this;
114  }
115 
116  /** Return minimum < maximum.
117  */
118  bool validMinMax() const
119  {
120  return minimum < maximum;
121  }
122 };
123 
124 template <class DataType, class BinType>
125 class HistogramView
126 {
127  BinType * bins_;
128  int size_, stride_;
129  DataType offset_;
130  double scale_, scaleInverse_;
131 
132  public:
133  HistogramView(DataType const & min, DataType const & max, int binCount,
134  BinType * bins = 0, int stride = 1)
135  : bins_(bins),
136  size_(binCount),
137  stride_(stride),
138  offset_(min),
139  scale_(double(binCount) / (max - min)),
140  scaleInverse_(1.0 / scale_)
141  {}
142 
143  HistogramView & setData(BinType * bins , int stride = 1)
144  {
145  bins_ = bins;
146  stride_ = stride;
147  return *this;
148  }
149 
150  HistogramView & reset()
151  {
152  if(hasData())
153  for(int k=0; k<size_; ++k)
154  *(bins_ +k*stride_) = BinType();
155  return *this;
156  }
157 
158  void getBinCenters(ArrayVector<DataType> * centers) const
159  {
160  for(int k=0; k < size_; ++k)
161  {
162  (*centers)[k] = mapItemInverse(k + 0.5) ;
163  }
164  }
165 
166  int size() const
167  {
168  return size_;
169  }
170 
171  bool hasData() const
172  {
173  return bins_ != 0;
174  }
175 
176  BinType const & operator[](int k) const
177  {
178  return *(bins_ + k*stride_);
179  }
180 
181  double mapItem(DataType const & d) const
182  {
183  return scale_ * (d - offset_);
184  }
185 
186  DataType mapItemInverse(double d) const
187  {
188  return DataType(d * scaleInverse_ + offset_);
189  }
190 
191  void add(DataType const & d, BinType weight = NumericTraits<BinType>::one())
192  {
193  get(int(mapItem(d))) += weight;
194  }
195 
196  protected:
197 
198  BinType & get(int index)
199  {
200  if(index < 0)
201  index = 0;
202  if(index >= size_)
203  index = size_ - 1;
204  return *(bins_ + index*stride_);
205  }
206 };
207 
208 template <class T>
209 class TrapezoidKernel
210 {
211  public:
212  typedef T value_type;
213 
214  T operator[](double f) const
215  {
216  if(f < -0.5)
217  return 0.5*(f + 1.5);
218  if(f > 0.5)
219  return 0.5*(1.5 - f);
220  return 0.5;
221  }
222 
223  double radius() const
224  {
225  return 1.5;
226  }
227 
228  T findMaximum(double l, double c, double r) const
229  {
230  double curv = -2.0*c + r + l;
231  if(curv == 0.0)
232  return T(-0.5);
233  double extr = 0.5*(l-r) / curv;
234  if(curv < 0.0)
235  {
236  return extr < -0.5
237  ? T(-0.5)
238  : extr > 0.5
239  ? T(0.5)
240  : T(extr);
241  }
242  else
243  {
244  return extr < 0.0
245  ? T(0.5)
246  : T(-0.5);
247  }
248  }
249 
250  bool findMode(double l, double c, double r, double * m) const
251  {
252  double curv = -2.0*c + r + l;
253  if(curv >= 0.0)
254  return false;
255  *m = 0.5*(l-r) / curv;
256  if(*m < -0.5 || *m > 0.5)
257  return false;
258  return true;
259  }
260 };
261 
262 template <class DataType, class KernelType>
263 class KernelHistogramView
264 : public HistogramView<DataType, typename KernelType::value_type>
265 {
266  KernelType kernel_;
267  int radius_;
268 
269  public:
270 
271  typedef typename KernelType::value_type BinType;
272  typedef HistogramView<DataType, BinType> BaseType;
273 
274  KernelHistogramView(DataType const & min, DataType const & max, int binCount,
275  BinType * bins = 0, int stride = 1)
276  : BaseType(min, max, binCount, bins, stride),
277  radius_(kernel_.radius()-0.5) // FIXME: this needs generalization
278  {}
279 
280  void add(DataType const & d, BinType weight = NumericTraits<BinType>::one())
281  {
282  double mapped = this->mapItem(d);
283  double f = mapped - std::floor(mapped) - kernel_.radius();
284  int center = int(mapped);
285 
286  for(int k=center+radius_; k>=center-radius_; --k, f += 1.0)
287  {
288  this->get(k) += weight*kernel_[f];
289  }
290  }
291 
292  DataType findMode() const
293  {
294  double mmax = 0, vmax = 0, m;
295 
296  for(int k=0; k<this->size(); ++k)
297  {
298  double l = k > 0
299  ? (*this)[k-1]
300  : 0.0;
301  double c = (*this)[k];
302  double r = k < this->size() - 1
303  ? (*this)[k+1]
304  : 0.0;
305  if(kernel_.findMode(l, c, r, &m))
306  {
307  double v = l*kernel_[m+1.0] + c*kernel_[m] + r*kernel_[m-1.0];
308  if(vmax < v)
309  {
310  mmax = m + k + 0.5;
311  vmax = v;
312  }
313  }
314  }
315  return this->mapItemInverse(mmax);
316  }
317 
318  template <class Array>
319  void findModes(Array * modes)
320  {
321  double m;
322  for(int k=0; k<this->size(); ++k)
323  {
324  double l = k > 0
325  ? (*this)[k-1]
326  : 0.0;
327  double c = (*this)[k];
328  double r = k < this->size() - 1
329  ? (*this)[k+1]
330  : 0.0;
331  if(kernel_.findMode(l, c, r, &m))
332  {
333  double v = l*kernel_[m+1.0] + c*kernel_[m] + r*kernel_[m-1.0];
334  modes->push_back(std::make_pair(this->mapItemInverse(m + k + 0.5), v));
335  }
336  }
337  }
338 };
339 
340 template <class DataType, class BinType>
341 class Histogram
342 : public HistogramView<DataType, BinType>
343 {
344  public:
345  typedef HistogramView<DataType, BinType> BaseType;
346  ArrayVector<BinType> data_;
347 
348  public:
349  Histogram(DataType const & min, DataType const & max, int binCount,
350  BinType * /*bins*/ = 0, int /*stride*/ = 1)
351  : BaseType(min, max, binCount),
352  data_(binCount)
353  {
354  this->setData(&data_[0]);
355  }
356 
357  Histogram const & reset()
358  {
359  this->setData(&data_[0]);
360  BaseType::reset();
361  return *this;
362  }
363  };
364 
365 } // namespace vigra
366 
367 #endif // VIGRA_HISTOGRAM_HXX
HistogramOptions & regionAutoInit()
Definition: histogram.hxx:99
HistogramOptions & setBinCount(int c)
Definition: histogram.hxx:90
HistogramOptions()
Definition: histogram.hxx:71
bool validMinMax() const
Definition: histogram.hxx:118
int binCount
Total number of bins in the histogram.
Definition: histogram.hxx:60
void add(FixedPoint< IntBits1, FracBits1 > l, FixedPoint< IntBits2, FracBits2 > r, FixedPoint< IntBits3, FracBits3 > &result)
addition with enforced result type.
Definition: fixedpoint.hxx:561
HistogramOptions & setMinMax(double mi, double ma)
Definition: histogram.hxx:79
HistogramOptions & globalAutoInit()
Definition: histogram.hxx:108
bool local_auto_init
If true, range mapping bounds are defined by minimum and maximum of the data.
Definition: histogram.hxx:63
double maximum
Upper bound for linear range mapping from values to indices.
Definition: histogram.hxx:57
int floor(FixedPoint< IntBits, FracBits > v)
rounding down.
Definition: fixedpoint.hxx:667
double minimum
Lower bound for linear range mapping from values to indices.
Definition: histogram.hxx:54
Set histogram options.
Definition: histogram.hxx:49

© Ullrich Köthe (ullrich.koethe@iwr.uni-heidelberg.de)
Heidelberg Collaboratory for Image Processing, University of Heidelberg, Germany

html generated using doxygen and Python
vigra 1.11.1 (Fri May 19 2017)