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>
55 struct 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(nullptr), m_I(nullptr) { }
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(nullptr), m_I(I)
70 ~vpHistogram_Param_t()
72 if (m_histogram !=
nullptr) {
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 !=
nullptr) {
196 memcpy(histogram, h.histogram, size *
sizeof(
unsigned));
206 void vpHistogram::init(
unsigned size_)
208 if (histogram !=
nullptr) {
214 histogram =
new unsigned[size];
216 memset(histogram, 0, size *
sizeof(
unsigned));
232 if (histogram !=
nullptr) {
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];
339 unsigned int cdf[256];
340 unsigned int cdfMin = std::numeric_limits<unsigned int>::max(), cdfMax = 0;
341 unsigned int minValue = std::numeric_limits<unsigned int>::max(), maxValue = 0;
342 cdf[0] = histogram[0];
344 if (cdf[0] < cdfMin && cdf[0] > 0) {
349 for (
unsigned int i = 1; i < 256; i++) {
350 cdf[i] = cdf[i - 1] + histogram[i];
352 if (cdf[i] < cdfMin && cdf[i] > 0) {
357 if (cdf[i] > cdfMax) {
364 if (nbPixels == cdfMin) {
370 unsigned char lut[256];
371 for (
unsigned int x = minValue; x <= maxValue; x++) {
372 lut[x] =
vpMath::round((cdf[x] - cdfMin) / (
double)(nbPixels - cdfMin) * 255.0);
391 unsigned int maxValue_)
395 if (width < 36 || height < 36) {
396 std::cerr <<
"Image I must have at least width >= 36 && height >= 36 !" << std::endl;
400 unsigned int maxValue = maxValue_;
402 for (
unsigned int i = 0; i < size; i++) {
403 if (histogram[i] > maxValue) {
404 maxValue = histogram[i];
413 unsigned int max_height = height - 12;
414 double ratio_height = max_height / (double)maxValue;
415 double ratio_width = (width - 1) / (
double)(size - 1.0);
417 for (
unsigned int i = 1; i < size; i++) {
418 unsigned int value1 = histogram[i - 1];
419 unsigned int value2 = histogram[i];
421 vpImagePoint startPt((height - 1) - (value1 * ratio_height), (i - 1) * ratio_width);
422 vpImagePoint endPt((height - 1) - (value2 * ratio_height), (i * ratio_width));
447 if (histogram ==
nullptr) {
455 int hsize = (int)fsize / 2;
457 for (
unsigned i = 0; i < size; i++) {
458 unsigned int sum = 0;
460 for (
int j = -hsize; j <= hsize; j++) {
462 if ( (i + (
unsigned int)j) < size) {
463 sum += h.histogram[i + (
unsigned int)j];
467 histogram[i] = sum / nb;
487 if (histogram ==
nullptr) {
500 unsigned sum_level = 0;
504 for (
unsigned i = 0; i < size - 1; i++) {
505 int next_slope = (int)histogram[i + 1] - (
int)histogram[i];
513 if ((prev_slope > 0) && (next_slope == 0)) {
520 if ((prev_slope > 0) && (next_slope < 0)) {
524 unsigned int level = sum_level / cpt;
525 p.
set((
unsigned char)level, histogram[level]);
532 prev_slope = next_slope;
536 if (prev_slope > 0) {
537 p.
set((
unsigned char)size - 1u, histogram[size - 1]);
565 std::list<vpHistogramPeak> peaks;
578 peak1 = peaks.front();
585 peak1 = peaks.front();
586 for (std::list<vpHistogramPeak>::const_iterator it = peaks.begin(); it != peaks.end(); ++it) {
619 unsigned index_highest_peak;
620 unsigned index_second_peak;
623 unsigned int maxprof;
625 unsigned int sumindmini;
627 unsigned int nbpeaks;
633 peak =
new unsigned char[size];
638 for (
unsigned i = 0; i < size - 1; i++) {
639 int next_slope = (int)histogram[i + 1] - (
int)histogram[i];
643 if ((prev_slope > 0) && (next_slope < 0))
644 peak[nbpeaks++] = (
unsigned char)i;
646 prev_slope = next_slope;
649 peak[nbpeaks++] = (
unsigned char)(size - 1);
652 index_highest_peak = 0;
653 for (
unsigned int i = 0; i < nbpeaks; i++) {
654 if (histogram[peak[i]] > histogram[peak[index_highest_peak]]) {
655 index_highest_peak = i;
660 index_second_peak = index_highest_peak;
663 for (
unsigned i = 0; i < index_highest_peak; i++) {
664 if (peak[index_highest_peak] - peak[i] > dist) {
666 for (
int j = peak[i]; j <= peak[index_highest_peak] - dist; j++)
667 if ((histogram[peak[i]] - histogram[j]) > prof)
668 prof = histogram[peak[i]] - histogram[j];
670 if (prof > maxprof) {
672 index_second_peak = i;
678 for (
unsigned i = index_highest_peak + 1; i < nbpeaks; i++) {
679 if (peak[i] - peak[index_highest_peak] > dist) {
681 for (
int j = peak[index_highest_peak] + dist; j <= peak[i]; j++)
682 if ((histogram[peak[i]] - histogram[j]) > prof)
683 prof = histogram[peak[i]] - histogram[j];
685 if (prof > maxprof) {
687 index_second_peak = i;
693 if (peak[index_highest_peak] < peak[index_second_peak]) {
694 peakr.
set(peak[index_second_peak], histogram[peak[index_second_peak]]);
695 peakl.
set(peak[index_highest_peak], histogram[peak[index_highest_peak]]);
698 peakl.
set(peak[index_second_peak], histogram[peak[index_second_peak]]);
699 peakr.
set(peak[index_highest_peak], histogram[peak[index_highest_peak]]);
702 if (peakl == peakr) {
714 if (histogram[i] < mini) {
720 if (histogram[i] == mini) {
738 mini = sumindmini / nbmini;
739 valey.
set((
unsigned char)mini, histogram[mini]);
760 if (histogram ==
nullptr) {
773 unsigned sum_level = 0;
777 for (
unsigned i = 0; i < size - 1; i++) {
778 int next_slope = (int)histogram[i + 1] - (
int)histogram[i];
780 if ((prev_slope < 0) && (next_slope == 0)) {
787 if ((prev_slope < 0) && (next_slope > 0)) {
791 unsigned int level = sum_level / cpt;
792 p.
set((
unsigned char)level, histogram[level]);
799 prev_slope = next_slope;
803 if (prev_slope < 0) {
804 p.
set((
unsigned char)size - 1u, histogram[size - 1]);
843 unsigned int sumindmini;
850 if (histogram[i] < mini) {
856 if (histogram[i] == mini) {
869 unsigned int minipos = sumindmini / nbmini;
871 valey.
set((
unsigned char)minipos, histogram[minipos]);
896 unsigned int ret = 0x11;
898 unsigned int sumindmini;
901 std::list<vpHistogramPeak> peaks;
910 valeyr.
set((
unsigned char)(size - 1), 0);
922 std::list<vpHistogramPeak>::const_iterator it;
924 for (it = peaks.begin(); it != peaks.end(); ++it) {
940 std::list<vpHistogramPeak>::const_iterator lit;
941 for (lit = peaks.begin(); lit != it; ++lit) {
942 if (abs((*lit).getLevel() - peak.
getLevel()) > dist) {
958 if (histogram[i] < mini) {
964 if (histogram[i] == mini) {
974 unsigned int minipos = sumindmini / nbmini;
975 valeyl.
set((
unsigned char)minipos, histogram[minipos]);
986 std::list<vpHistogramPeak>::const_iterator it;
987 for (it = peaks.begin(); it != peaks.end(); ++it) {
996 std::list<vpHistogramPeak>::const_iterator rit;
997 for (rit = it; rit != peaks.end(); ++rit)
999 if (abs((*rit).getLevel() - peak.
getLevel()) > dist) {
1007 peakr.
set((
unsigned char)(size - 1), 0);
1013 for (
unsigned i = (
unsigned int)peak.
getLevel() + 1; i <= (
unsigned int)peakr.
getLevel(); i++) {
1014 if (histogram[i] < mini) {
1015 mini = histogram[i];
1020 if (histogram[i] == mini) {
1026 valeyr.
set((
unsigned char)(size - 1), 0);
1030 unsigned int minipos = sumindmini / nbmini;
1031 valeyr.
set((
unsigned char)minipos, histogram[minipos]);
1050 if (peaks.empty()) {
1054 peaks.sort(compare_vpHistogramPeak);
1056 return (
unsigned int)peaks.size();
1087 FILE *fd = fopen(filename,
"w");
1090 for (
unsigned i = 0; i < size; i++)
1091 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)
void equalize(const vpImage< unsigned char > &I, vpImage< unsigned char > &Iout)
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 ...
unsigned int getWidth() const
void performLut(const Type(&lut)[256], unsigned int nbThreads=1)
unsigned int getSize() const
Type * bitmap
points toward the bitmap
unsigned int getHeight() const
static int round(double x)