Solved

# how to calculate bitmap 's contrast

Posted on 2004-11-11
702 Views
Experts

I am doing some image processing. i want to know how to calculate contrast
0
Question by:smallee

LVL 12

Expert Comment

Hi smallee,
Isn't there a graphics TA? Your question ist pretty much language-independent.

Cheers!

Stefan
0

LVL 22

Expert Comment

This is a bit of a toughie.

You could find the brightest pixel, the dimmest, and compute the contrast as the relative ratio of the two.

But then what if the picture is very low contrast, except for one black and one white pixel?

A better way would be to compute the standard deviation of the pixels.  A bit time consuming but probably much more accurate.

0

LVL 1

Expert Comment

// This calculates the contrast of the image:

vector<int> grayscale(width*height);

// fill image here

int x, y;
double xcontrast=0;
double ycontrast=0;
int xcount=0;
int ycount=0;

for (y=0; y<height; y++) {
for (x=0; x<width-1; x++) {
double xdiff = grayscale[y*width+x] - grayscale[y*width+x+1];
xcontrast += xdiff*xdiff;
xcount++;
}
}

for (y=0; y<height-1; y++) {
for (x=0; x<width; x++) {
double ydiff = grayscale[y*width+x] - grayscale[(y+1)*width+x];
ycontrast += ydiff*ydiff;
ycount++;
}
}

return hypot(sqrt(xcontrast/xcount), sqrt(ycontrast/ycount));

0

LVL 22

Expert Comment

Well, that code computes *something*, but it's not what I'd call the "contrast".

It's more like the average rate of change.  An image of alternating horizontal lines of 50% and 51% white (what most people would consider VERY LOW contrast) is going to give a much higher reading than an image that goes from 0 to 100% white from top to bottom.  Not quite most people's definition of contrast.

0

LVL 3

Author Comment

Hi grg99
Then what way should be better for calculating contrast

Actually, i want to split a bitmap into a number of n*n pixels region
and calculate the contrast of each region to find the max contrast region
0

LVL 22

Expert Comment

I'd compute a histogram of the pixel brightnesses, then start at both ends and throw away say 5 to 10% from each end, maybe  a bit more if the picture is noisy.

Then the span between those two points is a pretty good indication of the contrast.

0

LVL 3

Author Comment

Do you mean that Changing the RGB value to gray value

Gray = 0.3*Red + 0.59*Green + 0.11*Blue

then find the max and min gray value

However, I don't understand what mean "throw away say 5 to 10% from each end"

0

LVL 1

Assisted Solution

// This calculates the contrast of the image:
// Locality is not considered.
// This meets all objections by grg99...

vector<int> grayscale(width*height);

// fill image here

int n = width*height;
int i;
double sum=0;
for (i=0; i<n; i++) sum += grayscale[i];
double avg = sum / n;

double contrast;
for (i=0; i<n; i++) {
double diff = grayscale[i] - avg;
contrast += diff*diff;
}

return sqrt(contrast/n);
0

LVL 22

Expert Comment

Better, but not quite... You're still saying the contrast is proportional to the number of pixels away from the average.  So a black image with a 10x10 pixel white square will have by that algorithm,  1/100th the contrast of the same black background with a 100x100 white square.  IMHO neds a little more work....

0

LVL 1

Expert Comment

OK, whatever.  I think this answers smallee's question.
If you want to tweak these algorithms to make one you recommend to smallee over mine then feel free to do so, but these basic methods answer the question.
0

LVL 3

Author Comment

thx grg99 and foodlebardle

Give me some time to digest the answer

i will accept the answer as soon as possible
0

LVL 22

Accepted Solution

hard to describe without graphics, but here goes:

Build a histogram, a count of how many pixels have each level of gray.  Maybe use 100 bins.

You'll end up with something like:

0%:***         ( three black pixels )
1%:*****     ( five very dark gray pixels )
... and so on, up to:
50%:***********************************  ( a lot of medium gray pixels )
... and so on, up to:
99%:*******   (maybe 7 almost-white pixels )
100%: ***                      ( a few totally white pixels )

--------------------------------------------------------------------------------------------------------------------------

Now let's say there are 1000 total pixels.

I'd throw away the bottom 5%, as they're probably black noise pixels, same with top 5%.
So you start at 0% and keep counting pixels up the percentages until you've seen 5% of the pixels.
Take that percentage as "most dark".

Start at 100% too and count down 5% of the pixels, that will toss out a lot of white noise.
Call that the "most white" percentage.

The difference between those two will be one measure of contrast.

0

LVL 3

Author Comment

Thx again

I think i should increase the pts from your great help (grg99 and foodlebardle )

But give me some time for testing
0

LVL 9

Assisted Solution

>>
I'd throw away the bottom 5%, as they're probably black noise pixels, same with top 5%.
So you start at 0% and keep counting pixels up the percentages until you've seen 5% of the pixels.
Take that percentage as "most dark".

Start at 100% too and count down 5% of the pixels, that will toss out a lot of white noise.
Call that the "most white" percentage.

The difference between those two will be one measure of contrast.
<<

what if there are only black and white pixels? or for that matter one white pixel on black background. pixels should never be classified as noise but should be corrected if their value is within avg(neighbors) +/- noiselevel. then we can use (max-min) as contrast.

so the algo would be like this:
determine noise level:
process the image through a highpass filter.
take the median of absolute values as noise level
remove noise
if difference between pixel and avg of neighbors is within noise level, apply correction
use (max-min) as contrast

apply correction:
correction = |pixel value - avg|*(noise level - |pixel value - avg|)
corrected value = pixel value + correction * sign(pixel value - avg)
0

## Featured Post

Unlike C#, C++ doesn't have native support for sealing classes (so they cannot be sub-classed). At the cost of a virtual base class pointer it is possible to implement a pseudo sealing mechanism The trick is to virtually inherit from a base class…
What is C++ STL?: STL stands for Standard Template Library and is a part of standard C++ libraries. It contains many useful data structures (containers) and algorithms, which can spare you a lot of the time. Today we will look at the STL Vector. …
The viewer will learn how to user default arguments when defining functions. This method of defining functions will be contrasted with the non-default-argument of defining functions.
The viewer will be introduced to the technique of using vectors in C++. The video will cover how to define a vector, store values in the vector and retrieve data from the values stored in the vector.