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