# How to calculate median and standard deviation from histogram?

I have a 256 bin histogram of an 8 bit image.

Is it possible to calculate the Median, Variance and Standard deviation of the image from the given histogram?

If yes, then what is the procedure?

Thank you.

-

## 3 Answers

You can't calculate any of them exactly because all you have is the interval of values that they belong to and not their exact values. It is the mode and not the median that is in the tallest bin. You can determine which bin the median is in and thus know the two end points of its bin are values that it falls betweem. To find where the median is you just total the number of data points in each bin starting from the left unit the get to the integer equal to (n-1)/2 when n is odd and (n+1)/2 if (n-1)/2 and (n+1)/2 are in the same bin. If (n+1)/2 is in a higher bin then (n-1)/2 you can't be sure which bin the median is in but you know it is near the boundary separating the two adjacent bins.

You can calculate grouped mean and grouped variances which may be rough approximations to the actual sample means and variances but not exact.

-
Since the image is 8-bit, there are 256 discrete intensity levels (the integers from 0 to 255), so the histogram actually gives an exact representation of the data set. Having the histogram is equivalent to having the list of all pixel intensities, so the median, variance, etc. can be calculated exactly. –  Matthew Conroy Sep 25 '12 at 18:56

Since you have exactly all the pixel values and their occurrences, you could reorder them in an array in O(n) – with n the number of pixels – and simply pick the value in the middle of the array.

int* histogram(Image& img)
{
int hist[256] = {0};
int i,j;
for (i=0; i<img.height; i++)
{
for (j=0; j<img.width; j++)
{
hist[img.at(i,j)]++;
}
}
}

double median(int* hist, int n)
{
double med;
int *values = (int*) malloc(n, sizeof(int));
double position = double(n+1)/2.0;
int _position_ = (int) floor(position);
int i,j,k;
// Order pixel values
for (i=0; i<256; i++)
{
for (j=0; j<hist[i]; j++)
{
values[k++] = i;
}
}
// Get median value
if (position == (double)_position_)
{
// Odd number of pixels
med = (double) values[_position_];
}
else
{
// Even number of pixels
med = double(values[_position_] + values[_position_+1])/2.0;
}
free(values);
return med;
}

int main(int argc, char* argv[])
{
Image img;
int *hist;
double med;

// Load image
img = imread(argv[argc-1]);

// Compute histogram
hist = histogram(img);

// Compute median
med = median(hist, img.height*img.width);

printf("The median value is: %f", med);
return 0;
}

-

Adding to Michaels answer: You can compute grouped mean and std.dev, but they are approximations. While there are no systematic error in the approximation to the mean, the st.dev will be underestimated in this way (since you are calculating as if all observations falling in the same bin are in fact equal, so you miss the contribution to variance from variation within bins). Long time ago corrections was developed for this, based on the fact that the variance of a uniform distribution on $[a,b]$ is $\frac{ (b-a)^2}{12}$. They are Sheppards corrections: http://mathworld.wolfram.com/SheppardsCorrection.html

-