白平衡算法Gray World, Shades of Gray, Gray Edge python算法实现
参考链接:
https://blog.csdn.net/weixin_43194305/article/details/101758864
https://blog.csdn.net/weixin_43194305/article/details/101794682 (Gray Edge)
Understanding White Balance Control - 知乎 (zhihu.com)
背景
数字成像时的颜色主要依赖三个因素:物体表面光谱反射率、场景中的光照条件和成像元件对光的灵敏度。人类视觉系统存在一种颜色恒常性的功能,能够在不同光照下自动消除光照的影响,从而获得较稳定和准确的物体颜色,但是成像设备不具备这种特质,因此白平衡算法对成像颜色好坏起到了至关重要的作用。白平衡算法的核心就是估计光照,但是从已有的一幅图像去估计光照本身就是一个问题。因此,现有的白平衡算法基本都是基于一定的假设和先验条件。其中,Gray World是基于假设,简单、实用的白平衡算法。
Gray World
Gray World假设场景中所有物理表面的平均反射是无色差的(灰色的),这也是灰色世界名字的由来,简而言之,Gray World就是将整幅图像的平均颜色作为图像的光照颜色。Gray World的假设条件相对宽松,对一般图像适应能力强,同时也很简单,因此得到广泛使用。缺点是图像中颜色比较单一的时候,该法就会失效。改进主要也是针对基于如何适用于颜色较单一场景的情况,例如对图像分块处理。
灰度世界假设认为:对于一幅有着大量色彩变化的图像,R,G, B三个分量的统计平均值趋于同一灰度值。 从物理意义上讲,灰度世界模型假设自然界景物对于光线的反射系数的均值在总体上是个定值,这个定值近似地为“灰色”。 依据灰度世界模型实现的白平衡算法认为图像中R,G,B分量的平均值如果偏离1:1:1则一定是因为环境光线变化引起的,算法会据此对R,G,B增益进行反馈调节以补偿环境光的变化,使三个分量的平均值重新回到1:1:1。基于上述假设就不难理解灰度世界的计算流程了,整个计算流程如下:
-
确定 G r a y ‾ \overline{Gray} Gray值,通过计算图像R,G,B三通道的平均值 R ˉ , G ˉ , B ˉ \bar{R},\bar{G},\bar{B} Rˉ,Gˉ,Bˉ ,最后再用来计算 G r a y ‾ = R ˉ + G ˉ + B ˉ 3 \overline{Gray}=\frac{\bar{R}+\bar{G}+\bar{B}}{3} Gray=3Rˉ+Gˉ+Bˉ;另一种方式是直接取固定值,比如取灰度值的一半,按照8位显示取128;
-
计算R,G,B三通道的增益系数:
k r = G r a y ‾ R ˉ k g = G r a y ‾ G ˉ k B = G r a y ‾ B ˉ k_r=\frac{\overline{Gray}}{\bar{R}} \qquad k_g=\frac{\overline{Gray}}{\bar{G}} \qquad k_B=\frac{\overline{Gray}}{\bar{B}} kr=RˉGraykg=GˉGraykB=BˉGray -
根据Von Kries对角模型,即可用一个对角矩阵变换描述两种光照条件下同一物体表面颜色间的关系,其中对角矩阵可表示为:
D = [ k r 0 0 0 k g 0 0 0 k b ] D= \left[ \begin{array}{ccc} k_r & 0 & 0 \\ 0 & k_g & 0 \\ 0 & 0 & k_b \end{array} \right] D= kr000kg000kb
对于图像中的每个像素C,可以调整其分量R,G,B分量:
C ( R ′ ) = C ( R ) × k r C ( G ′ ) = C ( G ) × k g C ( B ′ ) = C ( B ) × k b C(R')=C(R)×k_r\\ C(G')=C(G)×k_g\\ C(B')=C(B)×k_b\\ C(R′)=C(R)×krC(G′)=C(G)×kgC(B′)=C(B)×kb
这种算法简单快速,但是当图像场景颜色并不丰富时,尤其出现大块单色物体时,该算法常会失效。
def GrayWorld(im, flag=None):
# Image should be normalized to 0-1
R_avg = np.mean(im[:, :, 0])
G_avg = np.mean(im[:, :, 1])
B_avg = np.mean(im[:, :, 2])
if flag is None or flag == 0:
Avg = 0.5
elif flag == 1:
Avg = np.mean(im)
else:
Avg = G_avg
k = np.array([R_avg, G_avg, B_avg], dtype=float) / Avg
out = np.copy(im)
for i in range(3):
out[:, :, i] = im[:, :, i] / k[i]
out[:, :, i] = np.minimum(out[:, :, i], 1)
return out
SoG(Shades of Gray)
为了将Gray World更加一般化,Finalayson等人在上式中引入了闵可夫斯基范式(Minkowskinorm),提出了一种SoG算法。SoG算法利用闵式距离 d 12 = ∑ k = 1 n ∣ x 1 k − x 2 k ∣ p p d_{12}=\sqrt[p]{\sum^n_{k=1}|x_{1k} - x_{2k}|^p} d12=p∑k=1n∣x1k−x2k∣p代替简单求平均的方法:
计算流程:
-
对输入图像 i m g img img计算 p p p的幂次方,得到新的图像 i m g p img_p imgp
-
分别计算图像 i m g p img_p imgp中红色通道、绿色通道和蓝色通道的均值,再对每个通道均值计算 1 p \frac{1}{p} p1,分别命名为 R a v g R_{avg} Ravg、 G a v g G_{avg} Gavg和 B a v g B_{avg} Bavg,计算全图 i m g p img_p imgp的均值命名为 Avg。
3)计算通道增益系数:
k
r
=
A
V
G
‾
R
a
v
g
k
g
=
A
V
G
‾
G
a
v
g
k
B
=
A
V
G
‾
B
a
v
g
k_r=\frac{\overline{AVG}}{R_{avg}} \qquad k_g=\frac{\overline{AVG}}{G_{avg}} \qquad k_B=\frac{\overline{AVG}}{B_{avg}}
kr=RavgAVGkg=GavgAVGkB=BavgAVG
4) 对于图像中的每个像素C,可以调整其分量R,G,B分量:
C
(
R
′
)
=
C
(
R
)
×
k
r
C
(
G
′
)
=
C
(
G
)
×
k
g
C
(
B
′
)
=
C
(
B
)
×
k
b
C(R')=C(R)×k_r\\ C(G')=C(G)×k_g\\ C(B')=C(B)×k_b\\
C(R′)=C(R)×krC(G′)=C(G)×kgC(B′)=C(B)×kb
def SoG(im, p=6):
# Image should be normalized to 0-1
imP = np.power(im, p)
R_avg = np.mean(imP[:, :, 0]) ** (1/p)
G_avg = np.mean(imP[:, :, 1]) ** (1/p)
B_avg = np.mean(imP[:, :, 2]) ** (1/p)
Avg = np.mean(imP) ** (1/p)
k = [R_avg, G_avg, B_avg] / Avg
out = np.copy(im)
for i in range(3):
out[:, :, i] = im[:, :, i] / k[i]
out[:, :, i] = np.minimum(out[:, :, i], 1)
return out
Gray Edge
GrayWorld算法都是基于原始图像的特征提出的。Weijer等人通过观察对立颜色空间的图像颜色导数分布,发现图像的颜色导数在对立颜色空间呈一定规则,对立颜色空间的获得是从RGB空间做一个变换得到。
根据图像颜色在这个空间上的一些特性,Weijer提出了一种新的Gray Edge假说:场景中所有物理表面的平均反射的差分是无色差的。同时,为了兼容几大基本算法,闵可夫斯基范式也被引入,得到了一个更为通用的颜色恒常性计算的算法框架。具体计算公式:
(
∫
∣
∂
n
f
σ
(
x
)
∂
X
n
∣
p
d
x
)
1
p
=
k
e
n
,
p
,
σ
(\int|\frac{\partial^nf^\sigma(x)}{\partial X^n}|^pdx)^{\frac{1}{p}}=ke^{n,p,\sigma}
(∫∣∂Xn∂nfσ(x)∣pdx)p1=ken,p,σ
其中**
f
n
=
f
⨂
G
σ
f^n=f\bigotimes G^{\sigma}
fn=f⨂Gσ**表示图像f和高斯滤波器
G
σ
G^{\sigma}
Gσ的卷积,$\frac{\partial^n}{\partial X^n}
表示
n
阶求导过程,选择不同的
表示n阶求导过程,选择不同的
表示n阶求导过程,选择不同的n,p,\sigma$参数表示不同的颜色恒常性算法。
计算流程:
- 用高斯滤波对图像进行卷积运算;
2)计算图像n阶导数,即计算图像梯度,在实际计算中用差分来近似求导;
-
对差分图像 i m g img img计算 p p p的幂次方,得到新的图像 i m g p img_p imgp;
-
分别计算图像 i m g p img_p imgp中红色通道、绿色通道和蓝色通道的均值,再对每个通道均值计算 1 p \frac{1}{p} p1,分别命名为 R a v g R_{avg} Ravg、 G a v g G_{avg} Gavg和 B a v g B_{avg} Bavg,计算全图 i m g p img_p imgp的均值命名为 Avg。
5)计算通道增益系数:
k
r
=
A
V
G
‾
R
a
v
g
k
g
=
A
V
G
‾
G
a
v
g
k
B
=
A
V
G
‾
B
a
v
g
k_r=\frac{\overline{AVG}}{R_{avg}} \qquad k_g=\frac{\overline{AVG}}{G_{avg}} \qquad k_B=\frac{\overline{AVG}}{B_{avg}}
kr=RavgAVGkg=GavgAVGkB=BavgAVG
6) 对于图像中的每个像素C,可以调整其分量R,G,B分量:
C
(
R
′
)
=
C
(
R
)
×
k
r
C
(
G
′
)
=
C
(
G
)
×
k
g
C
(
B
′
)
=
C
(
B
)
×
k
b
C(R')=C(R)×k_r\\ C(G')=C(G)×k_g\\ C(B')=C(B)×k_b\\
C(R′)=C(R)×krC(G′)=C(G)×kgC(B′)=C(B)×kb
def GrayEdge(im, p=6, sigma=2):
out = im.copy()
k_size = int(sigma * 3 + 0.5)
k = cv2.getGaussianKernel(k_size, sigma) # 高斯核
im_G = cv2.filter2D(im, -1, k, borderType=cv2.BORDER_REPLICATE) # 高斯滤波
im_edge = np.gradient(im_G) # 计算梯度
# 闵可夫斯基p范式
im_edge = np.abs(im_edge) ** p
r, g, b = im_edge[:, :, 0], im_edge[:, :, 1], im_edge[:, :, 2]
Avg = np.mean(im_edge) ** (1 / p)
R_avg = np.mean(r) ** (1 / p)
G_avg = np.mean(g) ** (1 / p)
B_avg = np.mean(b) ** (1 / p)
# 计算增益K
k = np.array([R_avg, G_avg, B_avg]) / Avg
for i in range(3):
out[:, :, i] = im[:, :, i] / k[i]
out[:, :, i] = np.minimum(out[:, :, i], 1)
return out
以下为图像分别为原图和GW, SoG, GrayEdge3种白平衡算法处理结果:
附:对立颜色空间
对立颜色空间(Opponent Color Space)是一种用于描述和表示颜色的色彩模型。它是基于对颜色感知的生物学原理而设计的,认为人类视觉系统中存在对立的颜色通道,这些通道对两种对立的颜色维度进行编码,这两种对立的颜色维度通常被称为对立色彩通道它们是:
亮度(Luminance): 这个通道表示图像中的亮度或明暗度,通常用来表示灰度信息。亮度通道不包含颜色信息,只包含灰度信息。
色度(Chrominance): 这个通道表示颜色的属性,包括颜色的饱和度和色调。色度通道包括了红绿对比度和蓝黄对比度两个对立的颜色维度。
对立颜色空间常用在图像分析和图像编码中,它允许将颜色信息分解为亮度和色度信息,从而可以更容易地进行各种图像处理任务,如边缘检测、颜色分割和压缩等。
常见的对立颜色空间模型包括:
RGB-RYB对立色彩空间: 在这个模型中,对立色彩通道包括红色(Red)-青色(Cyan)和黄色(Yellow)-蓝色(Blue)。
LAB对立色彩空间: 这是CIELAB色彩空间的一种表示方式,对立色彩通道包括明度(L)-对比度、绿-红通道(a轴)和蓝-黄通道(b轴)。
YUV对立色彩空间: 在这个模型中,亮度通道(Y)与色差通道(U和V)分别对应于亮度和色度信息,其中U通道表示蓝-黄对比度,V通道表示红-绿对比度。