Visual Servoing Platform version 3.6.0
Loading...
Searching...
No Matches
vpHistogram.cpp
1/****************************************************************************
2 *
3 * ViSP, open source Visual Servoing Platform software.
4 * Copyright (C) 2005 - 2023 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 https://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*****************************************************************************/
35
45#include <stdlib.h>
46#include <visp3/core/vpDisplay.h>
47#include <visp3/core/vpHistogram.h>
48#include <visp3/core/vpImageConvert.h>
49
50#if defined(VISP_HAVE_PTHREAD) || (defined(_WIN32) && !defined(WINRT_8_0))
51#include <visp3/core/vpThread.h>
52
53namespace
54{
55struct vpHistogram_Param_t
56{
57 unsigned int m_start_index;
58 unsigned int m_end_index;
59
60 unsigned int m_lut[256];
61 unsigned int *m_histogram;
62 const vpImage<unsigned char> *m_I;
63
64 vpHistogram_Param_t() : m_start_index(0), m_end_index(0), m_lut(), m_histogram(NULL), m_I(NULL) { }
65
66 vpHistogram_Param_t(unsigned int start_index, unsigned int end_index, const vpImage<unsigned char> *const I)
67 : m_start_index(start_index), m_end_index(end_index), m_lut(), m_histogram(NULL), m_I(I)
68 { }
69
70 ~vpHistogram_Param_t()
71 {
72 if (m_histogram != NULL) {
73 delete[] m_histogram;
74 }
75 }
76};
77
78vpThread::Return computeHistogramThread(vpThread::Args args)
79{
80 vpHistogram_Param_t *histogram_param = static_cast<vpHistogram_Param_t *>(args);
81 unsigned int start_index = histogram_param->m_start_index;
82 unsigned int end_index = histogram_param->m_end_index;
83
84 const vpImage<unsigned char> *I = histogram_param->m_I;
85
86 unsigned char *ptrStart = (unsigned char *)(I->bitmap) + start_index;
87 unsigned char *ptrEnd = (unsigned char *)(I->bitmap) + end_index;
88 unsigned char *ptrCurrent = ptrStart;
89
90 if (end_index - start_index >= 8) {
91 // Unroll loop version
92 for (; ptrCurrent <= ptrEnd - 8;) {
93 histogram_param->m_histogram[histogram_param->m_lut[*ptrCurrent]]++;
94 ++ptrCurrent;
95
96 histogram_param->m_histogram[histogram_param->m_lut[*ptrCurrent]]++;
97 ++ptrCurrent;
98
99 histogram_param->m_histogram[histogram_param->m_lut[*ptrCurrent]]++;
100 ++ptrCurrent;
101
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 }
118
119 for (; ptrCurrent != ptrEnd; ++ptrCurrent) {
120 histogram_param->m_histogram[histogram_param->m_lut[*ptrCurrent]]++;
121 }
122
123 return 0;
124}
125} // namespace
126#endif
127
128bool compare_vpHistogramPeak(vpHistogramPeak first, vpHistogramPeak second);
129
130// comparison,
131bool compare_vpHistogramPeak(vpHistogramPeak first, vpHistogramPeak second)
132{
133 if (first.getValue() > second.getValue())
134 return true;
135 else
136 return false;
137}
138
142vpHistogram::vpHistogram() : histogram(NULL), size(256) { init(); }
143
147vpHistogram::vpHistogram(const vpHistogram &h) : histogram(NULL), size(256)
148{
149 init(h.size);
150 memcpy(histogram, h.histogram, size * sizeof(unsigned));
151}
152
160vpHistogram::vpHistogram(const vpImage<unsigned char> &I) : histogram(NULL), size(256)
161{
162 init();
163
164 calculate(I);
165}
166
171{
172 if (histogram != NULL) {
173 // vpTRACE("free: %p", &histogram);
174 delete[] histogram;
175 histogram = NULL;
176 size = 0;
177 }
178}
179
194{
195 init(h.size);
196 memcpy(histogram, h.histogram, size * sizeof(unsigned));
197
198 return *this;
199}
200
206void vpHistogram::init(unsigned size_)
207{
208 if (histogram != NULL) {
209 delete[] histogram;
210 histogram = NULL;
211 }
212
213 this->size = size_;
214 histogram = new unsigned[size];
215
216 memset(histogram, 0, size * sizeof(unsigned));
217
218 // vpTRACE("alloc: %p", &histogram);
219}
220
229void vpHistogram::calculate(const vpImage<unsigned char> &I, unsigned int nbins, unsigned int nbThreads)
230{
231 if (size != nbins) {
232 if (histogram != NULL) {
233 delete[] histogram;
234 histogram = NULL;
235 }
236
237 size = nbins > 256 ? 256 : (nbins > 0 ? nbins : 256);
238 if (nbins > 256 || nbins == 0) {
239 std::cerr << "nbins=" << nbins << " , nbins should be between ]0 ; 256] ; use by default nbins=256" << std::endl;
240 }
241 histogram = new unsigned int[size];
242 }
243
244 memset(histogram, 0, size * sizeof(unsigned int));
245
246 bool use_single_thread;
247#if !defined(VISP_HAVE_PTHREAD) && !defined(_WIN32)
248 use_single_thread = true;
249#else
250 use_single_thread = (nbThreads == 0 || nbThreads == 1);
251#endif
252
253 if (!use_single_thread && I.getSize() <= nbThreads) {
254 use_single_thread = true;
255 }
256
257 unsigned int lut[256];
258 for (unsigned int i = 0; i < 256; i++) {
259 lut[i] = (unsigned int)(i * size / 256.0);
260 }
261
262 if (use_single_thread) {
263 // Single thread
264
265 unsigned int size_ = I.getWidth() * I.getHeight();
266 unsigned char *ptrStart = (unsigned char *)I.bitmap;
267 unsigned char *ptrEnd = ptrStart + size_;
268 unsigned char *ptrCurrent = ptrStart;
269
270 while (ptrCurrent != ptrEnd) {
271 histogram[lut[*ptrCurrent]]++;
272 ++ptrCurrent;
273 }
274 }
275 else {
276#if defined(VISP_HAVE_PTHREAD) || (defined(_WIN32) && !defined(WINRT_8_0))
277 // Multi-threads
278
279 std::vector<vpThread *> threadpool;
280 std::vector<vpHistogram_Param_t *> histogramParams;
281
282 unsigned int image_size = I.getSize();
283 unsigned int step = image_size / nbThreads;
284 unsigned int last_step = image_size - step * (nbThreads - 1);
285
286 for (unsigned int index = 0; index < nbThreads; index++) {
287 unsigned int start_index = index * step;
288 unsigned int end_index = (index + 1) * step;
289
290 if (index == nbThreads - 1) {
291 end_index = start_index + last_step;
292 }
293
294 vpHistogram_Param_t *histogram_param = new vpHistogram_Param_t(start_index, end_index, &I);
295 histogram_param->m_histogram = new unsigned int[size];
296 memset(histogram_param->m_histogram, 0, size * sizeof(unsigned int));
297 memcpy(histogram_param->m_lut, lut, 256 * sizeof(unsigned int));
298
299 histogramParams.push_back(histogram_param);
300
301 // Start the threads
302 vpThread *histogram_thread = new vpThread((vpThread::Fn)computeHistogramThread, (vpThread::Args)histogram_param);
303 threadpool.push_back(histogram_thread);
304 }
305
306 for (size_t cpt = 0; cpt < threadpool.size(); cpt++) {
307 // Wait until thread ends up
308 threadpool[cpt]->join();
309 }
310
311 for (unsigned int cpt1 = 0; cpt1 < size; cpt1++) {
312 unsigned int sum = 0;
313
314 for (size_t cpt2 = 0; cpt2 < histogramParams.size(); cpt2++) {
315 sum += histogramParams[cpt2]->m_histogram[cpt1];
316 }
317
318 histogram[cpt1] = sum;
319 }
320
321 // Delete
322 for (size_t cpt = 0; cpt < threadpool.size(); cpt++) {
323 delete threadpool[cpt];
324 }
325
326 for (size_t cpt = 0; cpt < histogramParams.size(); cpt++) {
327 delete histogramParams[cpt];
328 }
329#endif
330 }
331}
332
344void vpHistogram::display(const vpImage<unsigned char> &I, const vpColor &color, unsigned int thickness,
345 unsigned int maxValue_)
346{
347 unsigned int width = I.getWidth(), height = I.getHeight();
348 // Minimal width and height are 36 px
349 if (width < 36 || height < 36) {
350 std::cerr << "Image I must have at least width >= 36 && height >= 36 !" << std::endl;
351 return;
352 }
353
354 unsigned int maxValue = maxValue_;
355 if (maxValue == 0) {
356 for (unsigned int i = 0; i < size; i++) {
357 if (histogram[i] > maxValue) {
358 maxValue = histogram[i];
359 }
360 }
361 }
362
363 if (maxValue == 0) {
364 throw(vpException(vpException::divideByZeroError, "Cannot display histogram; max value=0"));
365 }
366 // Keep 12 free pixels at the top
367 unsigned int max_height = height - 12;
368 double ratio_height = max_height / (double)maxValue;
369 double ratio_width = (width - 1) / (double)(size - 1.0);
370
371 for (unsigned int i = 1; i < size; i++) {
372 unsigned int value1 = histogram[i - 1];
373 unsigned int value2 = histogram[i];
374
375 vpImagePoint startPt((height - 1) - (value1 * ratio_height), (i - 1) * ratio_width);
376 vpImagePoint endPt((height - 1) - (value2 * ratio_height), (i * ratio_width));
377 vpDisplay::displayLine(I, startPt, endPt, color, thickness);
378 }
379}
380
399void vpHistogram::smooth(unsigned int fsize)
400{
401 if (histogram == NULL) {
402 vpERROR_TRACE("Histogram array not initialised\n");
403 throw(vpImageException(vpImageException::notInitializedError, "Histogram array not initialised"));
404 }
405
406 vpHistogram h;
407 h = *this;
408
409 int hsize = (int)fsize / 2; // half filter size
410
411 for (unsigned i = 0; i < size; i++) {
412 unsigned int sum = 0;
413 unsigned int nb = 0;
414 for (int j = -hsize; j <= hsize; j++) {
415 // exploitation of the overflow to detect negative value...
416 if (/*(i + j) >= 0 &&*/ (i + (unsigned int)j) < size) {
417 sum += h.histogram[i + (unsigned int)j];
418 nb++;
419 }
420 }
421 histogram[i] = sum / nb;
422 }
423}
424
439unsigned vpHistogram::getPeaks(std::list<vpHistogramPeak> &peaks)
440{
441 if (histogram == NULL) {
442 vpERROR_TRACE("Histogram array not initialised\n");
443 throw(vpImageException(vpImageException::notInitializedError, "Histogram array not initialised"));
444 }
445
446 int prev_slope; // Previous histogram inclination
447 vpHistogramPeak p; // An histogram peak
448 unsigned nbpeaks; // Number of peaks in the histogram (ie local maxima)
449
450 peaks.clear();
451
452 // Parse the histogram to get the local maxima
453 unsigned cpt = 0;
454 unsigned sum_level = 0;
455 nbpeaks = 0;
456 prev_slope = 1;
457
458 for (unsigned i = 0; i < size - 1; i++) {
459 int next_slope = (int)histogram[i + 1] - (int)histogram[i]; // Next histogram inclination
460
461 // if ((prev_slope < 0) && (next_slope > 0) ) {
462 // sum_level += i;
463 // cpt ++;
464 // continue;
465 // }
466
467 if ((prev_slope > 0) && (next_slope == 0)) {
468 sum_level += i + 1;
469 cpt++;
470 continue;
471 }
472
473 // Peak detection
474 if ((prev_slope > 0) && (next_slope < 0)) {
475 sum_level += i;
476 cpt++;
477
478 unsigned int level = sum_level / cpt;
479 p.set((unsigned char)level, histogram[level]);
480 // vpTRACE("add %d %d", p.getLevel(), p.getValue());
481 peaks.push_back(p);
482
483 nbpeaks++;
484 }
485
486 prev_slope = next_slope;
487 sum_level = 0;
488 cpt = 0;
489 }
490 if (prev_slope > 0) {
491 p.set((unsigned char)size - 1u, histogram[size - 1]);
492 // vpTRACE("add %d %d", p.getLevel(), p.getValue());
493 peaks.push_back(p);
494 nbpeaks++;
495 }
496
497 return nbpeaks;
498}
499
517unsigned vpHistogram::getPeaks(unsigned char dist, vpHistogramPeak &peak1, vpHistogramPeak &peak2)
518{
519 std::list<vpHistogramPeak> peaks;
520 unsigned nbpeaks; // Number of peaks in the histogram (ie local maxima)
521
522 nbpeaks = getPeaks(peaks);
523 sort(peaks);
524
525 if (nbpeaks == 0) {
526 peak1.set(0, 0);
527 peak2.set(0, 0);
528 return 0;
529 }
530
531 if (nbpeaks == 1) {
532 peak1 = peaks.front();
533 peak2.set(0, 0);
534 return 1;
535 }
536
537 // Parse the peaks list to get the peak with a distance greater
538 // than dist to the highest
539 peak1 = peaks.front();
540 for (std::list<vpHistogramPeak>::const_iterator it = peaks.begin(); it != peaks.end(); ++it) {
541 vpHistogramPeak p = *it;
542 if (abs(p.getLevel() - peak1.getLevel()) > dist) {
543 // The second peak is found
544 peak2 = p;
545 return 2;
546 }
547 }
548
549 // No second peak found
550 peak2.set(0, 0);
551 return 1;
552}
553
569bool vpHistogram::getPeaks(unsigned char dist, vpHistogramPeak &peakl, vpHistogramPeak &peakr, vpHistogramValey &valey)
570{
571 unsigned char *peak; // Local maxima values
572 int prev_slope; // Previous histogram inclination
573 unsigned index_highest_peak; // Index in peak[] array of the highest peak
574 unsigned index_second_peak; // Index in peak[] array of the second peak
575
576 unsigned int prof;
577 unsigned int maxprof; // Nb pixels difference between 2 maxi peaks
578 unsigned int nbmini; // Minimum numbers
579 unsigned int sumindmini; // Sum
580 unsigned int mini; // current minimum
581 unsigned int nbpeaks; // Number of peaks in the histogram (ie local maxima)
582
583 // Init the valey
584 valey.set(0, 0);
585
586 // Allocation for the
587 peak = new unsigned char[size];
588
589 // Parse the histogram to get the local maxima
590 nbpeaks = 0;
591 prev_slope = 1;
592 for (unsigned i = 0; i < size - 1; i++) {
593 int next_slope = (int)histogram[i + 1] - (int)histogram[i]; // Next histogram inclination
594 if (next_slope == 0)
595 continue;
596 // Peak detection
597 if ((prev_slope > 0) && (next_slope < 0))
598 peak[nbpeaks++] = (unsigned char)i;
599
600 prev_slope = next_slope;
601 }
602 if (prev_slope > 0)
603 peak[nbpeaks++] = (unsigned char)(size - 1);
604
605 // Get the global maximum
606 index_highest_peak = 0;
607 for (unsigned int i = 0; i < nbpeaks; i++) {
608 if (histogram[peak[i]] > histogram[peak[index_highest_peak]]) {
609 index_highest_peak = i;
610 }
611 }
612
613 maxprof = 0;
614 index_second_peak = index_highest_peak;
615
616 // Search second local maximum on the left of the global maximum
617 for (unsigned i = 0; i < index_highest_peak; i++) {
618 if (peak[index_highest_peak] - peak[i] > dist) {
619 prof = 0;
620 for (int j = peak[i]; j <= peak[index_highest_peak] - dist; j++)
621 if ((histogram[peak[i]] - histogram[j]) > prof)
622 prof = histogram[peak[i]] - histogram[j];
623
624 if (prof > maxprof) {
625 maxprof = prof;
626 index_second_peak = i;
627 }
628 }
629 }
630
631 // Search second local maximum on the right of the global maximum
632 for (unsigned i = index_highest_peak + 1; i < nbpeaks; i++) {
633 if (peak[i] - peak[index_highest_peak] > dist) {
634 prof = 0;
635 for (int j = peak[index_highest_peak] + dist; j <= peak[i]; j++)
636 if ((histogram[peak[i]] - histogram[j]) > prof)
637 prof = histogram[peak[i]] - histogram[j];
638
639 if (prof > maxprof) {
640 maxprof = prof;
641 index_second_peak = i;
642 }
643 }
644 }
645
646 // Determine position of the first and second highest peaks
647 if (peak[index_highest_peak] < peak[index_second_peak]) {
648 peakr.set(peak[index_second_peak], histogram[peak[index_second_peak]]);
649 peakl.set(peak[index_highest_peak], histogram[peak[index_highest_peak]]);
650 }
651 else {
652 peakl.set(peak[index_second_peak], histogram[peak[index_second_peak]]);
653 peakr.set(peak[index_highest_peak], histogram[peak[index_highest_peak]]);
654 }
655
656 if (peakl == peakr) {
657
658 delete[] peak;
659
660 return (false); // Not a bimodal histogram
661 }
662
663 // Search the valey
664 mini = peakl.getValue();
665 sumindmini = 0;
666 nbmini = 0;
667 for (unsigned i = peakl.getLevel(); i <= peakr.getLevel(); i++) {
668 if (histogram[i] < mini) {
669 mini = histogram[i];
670 nbmini = 1;
671 sumindmini = i;
672 continue;
673 }
674 if (histogram[i] == mini) {
675 sumindmini += i;
676 nbmini++;
677 }
678 }
679 // vpTRACE("nbmini %d", nbmini);
680 // vpTRACE("sumindmini %d", sumindmini);
681 // vpTRACE("mini: indmini: %d", sumindmini/nbmini);
682
683 if (nbmini == 0) {
684 // no valey found
685 valey.set(0, 0);
686
687 delete[] peak;
688
689 return false;
690 }
691 else {
692 mini = sumindmini / nbmini; // mean
693 valey.set((unsigned char)mini, histogram[mini]);
694
695 delete[] peak;
696
697 return (true);
698 }
699}
700
712unsigned vpHistogram::getValey(std::list<vpHistogramValey> &valey)
713{
714 if (histogram == NULL) {
715 vpERROR_TRACE("Histogram array not initialised\n");
716 throw(vpImageException(vpImageException::notInitializedError, "Histogram array not initialised"));
717 }
718
719 int prev_slope; // Previous histogram inclination
720 vpHistogramValey p; // An histogram valey
721 unsigned nbvaley; // Number of valey in the histogram (ie local minima)
722
723 valey.clear();
724
725 // Parse the histogram to get the local minima
726 unsigned cpt = 0;
727 unsigned sum_level = 0;
728 nbvaley = 0;
729 prev_slope = -1;
730
731 for (unsigned i = 0; i < size - 1; i++) {
732 int next_slope = (int)histogram[i + 1] - (int)histogram[i]; // Next histogram inclination
733
734 if ((prev_slope < 0) && (next_slope == 0)) {
735 sum_level += i + 1;
736 cpt++;
737 continue;
738 }
739
740 // Valey detection
741 if ((prev_slope < 0) && (next_slope > 0)) {
742 sum_level += i;
743 cpt++;
744
745 unsigned int level = sum_level / cpt;
746 p.set((unsigned char)level, histogram[level]);
747 // vpTRACE("add %d %d", p.getLevel(), p.getValue());
748 valey.push_back(p);
749
750 nbvaley++;
751 }
752
753 prev_slope = next_slope;
754 sum_level = 0;
755 cpt = 0;
756 }
757 if (prev_slope < 0) {
758 p.set((unsigned char)size - 1u, histogram[size - 1]);
759 // vpTRACE("add %d %d", p.getLevel(), p.getValue());
760 valey.push_back(p);
761 nbvaley++;
762 }
763
764 return nbvaley;
765}
766
782{
783
784 // Set the left and right peaks
785 vpHistogramPeak peakl, peakr;
786 if (peak1.getLevel() > peak2.getLevel()) {
787 peakl = peak2;
788 peakr = peak1;
789 }
790 else {
791 peakl = peak1;
792 peakr = peak2;
793 }
794
795 // Search the valey
796 unsigned int nbmini; // Minimum numbers
797 unsigned int sumindmini; // Sum
798 unsigned int mini; // current minimum
799
800 mini = peakl.getValue();
801 sumindmini = 0;
802 nbmini = 0;
803 for (unsigned i = peakl.getLevel(); i <= peakr.getLevel(); i++) {
804 if (histogram[i] < mini) {
805 mini = histogram[i];
806 nbmini = 1;
807 sumindmini = i;
808 continue;
809 }
810 if (histogram[i] == mini) {
811 sumindmini += i;
812 nbmini++;
813 }
814 }
815
816 if (nbmini == 0) {
817 // no valey found
818 valey.set(0, 0);
819
820 return false;
821 }
822 else {
823 unsigned int minipos = sumindmini / nbmini; // position of the minimum
824
825 valey.set((unsigned char)minipos, histogram[minipos]);
826 return true;
827 }
828}
847unsigned vpHistogram::getValey(unsigned char dist, const vpHistogramPeak &peak, vpHistogramValey &valeyl,
848 vpHistogramValey &valeyr)
849{
850 unsigned int ret = 0x11;
851 unsigned int nbmini; // Minimum numbers
852 unsigned int sumindmini; // Sum
853 unsigned int mini; // current minimum
854 vpHistogramPeak peakr, peakl; // Left and right peaks of peak
855 std::list<vpHistogramPeak> peaks; // list of histogram peaks
856 // unsigned int nbpeaks=0; // Number of peaks in the histogram (ie local
857 // maxima)
858
859 if (peak.getLevel() == 0) {
860 valeyl.set(0, 0);
861 ret &= 0x01;
862 }
863 if (peak.getLevel() == size - 1) {
864 valeyr.set((unsigned char)(size - 1), 0);
865 ret &= 0x10;
866 }
867
868 if (ret >> 1) // consider the left part of the requested peak
869 {
870 // If the list of peaks is empty, compute it
871 if (peaks.empty()) {
872 /* nbpeaks = */ getPeaks(peaks);
873 }
874
875 // Go to the requested peak in the list
876 std::list<vpHistogramPeak>::const_iterator it;
877 unsigned index = 0;
878 for (it = peaks.begin(); it != peaks.end(); ++it) {
879 if (peak == *it) {
880 // we are on the peak.
881 break;
882 }
883 index++;
884 }
885
886 bool found = false;
887 if (index == 0) {
888 // No chance to get a peak on the left
889 // should not occur !
890 peakl.set(0, 0);
891 }
892 else {
893 // search for the nearest peak on the left that matches the distance
894 std::list<vpHistogramPeak>::const_iterator lit; // left iterator
895 for (lit = peaks.begin(); lit != it; ++lit) {
896 if (abs((*lit).getLevel() - peak.getLevel()) > dist) {
897 // peakl found
898 peakl = *lit;
899 found = true; // we cannot stop here, since the other peaks on the
900 // right may exist
901 }
902 }
903 }
904 if (!found)
905 peakl.set(0, 0);
906
907 // Search the valey on the left
908 mini = peak.getValue();
909 sumindmini = 0;
910 nbmini = 0;
911 for (unsigned i = peakl.getLevel(); i < peak.getLevel(); i++) {
912 if (histogram[i] < mini) {
913 mini = histogram[i];
914 nbmini = 1;
915 sumindmini = i;
916 continue;
917 }
918 if (histogram[i] == mini) {
919 sumindmini += i;
920 nbmini++;
921 }
922 }
923 if (nbmini == 0) {
924 valeyl.set(0, 0);
925 ret &= 0x01;
926 }
927 else {
928 unsigned int minipos = sumindmini / nbmini; // position of the minimum
929 valeyl.set((unsigned char)minipos, histogram[minipos]);
930 ret &= 0x11;
931 }
932 }
933
934 if (ret << 1) {
935 // If the list of peaks is empty, compute it
936 if (peaks.empty()) {
937 /* nbpeaks = */ getPeaks(peaks);
938 }
939 // Go to the requested peak in the list
940 std::list<vpHistogramPeak>::const_iterator it;
941 for (it = peaks.begin(); it != peaks.end(); ++it) {
942 if (peak == *it) {
943 // we are on the peak.
944 break;
945 }
946 }
947
948 bool found = false;
949 // search for the nearest peak on the right that matches the distance
950 std::list<vpHistogramPeak>::const_iterator rit; // right iterator
951 for (rit = it; rit != peaks.end(); ++rit)
952
953 if (abs((*rit).getLevel() - peak.getLevel()) > dist) {
954 // peakr found
955 peakr = *rit;
956 found = true;
957 break; // we can stop here
958 }
959
960 if (!found)
961 peakr.set((unsigned char)(size - 1), 0);
962
963 // Search the valey on the right
964 mini = peak.getValue();
965 sumindmini = 0;
966 nbmini = 0;
967 for (unsigned i = (unsigned int)peak.getLevel() + 1; i <= (unsigned int)peakr.getLevel(); i++) {
968 if (histogram[i] < mini) {
969 mini = histogram[i];
970 nbmini = 1;
971 sumindmini = i;
972 continue;
973 }
974 if (histogram[i] == mini) {
975 sumindmini += i;
976 nbmini++;
977 }
978 }
979 if (nbmini == 0) {
980 valeyr.set((unsigned char)(size - 1), 0);
981 ret &= 0x10;
982 }
983 else {
984 unsigned int minipos = sumindmini / nbmini; // position of the minimum
985 valeyr.set((unsigned char)minipos, histogram[minipos]);
986 ret &= 0x11;
987 }
988 }
989
990 return ret;
991}
992
1001unsigned vpHistogram::sort(std::list<vpHistogramPeak> &peaks)
1002{
1003
1004 if (peaks.empty()) {
1005 return 0;
1006 }
1007
1008 peaks.sort(compare_vpHistogramPeak);
1009
1010 return (unsigned int)peaks.size();
1011}
1012
1025bool vpHistogram::write(const std::string &filename) { return (this->write(filename.c_str())); }
1026
1039bool vpHistogram::write(const char *filename)
1040{
1041 FILE *fd = fopen(filename, "w");
1042 if (fd == NULL)
1043 return false;
1044 for (unsigned i = 0; i < size; i++)
1045 fprintf(fd, "%u %u\n", i, histogram[i]);
1046 fclose(fd);
1047
1048 return true;
1049}
Class to define RGB colors available for display functionalities.
Definition vpColor.h:152
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 emitted by ViSP classes.
Definition vpException.h:59
@ divideByZeroError
Division by zero.
Definition vpException.h:82
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.
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 emitted by the vpImage class and its derivatives.
@ notInitializedError
Image not initialized.
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Definition of the vpImage class member functions.
Definition vpImage.h:135
unsigned int getWidth() const
Definition vpImage.h:242
unsigned int getSize() const
Definition vpImage.h:223
Type * bitmap
points toward the bitmap
Definition vpImage.h:139
unsigned int getHeight() const
Definition vpImage.h:184
void * Return
Definition vpThread.h:73
void *(* Fn)(Args)
Definition vpThread.h:74
void * Args
Definition vpThread.h:72
#define vpERROR_TRACE
Definition vpDebug.h:388