how to calculate bitmap 's contrast

Experts

I am doing some image processing. i want to know how to calculate contrast
LVL 3
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

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

Cheers!

Stefan
0
Commented:
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
Commented:
// 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
Commented:
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
Author Commented:
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
Commented:
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
Author Commented:
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
Commented:

// 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
Commented:
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
Commented:
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
Author Commented:
thx grg99 and foodlebardle

Give me some time to digest the answer

i will accept the answer as soon as possible
0
Commented:
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

Experts Exchange Solution brought to you by

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Author Commented:
Thx again

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

But give me some time for testing
0
Commented:
>>
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
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C++

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.