Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
232 views
in Technique[技术] by (71.8m points)

python - 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?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...