Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Automatic White Balancing with Grayworld assumption

I have been trying to implement the white balancing algorithms provided by: https://pippin.gimp.org/image-processing/chapter-automaticadjustments.html

I have used python and opencv to implement them. I am unable to produce the same results as in the website.

In grayworld assumption, for example, i use the following code:

import cv2 as cv
import numpy as np

def show(final):
    print 'display'
    cv.imshow("Temple", final)
    cv.waitKey(0)
    cv.destroyAllWindows()

def saveimg(final):
    print 'saving'
    cv.imwrite("result.jpg", final)

# Insert any filename with path
img = cv.imread("grayworld_assumption_0.png")
res = img
final = cv.cvtColor(res, cv.COLOR_BGR2LAB)

avg_a = -np.average(final[:,:,1])
avg_b = -np.average(final[:,:,2])

for x in range(final.shape[0]):
    for y in range(final.shape[1]):
        l,a,b = final[x][y]
        shift_a = avg_a * (l/100.0) * 1.1
        shift_b = avg_b * (l/100.0) * 1.1
        final[x][y][1] = a + shift_a
        final[x][y][2] = b + shift_b

final = cv.cvtColor(final, cv.COLOR_LAB2BGR)
final = np.hstack((res, final))
show(final)
saveimg(final)

I am getting the result

instead of

Where am I going wrong?

like image 919
Saptarshi Avatar asked Sep 24 '17 13:09

Saptarshi


People also ask

What does auto white balance do?

In auto white balance mode, your camera examines the scene you're trying to photograph and chooses a color temperature (in Kelvin) it thinks will work best. However, your camera can easily get confused if the scene: Doesn't contain any colors which are white, or close to white.

What is white balancing in image processing?

White balance (WB) is the process of removing unrealistic color casts, so that objects which appear white in person are rendered white in your photo. Proper camera white balance has to take into account the "color temperature" of a light source, which refers to the relative warmth or coolness of white light.

What is the most common technique of color balancing a camera?

In film photography, color balance is typically achieved by using color correction filters over the lights or on the camera lens.

What is the formula for color balance?

The goal of IRGB intensity balance is to correct the intensity of a color image without modifying the R/G/B ratio of the pixels. We first compute the gray level intensity (I = (R + G + B)/3), then this intensity is balanced and transformed into I by the affine transformation with saturation.


1 Answers

The document you are implementing is not aware of CV internal conventions for LAB definition in case of 8-bit color depth.

In particular:

L: L / 100 * 255
A: A + 128
B: B + 128

I believe this is done for improved accuracy, because then one could use unsigned int8 precision in full for the luminosity while keeping a consistent unsigned data type for the whole array.

The code below, adapted from yours should work. Note that there are some minor fixes here and there (EDIT including wrapping up the interesting code in a function), but the actual sauce is within the nested for loop.

from __future__ import (
    division, absolute_import, print_function, unicode_literals)

import cv2 as cv
import numpy as np


def show(final):
    print('display')
    cv.imshow('Temple', final)
    cv.waitKey(0)
    cv.destroyAllWindows()

# Insert any filename with path
img = cv.imread('grayworld_assumption_0.png')

def white_balance_loops(img):
    result = cv.cvtColor(img, cv.COLOR_BGR2LAB)
    avg_a = np.average(result[:, :, 1])
    avg_b = np.average(result[:, :, 2])
    for x in range(result.shape[0]):
        for y in range(result.shape[1]):
            l, a, b = result[x, y, :]
            # fix for CV correction
            l *= 100 / 255.0
            result[x, y, 1] = a - ((avg_a - 128) * (l / 100.0) * 1.1)
            result[x, y, 2] = b - ((avg_b - 128) * (l / 100.0) * 1.1)
    result = cv.cvtColor(result, cv.COLOR_LAB2BGR)
    return result

final = np.hstack((img, white_balance_loops(img)))
show(final)
cv.imwrite('result.jpg', final)

EDIT:

The same result, but with much faster performances can be obtained by avoiding loops:

def white_balance(img):
    result = cv.cvtColor(img, cv.COLOR_BGR2LAB)
    avg_a = np.average(result[:, :, 1])
    avg_b = np.average(result[:, :, 2])
    result[:, :, 1] = result[:, :, 1] - ((avg_a - 128) * (result[:, :, 0] / 255.0) * 1.1)
    result[:, :, 2] = result[:, :, 2] - ((avg_b - 128) * (result[:, :, 0] / 255.0) * 1.1)
    result = cv.cvtColor(result, cv.COLOR_LAB2BGR)
    return result

which obviously gives the same result:

print(np.all(white_balance(img) == white_balance_loops(img)))
True

but with very different timings:

%timeit white_balance(img)
100 loops, best of 3: 2 ms per loop

%timeit white_balance_loops(img)
1 loop, best of 3: 529 ms per loop
like image 73
norok2 Avatar answered Oct 18 '22 20:10

norok2