KJB
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
histogram.h
Go to the documentation of this file.
1 // histogram.h - generic histogram functionality template class
3 // Author: Doron Tal
4 // Date Created: June, 1996
5 // Date Last Modified: Aug 5, 2000
6 //
7 // Both interface and implementation are in this file. tested only on
8 // float and unsigned char template arguments.
9 
10 #ifndef _HISTOGRAM_H
11 #define _HISTOGRAM_H
12 
13 #include <assert.h>
14 #include "wrap_dtlib_cpp/img.h"
15 #include "wrap_dtlib_cpp/utils.h"
16 #include "string"
17 #include <fstream>
18 
19 namespace DTLib {
20 
21  template <class T> class CHistogram
22  {
23  public:
24  CHistogram();
25 
26  CHistogram(const std::string & file_name);
27  CHistogram(std::istream & ifs);
28  ~CHistogram();
29 
30  void GetValues(float * pointer);
31 
32  void SetValues(float * pointer);
33 
34  // if you use this setup function, you can't call Update(),
35  // but you must call IncrementBin() instead.
36  void Setup(const int& nBins);
37 
38  // Initializes the histogram, allocating and zeroing bins.
39  // 1-D version
40  void Setup(const int& nBins, const T& RangeMin, const T& RangeMax);
41 
42  // 2-D version of above
43  void Setup(const int& nBinsX, const int& nBinsY, const T& XRangeMin,
44  const T& XRangeMax, const T& YRangeMin, const T& YRangeMax);
45 
46  // 3-D version of above
47  void Setup(const int& nBinsX, const int& nBinsY, const int& nBinsZ, const T& XRangeMin,
48  const T& XRangeMax, const T& YRangeMin, const T& YRangeMax, const T& ZRangeMin, const T& ZRangeMax);
49 
50  // Increment one of the histogram bins in a 1-D histogram acc. to Val
51  // i.e. first map from Val into the bin's index, then increment that
52  // bin by 1.
53  void Update(const T& Val);
54 
55  // same as above, but in 2-D
56  void Update(const T& XVal, const T& YVal);
57 
58  void Read(const std::string & file_name);
59 
60  void Read(std::istream & ifs);
61 
62  void Write(const std::string & file_name) const;
63 
64  void Write(std::ostream & ofs) const;
65 
66  // 2-D histogram soft binning: smooth before you bin and vote into
67  // neighboring bins according to your smoothing function, which is
68  // a Kernel provided by 'SmoothFun' (a float Img object), centered
69  // at the bin in which ('XVal', 'YVal') falls, this Img object
70  // is square, i.e. Width == Height and its width is odd.
71  void SoftUpdate(const T& XVal, const T& YVal, const float& Sigma);
72 
73  void SoftUpdate1D(const T& XVal, const float& Sigma);
74 
75  // #-D histogram soft binning: smooth before you bin and vote into
76  // neighboring bins according to your smoothing function, which is
77  // a Kernel provided by 'SmoothFun' (a float Img object), centered
78  // at the bin in which ('XVal', 'YVal') falls, this Img object
79  // is square, i.e. Width == Height and its width is odd.
80  void SoftUpdate3D(const T& XVal, const T& YVal, const T& ZVal, const float& Sigma);
81 
83 //Added by Prasad
84  // Same as above but avoids iterative exponential calculations
85  // because it accepts Gaussian Kernel as a function parameter
86  void SoftUpdate_fast(const T& XVal, const T& YVal, const int& Rad, const FloatCImgPtr pGauss_Window);
88 
89  // update a certain bin, indexed by iBin, by incrementing its
90  // value by Val
91  void IncrementBin(const int& iBin, const T& Val);
92 
93  // Normalize the histogram so that its area = 'Area'
94  void Normalize(const float& Area = 1.0f);
95 
96  // Normalize the histogram so that its maximum element = 'Max'
97  void NormalizeToMax(const float& Max = 255.0f);
98 
99  // Return the Prob, 1-D Version, the returned Value is just the number
100  // of hits in the bin that corresponds to the range containing 'Val'
101  float GetProb(const T& Val);
102 
103  // 2-D Version
104  float GetProb(const T& XVal, const T& YVal);
105 
106  // precond: must be normalized first
107  inline float GetProbOfBin(int iBin) { return m_pBins[iBin]; };
108 
109  // Use this histogram to get a probability distribution score-
110  // map, i.e. run through Img 'InImg' (in the 1-D case, that
111  // is.. if you're dealing with 2-D histograms, then you'll be
112  // running through Imgs InImg1 and InImg2 simulataneously),
113  // and get the probability associated with each pixel (which is
114  // this histogram's number of hits in the bin that corresponds to
115  // the range containing each pixel's Value. Return all these
116  // probabilities in the Img 'PDistImg'
117  // PRECOND: (1) InImg1 and InImg2 and PDistImg have the same ROI;
118  // (2) Normalize() has been called on 'this'
119  // 1-D version
120  void GetProbDist(CImg<T>& InImg, CImg<float>& PDistImg);
121 
122  // 2-D version
123  void GetProbDist(CImg<T>& InImg1, CImg<T>& InImg2,
124  CImg<float>& PDistImg);
125 
126  // Zero histogram bins
127  void Zero();
128 
129  // return true if the histogram's bins are all zero, false otherwise
130  bool IsEmpty();
131 
132  // return the maximum value of each bin
133  float MaxBinVal();
134 
135  // Subtract the Value 'Value' from each bin, rectifying at 0.
136  void AdjustDown(const float& Value);
137 
138  void Add(const CHistogram<T>& OtherHisto);
139 
140  void ScalarMultiply(const float& Multiplier);
141 
142  // show the histogram in an Img. if the histogram is 1-D, a
143  // bar-graph is shown (a binary Img, x-axis is bin index,
144  // y-axis is number of hits, and the Height of each bar represents
145  // the number of hits); if the histogram is 2-D, then the Img
146  // is broken up into boxes, each corresponding to a bin. The
147  // number of hits per bin of the 2-D histograms displayed is
148  // represented by the grayscale Value (brighter = more hits/bin).
149  void Display(CImg<BYTE>& InImg);
150 
151  // given the bin #, returns the range associated with that bin#
152  // (but doesn't return full range, only lower boudns on the range,
153  // to get the upper bound, just call this again with 'BinIndex'+1
154  // as the argument.
155  T BinIndexToValue(const int& BinIndex);
156 
157  // compare with another histogram via chi square
158  float ChiSquareCompare(CHistogram<T> *OtherHisto);
159 
160  // compare with another histogram via chi square
161  float NormalCompare(CHistogram<T> *OtherHisto);
162 
163  int nBins() { return m_nBins; }
164  float* pBins() { return m_pBins; }
165 
166  // ***TODO***: make member variables protected and
167  // use access functions
168  public:
169  int m_nBinsX;
170  int m_nBinsY;
171  int m_nBinsZ;
172  int m_nBins; // # of elements (size) of histogram
179  float *m_pBins; // the histogram (1d or 2d)
180  float m_XFactor;
181  float m_YFactor;
182  float m_ZFactor;
183  };
184 
188 
192 
194  // END OF INTERFACE -- IMPLEMENTATION STARTS HERE:
196 
197  template <class T>
199  {
200  m_pBins = NULL;
201  }
202 
203  template <class T>
204  CHistogram<T>::CHistogram(const std::string & file_name)
205  {
206  m_pBins = NULL;
207  Read(file_name);
208  }
209 
210  template <class T>
211  CHistogram<T>::CHistogram(std::istream & ifs)
212  {
213  m_pBins = NULL;
214  Read(ifs);
215  }
216 
218 
219  template <class T>
221  {
222  zap(m_pBins);
223  }
224 
225  template <class T>
226  void CHistogram<T>::GetValues(float * pointer)
227  {
228  for(unsigned int i = 0; i < m_nBins; i++)
229  {
230  pointer[i] = m_pBins[i];
231  }
232  }
233 
234  template <class T>
235  void CHistogram<T>::SetValues(float * pointer)
236  {
237  for(unsigned int i = 0; i < m_nBins; i++)
238  {
239  m_pBins[i] = pointer[i];
240  }
241  }
242 
243  template <class T>
244  void CHistogram<T>::Read(const std::string & file_name)
245  {
246  std::ifstream ifs(file_name.c_str());
247  Read(ifs);
248  ifs.close();
249  }
250 
251  template <class T>
252  void CHistogram<T>::Read(std::istream & ifs)
253  {
254  if(m_pBins)
255  {
256  zap(m_pBins);
257  }
258  m_pBins = NULL;
259  ifs >> m_nBins;
260  ifs >> m_nBinsX;
261  ifs >> m_nBinsY;
262  ifs >> m_XRangeMin;
263  ifs >> m_XRangeMax;
264  ifs >> m_YRangeMin;
265  ifs >> m_YRangeMax;
266  ifs >> m_XFactor;
267  ifs >> m_YFactor;
268 
269  if(m_nBinsY == 0)
270  {
271  assert(m_nBinsX == m_nBins);
272  }
273  else
274  {
275  assert( (m_nBinsX*m_nBinsY) == m_nBins);
276  }
277 
278  if(m_nBins != 0)
279  {
280  m_pBins = new float[m_nBins];
281  }
282  float tempf = 0.0;
283  for(unsigned int i = 0; i < m_nBins; i++)
284  {
285  ifs >> tempf;
286  m_pBins[i] = tempf;
287  }
288  }
289 
290  template <class T>
291  void CHistogram<T>::Write(const std::string & file_name) const
292  {
293  using namespace std;
294  ofstream ofs(file_name.c_str());
295  Write(ofs);
296  ofs.close();
297  }
298 
299  template <class T>
300  void CHistogram<T>::Write(std::ostream & ofs) const
301  {
302  ofs << m_nBins << std::endl;
303  ofs << m_nBinsX << std::endl;
304  ofs << m_nBinsY << std::endl;
305  ofs << m_XRangeMin << std::endl;
306  ofs << m_XRangeMax << std::endl;
307  ofs << m_YRangeMin << std::endl;
308  ofs << m_YRangeMax << std::endl;
309  ofs << m_XFactor << std::endl;
310  ofs << m_YFactor << std::endl;
311  for(unsigned int i = 0; i < m_nBins; i++)
312  {
313  ofs << m_pBins[i] << " ";
314  }
315  ofs << std::endl;
316  }
317 
319 
320  template <class T>
321  void CHistogram<T>::Setup(const int& nBins)
322  {
323  zap(m_pBins);
324 
325  m_nBinsX = m_nBins = nBins;
326  m_nBinsY = 0;
327  m_nBinsZ = 0;
328  m_XRangeMin = -1.0f;
329  m_XRangeMax = -1.0f;
330  m_YRangeMin = -1.0f;
331  m_YRangeMax = -1.0f;
332  m_ZRangeMin = -1.0f;
333  m_ZRangeMax = -1.0f;
334  m_XFactor = -1.0f;
335  m_YFactor = -1.0f;
336  m_pBins = new float[m_nBins];
337  Zero();
338  }
339 
340 
341  // 1-D version
342  template <class T>
343  void CHistogram<T>::Setup(const int& nBins, const T& RangeMin,
344  const T& RangeMax)
345  {
346  zap(m_pBins);
347  m_nBinsX = m_nBins = nBins;
348  m_nBinsY = 0;
349  m_XRangeMin = RangeMin;
350  m_XRangeMax = RangeMax;
351 
352  // cout << "SETUP" << RangeMin << " " << RangeMax << endl;
353 
354  const float Range = (float)(RangeMax-RangeMin);
355  m_XFactor = (float)(nBins-1)/Range;
356  m_YFactor = 0.0f;
357  m_pBins = new float[m_nBins];
358  Zero();
359  }
360 
361  // 3-D version
362  template <class T>
363  void CHistogram<T>::Setup(const int& nBinsX, const int& nBinsY, const int& nBinsZ,
364  const T& XRangeMin, const T& XRangeMax,
365  const T& YRangeMin, const T& YRangeMax,
366  const T& ZRangeMin, const T& ZRangeMax)
367  {
368  zap(m_pBins);
369  m_nBinsX = nBinsX;
370  m_nBinsY = nBinsY;
371  m_nBinsZ = nBinsZ;
372  m_XRangeMin = XRangeMin;
373  m_XRangeMax = XRangeMax;
374  m_YRangeMin = YRangeMin;
375  m_YRangeMax = YRangeMax;
376  m_ZRangeMin = ZRangeMin;
377  m_ZRangeMax = ZRangeMax;
378  const float XRange = (float)(m_XRangeMax-m_XRangeMin);
379  const float YRange = (float)(m_YRangeMax-m_YRangeMin);
380  const float ZRange = (float)(m_ZRangeMax-m_ZRangeMin);
381  m_XFactor = (float)(nBinsX-1)/XRange;
382  m_YFactor = (float)(nBinsY-1)/YRange;
383  m_ZFactor = (float)(nBinsZ-1)/ZRange;
384  m_nBins = nBinsX*nBinsY*nBinsZ;
385  m_pBins = new float[m_nBins];
386  Zero();
387  }
388 
389  // 2-D version
390  template <class T>
391  void CHistogram<T>::Setup(const int& nBinsX, const int& nBinsY,
392  const T& XRangeMin, const T& XRangeMax,
393  const T& YRangeMin, const T& YRangeMax)
394  {
395  zap(m_pBins);
396  m_nBinsX = nBinsX;
397  m_nBinsY = nBinsY;
398  m_nBinsZ = 0;
399  m_XRangeMin = XRangeMin;
400  m_XRangeMax = XRangeMax;
401  m_YRangeMin = YRangeMin;
402  m_YRangeMax = YRangeMax;
403  m_ZRangeMin = -1.0f;
404  m_ZRangeMax = -1.0f;
405  const float XRange = (float)(m_XRangeMax-m_XRangeMin);
406  const float YRange = (float)(m_YRangeMax-m_YRangeMin);
407  m_XFactor = (float)(nBinsX-1)/XRange;
408  m_YFactor = (float)(nBinsY-1)/YRange;
409  m_nBins = nBinsX*nBinsY;
410  m_pBins = new float[m_nBins];
411  Zero();
412  }
413 
415 
416  // 1-D version
417  template <class T>
418  inline void CHistogram<T>::Update(const T& Val)
419  {
420  assert(Val >= m_XRangeMin);
421  assert(Val <= m_XRangeMax);
422  (*(m_pBins+F2I((float)(Val-m_XRangeMin)*m_XFactor)))++;
423  }
424 
425  // 2-D version
426  template <class T>
427  inline void CHistogram<T>::Update(const T& XVal, const T& YVal)
428  {
429  assert(XVal >= m_XRangeMin);
430  assert(XVal <= m_XRangeMax);
431  assert(YVal >= m_YRangeMin);
432  assert(YVal <= m_YRangeMax);
433 
434  const int X = F2I((float)(XVal-(float)m_XRangeMin)*m_XFactor);
435  const int Y = F2I((float)(YVal-(float)m_YRangeMin)*m_YFactor);
436  (*(m_pBins+Y*m_nBinsX+X))++;
437  }
438 
440  // 2-D histogram soft binning
441  // ARGUMENTS:
442  // ----------
443  // 'XVal' - value along first dimension
444  // 'YVal' - value along second dimension
445  // 'Sigma' - Sigma of Gaussian Kernel, in units of this histogram's
446  // bin width
447 
448  template <class T>
449  inline void CHistogram<T>::SoftUpdate(const T& XVal, const T& YVal,
450  const float& Sigma)
451  {
452  //Debugging
453  //if (XVal < m_XRangeMin || XVal > m_XRangeMax || YVal < m_YRangeMin || YVal > m_YRangeMax){
454  //cout << " Faulty A value = " << XVal << endl;
455  //cout << " Faulty B value = " << YVal << endl;
456  //}// if (XVal....
457 
458 
459  assert(XVal >= m_XRangeMin);
460  assert(XVal <= m_XRangeMax);
461  assert(YVal >= m_YRangeMin);
462  assert(YVal <= m_YRangeMax);
463 
464  // RealX and RealY are how far we are from the zero of
465  // each dimension, i.e. (RealX, RealY) is the floating point
466  // coordinate of which bin we fell into
467  const float RealX = (XVal-m_XRangeMin)*m_XFactor;
468  const float RealY = (YVal-m_YRangeMin)*m_YFactor;
469 
470  // we need to decide where to CENTER the Gaussian kernel's
471  // window, so for our (integer) bin coordinates we choose the
472  // integer coordinates closest to (RealX, RealY):
473  const int xw_center = F2I(RealX);
474  const int yw_center = F2I(RealY);
475 
476  // now we need to determine a window width over which
477  // we'll soft-bin, the radius of this window should
478  // be enough to encompass most of our Gaussian kernel,
479  // so we'll use 3.0 * Sigma. (FWHM=2.35sigma)
480  const int Rad = F2I(3.0f*Sigma);
481 
482  const float RecipSigmaSqr = 1.0f/SQR(Sigma);
483  for (int yw = -Rad; yw <= Rad; yw++) {
484  for (int xw = -Rad; xw <= Rad; xw++) {
485  const int binXcoord = xw_center+xw;
486  const int binYcoord = yw_center+yw;
487  if ((binXcoord >= 0) && (binXcoord < m_nBinsX) &&
488  (binYcoord >= 0) && (binYcoord < m_nBinsY)) {
489  const float DeltaX = RealX-(float)binXcoord;
490  const float DeltaY = RealY-(float)binYcoord;
491  const float SquaredSum = SQR(DeltaX)+SQR(DeltaY);
492  const float Weight = exp(-SquaredSum*RecipSigmaSqr);
493  const int iBin = binYcoord*m_nBinsX+binXcoord;
494  m_pBins[iBin] += Weight;
495  } // if
496  } // for xw
497  } // for yw
498  }
499 
500  template <class T>
501  inline void CHistogram<T>::SoftUpdate1D(const T& XVal, const float& Sigma)
502  {
503  //Debugging
504  //if (XVal < m_XRangeMin || XVal > m_XRangeMax || YVal < m_YRangeMin || YVal > m_YRangeMax){
505  //cout << " Faulty A value = " << XVal << endl;
506  //cout << " Faulty B value = " << YVal << endl;
507  //}// if (XVal....
508 
509 
510  assert(XVal >= m_XRangeMin);
511  assert(XVal <= m_XRangeMax);
512 
513  // RealX and RealY are how far we are from the zero of
514  // each dimension, i.e. (RealX, RealY) is the floating point
515  // coordinate of which bin we fell into
516  const float RealX = (XVal-m_XRangeMin)*m_XFactor;
517 
518  // we need to decide where to CENTER the Gaussian kernel's
519  // window, so for our (integer) bin coordinates we choose the
520  // integer coordinates closest to (RealX, RealY):
521  const int xw_center = F2I(RealX);
522 
523  // now we need to determine a window width over which
524  // we'll soft-bin, the radius of this window should
525  // be enough to encompass most of our Gaussian kernel,
526  // so we'll use 3.0 * Sigma. (FWHM=2.35sigma)
527  const int Rad = F2I(3.0f*Sigma);
528 
529  const float RecipSigmaSqr = 1.0f/Sigma;
530  for (int xw = -Rad; xw <= Rad; xw++) {
531  const int binXcoord = xw_center+xw;
532  if ((binXcoord >= 0) && (binXcoord < m_nBinsX)) {
533  const float DeltaX = RealX-(float)binXcoord;
534  const float SquaredSum = SQR(DeltaX);
535  const float Weight = exp(-SquaredSum*RecipSigmaSqr);
536  const int iBin = binXcoord;
537  m_pBins[iBin] += Weight;
538  } // if
539  } // for xw
540  }
541 
542  template <class T>
543  inline void CHistogram<T>::SoftUpdate3D(const T& XVal, const T& YVal, const T& ZVal,
544  const float& Sigma)
545  {
546  //Debugging
547  //if (XVal < m_XRangeMin || XVal > m_XRangeMax || YVal < m_YRangeMin || YVal > m_YRangeMax){
548  //cout << " Faulty A value = " << XVal << endl;
549  //cout << " Faulty B value = " << YVal << endl;
550  //}// if (XVal....
551 
552 
553  assert(XVal >= m_XRangeMin);
554  assert(XVal <= m_XRangeMax);
555  assert(YVal >= m_YRangeMin);
556  assert(YVal <= m_YRangeMax);
557  assert(ZVal >= m_ZRangeMin);
558  assert(ZVal <= m_ZRangeMax);
559 
560  // RealX and RealY are how far we are from the zero of
561  // each dimension, i.e. (RealX, RealY) is the floating point
562  // coordinate of which bin we fell into
563  const float RealX = (XVal-m_XRangeMin)*m_XFactor;
564  const float RealY = (YVal-m_YRangeMin)*m_YFactor;
565  const float RealZ = (ZVal-m_ZRangeMin)*m_ZFactor;
566 
567  // we need to decide where to CENTER the Gaussian kernel's
568  // window, so for our (integer) bin coordinates we choose the
569  // integer coordinates closest to (RealX, RealY):
570  const int xw_center = F2I(RealX);
571  const int yw_center = F2I(RealY);
572  const int zw_center = F2I(RealZ);
573 
574  // now we need to determine a window width over which
575  // we'll soft-bin, the radius of this window should
576  // be enough to encompass most of our Gaussian kernel,
577  // so we'll use 3.0 * Sigma. (FWHM=2.35sigma)
578  const int Rad = F2I(3.0f*Sigma);
579 
580  //const float RecipSigmaSqr = 1.0f/SQR(Sigma);
581  const float RecipSigmaSqr = 1.0f/pow((double) Sigma,1.0/3.0);
582  for (int yw = -Rad; yw <= Rad; yw++) {
583  for (int xw = -Rad; xw <= Rad; xw++) {
584  for (int zw = -Rad; zw <= Rad; zw++) {
585  const int binXcoord = xw_center+xw;
586  const int binYcoord = yw_center+yw;
587  const int binZcoord = zw_center+zw;
588  if ((binXcoord >= 0) && (binXcoord < m_nBinsX) &&
589  (binYcoord >= 0) && (binYcoord < m_nBinsY) &&
590  (binZcoord >= 0) && (binZcoord < m_nBinsZ)) {
591  const float DeltaX = RealX-(float)binXcoord;
592  const float DeltaY = RealY-(float)binYcoord;
593  const float DeltaZ = RealZ-(float)binZcoord;
594  const float SquaredSum = SQR(DeltaX)+SQR(DeltaY)+SQR(DeltaZ);
595  const float Weight = exp(-SquaredSum*RecipSigmaSqr);
596  const int iBin = m_nBinsZ*(binYcoord*m_nBinsX) + (binXcoord)*m_nBinsZ + binZcoord;
597  m_pBins[iBin] += Weight;
598  } // if
599  } // for zw
600  } // for xw
601  } // for yw
602  }
603 
604 
606 //Added by Prasad
607 //This routine does 2-D histogram soft-binning but does not involve the Gaussian
608 //exponential calculations within it. It instead accepts the Gaussian weight values
609 //as a function parameter
610 
611  // 2-D histogram soft binning
612  // ARGUMENTS:
613  // ----------
614  // 'XVal' - value along first dimension
615  // 'YVal' - value along second dimension
616  // 'Rad' - Radius of Gaussian Kernel
617  // 'pGauss_Window' - Matrix containing the Gaussian weight
618 
619  template <class T>
620  inline void CHistogram<T>::SoftUpdate_fast(const T& XVal, const T& YVal,
621  const int& Rad, const FloatCImgPtr pGauss_Window)
622  {
623  //Debugging
624  //if (XVal < m_XRangeMin || XVal > m_XRangeMax || YVal < m_YRangeMin || YVal > m_YRangeMax){
625  //cout << " Faulty A value = " << XVal << endl;
626  //cout << " Faulty B value = " << YVal << endl;
627  //}// if (XVal....
628 
629 
630  assert(XVal >= m_XRangeMin);
631  assert(XVal <= m_XRangeMax);
632  assert(YVal >= m_YRangeMin);
633  assert(YVal <= m_YRangeMax);
634 
635  // RealX and RealY are how far we are from the zero of
636  // each dimension, i.e. (RealX, RealY) is the floating point
637  // coordinate of which bin we fell into
638  const float RealX = (XVal-m_XRangeMin)*m_XFactor;
639  const float RealY = (YVal-m_YRangeMin)*m_YFactor;
640 
641  // we need to decide where to CENTER the Gaussian kernel's
642  // window, so for our (integer) bin coordinates we choose the
643  // integer coordinates closest to (RealX, RealY):
644  const int xw_center = F2I(RealX);
645  const int yw_center = F2I(RealY);
646 
647  // now we need to determine a window width over which
648  // we'll soft-bin, the radius of this window should
649  // be enough to encompass most of our Gaussian kernel,
650  // so we'll use 3.0 * Sigma. (FWHM=2.35sigma)
651  //const int Rad = F2I(3.0f*Sigma);
652 
653  //const float RecipSigmaSqr = 1.0f/SQR(Sigma);
654  float* pWindow = pGauss_Window->pBuffer();
655 
656  for (int yw = -Rad; yw <= Rad; yw++) {
657  for (int xw = -Rad; xw <= Rad; xw++, pWindow++) {
658  const int binXcoord = xw_center+xw;
659  const int binYcoord = yw_center+yw;
660  if ((binXcoord >= 0) && (binXcoord < m_nBinsX) &&
661  (binYcoord >= 0) && (binYcoord < m_nBinsY)) {
662  //const float DeltaX = RealX-(float)binXcoord;
663  //const float DeltaY = RealY-(float)binYcoord;
664  //const float SquaredSum = SQR(DeltaX)+SQR(DeltaY);
665  //const float Weight = exp(-SquaredSum*RecipSigmaSqr);
666  const int iBin = binYcoord*m_nBinsX+binXcoord;
667  m_pBins[iBin] += *pWindow;
668  } // if
669  } // for xw
670  } // for yw
671  }
672 
674 
675 
677  // Update the i'th bin 'iBin' by incrementing it by a value 'Val'
678 
679  template<class T>
680  inline void CHistogram<T>::IncrementBin(const int& iBin, const T& Val)
681  {
682  *(m_pBins+iBin) += Val;
683  }
684 
686 
687  template <class T>
688  void CHistogram<T>::Normalize(const float& Area)
689  {
690  // doesn't rely on anything but m_nBins and m_pBins
691  T *pBin = m_pBins;
692  float EltSum = 0.0f;
693  int i;
694  for (i = 0; i < m_nBins; i++, pBin++) {
695  assert(*pBin >= 0.0f);
696  EltSum += (float)*pBin;
697  }
698  // assert(EltSum >= 0.0f);
699 
700  if (EltSum > 0.0f) {
701  const float Factor = Area/EltSum;
702 
703  pBin = m_pBins;
704  for (i = 0; i < m_nBins; i++, pBin++) {
705  *pBin = (T)((float)*pBin*(float)Factor);
706  }
707  }
708  }
709 
711 
712  template <class T>
713  void CHistogram<T>::NormalizeToMax(const float& NMax)
714  {
715  const float HistoMax = Max(m_pBins, m_nBins);
716  const float Factor = NMax/HistoMax;
717  float *pBin = m_pBins;
718  for (int i = 0; i < m_nBins; i++, pBin++)
719  *pBin *= Factor;
720  }
721 
723 
724  // 1-D version
725  template <class T>
726  float CHistogram<T>::GetProb(const T& Val)
727  {
728  return *(m_pBins+F2I((float)(Val-m_XRangeMin)*m_XFactor));
729  }
730 
731  // 2-D version
732  template <class T>
733  float CHistogram<T>::GetProb(const T& XVal, const T& YVal)
734  {
735  const int X = F2I((float)(XVal-m_XRangeMin)*m_XFactor);
736  const int Y = F2I((float)(YVal-m_YRangeMin)*m_YFactor);
737  return *(m_pBins+Y*m_nBinsX+X);
738  }
739 
741 
742  template <class T>
744  {
745  PDistImg.SetROIVal(0.0f); // zero out initially
746  const int ystart = InImg.ROIStartY(), yend = InImg.ROIEndY(),
747  xstart = InImg.ROIStartX(), xend = InImg.ROIEndX(),
748  sk = InImg.ROISkipCols();
749  T *pBuf = InImg.pROI();
750  float *pDistBuf = PDistImg.pROI();
751  for (int y = ystart; y < yend; y++, pBuf += sk, pDistBuf += sk)
752  for (int x = xstart; x < xend; x++, pBuf++, pDistBuf++)
753  *pDistBuf = GetProb(*pBuf);
754  }
755 
757 
758  template <class T>
760  CImg<float>& PDistImg)
761  {
762  PDistImg.SetROIVal(0.0f); // zero out initially
763  const int ystart = InImg1.ROIStartY(), yend = InImg1.ROIEndY(),
764  xstart = InImg1.ROIStartX(), xend = InImg1.ROIEndX(),
765  sk = InImg1.ROISkipCols();
766  T *pBuf1 = InImg1.pROI(), *pBuf2 = InImg2.pROI();
767  float *pDistBuf = PDistImg.pROI();
768  for (int y = ystart; y < yend;
769  y++, pBuf1 += sk, pBuf2 += sk, pDistBuf += sk)
770  for (int x = xstart; x < xend;
771  x++, pBuf1++, pBuf2++, pDistBuf++)
772  *pDistBuf = GetProb(*pBuf1, *pBuf2);
773  }
774 
776 
777  template <class T>
779  {
780  memset(m_pBins, 0, sizeof(float)*m_nBins);
781  }
782 
784 
785  template <class T>
787  {
788  bool bIsEmpty = true;
789  for (int i = 0; i < m_nBins; i++) {
790  if (m_pBins[i] != (T)0) {
791  bIsEmpty = false;
792  break;
793  }
794  }
795  return bIsEmpty;
796  }
797 
799 
800  template <class T>
802  {
803  float MaxVal = CONST_MIN_FLOAT;
804  for (int i = 0; i < m_nBins; i++)
805  if (m_pBins[i] > MaxVal)
806  MaxVal = m_pBins[i];
807  return MaxVal;
808  }
809 
811 
812  template <class T>
813  void CHistogram<T>::AdjustDown(const float& Value)
814  {
815  float *pBin = m_pBins;
816  for (int i = 0; i < m_nBins; i++, pBin++) {
817  *pBin -= Value;
818  if (*pBin < 0.0f) *pBin = 0.0f;
819  }
820  }
821 
823 
824  template <class T>
825  void CHistogram<T>::Add(const CHistogram<T>& OtherHisto)
826  {
827  T *pBin = m_pBins;
828  T *pOtherBin = OtherHisto.m_pBins;
829  int nElts = m_nBins;
830  for (int i = 0; i < nElts; i++, pBin++, pOtherBin++)
831  *pBin += *pOtherBin;
832  }
833 
835 
836  template <class T>
837  void CHistogram<T>::ScalarMultiply(const float& Multiplier)
838  {
839  T *pBin = m_pBins;
840  int nElts = m_nBins;
841  for (int i = 0; i < nElts; i++, pBin++)
842  *pBin *= Multiplier;
843  }
844 
846 
847  template <class T>
848  T CHistogram<T>::BinIndexToValue(const int& BinIndex)
849  {
850  return (T)((float)(m_XRangeMax-m_XRangeMin)*(float)BinIndex/
851  (float)m_nBinsX+(float)m_XRangeMin);
852  }
853 
855 
856  template <class T>
858  {
859  T *pBin = m_pBins;
860  T *pOtherBin = OtherHisto->m_pBins;
861  float Sum = 0.0f;
862  for (int i = 0; i < m_nBins; i++, pBin++, pOtherBin++) {
863  float Val = (float)*pBin;
864  float OtherVal = (float)*pOtherBin;
865  float diffsqr = Val-OtherVal; diffsqr *= diffsqr;
866  float ValSum = Val+OtherVal;
867  if (ValSum != 0.0f) Sum += diffsqr/ValSum;
868  } // for (int i = 0; i < m_nBins; i++, pBin++, pOtherBin++) {
869  Sum *= 0.5f;
870  // assert((Sum >= 0.0f) && (Sum <= 1.0f));
871  // assert(Sum >= 0.0f);
872  if (Sum > 1.0f) {
873  // cout << Sum << endl;
874  assert(Sum < 1.001f);
875  Sum = 1.0f;
876  }
877  return Sum;
878  }
879 
880  // compare with another histogram via normal compare
881  template <class T>
883  {
884  double total = 0.0;
885  for(int i = 0; i < m_nBins; i++)
886  {
887  double val1 = (float)m_pBins[i];
888  double val2 = (float)OtherHisto->m_pBins[i];
889  double diff = fabs(val1 - val2);
890  total += diff;
891  }
892  total /= m_nBins;
893  return float(total);
894  }
895 
896 } // namespace DTLib {
897 
898 #endif /* #ifndef _HISTOGRAM_H */
int m_nBinsY
Definition: histogram.h:170
#define zap(x)
Definition: utils.h:137
T BinIndexToValue(const int &BinIndex)
Definition: histogram.h:848
float * m_pBins
Definition: histogram.h:179
void GetValues(float *pointer)
Definition: histogram.h:226
float GetProbOfBin(int iBin)
Definition: histogram.h:107
int m_nBinsZ
Definition: histogram.h:171
float Max(float *pBuf, int Size)
Definition: utils.cpp:90
T m_ZRangeMax
Definition: histogram.h:178
float m_ZFactor
Definition: histogram.h:182
float ChiSquareCompare(CHistogram< T > *OtherHisto)
Definition: histogram.h:857
float m_XFactor
Definition: histogram.h:180
T m_XRangeMin
Definition: histogram.h:173
#define F2I(x)
Definition: utils.h:111
int nBins()
Definition: histogram.h:163
int m_nBinsX
Definition: histogram.h:169
int ROIEndX()
Definition: img.h:163
Definition: histogram.h:21
int ROIEndY()
Definition: img.h:165
void SoftUpdate1D(const T &XVal, const float &Sigma)
Definition: histogram.h:501
void IncrementBin(const int &iBin, const T &Val)
Definition: histogram.h:680
int ROIStartY()
Definition: img.h:164
void SoftUpdate_fast(const T &XVal, const T &YVal, const int &Rad, const FloatCImgPtr pGauss_Window)
Definition: histogram.h:620
void SetROIVal(const T &Val)
Definition: img.h:1071
void Update(const T &Val)
Definition: histogram.h:418
void Display(CImg< BYTE > &InImg)
bool IsEmpty()
Definition: histogram.h:786
void Add(const CHistogram< T > &OtherHisto)
Definition: histogram.h:825
int ROISkipCols()
Definition: img.h:166
T m_YRangeMax
Definition: histogram.h:176
T m_YRangeMin
Definition: histogram.h:175
~CHistogram()
Definition: histogram.h:220
x
Definition: APPgetLargeConnectedEdges.m:100
void Normalize(const float &Area=1.0f)
Definition: histogram.h:688
float m_YFactor
Definition: histogram.h:181
#define CONST_MIN_FLOAT
Definition: utils.h:20
CHistogram< float > * FloatCHistogramPtr
TYPES.
Definition: histogram.h:189
float * pBins()
Definition: histogram.h:164
void Setup(const int &nBins)
Definition: histogram.h:321
CHistogram()
Definition: histogram.h:198
void Read(const std::string &file_name)
Definition: histogram.h:244
void ScalarMultiply(const float &Multiplier)
Definition: histogram.h:837
int m_nBins
Definition: histogram.h:172
float NormalCompare(CHistogram< T > *OtherHisto)
Definition: histogram.h:882
void Write(const std::string &file_name) const
Definition: histogram.h:291
int ROIStartX()
Definition: img.h:162
void GetProbDist(CImg< T > &InImg, CImg< float > &PDistImg)
Definition: histogram.h:743
get the indices of edges in each direction for i
Definition: APPgetLargeConnectedEdges.m:48
CHistogram< long > * LongCHistogramPtr
Definition: histogram.h:191
#define SQR(x)
Definition: utils.h:99
void NormalizeToMax(const float &Max=255.0f)
Definition: histogram.h:713
void SoftUpdate3D(const T &XVal, const T &YVal, const T &ZVal, const float &Sigma)
Definition: histogram.h:543
void Zero()
Definition: histogram.h:778
T m_XRangeMax
Definition: histogram.h:174
T m_ZRangeMin
Definition: histogram.h:177
void SoftUpdate(const T &XVal, const T &YVal, const float &Sigma)
Definition: histogram.h:449
float MaxBinVal()
Definition: histogram.h:801
float GetProb(const T &Val)
Definition: histogram.h:726
CHistogram< int > * IntCHistogramPtr
Definition: histogram.h:190
T * pBuffer()
Definition: img.h:148
void AdjustDown(const float &Value)
Definition: histogram.h:813
T * pROI()
Definition: img.h:151
void SetValues(float *pointer)
Definition: histogram.h:235