Visual Servoing Platform  version 3.5.0 under development (2022-02-15)
vpHistogram.cpp
1 /****************************************************************************
2  *
3  * ViSP, open source Visual Servoing Platform software.
4  * Copyright (C) 2005 - 2019 by Inria. All rights reserved.
5  *
6  * This software 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 2 of the License, or
9  * (at your option) any later version.
10  * See the file LICENSE.txt at the root directory of this source
11  * distribution for additional information about the GNU GPL.
12  *
13  * For using ViSP with software that can not be combined with the GNU
14  * GPL, please contact Inria about acquiring a ViSP Professional
15  * Edition License.
16  *
17  * See http://visp.inria.fr for more information.
18  *
19  * This software was developed at:
20  * Inria Rennes - Bretagne Atlantique
21  * Campus Universitaire de Beaulieu
22  * 35042 Rennes Cedex
23  * France
24  *
25  * If you have questions regarding the use of this file, please contact
26  * Inria at visp@inria.fr
27  *
28  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
29  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
30  *
31  * Description:
32  * Gray level histogram manipulation.
33  *
34  * Author:
35  * Fabien Spindler
36  *
37  *****************************************************************************/
38 
48 #include <stdlib.h>
49 #include <visp3/core/vpDisplay.h>
50 #include <visp3/core/vpHistogram.h>
51 #include <visp3/core/vpImageConvert.h>
52 
53 #if defined(VISP_HAVE_PTHREAD) || (defined(_WIN32) && !defined(WINRT_8_0))
54 #include <visp3/core/vpThread.h>
55 
56 namespace
57 {
58 struct Histogram_Param_t {
59  unsigned int m_start_index;
60  unsigned int m_end_index;
61 
62  unsigned int m_lut[256];
63  unsigned int *m_histogram;
64  const vpImage<unsigned char> *m_I;
65 
66  Histogram_Param_t() : m_start_index(0), m_end_index(0), m_lut(), m_histogram(NULL), m_I(NULL) {}
67 
68  Histogram_Param_t(unsigned int start_index, unsigned int end_index, const vpImage<unsigned char> *const I)
69  : m_start_index(start_index), m_end_index(end_index), m_lut(), m_histogram(NULL), m_I(I)
70  {
71  }
72 
73  ~Histogram_Param_t()
74  {
75  if (m_histogram != NULL) {
76  delete[] m_histogram;
77  }
78  }
79 };
80 
81 vpThread::Return computeHistogramThread(vpThread::Args args)
82 {
83  Histogram_Param_t *histogram_param = static_cast<Histogram_Param_t *>(args);
84  unsigned int start_index = histogram_param->m_start_index;
85  unsigned int end_index = histogram_param->m_end_index;
86 
87  const vpImage<unsigned char> *I = histogram_param->m_I;
88 
89  unsigned char *ptrStart = (unsigned char *)(I->bitmap) + start_index;
90  unsigned char *ptrEnd = (unsigned char *)(I->bitmap) + end_index;
91  unsigned char *ptrCurrent = ptrStart;
92 
93  // while(ptrCurrent != ptrEnd) {
94  // histogram_param->m_histogram[ histogram_param->m_lut[ *ptrCurrent ]
95  // ] ++;
96  // ++ptrCurrent;
97  // }
98 
99  if (end_index - start_index >= 8) {
100  // Unroll loop version
101  for (; ptrCurrent <= ptrEnd - 8;) {
102  histogram_param->m_histogram[histogram_param->m_lut[*ptrCurrent]]++;
103  ++ptrCurrent;
104 
105  histogram_param->m_histogram[histogram_param->m_lut[*ptrCurrent]]++;
106  ++ptrCurrent;
107 
108  histogram_param->m_histogram[histogram_param->m_lut[*ptrCurrent]]++;
109  ++ptrCurrent;
110 
111  histogram_param->m_histogram[histogram_param->m_lut[*ptrCurrent]]++;
112  ++ptrCurrent;
113 
114  histogram_param->m_histogram[histogram_param->m_lut[*ptrCurrent]]++;
115  ++ptrCurrent;
116 
117  histogram_param->m_histogram[histogram_param->m_lut[*ptrCurrent]]++;
118  ++ptrCurrent;
119 
120  histogram_param->m_histogram[histogram_param->m_lut[*ptrCurrent]]++;
121  ++ptrCurrent;
122 
123  histogram_param->m_histogram[histogram_param->m_lut[*ptrCurrent]]++;
124  ++ptrCurrent;
125  }
126  }
127 
128  for (; ptrCurrent != ptrEnd; ++ptrCurrent) {
129  histogram_param->m_histogram[histogram_param->m_lut[*ptrCurrent]]++;
130  }
131 
132  return 0;
133 }
134 }
135 #endif
136 
137 bool compare_vpHistogramPeak(vpHistogramPeak first, vpHistogramPeak second);
138 
139 // comparison,
140 bool compare_vpHistogramPeak(vpHistogramPeak first, vpHistogramPeak second)
141 {
142  if (first.getValue() > second.getValue())
143  return true;
144  else
145  return false;
146 }
147 
151 vpHistogram::vpHistogram() : histogram(NULL), size(256) { init(); }
152 
156 vpHistogram::vpHistogram(const vpHistogram &h) : histogram(NULL), size(256)
157 {
158  init(h.size);
159  memcpy(histogram, h.histogram, size * sizeof(unsigned));
160 }
161 
169 vpHistogram::vpHistogram(const vpImage<unsigned char> &I) : histogram(NULL), size(256)
170 {
171  init();
172 
173  calculate(I);
174 }
175 
180 {
181  if (histogram != NULL) {
182  // vpTRACE("free: %p", &histogram);
183  delete[] histogram;
184  histogram = NULL;
185  size = 0;
186  }
187 }
188 
203 {
204  init(h.size);
205  memcpy(histogram, h.histogram, size * sizeof(unsigned));
206 
207  return *this;
208 }
209 
215 void vpHistogram::init(unsigned size_)
216 {
217  if (histogram != NULL) {
218  delete[] histogram;
219  histogram = NULL;
220  }
221 
222  this->size = size_;
223  histogram = new unsigned[size];
224 
225  memset(histogram, 0, size * sizeof(unsigned));
226 
227  // vpTRACE("alloc: %p", &histogram);
228 }
229 
238 void vpHistogram::calculate(const vpImage<unsigned char> &I, unsigned int nbins, unsigned int nbThreads)
239 {
240  if (size != nbins) {
241  if (histogram != NULL) {
242  delete[] histogram;
243  histogram = NULL;
244  }
245 
246  size = nbins > 256 ? 256 : (nbins > 0 ? nbins : 256);
247  if (nbins > 256 || nbins == 0) {
248  std::cerr << "nbins=" << nbins << " , nbins should be between ]0 ; 256] ; use by default nbins=256" << std::endl;
249  }
250  histogram = new unsigned int[size];
251  }
252 
253  memset(histogram, 0, size * sizeof(unsigned int));
254 
255  bool use_single_thread;
256 #if !defined(VISP_HAVE_PTHREAD) && !defined(_WIN32)
257  use_single_thread = true;
258 #else
259  use_single_thread = (nbThreads == 0 || nbThreads == 1);
260 #endif
261 
262  if (!use_single_thread && I.getSize() <= nbThreads) {
263  use_single_thread = true;
264  }
265 
266  unsigned int lut[256];
267  for (unsigned int i = 0; i < 256; i++) {
268  lut[i] = (unsigned int)(i * size / 256.0);
269  }
270 
271  if (use_single_thread) {
272  // Single thread
273 
274  unsigned int size_ = I.getWidth() * I.getHeight();
275  unsigned char *ptrStart = (unsigned char *)I.bitmap;
276  unsigned char *ptrEnd = ptrStart + size_;
277  unsigned char *ptrCurrent = ptrStart;
278 
279  while (ptrCurrent != ptrEnd) {
280  histogram[lut[*ptrCurrent]]++;
281  ++ptrCurrent;
282  }
283  } else {
284 #if defined(VISP_HAVE_PTHREAD) || (defined(_WIN32) && !defined(WINRT_8_0))
285  // Multi-threads
286 
287  std::vector<vpThread *> threadpool;
288  std::vector<Histogram_Param_t *> histogramParams;
289 
290  unsigned int image_size = I.getSize();
291  unsigned int step = image_size / nbThreads;
292  unsigned int last_step = image_size - step * (nbThreads - 1);
293 
294  for (unsigned int index = 0; index < nbThreads; index++) {
295  unsigned int start_index = index * step;
296  unsigned int end_index = (index + 1) * step;
297 
298  if (index == nbThreads - 1) {
299  end_index = start_index + last_step;
300  }
301 
302  Histogram_Param_t *histogram_param = new Histogram_Param_t(start_index, end_index, &I);
303  histogram_param->m_histogram = new unsigned int[size];
304  memset(histogram_param->m_histogram, 0, size * sizeof(unsigned int));
305  memcpy(histogram_param->m_lut, lut, 256 * sizeof(unsigned int));
306 
307  histogramParams.push_back(histogram_param);
308 
309  // Start the threads
310  vpThread *histogram_thread = new vpThread((vpThread::Fn)computeHistogramThread, (vpThread::Args)histogram_param);
311  threadpool.push_back(histogram_thread);
312  }
313 
314  for (size_t cpt = 0; cpt < threadpool.size(); cpt++) {
315  // Wait until thread ends up
316  threadpool[cpt]->join();
317  }
318 
319  for (unsigned int cpt1 = 0; cpt1 < size; cpt1++) {
320  unsigned int sum = 0;
321 
322  for (size_t cpt2 = 0; cpt2 < histogramParams.size(); cpt2++) {
323  sum += histogramParams[cpt2]->m_histogram[cpt1];
324  }
325 
326  histogram[cpt1] = sum;
327  }
328 
329  // Delete
330  for (size_t cpt = 0; cpt < threadpool.size(); cpt++) {
331  delete threadpool[cpt];
332  }
333 
334  for (size_t cpt = 0; cpt < histogramParams.size(); cpt++) {
335  delete histogramParams[cpt];
336  }
337 #endif
338  }
339 }
340 
352 void vpHistogram::display(const vpImage<unsigned char> &I, const vpColor &color, unsigned int thickness,
353  unsigned int maxValue_)
354 {
355  unsigned int width = I.getWidth(), height = I.getHeight();
356  // Minimal width and height are 36 px
357  if (width < 36 || height < 36) {
358  std::cerr << "Image I must have at least width >= 36 && height >= 36 !" << std::endl;
359  return;
360  }
361 
362  unsigned int maxValue = maxValue_;
363  if (maxValue == 0) {
364  for (unsigned int i = 0; i < size; i++) {
365  if (histogram[i] > maxValue) {
366  maxValue = histogram[i];
367  }
368  }
369  }
370 
371  if (maxValue == 0) {
372  throw(vpException(vpException::divideByZeroError, "Cannot display histogram; max value=0"));
373  }
374  // Keep 12 free pixels at the top
375  unsigned int max_height = height - 12;
376  double ratio_height = max_height / (double)maxValue;
377  double ratio_width = (width - 1) / (double)(size - 1.0);
378 
379  for (unsigned int i = 1; i < size; i++) {
380  unsigned int value1 = histogram[i - 1];
381  unsigned int value2 = histogram[i];
382 
383  vpImagePoint startPt((height - 1) - (value1 * ratio_height), (i - 1) * ratio_width);
384  vpImagePoint endPt((height - 1) - (value2 * ratio_height), (i * ratio_width));
385  vpDisplay::displayLine(I, startPt, endPt, color, thickness);
386  }
387 }
388 
409 void vpHistogram::smooth(unsigned int fsize)
410 {
411  if (histogram == NULL) {
412  vpERROR_TRACE("Histogram array not initialised\n");
413  throw(vpImageException(vpImageException::notInitializedError, "Histogram array not initialised"));
414  }
415 
416  vpHistogram h;
417  h = *this;
418 
419  int hsize = (int)fsize / 2; // half filter size
420 
421  for (unsigned i = 0; i < size; i++) {
422  unsigned int sum = 0;
423  unsigned int nb = 0;
424  for (int j = -hsize; j <= hsize; j++) {
425  // exploitation of the overflow to detect negative value...
426  if (/*(i + j) >= 0 &&*/ (i + (unsigned int)j) < size) {
427  sum += h.histogram[i + (unsigned int)j];
428  nb++;
429  }
430  }
431  histogram[i] = sum / nb;
432  }
433 }
434 
449 unsigned vpHistogram::getPeaks(std::list<vpHistogramPeak> &peaks)
450 {
451  if (histogram == NULL) {
452  vpERROR_TRACE("Histogram array not initialised\n");
453  throw(vpImageException(vpImageException::notInitializedError, "Histogram array not initialised"));
454  }
455 
456  int prev_slope; // Previous histogram inclination
457  vpHistogramPeak p; // An histogram peak
458  unsigned nbpeaks; // Number of peaks in the histogram (ie local maxima)
459 
460  peaks.clear();
461 
462  // Parse the histogram to get the local maxima
463  unsigned cpt = 0;
464  unsigned sum_level = 0;
465  nbpeaks = 0;
466  prev_slope = 1;
467 
468  for (unsigned i = 0; i < size - 1; i++) {
469  int next_slope = (int)histogram[i + 1] - (int)histogram[i]; // Next histogram inclination
470 
471  // if ((prev_slope < 0) && (next_slope > 0) ) {
472  // sum_level += i;
473  // cpt ++;
474  // continue;
475  // }
476 
477  if ((prev_slope > 0) && (next_slope == 0)) {
478  sum_level += i + 1;
479  cpt++;
480  continue;
481  }
482 
483  // Peak detection
484  if ((prev_slope > 0) && (next_slope < 0)) {
485  sum_level += i;
486  cpt++;
487 
488  unsigned int level = sum_level / cpt;
489  p.set((unsigned char)level, histogram[level]);
490  // vpTRACE("add %d %d", p.getLevel(), p.getValue());
491  peaks.push_back(p);
492 
493  nbpeaks++;
494  }
495 
496  prev_slope = next_slope;
497  sum_level = 0;
498  cpt = 0;
499  }
500  if (prev_slope > 0) {
501  p.set((unsigned char)size - 1u, histogram[size - 1]);
502  // vpTRACE("add %d %d", p.getLevel(), p.getValue());
503  peaks.push_back(p);
504  nbpeaks++;
505  }
506 
507  return nbpeaks;
508 }
509 
527 unsigned vpHistogram::getPeaks(unsigned char dist, vpHistogramPeak &peak1, vpHistogramPeak &peak2)
528 {
529  std::list<vpHistogramPeak> peaks;
530  unsigned nbpeaks; // Number of peaks in the histogram (ie local maxima)
531 
532  nbpeaks = getPeaks(peaks);
533  sort(peaks);
534 
535  if (nbpeaks == 0) {
536  peak1.set(0, 0);
537  peak2.set(0, 0);
538  return 0;
539  }
540 
541  if (nbpeaks == 1) {
542  peak1 = peaks.front();
543  peak2.set(0, 0);
544  return 1;
545  }
546 
547  // Parse the peaks list to get the peak with a distance greater
548  // than dist to the highest
549  peak1 = peaks.front();
550  for (std::list<vpHistogramPeak>::const_iterator it = peaks.begin(); it != peaks.end(); ++it) {
551  vpHistogramPeak p = *it;
552  if (abs(p.getLevel() - peak1.getLevel()) > dist) {
553  // The second peak is found
554  peak2 = p;
555  return 2;
556  }
557  }
558 
559  // No second peak found
560  peak2.set(0, 0);
561  return 1;
562 }
563 
579 bool vpHistogram::getPeaks(unsigned char dist, vpHistogramPeak &peakl, vpHistogramPeak &peakr, vpHistogramValey &valey)
580 {
581  unsigned char *peak; // Local maxima values
582  int prev_slope; // Previous histogram inclination
583  unsigned index_highest_peak; // Index in peak[] array of the highest peak
584  unsigned index_second_peak; // Index in peak[] array of the second peak
585 
586  unsigned int prof;
587  unsigned int maxprof; // Nb pixels difference between 2 maxi peaks
588  unsigned int nbmini; // Minimum numbers
589  unsigned int sumindmini; // Sum
590  unsigned int mini; // current minimum
591  unsigned int nbpeaks; // Number of peaks in the histogram (ie local maxima)
592 
593  // Init the valey
594  valey.set(0, 0);
595 
596  // Allocation for the
597  peak = new unsigned char[size];
598 
599  // Parse the histogram to get the local maxima
600  nbpeaks = 0;
601  prev_slope = 1;
602  for (unsigned i = 0; i < size - 1; i++) {
603  int next_slope = (int)histogram[i + 1] - (int)histogram[i]; // Next histogram inclination
604  if (next_slope == 0)
605  continue;
606  // Peak detection
607  if ((prev_slope > 0) && (next_slope < 0))
608  peak[nbpeaks++] = (unsigned char)i;
609 
610  prev_slope = next_slope;
611  }
612  if (prev_slope > 0)
613  peak[nbpeaks++] = (unsigned char)(size - 1);
614 
615  // vpTRACE("nb peaks: %d", nbpeaks);
616  // for (unsigned i=0; i < nbpeaks; i ++)
617  // vpTRACE("peak %d: pos %d value: %d", i, peak[i], histogram[ peak[i]
618  // ]);
619 
620  // Get the global maximum
621  index_highest_peak = 0;
622  for (unsigned int i = 0; i < nbpeaks; i++) {
623  if (histogram[peak[i]] > histogram[peak[index_highest_peak]]) {
624  index_highest_peak = i;
625  }
626  }
627 
628  // vpTRACE("highest peak index: %d pos: %d value: %d",
629  // index_highest_peak, peak[index_highest_peak],
630  // histogram[ peak[index_highest_peak] ]);
631 
632  maxprof = 0;
633  index_second_peak = index_highest_peak;
634 
635  // Search second local maximum on the left of the global maximum
636  for (unsigned i = 0; i < index_highest_peak; i++) {
637  if (peak[index_highest_peak] - peak[i] > dist) {
638  prof = 0;
639  for (int j = peak[i]; j <= peak[index_highest_peak] - dist; j++)
640  if ((histogram[peak[i]] - histogram[j]) > prof)
641  prof = histogram[peak[i]] - histogram[j];
642 
643  if (prof > maxprof) {
644  maxprof = prof;
645  index_second_peak = i;
646  }
647  }
648  }
649 
650  // Search second local maximum on the right of the global maximum
651  for (unsigned i = index_highest_peak + 1; i < nbpeaks; i++) {
652  if (peak[i] - peak[index_highest_peak] > dist) {
653  prof = 0;
654  for (int j = peak[index_highest_peak] + dist; j <= peak[i]; j++)
655  if ((histogram[peak[i]] - histogram[j]) > prof)
656  prof = histogram[peak[i]] - histogram[j];
657 
658  if (prof > maxprof) {
659  maxprof = prof;
660  index_second_peak = i;
661  }
662  }
663  }
664  // vpTRACE("second peak index: %d pos: %d value: %d",
665  // index_second_peak, peak[index_second_peak],
666  // histogram[ peak[index_second_peak] ]);
667 
668  // Determine position of the first and second highest peaks
669  if (peak[index_highest_peak] < peak[index_second_peak]) {
670  peakr.set(peak[index_second_peak], histogram[peak[index_second_peak]]);
671  peakl.set(peak[index_highest_peak], histogram[peak[index_highest_peak]]);
672  } else {
673  peakl.set(peak[index_second_peak], histogram[peak[index_second_peak]]);
674  peakr.set(peak[index_highest_peak], histogram[peak[index_highest_peak]]);
675  }
676 
677  if (peakl == peakr) {
678 
679  delete[] peak;
680 
681  return (false); // Not a bimodal histogram
682  }
683 
684  // Search the valey
685  mini = peakl.getValue();
686  sumindmini = 0;
687  nbmini = 0;
688  for (unsigned i = peakl.getLevel(); i <= peakr.getLevel(); i++) {
689  if (histogram[i] < mini) {
690  mini = histogram[i];
691  nbmini = 1;
692  sumindmini = i;
693  continue;
694  }
695  if (histogram[i] == mini) {
696  sumindmini += i;
697  nbmini++;
698  }
699  }
700  // vpTRACE("nbmini %d", nbmini);
701  // vpTRACE("sumindmini %d", sumindmini);
702  // vpTRACE("mini: indmini: %d", sumindmini/nbmini);
703 
704  if (nbmini == 0) {
705  // no valey found
706  valey.set(0, 0);
707 
708  delete[] peak;
709 
710  return false;
711  } else {
712  mini = sumindmini / nbmini; // mean
713  valey.set((unsigned char)mini, histogram[mini]);
714 
715  delete[] peak;
716 
717  return (true);
718  }
719 }
720 
732 unsigned vpHistogram::getValey(std::list<vpHistogramValey> &valey)
733 {
734  if (histogram == NULL) {
735  vpERROR_TRACE("Histogram array not initialised\n");
736  throw(vpImageException(vpImageException::notInitializedError, "Histogram array not initialised"));
737  }
738 
739  int prev_slope; // Previous histogram inclination
740  vpHistogramValey p; // An histogram valey
741  unsigned nbvaley; // Number of valey in the histogram (ie local minima)
742 
743  valey.clear();
744 
745  // Parse the histogram to get the local minima
746  unsigned cpt = 0;
747  unsigned sum_level = 0;
748  nbvaley = 0;
749  prev_slope = -1;
750 
751  for (unsigned i = 0; i < size - 1; i++) {
752  int next_slope = (int)histogram[i + 1] - (int)histogram[i]; // Next histogram inclination
753 
754  if ((prev_slope < 0) && (next_slope == 0)) {
755  sum_level += i + 1;
756  cpt++;
757  continue;
758  }
759 
760  // Valey detection
761  if ((prev_slope < 0) && (next_slope > 0)) {
762  sum_level += i;
763  cpt++;
764 
765  unsigned int level = sum_level / cpt;
766  p.set((unsigned char)level, histogram[level]);
767  // vpTRACE("add %d %d", p.getLevel(), p.getValue());
768  valey.push_back(p);
769 
770  nbvaley++;
771  }
772 
773  prev_slope = next_slope;
774  sum_level = 0;
775  cpt = 0;
776  }
777  if (prev_slope < 0) {
778  p.set((unsigned char)size - 1u, histogram[size - 1]);
779  // vpTRACE("add %d %d", p.getLevel(), p.getValue());
780  valey.push_back(p);
781  nbvaley++;
782  }
783 
784  return nbvaley;
785 }
786 
802 {
803 
804  // Set the left and right peaks
805  vpHistogramPeak peakl, peakr;
806  if (peak1.getLevel() > peak2.getLevel()) {
807  peakl = peak2;
808  peakr = peak1;
809  } else {
810  peakl = peak1;
811  peakr = peak2;
812  }
813 
814  // Search the valey
815  unsigned int nbmini; // Minimum numbers
816  unsigned int sumindmini; // Sum
817  unsigned int mini; // current minimum
818 
819  mini = peakl.getValue();
820  sumindmini = 0;
821  nbmini = 0;
822  for (unsigned i = peakl.getLevel(); i <= peakr.getLevel(); i++) {
823  if (histogram[i] < mini) {
824  mini = histogram[i];
825  nbmini = 1;
826  sumindmini = i;
827  continue;
828  }
829  if (histogram[i] == mini) {
830  sumindmini += i;
831  nbmini++;
832  }
833  }
834 
835  if (nbmini == 0) {
836  // no valey found
837  valey.set(0, 0);
838 
839  return false;
840  } else {
841  unsigned int minipos = sumindmini / nbmini; // position of the minimum
842 
843  valey.set((unsigned char)minipos, histogram[minipos]);
844  return true;
845  }
846 }
865 unsigned vpHistogram::getValey(unsigned char dist, const vpHistogramPeak &peak, vpHistogramValey &valeyl,
866  vpHistogramValey &valeyr)
867 {
868  unsigned int ret = 0x11;
869  unsigned int nbmini; // Minimum numbers
870  unsigned int sumindmini; // Sum
871  unsigned int mini; // current minimum
872  vpHistogramPeak peakr, peakl; // Left and right peaks of peak
873  std::list<vpHistogramPeak> peaks; // list of histogram peaks
874  // unsigned int nbpeaks=0; // Number of peaks in the histogram (ie local
875  // maxima)
876 
877  if (peak.getLevel() == 0) {
878  valeyl.set(0, 0);
879  ret &= 0x01;
880  }
881  if (peak.getLevel() == size - 1) {
882  valeyr.set((unsigned char)(size - 1), 0);
883  ret &= 0x10;
884  }
885 
886  if (ret >> 1) // consider the left part of the requested peak
887  {
888  // If the list of peaks is empty, compute it
889  if (peaks.empty()) {
890  /* nbpeaks = */ getPeaks(peaks);
891  }
892 
893  // if (1) {
894  // // vpTRACE("nb peaks: %d", nbpeaks);
895  // peaks.front();
896  // for (unsigned i=0; i < nbpeaks; i ++) {
897  // vpHistogramPeak p = peaks.value();
898  // // vpTRACE("peak index %d: pos %d value: %d",
899  // // i, p.getLevel(), p.getValue());
900  // peaks.next();
901  // }
902  // }
903  // Go to the requested peak in the list
904  std::list<vpHistogramPeak>::const_iterator it;
905  unsigned index = 0;
906  for (it = peaks.begin(); it != peaks.end(); ++it) {
907  if (peak == *it) {
908  // we are on the peak.
909  break;
910  }
911  index++;
912  }
913 
914  bool found = false;
915  if (index == 0) {
916  // No chance to get a peak on the left
917  // should not occur !
918  peakl.set(0, 0);
919  } else {
920  // search for the nearest peak on the left that matches the distance
921  std::list<vpHistogramPeak>::const_iterator lit; // left iterator
922  for (lit = peaks.begin(); lit != it; ++lit) {
923  if (abs((*lit).getLevel() - peak.getLevel()) > dist) {
924  // peakl found
925  peakl = *lit;
926  found = true; // we cannot stop here, since the other peaks on the
927  // right may exist
928  }
929  }
930  }
931  if (!found)
932  peakl.set(0, 0);
933 
934  // Search the valey on the left
935  mini = peak.getValue();
936  sumindmini = 0;
937  nbmini = 0;
938  for (unsigned i = peakl.getLevel(); i < peak.getLevel(); i++) {
939  if (histogram[i] < mini) {
940  mini = histogram[i];
941  nbmini = 1;
942  sumindmini = i;
943  continue;
944  }
945  if (histogram[i] == mini) {
946  sumindmini += i;
947  nbmini++;
948  }
949  }
950  if (nbmini == 0) {
951  valeyl.set(0, 0);
952  ret &= 0x01;
953  } else {
954  unsigned int minipos = sumindmini / nbmini; // position of the minimum
955  valeyl.set((unsigned char)minipos, histogram[minipos]);
956  ret &= 0x11;
957  }
958  }
959 
960  if (ret << 1) {
961  // If the list of peaks is empty, compute it
962  if (peaks.empty()) {
963  /* nbpeaks = */ getPeaks(peaks);
964  }
965  // Go to the requested peak in the list
966  std::list<vpHistogramPeak>::const_iterator it;
967  unsigned index = 0;
968  for (it = peaks.begin(); it != peaks.end(); ++it) {
969  if (peak == *it) {
970  // we are on the peak.
971  break;
972  }
973  index++;
974  }
975 
976  bool found = false;
977  // search for the nearest peak on the right that matches the distance
978  std::list<vpHistogramPeak>::const_iterator rit; // right iterator
979  for (rit = it; rit != peaks.end(); ++rit)
980 
981  if (abs((*rit).getLevel() - peak.getLevel()) > dist) {
982  // peakr found
983  peakr = *rit;
984  found = true;
985  break; // we can stop here
986  }
987 
988  if (!found)
989  peakr.set((unsigned char)(size - 1), 0);
990 
991  // Search the valey on the right
992  mini = peak.getValue();
993  sumindmini = 0;
994  nbmini = 0;
995  for (unsigned i = (unsigned int)peak.getLevel() + 1; i <= (unsigned int)peakr.getLevel(); i++) {
996  if (histogram[i] < mini) {
997  mini = histogram[i];
998  nbmini = 1;
999  sumindmini = i;
1000  continue;
1001  }
1002  if (histogram[i] == mini) {
1003  sumindmini += i;
1004  nbmini++;
1005  }
1006  }
1007  if (nbmini == 0) {
1008  valeyr.set((unsigned char)(size - 1), 0);
1009  ret &= 0x10;
1010  } else {
1011  unsigned int minipos = sumindmini / nbmini; // position of the minimum
1012  valeyr.set((unsigned char)minipos, histogram[minipos]);
1013  ret &= 0x11;
1014  }
1015  }
1016 
1017  return ret;
1018 }
1019 
1028 unsigned vpHistogram::sort(std::list<vpHistogramPeak> &peaks)
1029 {
1030 
1031  if (peaks.empty()) {
1032  return 0;
1033  }
1034 
1035  peaks.sort(compare_vpHistogramPeak);
1036 
1037  return (unsigned int)peaks.size();
1038 }
1039 
1052 bool vpHistogram::write(const std::string &filename) { return (this->write(filename.c_str())); }
1053 
1066 bool vpHistogram::write(const char *filename)
1067 {
1068  FILE *fd = fopen(filename, "w");
1069  if (fd == NULL)
1070  return false;
1071  for (unsigned i = 0; i < size; i++)
1072  fprintf(fd, "%u %u\n", i, histogram[i]);
1073  fclose(fd);
1074 
1075  return true;
1076 }
unsigned getPeaks(std::list< vpHistogramPeak > &peaks)
virtual ~vpHistogram()
void smooth(unsigned int fsize=3)
void * Return
Definition: vpThread.h:78
Type * bitmap
points toward the bitmap
Definition: vpImage.h:143
#define vpERROR_TRACE
Definition: vpDebug.h:393
vpHistogram & operator=(const vpHistogram &h)
Class to define RGB colors available for display functionnalities.
Definition: vpColor.h:157
error that can be emited by ViSP classes.
Definition: vpException.h:71
Class to compute a gray level image histogram.
Definition: vpHistogram.h:112
Error that can be emited by the vpImage class and its derivates.
Declaration of the peak (maximum value) in a gray level image histogram.
unsigned char getLevel() const
void display(const vpImage< unsigned char > &I, const vpColor &color=vpColor::white, unsigned int thickness=2, unsigned int maxValue_=0)
void set(unsigned char lvl, unsigned val)
void *(* Fn)(Args)
Definition: vpThread.h:79
void * Args
Definition: vpThread.h:77
void set(unsigned char lvl, unsigned val)
void calculate(const vpImage< unsigned char > &I, unsigned int nbins=256, unsigned int nbThreads=1)
unsigned sort(std::list< vpHistogramPeak > &peaks)
unsigned int getHeight() const
Definition: vpImage.h:188
unsigned int getSize() const
Definition: vpImage.h:227
unsigned getValue() const
bool write(const std::string &filename)
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Definition: vpImagePoint.h:87
unsigned int getWidth() const
Definition: vpImage.h:246
static void displayLine(const vpImage< unsigned char > &I, const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int thickness=1, bool segment=true)
Declaration of the valey (minimum value) in a gray level image histogram.
unsigned getValey(std::list< vpHistogramValey > &valey)