KSquare Utilities
Histogram.cpp
Go to the documentation of this file.
1 /* Histogram.cpp -- Class that represents a single Histogram.
2  * Copyright (C) 1994-2011 Kurt Kramer
3  * For conditions of distribution and use, see copyright notice in KKB.h
4  */
5 #include "FirstIncludes.h"
6 #include <float.h>
7 #include <math.h>
8 #include <string>
9 #include <iostream>
10 #include <fstream>
11 #include <vector>
12 #include "MemoryDebug.h"
13 using namespace std;
14 
15 
16 #include "Histogram.h"
17 #include "ImageIO.h"
18 #include "KKBaseTypes.h"
19 #include "Raster.h"
20 using namespace KKB;
21 
22 
23 
24 Histogram::Histogram (float _minValue,
25  kkint32 _numOfBuckets,
26  float _bucketSize,
27  bool _wrapArround
28  ):
29 
30  bucketSize (_bucketSize),
31  buckets (NULL),
32  equalizedMapTable (NULL),
33  minValue (_minValue),
34  numOfBuckets (_numOfBuckets),
35  totalCount (0.0),
36  totalVal (0.0),
37  wrapArround (_wrapArround)
38 
39 {
40  if (numOfBuckets < 1)
41  {
42  cerr << std::endl
43  << "*** ERROR *** Histogram, Negative numOfBuckets[" << numOfBuckets << "." << std::endl
44  << std::endl;
45  exit (-1);
46  }
47 
48  range = bucketSize * numOfBuckets;
49 
50  buckets = new float[numOfBuckets];
51  bucketTotals = new float[numOfBuckets];
52 
53  for (kkint32 x = 0; x < numOfBuckets; x++)
54  {
55  buckets [x] = (float)0.0;
56  bucketTotals[x] = (float)0.0;
57  }
58 }
59 
60 
61 
62 
63 
65 {
66  delete buckets;
67  delete bucketTotals;
68  if (equalizedMapTable)
69  delete equalizedMapTable;
70 }
71 
72 
73 
74 
75 
77 {
78  kkint32 idx;
79 
80  float maxCount = -1;
81  kkint32 maxIdx = -1;
82 
83  for (idx = 0; idx < numOfBuckets; idx++)
84  {
85  if (buckets[idx] > maxCount)
86  {
87  maxCount = buckets[idx];
88  maxIdx = idx;
89  }
90  }
91 
92  return maxIdx;
93 } /* MaxBucketIdx */
94 
95 
96 
97 
99 {
100  kkint32 idx = MaxBucketIdx ();
101 
102  if (buckets[idx] <= (float)0.0)
103  return (float)0.0;
104  else
105  return bucketTotals[idx] / buckets[idx];
106 
107 } /* AverageOfMaxBucket */
108 
109 
110 
111 
112 
114 {
115  kkint32 idx = MaxBucketIdx ();
116 
117  return buckets[idx];
118 } /* CountOfMaxBucket */
119 
120 
121 
122 float Histogram::Bucket (kkint32 bucket) const
123 {
124  if ((bucket < 0) || (bucket >= numOfBuckets))
125  {
126  cerr << std::endl
127  << "*** ERROR *** Histogram::Bucket, Bucket[" << bucket << "] is out of range." << std::endl
128  << std::endl;
129  exit (-1);
130  }
131 
132  return buckets[bucket];
133 } /* Bucket */
134 
135 
136 
137 void Histogram::Increment (float val)
138 {
139  if (val < minValue)
140  {
141  cerr << std::endl
142  << "*** ERROR *** val[" << val << "] is out of range [" << minValue << "]." << std::endl
143  << std::endl;
144  exit (-1);
145  }
146 
147  kkint32 bucket = (kkint32) ((val - minValue) / bucketSize);
148  if (bucket >= numOfBuckets)
149  bucket = numOfBuckets - 1;
150  else if (bucket < 0)
151  bucket = 0;
152 
153  buckets[bucket] = buckets[bucket] + (float)1.0;
154  bucketTotals[bucket] += val;
155 
156  totalCount += (float)1.0;
157  totalVal += val;
158 } /* Increment */
159 
160 
161 
162 RasterPtr Histogram::CreateGraph () const
163 {
164  kkint32 bucket = 0;
165  kkint32 col = 10;
166  kkint32 barWidth = 2;
167  kkint32 interBarWidth = 5;
168  kkint32 colHeight = 0;
169  float maxCount = (float)0.0;
170  kkint32 row = 0;
171  kkint32 x;
172  kkint32 y;
173 
174  uchar borderColor = 100;
175  uchar colorAxis = 150;
176  uchar colorBar = 200;
177  uchar colorBarMax = 255;
178  uchar colorBarPeak = 255;
179  uchar gridColor = 180;
180  uchar hashColor = 70;
181  uchar hashColor2 = 45;
182 
183  kkint32 graphWidth = numOfBuckets * (barWidth + interBarWidth) + 20; // 3 pixels per bar, +
184  // 3 pixels space +
185  // 10 pixel Padding on both sides.
186 
187  // Set up where Grid lines should go
188  bool* vertGridLines = new bool[numOfBuckets];
189  bool* peakBarLines = new bool[numOfBuckets];
190  for (x = 0; x < numOfBuckets; x++)
191  {
192  vertGridLines[x] = false;
193  peakBarLines [x] = IsBucketAPeak (x, 2); // Make sure that we are greater than
194  // our 2 left and right neighbors
195  }
196 
197  // Look for the Zero Grid Line should go
198 
199  kkint32 middleIdx = 0;
200  if (minValue < 0)
201  {
202  kkint32 numOfBucketsToZero = (kkint32)(0.5 + fabs (minValue) / bucketSize);
203 
204  if (numOfBucketsToZero < numOfBuckets)
205  middleIdx = numOfBucketsToZero;
206  }
207 
208  x = middleIdx;
209  while (x < numOfBuckets)
210  {
211  vertGridLines[x] = true;
212  x += 100;
213  }
214 
215  x = middleIdx;
216  while (x > 0)
217  {
218  vertGridLines[x] = true;
219  x -= 100;
220  }
221 
222  for (bucket = 0; bucket < numOfBuckets; bucket++)
223  {
224  if (buckets[bucket] > maxCount)
225  maxCount = buckets[bucket];
226  }
227 
228  kkint32 maxColHeight = Min ((kkint32)(maxCount * (barWidth + interBarWidth) + (float)0.5), (kkint32)512);
229  kkint32 graphHeight = maxColHeight + 20;
230 
231 
232  RasterPtr graph = new Raster (graphHeight, graphWidth);
233 
234  graph->DrawLine ( 10, 10, 10, graphWidth - 10, borderColor); // TopLeft -> TopRight
235 
236  graph->DrawLine ( 10, graphWidth - 10, graphHeight - 10, graphWidth - 10, borderColor); // TopRight -> BotRight
237 
238  graph->DrawLine (graphHeight - 10, graphWidth - 10, graphHeight - 10, 10, borderColor); // BotRight -> BotLeft
239 
240  graph->DrawLine (graphHeight - 10, 10, 10, 10, borderColor); // BotLeft -> TopLeft
241 
242 
243  x = 0;
244  row = graphHeight - 10;
245 
246  // Draw Y Axis
247  while (x < maxColHeight)
248  {
249  if ((x % 10) == 0)
250  {
251  if ((x % 50) == 0)
252  {
253  graph->SetPixelValue (row, 4, hashColor2);
254  graph->SetPixelValue (row, 5, hashColor2);
255  graph->SetPixelValue (row, 6, hashColor2);
256 
257  if ((x % 100) == 0)
258  {
259  graph->DrawLine (row, 9, row, graphWidth - 11, gridColor);
260  }
261  }
262 
263  graph->SetPixelValue (row, 7, hashColor);
264  graph->SetPixelValue (row, 8, hashColor);
265  graph->SetPixelValue (row, 9, hashColor);
266  }
267 
268  graph->SetPixelValue (row, 9, colorAxis);
269  row--;
270  x++;
271  }
272 
273 
274 
275  col = 10;
276 
277  for (bucket = 0; bucket < numOfBuckets; bucket++)
278  {
279  for (x = 0; x < (barWidth + interBarWidth); x++)
280  {
281  graph->SetPixelValue (graphHeight - 9, col + x, colorAxis);
282  }
283 
284  if ((bucket % 10) == 0)
285  {
286  // Lets add a Hash Mark
287  graph->SetPixelValue (graphHeight - 8, col + 1, hashColor);
288  graph->SetPixelValue (graphHeight - 7, col + 1, hashColor);
289  graph->SetPixelValue (graphHeight - 6, col + 1, hashColor);
290  graph->SetPixelValue (graphHeight - 5, col + 1, hashColor);
291  }
292 
293  if (vertGridLines[bucket] == true)
294  {
295  graph->DrawLine (graphHeight - 10, col + 1, 10, col + 1, gridColor);
296  }
297 
298  colHeight = (kkint32)ceil ((((float)maxColHeight * buckets[bucket]) / maxCount));
299 
300  if ((colHeight < 1) && (buckets[bucket] > (float)0.0))
301  {
302  cout << "I want to know about this." << std::endl;
303  }
304 
305  row = graphHeight - 10;
306 
307  uchar barCodeToUse = colorBar;
308  if (buckets[bucket] >= maxCount)
309  barCodeToUse = colorBarMax;
310 
311  else if (peakBarLines[bucket])
312  barCodeToUse = colorBarPeak;
313 
314  for (kkint32 x = 0; x < colHeight; x++)
315  {
316  for (y = 0; y < barWidth; y++)
317  {
318  graph->SetPixelValue (row, col + y, barCodeToUse);
319  }
320 
321  row--;
322  }
323 
324  col += (barWidth + interBarWidth);
325  }
326 
327  delete[] peakBarLines;
328  delete[] vertGridLines;
329 
330  graph->ReverseImage ();
331 
332  return graph;
333 } /* CreateGraph */
334 
335 
336 
337 RasterPtr Histogram::CreateGraph (kkint32 barSize) const
338 {
339  kkint32 bucket = 0;
340  kkint32 col = 10;
341  kkint32 barWidth = 2;
342  kkint32 interBarWidth = 5;
343  kkint32 colHeight = 0;
344  float maxCount = (float)0.0;
345  kkint32 row = 0;
346  kkint32 x;
347  kkint32 y;
348 
349  uchar borderColor = 100;
350  uchar colorAxis = 150;
351  uchar colorBar = 200;
352  uchar colorBarMax = 255;
353  uchar colorBarPeak = 255;
354  uchar gridColor = 180;
355  uchar hashColor = 70;
356  uchar hashColor2 = 45;
357 
358  kkint32 graphWidth = numOfBuckets * (barWidth + interBarWidth) + 20; // 3 pixels per bar, +
359  // 3 pixels space +
360  // 10 pixels Padding on both sides.
361 
362  // Set up where Grid lines should go
363  bool* vertGridLines = new bool[numOfBuckets];
364  bool* peakBarLines = new bool[numOfBuckets];
365  for (x = 0; x < numOfBuckets; x++)
366  {
367  vertGridLines[x] = false;
368  peakBarLines [x] = IsBucketAPeak (x, 2); // Make sure that we are greater than
369  // our 2 left and right neighbors
370  }
371 
372  // Look for the Zero Grid Line should go
373 
374  kkint32 middleIdx = 0;
375  if (minValue < 0)
376  {
377  kkint32 numOfBucketsToZero = (kkint32)(0.5 + fabs (minValue) / bucketSize);
378 
379  if (numOfBucketsToZero < numOfBuckets)
380  middleIdx = numOfBucketsToZero;
381  }
382 
383  x = middleIdx;
384  while (x < numOfBuckets)
385  {
386  vertGridLines[x] = true;
387  x += 100;
388  }
389 
390  x = middleIdx;
391  while (x > 0)
392  {
393  vertGridLines[x] = true;
394  x -= 100;
395  }
396 
397 
398  for (bucket = 0; bucket < numOfBuckets; bucket++)
399  {
400  if (buckets[bucket] > maxCount)
401  maxCount = buckets[bucket];
402  }
403 
404 
405  kkint32 maxColHeight = Min ((kkint32)(maxCount * (barWidth + interBarWidth) + (float)0.5), (kkint32)512);
406  kkint32 graphHeight = maxColHeight + 20;
407 
408  RasterPtr graph = new Raster (graphHeight, graphWidth);
409 
410  graph->DrawLine ( 10, 10, 10, graphWidth - 10, borderColor); // TopLeft -> TopRight
411  graph->DrawLine ( 10, graphWidth - 10, graphHeight - 10, graphWidth - 10, borderColor); // TopRight -> BotRight
412  graph->DrawLine (graphHeight - 10, graphWidth - 10, graphHeight - 10, 10, borderColor); // BotRight -> BotLeft
413  graph->DrawLine (graphHeight - 10, 10, 10, 10, borderColor); // BotLeft -> TopLeft
414 
415  x = 0;
416  row = graphHeight - 10;
417 
418  // Draw Y Axis
419  while (x < maxColHeight)
420  {
421  if ((x % 10) == 0)
422  {
423  if ((x % 50) == 0)
424  {
425  graph->SetPixelValue (row, 4, hashColor2);
426  graph->SetPixelValue (row, 5, hashColor2);
427  graph->SetPixelValue (row, 6, hashColor2);
428 
429  if ((x % 100) == 0)
430  {
431  graph->DrawLine (row, 9, row, graphWidth - 11, gridColor);
432  }
433  }
434 
435  graph->SetPixelValue (row, 7, hashColor);
436  graph->SetPixelValue (row, 8, hashColor);
437  graph->SetPixelValue (row, 9, hashColor);
438  }
439 
440  graph->SetPixelValue (row, 9, colorAxis);
441  row--;
442  x++;
443  }
444 
445  col = 10;
446 
447  for (bucket = 0; bucket < numOfBuckets; bucket++)
448  {
449  for (x = 0; x < (barWidth + interBarWidth); x++)
450  {
451  graph->SetPixelValue (graphHeight - 9, col + x, colorAxis);
452  }
453 
454  if ((bucket % 10) == 0)
455  {
456  // Lets add a Hash Mark
457  graph->SetPixelValue (graphHeight - 8, col + 1, hashColor);
458  graph->SetPixelValue (graphHeight - 7, col + 1, hashColor);
459  graph->SetPixelValue (graphHeight - 6, col + 1, hashColor);
460  graph->SetPixelValue (graphHeight - 5, col + 1, hashColor);
461  }
462 
463  if (vertGridLines[bucket] == true)
464  {
465  graph->DrawLine (graphHeight - 10, col + 1, 10, col + 1, gridColor);
466  }
467 
468  colHeight = (kkint32)ceil ((((float)maxColHeight * buckets[bucket]) / maxCount));
469 
470  if ((colHeight < 1) && (buckets[bucket] > (float)0.0))
471  {
472  cout << "I want to know about this." << std::endl;
473  }
474 
475  row = graphHeight - 10;
476 
477  uchar barCodeToUse = colorBar;
478  if (buckets[bucket] >= maxCount)
479  barCodeToUse = colorBarMax;
480 
481  else if (peakBarLines[bucket])
482  barCodeToUse = colorBarPeak;
483 
484  for (kkint32 x = 0; x < colHeight; x++)
485  {
486  for (y = 0; y < barWidth; y++)
487  {
488  graph->SetPixelValue (row, col + y, barCodeToUse);
489  }
490 
491  row--;
492  }
493 
494  col += (barWidth + interBarWidth);
495  }
496 
497  delete[] peakBarLines;
498  delete[] vertGridLines;
499 
500  graph->ReverseImage ();
501 
502  return graph;
503 } /* CreateGraph */
504 
505 
506 
507 
508 
509 
510 void Histogram::SaveGraphImage (const KKStr& fileName) const
511 {
512  RasterPtr graphImage = CreateGraph ();
513  SaveImage (*graphImage, fileName);
514  delete graphImage;
515 } /* SaveGraphImage */
516 
517 
518 void Histogram::SaveGraphImage (const KKStr& fileName,
519  kkint32 barSize
520  ) const
521 {
522  RasterPtr graphImage = CreateGraph (barSize);
523  SaveImage (*graphImage, fileName);
524  delete graphImage;
525 }
526 
527 
528 
529 void Histogram::Save (KKStr fileName) const
530 {
531  ofstream o (fileName.Str ());
532 
533  kkint32 bucketIDX;
534 
535 
536  float avgVal = totalVal / totalCount;
537 
538  o << "MinValue" << "\t" << "\t" << "BucketSize" << "\t" << "NumOfBuckets" << "\t" << "TotalCount" << "\t" << "Average" << std::endl;
539  o << minValue << "\t" << "\t" << bucketSize << "\t" << numOfBuckets << "\t" << totalCount << "\t" << avgVal << std::endl;
540 
541  o << std::endl;
542  o << std::endl;
543 
544  float avg;
545  float percentage;
546  float bucketVal = minValue + bucketSize;
547 
548  o << "BucketValue" << "\t"
549  << "Count" << "\t"
550  << "AvgValue" << "\t"
551  << "%OfTotalCount"
552  << std::endl
553  << std::endl;
554 
555  for (bucketIDX = 0; bucketIDX < numOfBuckets; bucketIDX++)
556  {
557  o << bucketVal;
558 
559  o << "\t" << buckets[bucketIDX];
560 
561  if (buckets[bucketIDX] > (float)0.0)
562  avg = bucketTotals[bucketIDX] / buckets[bucketIDX];
563  else
564  avg = 0.0;
565  o << "\t" << avg;
566 
567 
568  percentage = (float)100.0 * buckets[bucketIDX] / totalCount;
569  o << "\t" << percentage << "%";
570 
571  bucketVal += bucketSize;
572  o << std::endl;
573  }
574 
575  o << std::endl;
576  o << std::endl;
577 
578  o.close ();
579 } /* Save */
580 
581 
582 
583 
584 
585 HistogramPtr Histogram::Smooth (kkint32 smoothWidth)
586 {
587  kkint32 bucket;
588  kkint32 endBuckOffset;
589  kkint32 startBuckOffset;
590  float sumOfbuckets = (float)0.0;
591  float sumOfBucketTotals = (float)0.0;
592 
593  HistogramPtr hist = new Histogram (minValue,
594  numOfBuckets,
595  bucketSize,
596  wrapArround
597  );
598 
599 
600  if (wrapArround)
601  {
602  startBuckOffset = numOfBuckets - (smoothWidth / 2);
603  endBuckOffset = startBuckOffset + smoothWidth - 1 - numOfBuckets;
604 
605 
606  // Lets Build Initial Totals
607 
608  bucket = startBuckOffset;
609 
610  while (true)
611  {
612  sumOfbuckets += buckets [bucket];
613  sumOfBucketTotals += bucketTotals [bucket];
614 
615  if (bucket == endBuckOffset)
616  break;
617 
618  bucket++;
619  if (bucket >= numOfBuckets)
620  bucket = bucket - numOfBuckets;
621  }
622 
623  for (bucket = 0; bucket < numOfBuckets; bucket++)
624  {
625  hist->buckets [bucket] = sumOfbuckets / (float)smoothWidth;
626  hist->bucketTotals [bucket] = sumOfBucketTotals / (float)smoothWidth;
627 
628  sumOfbuckets -= buckets [startBuckOffset];
629  sumOfBucketTotals -= bucketTotals [startBuckOffset];
630 
631  startBuckOffset++;
632  if (startBuckOffset >= numOfBuckets)
633  startBuckOffset = startBuckOffset - numOfBuckets;
634 
635  endBuckOffset++;
636  if (endBuckOffset >= numOfBuckets)
637  endBuckOffset = endBuckOffset - numOfBuckets;
638 
639  sumOfbuckets += buckets [endBuckOffset];
640  sumOfBucketTotals += bucketTotals [endBuckOffset];
641  }
642  } /* End of WrapArround Version */
643 
644  else
645  {
646  // No WrapArround.
647 
648  startBuckOffset = -(smoothWidth / 2);
649  endBuckOffset = startBuckOffset + smoothWidth - 1;
650 
651  kkint32 spreadSize = endBuckOffset + 1;
652 
653  // Lets Build Initial Totals
654  for (bucket = 0; bucket <= endBuckOffset; bucket++)
655  {
656  sumOfbuckets += buckets [bucket];
657  sumOfBucketTotals += bucketTotals [bucket];
658  }
659 
660 
661  for (bucket = 0; bucket < numOfBuckets; bucket++)
662  {
663  hist->buckets [bucket] = sumOfbuckets / (float)spreadSize;
664 
665  if (sumOfbuckets > (float)0.0)
666  {
667  hist->bucketTotals [bucket] = hist->buckets [bucket] * sumOfBucketTotals / sumOfbuckets;
668  }
669  else
670  {
671  hist->bucketTotals [bucket] = (float)0.0;
672  }
673 
674  if (startBuckOffset >= 0)
675  {
676  sumOfbuckets = sumOfbuckets - buckets [startBuckOffset];
677  sumOfBucketTotals = sumOfBucketTotals - bucketTotals [startBuckOffset];
678  spreadSize--;
679  }
680 
681  startBuckOffset++;
682 
683  endBuckOffset++;
684  if (endBuckOffset < numOfBuckets)
685  {
686  sumOfbuckets = sumOfbuckets + buckets [endBuckOffset];
687  sumOfBucketTotals = sumOfBucketTotals + bucketTotals [endBuckOffset];
688  spreadSize++;
689  }
690  }
691  }
692 
693  hist->totalCount = totalCount;
694  hist->totalVal = totalVal;
695 
696  return hist;
697 } /* Smooth */
698 
699 
700 
701 
702 
704  kkint32 tolerance
705  ) const
706 {
707  kkint32 beforeIDX = bucket;
708  kkint32 afterIDX = bucket;
709  kkint32 lastBeforeIDX = bucket;
710  kkint32 lastAfterIDX = bucket;
711 
712  if (buckets[bucket] == (float)0.0)
713  return false;
714 
715  for (kkint32 x = 1; x <= tolerance; x++)
716  {
717  beforeIDX--;
718  afterIDX++;
719 
720  if (beforeIDX < 0)
721  {
722  if (wrapArround)
723  beforeIDX = beforeIDX + numOfBuckets;
724  }
725 
726  if (afterIDX < 0)
727  {
728  if (wrapArround)
729  afterIDX = afterIDX - numOfBuckets;
730  }
731 
732  if (beforeIDX >= 0)
733  {
734  if (buckets [beforeIDX] > buckets[lastBeforeIDX])
735  return false;
736  }
737 
738  if (afterIDX < numOfBuckets)
739  {
740  if (buckets [afterIDX] > buckets[lastAfterIDX])
741  return false;
742  }
743 
744  lastBeforeIDX = beforeIDX;
745  lastAfterIDX = afterIDX;
746  }
747 
748  return true;
749 } /* IsBucketAPeak */
750 
751 
752 
753 
754 
755 
757 {
758  kkint32 bucket;
759 
760  peaks.erase (peaks.begin (), peaks.end ());
761 
762  for (bucket = 0; bucket < numOfBuckets; bucket++)
763  {
764  if (IsBucketAPeak (bucket, threshold))
765  peaks.push_back (bucket);
766  }
767 } /* CalculatePeaks */
768 
769 
770 
772 {
773  if (peaks.empty ())
774  CalculatePeaks (2);
775 
776  if (peakNum > (kkint32)peaks.size ())
777  return -1;
778 
779  else
780  return peaks[peakNum];
781 }
782 
783 
784 
786 {
787  if (peaks.empty ())
788  CalculatePeaks (2);
789 
790  if (peakNum > (kkint32)peaks.size ())
791  return -1;
792 
793  kkint32 t;
794  kkint32 x;
795  kkint32 y;
796 
797  VectorInt32 sortedPeaks (peaks);
798 
799  for (x = 1; x < (kkint32)sortedPeaks.size (); x++)
800  {
801  for (y = x; y > 0; y--)
802  {
803  if (buckets[sortedPeaks[y - 1]] < buckets[sortedPeaks[y]])
804  {
805  t = sortedPeaks[y];
806  sortedPeaks[y] = sortedPeaks[y - 1];
807  sortedPeaks[y - 1] = t;
808  }
809  }
810  }
811 
812  kkint32 returnIdxNum = sortedPeaks[peakNum];
813 
814  return returnIdxNum;
815 
816 } /* GetPeakByHighestOrder */
817 
818 
819 
821 {
822  kkint32 x = GetPeakByHighestOrder (peakNum);
823 
824  if (x < 0)
825  {
826  cout << std::endl;
827  cout << "GetPeakAvgByHighestOrder GetPeakByHighestOrder returned[" << x << "]" << std::endl;
828  return 0;
829  }
830 
831  if (x >= this->numOfBuckets)
832  {
833  cout << std::endl;
834  cout << "GetPeakAvgByHighestOrder GetPeakByHighestOrder returned[" << x << "]" << std::endl;
835  x = 1;
836  return 0;
837  }
838 
839  if (buckets[x] <= (float)0.0)
840  return 0.0;
841 
842  return (bucketTotals[x] / buckets[x]);
843 } /* GetPeakAvgByHighestOrder */
844 
845 
846 
847 
848 HistogramPtr Histogram::Equalized ()
849 {
850  float* histSumTable = new float[numOfBuckets];
851  kkint32 idx;
852 
853  HistogramPtr newHist = new Histogram (minValue, numOfBuckets, bucketSize, wrapArround);
854 
855  kkint32 x;
856 
857  newHist->equalizedMapTable = new kkint32[numOfBuckets];
858 
859  float accumulatedCount = (float)0.0;
860  for (x = 0; x < numOfBuckets; x++)
861  {
862  accumulatedCount += buckets[x];
863  histSumTable[x] = accumulatedCount;
864  }
865 
866 
867  for (x = 0; x < numOfBuckets; x++)
868  {
869  idx = (kkint32)((float)0.5 + (((float)(histSumTable[x] * (numOfBuckets - 1)) / totalCount)));
870  if (idx >= numOfBuckets)
871  idx = numOfBuckets - 1;
872 
873  newHist->equalizedMapTable[x] = idx;
874  newHist->buckets[idx] += buckets[x];
875  newHist->bucketTotals[idx] += bucketTotals[x];
876  }
877 
878 
879  newHist->totalCount = totalCount;
880  newHist->totalVal = totalVal;
881 
882 
883  delete[] histSumTable;
884 
885  return newHist;
886 } /* Equalize */
887 
888 
889 
890 
892  kkint32 maxBucket
893  ) const
894 {
895  if ((minBucket < 0) || (minBucket >= numOfBuckets) ||
896  (maxBucket < 0) || (maxBucket >= numOfBuckets) ||
897  (minBucket > maxBucket)
898  )
899  {
900  cerr << std::endl;
901  cerr << "Histogram::AverageOfMaxBucketInRange *** ERROR *** Invalid Parameters" << std::endl;
902  cerr << "NumOfBuckets[" << numOfBuckets << "] MinBucket[" << minBucket << "] MaxBucket[" << maxBucket << "]" << std::endl;
903  exit (-1);
904  }
905 
906 
907  kkint32 b;
908 
909  kkint32 maxBucketIDX = minBucket;
910  float maxBucketVal = buckets[minBucket];
911 
912  for (b = minBucket; b <= maxBucket; b++)
913  {
914  if (buckets[b] > maxBucketVal)
915  {
916  maxBucketIDX = b;
917  maxBucketVal = buckets[b];
918  }
919  }
920 
921  if (maxBucketVal > (float)0.0)
922  return bucketTotals[maxBucketIDX] / buckets[maxBucketIDX];
923  else
924  return (float)0.0;
925 } /* AverageOfMaxBucketInRange */
926 
927 
928 
929 
931  kkint32 lastBucket
932  ) const
933 {
934  if ((firstBucket < 0) || (firstBucket >= numOfBuckets) ||
935  (lastBucket < 0) || (lastBucket >= numOfBuckets) ||
936  (firstBucket > lastBucket)
937  )
938  {
939  cerr << std::endl;
940  cerr << "Histogram::AverageOfMaxBucketInRange *** ERROR *** Invalid Parameters" << std::endl;
941  cerr << "NumOfBuckets[" << numOfBuckets << "] FirstBucket[" << firstBucket << "] LastBucket[" << lastBucket << "]" << std::endl;
942  exit (-1);
943  }
944 
945  kkint32 b;
946 
947  kkint32 minBucketIDX = firstBucket;
948  float minBucketVal = buckets[firstBucket];
949 
950  for (b = firstBucket; b <= lastBucket; b++)
951  {
952  if (buckets[b] <= minBucketVal)
953  {
954  minBucketIDX = b;
955  minBucketVal = buckets[b];
956  }
957  }
958 
959  if (minBucketVal > 0)
960  return bucketTotals[minBucketIDX] / buckets[minBucketIDX];
961  else
962  return (float)0.0;
963 } /* AverageOfMaxBucketInRange */
964 
965 
966 
968  kkint32 maxBucket
969  ) const
970 {
971  if ((minBucket < 0) || (minBucket >= numOfBuckets) ||
972  (maxBucket < 0) || (maxBucket >= numOfBuckets) ||
973  (minBucket > maxBucket)
974  )
975  {
976  cerr << std::endl;
977  cerr << "Histogram::AverageOfMaxBucketExcludingRange *** ERROR *** Invalid Parameters" << std::endl;
978  cerr << "NumOfBuckets[" << numOfBuckets << "] MinBucket[" << minBucket << "] MaxBucket[" << maxBucket << "]" << std::endl;
979  exit (-1);
980  }
981 
982  kkint32 b;
983 
984  kkint32 maxBucketIDX = -1;
985  float maxBucketVal = 0;
986 
987  for (b = 0; b < numOfBuckets; b++)
988  {
989  if ((b < minBucket) || (b > maxBucket))
990  {
991  if (buckets[b] > maxBucketVal)
992  {
993  maxBucketIDX = b;
994  maxBucketVal = buckets[b];
995  }
996  }
997  }
998 
999  if (maxBucketIDX < 0)
1000  return 0;
1001 
1002  if (maxBucketVal > (float)0.0)
1003  return bucketTotals[maxBucketIDX] / buckets[maxBucketIDX];
1004  else
1005  return (float)0.0;
1006 } /* AverageOfMaxBucketExcludingRange */
1007 
1008 
1009 
1011  kkint32 maxBucket
1012  ) const
1013 {
1014  if ((minBucket < 0) || (minBucket >= numOfBuckets) ||
1015  (maxBucket < 0) || (maxBucket >= numOfBuckets) ||
1016  (minBucket > maxBucket)
1017  )
1018  {
1019  cerr << std::endl;
1020  cerr << "Histogram::AreaInRange *** ERROR *** Invalid Parameters" << std::endl;
1021  cerr << "NumOfBuckets[" << numOfBuckets << "] MinBucket[" << minBucket << "] MaxBucket[" << maxBucket << "]" << std::endl;
1022  exit (-1);
1023  }
1024 
1025  float area = (float)0.0;
1026  for (kkint32 b = minBucket; b <= maxBucket; b++)
1027  {
1028  area += buckets[b];
1029  }
1030 
1031  return (kkint32)(area + (float)0.5);
1032 } /* AreaInRange */
1033 
1034 
1035 
1037  kkint32 maxBucket
1038  ) const
1039 {
1040  if (totalCount <= (float)0.0)
1041  return (float)0.0;
1042 
1043  return (float)100.0 * (float)((float)AreaInRange (minBucket, maxBucket) / totalCount);
1044 }
1045 
1046 
1047 
1048 void Histogram::PrintTable (ostream& o)
1049 {
1050  kkint32 x;
1051  float l = minValue;
1052 
1053  o << l;
1054  for (x = 1; x < numOfBuckets; x++)
1055  {
1056  l += bucketSize;
1057  o << "\t" << l;
1058  }
1059  o << std::endl;
1060 
1061  o << buckets[0];
1062  for (x = 1; x < numOfBuckets; x++)
1063  {
1064  o << "\t" << buckets[x];
1065  }
1066  o << std::endl;
1067 } /* PrintTable */
1068 
1069 
1070 
1071 void Histogram::GetStats (float& min, // smallest amt in a bucket.
1072  float& max, // largest amt in a bucket.
1073  float& mean, // average number in each bucket.
1074  float& variance // variance.
1075  )
1076 {
1077  min = FLT_MAX;
1078  max = FLT_MIN;
1079  mean = totalCount / numOfBuckets;
1080  variance = 0.0f;
1081 
1082  float deltaSquareTotal = 0.0f;
1083  for (kkint32 idx = 0; idx < numOfBuckets; idx++)
1084  {
1085  if (buckets[idx] < min) min = buckets[idx];
1086  if (buckets[idx] > max) max = buckets[idx];
1087 
1088  float delta = buckets[idx] - mean;
1089  float deltaSquare = delta * delta;
1090  deltaSquareTotal += deltaSquare;
1091  }
1092  variance = deltaSquareTotal / (float)numOfBuckets;
1093 } /* GetStats */
void CalculatePeaks(kkint32 threshold)
Definition: Histogram.cpp:756
kkint32 MaxBucketIdx() const
Definition: Histogram.cpp:76
__int32 kkint32
Definition: KKBaseTypes.h:88
void Save(KKStr fileName) const
Definition: Histogram.cpp:529
void DrawLine(kkint32 bpRow, kkint32 bpCol, kkint32 epRow, kkint32 epCol, uchar pixelVal)
Definition: Raster.cpp:6253
void SetPixelValue(kkint32 row, kkint32 col, uchar pixVal)
Definition: Raster.cpp:1390
float AreaInRangePercent(kkint32 minBucket, kkint32 maxBucket) const
Definition: Histogram.cpp:1036
A class that is used by to represent a single image in memory.
Definition: Raster.h:108
float AverageOfMaxBucketExcludingRange(kkint32 minBucket, kkint32 maxBucket) const
Definition: Histogram.cpp:967
float AverageOfMinBucketInRange(kkint32 minBucket, kkint32 maxBucket) const
Definition: Histogram.cpp:930
RasterPtr CreateGraph() const
Definition: Histogram.cpp:162
void PrintTable(ostream &o)
Definition: Histogram.cpp:1048
Raster(kkint32 _height, kkint32 _width)
Constructs a blank image with given dimensions; all pixels will be initialized to 0...
Definition: Raster.cpp:318
RasterPtr CreateGraph(kkint32 barSize) const
Definition: Histogram.cpp:337
kkint32 GetPeakByHighestOrder(kkint32 peakNum)
Definition: Histogram.cpp:785
float AverageOfMaxBucketInRange(kkint32 firstBucket, kkint32 lastBucket) const
Definition: Histogram.cpp:891
KKTHread * KKTHreadPtr
void SaveImage(const Raster &image, const KKStr &imageFileName)
Definition: ImageIO.cpp:617
kkint32 GetPeakBucket(kkint32 peakNum)
Definition: Histogram.cpp:771
unsigned char uchar
Unsigned character.
Definition: KKBaseTypes.h:77
float GetPeakAvgByHighestOrder(kkint32 peakNum)
Definition: Histogram.cpp:820
Histogram * Smooth(kkint32 smoothWidth)
Definition: Histogram.cpp:585
static KKStr Concat(const std::vector< std::string > &values)
Concatenates the list of &#39;std::string&#39; strings.
Definition: KKStr.cpp:1082
std::vector< kkint32 > VectorInt32
Vector of signed 32 bit integers.
Definition: KKBaseTypes.h:144
Histogram(float _minValue, kkint32 _numOfBuckets, float _bucketSize, bool _wrapArround)
Definition: Histogram.cpp:24
bool IsBucketAPeak(kkint32 bucket, kkint32 tolerance) const
Definition: Histogram.cpp:703
float CountOfMaxBucket() const
Definition: Histogram.cpp:113
std::ostream &__cdecl operator<<(std::ostream &os, const KKStr &str)
void GetStats(float &min, float &max, float &mean, float &variance)
Definition: Histogram.cpp:1071
Histogram * Equalized()
Definition: Histogram.cpp:848
void SaveGraphImage(const KKStr &fileName) const
Definition: Histogram.cpp:510
void SaveGraphImage(const KKStr &fileName, kkint32 barSize) const
Definition: Histogram.cpp:518
float AverageOfMaxBucket() const
Definition: Histogram.cpp:98
void Increment(float val)
Definition: Histogram.cpp:137
void ReverseImage()
Definition: Raster.cpp:1198
float Bucket(kkint32 bucket) const
Definition: Histogram.cpp:122
Used to manage the construction of a Histogram.
Definition: Histogram.h:24
kkint32 AreaInRange(kkint32 minBucket, kkint32 maxBucket) const
Definition: Histogram.cpp:1010