Visual Servoing Platform version 3.5.0
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
56namespace
57{
58struct 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
81vpThread::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
137bool compare_vpHistogramPeak(vpHistogramPeak first, vpHistogramPeak second);
138
139// comparison,
140bool compare_vpHistogramPeak(vpHistogramPeak first, vpHistogramPeak second)
141{
142 if (first.getValue() > second.getValue())
143 return true;
144 else
145 return false;
146}
147
151vpHistogram::vpHistogram() : histogram(NULL), size(256) { init(); }
152
156vpHistogram::vpHistogram(const vpHistogram &h) : histogram(NULL), size(256)
157{
158 init(h.size);
159 memcpy(histogram, h.histogram, size * sizeof(unsigned));
160}
161
169vpHistogram::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
215void 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
238void 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
352void 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
409void 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
449unsigned 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
527unsigned 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
579bool 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
732unsigned 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}
865unsigned 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
1028unsigned 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
1052bool vpHistogram::write(const std::string &filename) { return (this->write(filename.c_str())); }
1053
1066bool 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}
Class to define RGB colors available for display functionnalities.
Definition: vpColor.h:158
static void displayLine(const vpImage< unsigned char > &I, const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int thickness=1, bool segment=true)
error that can be emited by ViSP classes.
Definition: vpException.h:72
@ divideByZeroError
Division by zero.
Definition: vpException.h:94
Declaration of the peak (maximum value) in a gray level image histogram.
void set(unsigned char lvl, unsigned val)
unsigned getValue() const
unsigned char getLevel() const
Declaration of the valey (minimum value) in a gray level image histogram.
void set(unsigned char lvl, unsigned val)
Class to compute a gray level image histogram.
Definition: vpHistogram.h:113
unsigned getPeaks(std::list< vpHistogramPeak > &peaks)
void smooth(unsigned int fsize=3)
void calculate(const vpImage< unsigned char > &I, unsigned int nbins=256, unsigned int nbThreads=1)
vpHistogram & operator=(const vpHistogram &h)
unsigned sort(std::list< vpHistogramPeak > &peaks)
virtual ~vpHistogram()
unsigned getValey(std::list< vpHistogramValey > &valey)
bool write(const std::string &filename)
void display(const vpImage< unsigned char > &I, const vpColor &color=vpColor::white, unsigned int thickness=2, unsigned int maxValue_=0)
Error that can be emited by the vpImage class and its derivates.
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Definition: vpImagePoint.h:88
unsigned int getWidth() const
Definition: vpImage.h:246
unsigned int getSize() const
Definition: vpImage.h:227
Type * bitmap
points toward the bitmap
Definition: vpImage.h:143
unsigned int getHeight() const
Definition: vpImage.h:188
void * Return
Definition: vpThread.h:78
void *(* Fn)(Args)
Definition: vpThread.h:79
void * Args
Definition: vpThread.h:77
#define vpERROR_TRACE
Definition: vpDebug.h:393