48 #include <visp3/core/vpHistogram.h>
49 #include <visp3/core/vpImageConvert.h>
50 #include <visp3/core/vpDisplay.h>
53 #if defined(VISP_HAVE_PTHREAD) || (defined(_WIN32) && !defined(WINRT_8_0))
54 #include <visp3/core/vpThread.h>
57 struct Histogram_Param_t {
58 unsigned int m_start_index;
59 unsigned int m_end_index;
61 unsigned int m_lut[256];
62 unsigned int *m_histogram;
65 Histogram_Param_t() : m_start_index(0), m_end_index(0), m_lut(), m_histogram(NULL), m_I(NULL) {
68 Histogram_Param_t(
const unsigned int start_index,
const unsigned int end_index,
70 m_start_index(start_index), m_end_index(end_index), m_lut(), m_histogram(NULL), m_I(I) {
73 ~Histogram_Param_t() {
74 if(m_histogram != NULL) {
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;
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;
97 if(end_index - start_index >= 8) {
99 for(; ptrCurrent <= ptrEnd - 8;) {
100 histogram_param->m_histogram[ histogram_param->m_lut[ *ptrCurrent ] ] ++;
103 histogram_param->m_histogram[ histogram_param->m_lut[ *ptrCurrent ] ] ++;
106 histogram_param->m_histogram[ histogram_param->m_lut[ *ptrCurrent ] ] ++;
109 histogram_param->m_histogram[ histogram_param->m_lut[ *ptrCurrent ] ] ++;
112 histogram_param->m_histogram[ histogram_param->m_lut[ *ptrCurrent ] ] ++;
115 histogram_param->m_histogram[ histogram_param->m_lut[ *ptrCurrent ] ] ++;
118 histogram_param->m_histogram[ histogram_param->m_lut[ *ptrCurrent ] ] ++;
121 histogram_param->m_histogram[ histogram_param->m_lut[ *ptrCurrent ] ] ++;
126 for(; ptrCurrent != ptrEnd; ++ptrCurrent) {
127 histogram_param->m_histogram[ histogram_param->m_lut[ *ptrCurrent ] ] ++;
160 memcpy(histogram, h.histogram, size *
sizeof(
unsigned));
171 : histogram(NULL), size(256)
183 if (histogram != NULL) {
208 memcpy(histogram, h.histogram, size *
sizeof(
unsigned));
219 vpHistogram::init(
unsigned size_)
221 if (histogram != NULL) {
227 histogram =
new unsigned [size];
229 memset(histogram, 0, size *
sizeof(
unsigned));
246 if (histogram != NULL) {
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;
255 histogram =
new unsigned int[size];
258 memset(histogram, 0, size *
sizeof(
unsigned int));
261 bool use_single_thread;
262 #if !defined(VISP_HAVE_PTHREAD) && !defined(_WIN32)
263 use_single_thread =
true;
265 use_single_thread = (nbThreads == 0 || nbThreads == 1);
268 if(!use_single_thread && I.
getSize() <= nbThreads) {
269 use_single_thread =
true;
273 unsigned int lut[256];
274 for(
unsigned int i = 0; i < 256; i++) {
275 lut[i] = (
unsigned int) (i * size / 256.0);
278 if(use_single_thread) {
282 unsigned char *ptrStart = (
unsigned char*) I.
bitmap;
283 unsigned char *ptrEnd = ptrStart + size_;
284 unsigned char *ptrCurrent = ptrStart;
286 while(ptrCurrent != ptrEnd) {
287 histogram[ lut[ *ptrCurrent ] ] ++;
291 #if defined(VISP_HAVE_PTHREAD) || (defined(_WIN32) && !defined(WINRT_8_0))
294 std::vector<vpThread *> threadpool;
295 std::vector<Histogram_Param_t *> histogramParams;
297 unsigned int image_size = I.
getSize();
298 unsigned int step = image_size / nbThreads;
299 unsigned int last_step = image_size - step * (nbThreads-1);
301 for(
unsigned int index = 0; index < nbThreads; index++) {
302 unsigned int start_index = index*step;
303 unsigned int end_index = (index+1)*step;
305 if(index == nbThreads-1) {
306 end_index = start_index+last_step;
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));
314 histogramParams.push_back(histogram_param);
318 threadpool.push_back(histogram_thread);
321 for(
size_t cpt = 0; cpt < threadpool.size(); cpt++) {
323 threadpool[cpt]->join();
326 for(
unsigned int cpt1 = 0; cpt1 < size; cpt1++) {
327 unsigned int sum = 0;
329 for(
size_t cpt2 = 0; cpt2 < histogramParams.size(); cpt2++) {
330 sum += histogramParams[cpt2]->m_histogram[cpt1];
333 histogram[cpt1] = sum;
337 for(
size_t cpt = 0; cpt < threadpool.size(); cpt++) {
338 delete threadpool[cpt];
341 for(
size_t cpt = 0; cpt < histogramParams.size(); cpt++) {
342 delete histogramParams[cpt];
358 const unsigned int maxValue_) {
361 if(width < 36 || height < 36) {
362 std::cerr <<
"Image I must have at least width >= 36 && height >= 36 !" << std::endl;
366 unsigned int maxValue = maxValue_;
368 for(
unsigned int i = 0; i < size; i++) {
369 if(histogram[i] > maxValue) {
370 maxValue = histogram[i];
377 "Cannot display histogram; max value=0"));
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);
384 for(
unsigned int i = 1; i < size; i++) {
385 unsigned int value1 = histogram[i-1];
386 unsigned int value2 = histogram[i];
388 vpImagePoint startPt((height-1)-(value1*ratio_height), (i-1)*ratio_width);
389 vpImagePoint endPt((height-1)-(value2*ratio_height), (i*ratio_width));
417 if (histogram == NULL) {
420 "Histogram array not initialised")) ;
426 int hsize = (int)fsize / 2;
428 for (
unsigned i=0; i < size; i ++) {
429 unsigned int sum = 0;
431 for (
int j=-hsize; j <= hsize; j ++) {
433 if ( (i + (
unsigned int)j) < size ) {
434 sum += h.histogram[i + (
unsigned int)j];
438 histogram[i] = sum / nb;
459 if (histogram == NULL) {
462 "Histogram array not initialised")) ;
473 unsigned sum_level = 0;
477 for (
unsigned i = 0; i < size-1; i++) {
478 int next_slope = (int)histogram[i+1] - (
int)histogram[i];
486 if ((prev_slope > 0) && (next_slope == 0) ) {
494 if ( (prev_slope > 0) && (next_slope < 0) ) {
498 unsigned int level = sum_level / cpt;
499 p.
set((
unsigned char)level, histogram[level]);
507 prev_slope = next_slope;
511 if (prev_slope > 0) {
512 p.
set((
unsigned char)size-1u, histogram[size-1]);
542 std::list<vpHistogramPeak> peaks;
555 peak1 = peaks.front();
562 peak1 = peaks.front();
563 for(std::list<vpHistogramPeak>::const_iterator it = peaks.begin(); it != peaks.end(); ++ it)
602 unsigned index_highest_peak;
603 unsigned index_second_peak;
606 unsigned int maxprof;
608 unsigned int sumindmini;
610 unsigned int nbpeaks;
616 peak =
new unsigned char [size];
621 for (
unsigned i = 0; i < size-1; i++) {
622 int next_slope = (int)histogram[i+1] - (
int)histogram[i];
626 if ( (prev_slope > 0) && (next_slope < 0) )
627 peak[nbpeaks ++] = (
unsigned char)i;
629 prev_slope = next_slope;
632 peak[nbpeaks ++] = (
unsigned char)(size-1);
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;
651 index_second_peak=index_highest_peak;
654 for (
unsigned i = 0; i < index_highest_peak; i++) {
655 if (peak[index_highest_peak] - peak[i] > dist) {
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];
661 if (prof > maxprof) {
663 index_second_peak = i;
669 for (
unsigned i = index_highest_peak+1; i < nbpeaks; i++) {
670 if (peak[i] - peak[index_highest_peak] > dist) {
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];
676 if (prof > maxprof) {
678 index_second_peak = i;
687 if (peak[index_highest_peak] < peak[index_second_peak])
689 peakr.
set(peak[index_second_peak], histogram[ peak[index_second_peak] ]);
690 peakl.
set(peak[index_highest_peak], histogram[ peak[index_highest_peak] ]);
694 peakl.
set(peak[index_second_peak], histogram[ peak[index_second_peak] ]);
695 peakr.
set(peak[index_highest_peak], histogram[ peak[index_highest_peak]]);
698 if (peakl == peakr) {
710 if (histogram[i] < mini) {
716 if (histogram[i] == mini) {
734 mini = sumindmini/nbmini;
735 valey.
set((
unsigned char)mini, histogram[mini]);
756 if (histogram == NULL) {
759 "Histogram array not initialised")) ;
770 unsigned sum_level = 0;
774 for (
unsigned i = 0; i < size-1; i++) {
775 int next_slope = (int)histogram[i+1] - (
int)histogram[i];
777 if ((prev_slope < 0) && (next_slope == 0) ) {
784 if ( (prev_slope < 0) && (next_slope > 0) ) {
788 unsigned int level = sum_level / cpt;
789 p.
set((
unsigned char)level, histogram[level]);
797 prev_slope = next_slope;
801 if (prev_slope < 0) {
802 p.
set((
unsigned char)size-1u, histogram[size-1]);
844 unsigned int sumindmini;
851 if (histogram[i] < mini) {
857 if (histogram[i] == mini) {
870 unsigned int minipos = sumindmini/nbmini;
872 valey.
set((
unsigned char)minipos, histogram[minipos]);
900 unsigned int ret = 0x11;
902 unsigned int sumindmini;
905 std::list<vpHistogramPeak> peaks;
913 valeyr.
set((
unsigned char)(size-1), 0);
936 std::list<vpHistogramPeak>::const_iterator it;
938 for (it = peaks.begin(); it != peaks.end(); ++ it)
955 std::list<vpHistogramPeak>::const_iterator lit;
956 for(lit = peaks.begin(); lit != it; ++ lit)
958 if (abs((*lit).getLevel() - peak.
getLevel()) > dist) {
973 if (histogram[i] < mini) {
979 if (histogram[i] == mini) {
989 unsigned int minipos = sumindmini/nbmini;
990 valeyl.
set((
unsigned char)minipos, histogram[minipos]);
1001 std::list<vpHistogramPeak>::const_iterator it;
1003 for (it = peaks.begin(); it != peaks.end(); ++ it)
1014 std::list<vpHistogramPeak>::const_iterator rit;
1015 for(rit = it; rit != peaks.end(); ++ rit)
1017 if (abs((*rit).getLevel() - peak.
getLevel()) > dist) {
1025 peakr.
set((
unsigned char)(size-1),0);
1031 for (
unsigned i=(
unsigned int)peak.
getLevel()+1; i <= (
unsigned int)peakr.
getLevel(); i++) {
1032 if (histogram[i] < mini) {
1038 if (histogram[i] == mini) {
1044 valeyr.
set((
unsigned char)(size-1), 0);
1048 unsigned int minipos = sumindmini/nbmini;
1049 valeyr.
set((
unsigned char)minipos, histogram[minipos]);
1068 if ( peaks.empty() ) {
1072 peaks.sort(compare_vpHistogramPeak);
1074 return (
unsigned int)peaks.size();
1092 return ( this->
write(filename.c_str()) );
1110 FILE *fd = fopen(filename,
"w");
1113 for (
unsigned i=0; i < size; i ++)
1114 fprintf(fd,
"%u %d\n", i, histogram[i]);
unsigned getPeaks(std::list< vpHistogramPeak > &peaks)
void display(const vpImage< unsigned char > &I, const vpColor &color=vpColor::white, const unsigned int thickness=2, const unsigned int maxValue_=0)
unsigned int getWidth() const
unsigned getValue() const
Type * bitmap
points toward the bitmap
vpHistogram & operator=(const vpHistogram &h)
Class to define colors available for display functionnalities.
error that can be emited by ViSP classes.
Class to compute a gray level image histogram.
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 smooth(const unsigned int fsize=3)
void set(unsigned char lvl, unsigned val)
unsigned int getSize() const
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
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
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)