46#include <visp3/core/vpDisplay.h>
47#include <visp3/core/vpHistogram.h>
48#include <visp3/core/vpImageConvert.h>
50#if defined(VISP_HAVE_PTHREAD) || (defined(_WIN32) && !defined(WINRT_8_0))
51#include <visp3/core/vpThread.h>
55struct vpHistogram_Param_t
57 unsigned int m_start_index;
58 unsigned int m_end_index;
60 unsigned int m_lut[256];
61 unsigned int *m_histogram;
64 vpHistogram_Param_t() : m_start_index(0), m_end_index(0), m_lut(), m_histogram(NULL), m_I(NULL) { }
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)
70 ~vpHistogram_Param_t()
72 if (m_histogram != NULL) {
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;
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;
90 if (end_index - start_index >= 8) {
92 for (; ptrCurrent <= ptrEnd - 8;) {
93 histogram_param->m_histogram[histogram_param->m_lut[*ptrCurrent]]++;
96 histogram_param->m_histogram[histogram_param->m_lut[*ptrCurrent]]++;
99 histogram_param->m_histogram[histogram_param->m_lut[*ptrCurrent]]++;
102 histogram_param->m_histogram[histogram_param->m_lut[*ptrCurrent]]++;
105 histogram_param->m_histogram[histogram_param->m_lut[*ptrCurrent]]++;
108 histogram_param->m_histogram[histogram_param->m_lut[*ptrCurrent]]++;
111 histogram_param->m_histogram[histogram_param->m_lut[*ptrCurrent]]++;
114 histogram_param->m_histogram[histogram_param->m_lut[*ptrCurrent]]++;
119 for (; ptrCurrent != ptrEnd; ++ptrCurrent) {
120 histogram_param->m_histogram[histogram_param->m_lut[*ptrCurrent]]++;
150 memcpy(histogram, h.histogram, size *
sizeof(
unsigned));
172 if (histogram != NULL) {
196 memcpy(histogram, h.histogram, size *
sizeof(
unsigned));
206void vpHistogram::init(
unsigned size_)
208 if (histogram != NULL) {
214 histogram =
new unsigned[size];
216 memset(histogram, 0, size *
sizeof(
unsigned));
232 if (histogram != NULL) {
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;
241 histogram =
new unsigned int[size];
244 memset(histogram, 0, size *
sizeof(
unsigned int));
246 bool use_single_thread;
247#if !defined(VISP_HAVE_PTHREAD) && !defined(_WIN32)
248 use_single_thread =
true;
250 use_single_thread = (nbThreads == 0 || nbThreads == 1);
253 if (!use_single_thread && I.
getSize() <= nbThreads) {
254 use_single_thread =
true;
257 unsigned int lut[256];
258 for (
unsigned int i = 0; i < 256; i++) {
259 lut[i] = (
unsigned int)(i * size / 256.0);
262 if (use_single_thread) {
266 unsigned char *ptrStart = (
unsigned char *)I.
bitmap;
267 unsigned char *ptrEnd = ptrStart + size_;
268 unsigned char *ptrCurrent = ptrStart;
270 while (ptrCurrent != ptrEnd) {
271 histogram[lut[*ptrCurrent]]++;
276#if defined(VISP_HAVE_PTHREAD) || (defined(_WIN32) && !defined(WINRT_8_0))
279 std::vector<vpThread *> threadpool;
280 std::vector<vpHistogram_Param_t *> histogramParams;
282 unsigned int image_size = I.
getSize();
283 unsigned int step = image_size / nbThreads;
284 unsigned int last_step = image_size - step * (nbThreads - 1);
286 for (
unsigned int index = 0; index < nbThreads; index++) {
287 unsigned int start_index = index * step;
288 unsigned int end_index = (index + 1) * step;
290 if (index == nbThreads - 1) {
291 end_index = start_index + last_step;
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));
299 histogramParams.push_back(histogram_param);
303 threadpool.push_back(histogram_thread);
306 for (
size_t cpt = 0; cpt < threadpool.size(); cpt++) {
308 threadpool[cpt]->join();
311 for (
unsigned int cpt1 = 0; cpt1 < size; cpt1++) {
312 unsigned int sum = 0;
314 for (
size_t cpt2 = 0; cpt2 < histogramParams.size(); cpt2++) {
315 sum += histogramParams[cpt2]->m_histogram[cpt1];
318 histogram[cpt1] = sum;
322 for (
size_t cpt = 0; cpt < threadpool.size(); cpt++) {
323 delete threadpool[cpt];
326 for (
size_t cpt = 0; cpt < histogramParams.size(); cpt++) {
327 delete histogramParams[cpt];
345 unsigned int maxValue_)
349 if (width < 36 || height < 36) {
350 std::cerr <<
"Image I must have at least width >= 36 && height >= 36 !" << std::endl;
354 unsigned int maxValue = maxValue_;
356 for (
unsigned int i = 0; i < size; i++) {
357 if (histogram[i] > maxValue) {
358 maxValue = histogram[i];
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);
371 for (
unsigned int i = 1; i < size; i++) {
372 unsigned int value1 = histogram[i - 1];
373 unsigned int value2 = histogram[i];
375 vpImagePoint startPt((height - 1) - (value1 * ratio_height), (i - 1) * ratio_width);
376 vpImagePoint endPt((height - 1) - (value2 * ratio_height), (i * ratio_width));
401 if (histogram == NULL) {
409 int hsize = (int)fsize / 2;
411 for (
unsigned i = 0; i < size; i++) {
412 unsigned int sum = 0;
414 for (
int j = -hsize; j <= hsize; j++) {
416 if ( (i + (
unsigned int)j) < size) {
417 sum += h.histogram[i + (
unsigned int)j];
421 histogram[i] = sum / nb;
441 if (histogram == NULL) {
454 unsigned sum_level = 0;
458 for (
unsigned i = 0; i < size - 1; i++) {
459 int next_slope = (int)histogram[i + 1] - (
int)histogram[i];
467 if ((prev_slope > 0) && (next_slope == 0)) {
474 if ((prev_slope > 0) && (next_slope < 0)) {
478 unsigned int level = sum_level / cpt;
479 p.
set((
unsigned char)level, histogram[level]);
486 prev_slope = next_slope;
490 if (prev_slope > 0) {
491 p.
set((
unsigned char)size - 1u, histogram[size - 1]);
519 std::list<vpHistogramPeak> peaks;
532 peak1 = peaks.front();
539 peak1 = peaks.front();
540 for (std::list<vpHistogramPeak>::const_iterator it = peaks.begin(); it != peaks.end(); ++it) {
573 unsigned index_highest_peak;
574 unsigned index_second_peak;
577 unsigned int maxprof;
579 unsigned int sumindmini;
581 unsigned int nbpeaks;
587 peak =
new unsigned char[size];
592 for (
unsigned i = 0; i < size - 1; i++) {
593 int next_slope = (int)histogram[i + 1] - (
int)histogram[i];
597 if ((prev_slope > 0) && (next_slope < 0))
598 peak[nbpeaks++] = (
unsigned char)i;
600 prev_slope = next_slope;
603 peak[nbpeaks++] = (
unsigned char)(size - 1);
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;
614 index_second_peak = index_highest_peak;
617 for (
unsigned i = 0; i < index_highest_peak; i++) {
618 if (peak[index_highest_peak] - peak[i] > dist) {
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];
624 if (prof > maxprof) {
626 index_second_peak = i;
632 for (
unsigned i = index_highest_peak + 1; i < nbpeaks; i++) {
633 if (peak[i] - peak[index_highest_peak] > dist) {
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];
639 if (prof > maxprof) {
641 index_second_peak = i;
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]]);
652 peakl.
set(peak[index_second_peak], histogram[peak[index_second_peak]]);
653 peakr.
set(peak[index_highest_peak], histogram[peak[index_highest_peak]]);
656 if (peakl == peakr) {
668 if (histogram[i] < mini) {
674 if (histogram[i] == mini) {
692 mini = sumindmini / nbmini;
693 valey.
set((
unsigned char)mini, histogram[mini]);
714 if (histogram == NULL) {
727 unsigned sum_level = 0;
731 for (
unsigned i = 0; i < size - 1; i++) {
732 int next_slope = (int)histogram[i + 1] - (
int)histogram[i];
734 if ((prev_slope < 0) && (next_slope == 0)) {
741 if ((prev_slope < 0) && (next_slope > 0)) {
745 unsigned int level = sum_level / cpt;
746 p.
set((
unsigned char)level, histogram[level]);
753 prev_slope = next_slope;
757 if (prev_slope < 0) {
758 p.
set((
unsigned char)size - 1u, histogram[size - 1]);
797 unsigned int sumindmini;
804 if (histogram[i] < mini) {
810 if (histogram[i] == mini) {
823 unsigned int minipos = sumindmini / nbmini;
825 valey.
set((
unsigned char)minipos, histogram[minipos]);
850 unsigned int ret = 0x11;
852 unsigned int sumindmini;
855 std::list<vpHistogramPeak> peaks;
864 valeyr.
set((
unsigned char)(size - 1), 0);
876 std::list<vpHistogramPeak>::const_iterator it;
878 for (it = peaks.begin(); it != peaks.end(); ++it) {
894 std::list<vpHistogramPeak>::const_iterator lit;
895 for (lit = peaks.begin(); lit != it; ++lit) {
896 if (abs((*lit).getLevel() - peak.
getLevel()) > dist) {
912 if (histogram[i] < mini) {
918 if (histogram[i] == mini) {
928 unsigned int minipos = sumindmini / nbmini;
929 valeyl.
set((
unsigned char)minipos, histogram[minipos]);
940 std::list<vpHistogramPeak>::const_iterator it;
941 for (it = peaks.begin(); it != peaks.end(); ++it) {
950 std::list<vpHistogramPeak>::const_iterator rit;
951 for (rit = it; rit != peaks.end(); ++rit)
953 if (abs((*rit).getLevel() - peak.
getLevel()) > dist) {
961 peakr.
set((
unsigned char)(size - 1), 0);
967 for (
unsigned i = (
unsigned int)peak.
getLevel() + 1; i <= (
unsigned int)peakr.
getLevel(); i++) {
968 if (histogram[i] < mini) {
974 if (histogram[i] == mini) {
980 valeyr.
set((
unsigned char)(size - 1), 0);
984 unsigned int minipos = sumindmini / nbmini;
985 valeyr.
set((
unsigned char)minipos, histogram[minipos]);
1004 if (peaks.empty()) {
1008 peaks.sort(compare_vpHistogramPeak);
1010 return (
unsigned int)peaks.size();
1041 FILE *fd = fopen(filename,
"w");
1044 for (
unsigned i = 0; i < size; i++)
1045 fprintf(fd,
"%u %u\n", i, histogram[i]);
Class to define RGB colors available for display functionalities.
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.
@ divideByZeroError
Division by zero.
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)
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.
unsigned int getWidth() const
unsigned int getSize() const
Type * bitmap
points toward the bitmap
unsigned int getHeight() const