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;
62 const vpImage<unsigned char> *m_I;
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) {
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;
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_)
347 unsigned int width = I.getWidth(), height = I.getHeight();
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)
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.