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