Create an histogram from datas vector

Hi Everybody,

I would like to print a histogram from datas vector.

My vector is composed of a 256 index and each index counts the number of gray scale level (present in an image) corresponding to the index vector.

Thus, my histogram will have 256 bins.

Next I would like to do statistics (mean, median, min, max) from my histogram

A need help !! Thanks a lot
mean = (histogram[0] + ... + histogram[255]) / 256
median = (histogram[127] + histogram[128]) / 2

min = least value of i such that histogram[i] > 0
max = greatest value of i such that histogram[i] > 0
Last edited on
median = (histogram[127] + histogram[128]) / 2

That is NOT true. The median is the i value for which half the data lies to the lower side.

For example, in an exaggerated case where one quarter of all your data lay in histogram[0] and three-quarters in histogram [255] then the median would be index 255.




mean = (histogram[0] + ... + histogram[255]) / 256

That is not true either. A normalised histogram would be like a probability density function, so the mean is a value of i, namely
(0*histogram[0] + 1*histogram[1] + 2*histogram[2] + ... + 255 * histogram[255]) / (histogram[0] + histogram[1] + histogram[2] + ... + histogram[255])




When binned like this, all those statistics are calling for a value of i (like you do correctly with min and max), not the counts in the bins.
Last edited on
D'oh! Lack of sleep, man.
Thanks for your answers !!

what is the code for find :
- min = least value of i such that histogram[i] > 0
- max = greatest value of i such that histogram[i] > 0

I work with iterator to browse my vector but I how can I get iterator value for which min and max values ??
I work with iterator to browse my vector but I how can I get iterator value for which min and max values ??

That is std::minmax_element
https://en.cppreference.com/w/cpp/algorithm/minmax_element
> what is the code for find :
> - min = least value of i such that histogram[i] > 0
> - max = greatest value of i such that histogram[i] > 0
> I work with iterator

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#include <iostream>
#include <vector>
#include <type_traits>
#include <cassert>

// returns a pair { iterator to the smallest positive element, iterator to the greatest positive element }
// if the range has no positive elements returns { end, end }.
// if many elements are equal to min or max, the iterator to the first such element is returned.
template < typename ITERATOR >
std::pair<ITERATOR,ITERATOR> min_max_positive_element( ITERATOR begin, ITERATOR end )
{
    using value_type = typename std::iterator_traits<ITERATOR>::value_type ;
    static_assert( std::is_arithmetic<value_type>::value, "a sequence of numeric values is expected" ) ;
    static constexpr auto ZERO = value_type{} ;

    // if the value at iter is non-positive, increment iter to 'point' to the next positive value
    static const auto positive_element = [] ( ITERATOR iter, ITERATOR iend )
    {
        while( iter != iend && *iter <= ZERO ) ++iter ;
        return iter ;
    };

    begin = positive_element(begin,end) ;
    auto min = begin ;
    auto max = begin ;

    while( begin != end )
    {
        if( *begin < *min ) min = begin ;
        if( *begin > *max ) max = begin ;

        ++begin ;
        begin = positive_element(begin,end) ;
    }

    return { min, max } ;
}

int main()
{
    {
        const std::vector<int> seq { 0, -5, 33, 0, 22, 4, -6, 11, 33, -2, 4, 33, -3, 0 } ;
        const auto [min,max] = min_max_positive_element( std::begin(seq), std::end(seq) ) ;
        assert( min != std::end(seq) && *min == 4 && *max == 33 ) ;
        // if many elements are equal to min or max, the iterator to the first such element is returned.
        assert( min == std::begin(seq)+5 && max == std::begin(seq)+2 ) ;
    }

    {
        // no positive elements
        const std::vector<double> seq { -1.2, 0.0, -3.4, 0.0, -2.3 } ;
        const auto [min,max] = min_max_positive_element( std::begin(seq), std::end(seq) ) ;
        //
        assert( min == std::end(seq) && max == std::end(seq) ) ;
    }

    std::cout << "ok\n" ;
}

http://coliru.stacked-crooked.com/a/9597aa89da5a6d47
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
#include <iostream>
#include <vector>
using namespace std;

//======================================================================

// Returns the smallest piece of DATA; i.e. the smallest index that has a positive count in the histogram
int minimum( const vector<int> &hist )
{
   for ( int i = 0; i < hist.size(); i++ ) if ( hist[i] > 0 ) return i;
   return -1;  // shouldn't happen; signifies no data
}

//======================================================================

// Returns the largest piece of DATA; i.e. the largest index that has a positive count in the histogram
int maximum( const vector<int> &hist )
{
   for ( int i = hist.size() - 1; i >= 0; i-- ) if ( hist[i] > 0 ) return i;
   return -1;  // shouldn't happen; signifies no data
}

//======================================================================

// Mean = sum( i * f_i ) / Ndata
double mean( const vector<int> &hist )
{
   int Ndata = 0, moment = 0;
   for ( int i = 0; i < hist.size(); i++ )
   {
      Ndata  += hist[i];
      moment += hist[i] * i;
   }
   if ( Ndata == 0 ) return -1.0;
   else              return ( moment + 0.0 ) / Ndata;
}

//======================================================================

// Find bin with xth piece of data, where F holds cumulative frequency; helper routine for median
int findNth( const vector<int> &F, int x )
{
   for ( int i = 0; i < F.size(); i++ ) if ( F[i] >= x ) return i;
   return -1;   // shouldn't happen, but keeps the compiler off my back
}

//======================================================================

// Median (requires a valid histogram)
double median( const vector<int> &hist )
{
   int N = hist.size();
   vector<int> F(N);       // cumulative frequency
   F[0] = hist[0];
   for ( int i = 1; i < N; i++ ) F[i] = F[i-1] + hist[i];
   int Ndata = F[N-1];     // total amount of data

   // if Ndata is odd, require bin with (1+Ndata)/2_th item in
   // if Ndata is even, require average of bins with Ndata/2_th and Ndata/2+1_th items in
   // bin i contains the x_th piece of data if F[i] >= x but F[i-1] < x, where F is cumulative frequency
   if ( Ndata % 2 ) return (double)findNth( F, ( 1 + Ndata ) / 2 );
   else             return 0.5 * ( findNth( F, Ndata / 2 ) + findNth( F, Ndata / 2 + 1 ) );
}

//======================================================================


int main()
{
   // a histogram contains NON-NEGATIVE counts
   vector<int> hist = { 0, 0, 0, 1, 2, 3, 2, 4, 3, 5, 10, 10, 6, 0, 0 };

   cout << "Minimum: " << minimum( hist ) << '\n';
   cout << "Maximum: " << maximum( hist ) << '\n';
   cout << "Mean:    " << mean   ( hist ) << '\n';
   cout << "Median:  " << median ( hist ) << '\n';
}


Minimum: 3
Maximum: 12
Mean:    9.06522
Median:  10
Last edited on
Thanks for all !!
Topic archived. No new replies allowed.