Fast image gamma correction

2.1k views Asked by At

I am doing a gamma correction on an image of dimensions 5000x3000x3.

The formula is

value ^ (1 / gamma)

for RGB values from 0.0 to 1.0

My input gamma values range from 0.0 to 10.0 while gamma = 0.0 always outputs 0.0.

The trouble is that the involved pow computation is so slow.

Doing this takes about 1300 milliseconds on a float[, ,]:

for (int y = 0; y < 3000; y++)
{
    for (int x = 0; x < 5000; x++)
    {
        for (int z = 0; z < 3; z++)
        {
            arr[x, y, z] = (float)Math.Pow(arr[x, y, z], 0.3);
        }
    }
}

And using NMathFunctions.Pow on a FloatMatrix this takes about 1100 milliseconds:

a = NMathFunctions.Pow(a, 0.3f);

Any idea how to speed things up?

1

There are 1 answers

3
Basile Perrenoud On BEST ANSWER

EDIT: Actually I'm not sure this works will if the power is smaller than 1. I know it works for gamma correction when you want to replace pow(x, 2.2). it works even better when the power is higher, but might not be good with powers smaller than 1


Indeed, pow is a really slow function, even slower than sqrt (Which make sense since any sqrt operation could be done with pow using a fraction as exponent)

There is no way to compute the power exactly more efficiently, but there are pretty good way to estimate it.

One condition is that your base value is in the range [0, 1], which is true in your case. Then you can get a good estimate (accurate at around 99%). here is how you can do it:

Use a mix of discrete powers, that you compute yourself instead of with pow. so for example with x in the range [0, 1],

instead of

result = pow(x, 2.2)

do

result = 0.8*x*x + 0.2*x*x*x

Note that it is perfectly accurate when x is 0 and when x is 1 (results are 0 and 1 respectively)

I hope this will work for you