带有灰色世界假设的自动白平衡
Posted
技术标签:
【中文标题】带有灰色世界假设的自动白平衡【英文标题】:Automatic White Balancing with Grayworld assumption 【发布时间】:2017-09-24 13:52:51 【问题描述】:我一直在尝试实现以下提供的白平衡算法: https://pippin.gimp.org/image-processing/chapter-automaticadjustments.html
我已经使用 python 和 opencv 来实现它们。我无法产生与网站相同的结果。
在灰色世界假设中,例如,我使用以下代码:
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)
我得到了结果
而不是
我哪里错了?
【问题讨论】:
cv.imread()
是否默认为 BGR?我曾假设它使用 RGB,但我现在找不到文档。这可能是问题吗? ...NVM 找到了文档,默认使用 BGR。
@norok 它在docs.opencv.org/3.0-beta/modules/imgcodecs/doc/… 中说,“在彩色图像的情况下,解码后的图像将具有以 B G R 顺序存储的通道。”
【参考方案1】:
在 8 位色深的情况下,您正在实施的文档不知道 LAB definition 的 CV 内部约定。
特别是:
L: L / 100 * 255
A: A + 128
B: B + 128
我相信这样做是为了提高准确性,因为这样可以完全使用 unsigned int8
精度来获得亮度,同时为整个数组保持一致的无符号数据类型。
下面的代码,改编自你的应该可以工作。
请注意,这里和那里都有一些小修复(EDIT 包括将有趣的代码包装在一个函数中),但实际的 sauce 位于嵌套的 for
循环中。
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)
编辑:
同样的结果,但通过避免循环可以获得更快的性能:
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
这显然给出了相同的结果:
print(np.all(white_balance(img) == white_balance_loops(img)))
True
但时间非常不同:
%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
【讨论】:
你能帮忙用 C++ 编写这些代码吗? 只问你自己的 C++ 问题可能更简单......不过,如果你愿意,你可以参考这个问题。该代码将类似于非矢量化代码。以上是关于带有灰色世界假设的自动白平衡的主要内容,如果未能解决你的问题,请参考以下文章