第11篇:色彩平衡与通道混合

系列导语:本文是"有趣的图像处理"系列第11篇,也是色彩映射章节的最后一篇。前三篇依次讲了点运算(亮度/对比度/Gamma)、HSL 独立调色、曲线与直方图。本篇聚焦两个更精细的工具:色彩平衡(对阴影/中间调/高光分区调色)和通道混合(R/G/B 通道间的线性组合),并延伸到色温调整与自然饱和度(Vibrance)。

[← 第10篇:曲线与直方图——色调重映射的两种方式] | [第12篇:仿射变换与极坐标变换 →] | [系列目录]


导语

前面讲的调色操作都对整张图像一视同仁——每个像素无论亮暗,都使用同一条映射曲线。但摄影师和调色师常常需要更精细的控制:

“只把暗部的蓝色调暖,但不影响高光区域的颜色。”
“把红通道的一部分混入绿通道,模拟某种胶片风格。”

这两种需求分别对应色彩平衡通道混合。理解它们,你就掌握了专业调色的核心工具。

本文将带你理解:

  • 色彩平衡的分区原理:如何用亮度权重把调色限定在阴影/中间调/高光
  • 通道混合的矩阵本质:任何线性调色都是一次矩阵乘法
  • 色温调整:暖色/冷色的数学模型
  • 自然饱和度(Vibrance):为什么它比普通饱和度"更聪明"

一、色彩平衡——分区域调色

1.1 为什么要分区?

直接在 RGB 上加减颜色(如 R 通道加 20)会对整张图一致生效,无法区分"让暗部偏暖、高光保持冷调"这类需求。

色彩平衡的核心思路:根据每个像素的亮度值,计算它属于阴影/中间调/高光的权重,然后按权重分配调色量。

1.2 三区权重函数

设像素亮度归一化值 l ∈ [ 0 , 1 ] l \in [0,1] l[0,1](通常取 l = ( R + G + B ) / ( 3 × 255 ) l = (R+G+B)/(3 \times 255) l=(R+G+B)/(3×255)),三个区域的权重:

w shadows ( l ) = 1 4 ( 1 − l ) ⋅ 1 1 + e 10 ( l − 0.25 ) ⋅ 4 w_{\text{shadows}}(l) = \frac{1}{4}(1-l) \cdot \frac{1}{1 + e^{10(l-0.25)}} \cdot 4 wshadows(l)=41(1l)1+e10(l0.25)14

更简洁的实现(Photoshop 风格的分段线性近似):

w s ( l ) = max ⁡ ( 0 ,   1 − 2 l ) (阴影:亮度越低权重越高) w_s(l) = \max(0,\ 1 - 2l) \qquad \text{(阴影:亮度越低权重越高)} ws(l)=max(0, 12l)(阴影:亮度越低权重越高)

w m ( l ) = max ⁡ ( 0 ,   1 − 2 ∣ l − 0.5 ∣ ) (中间调:亮度在0.5附近权重最高) w_m(l) = \max(0,\ 1 - 2|l - 0.5|) \qquad \text{(中间调:亮度在0.5附近权重最高)} wm(l)=max(0, 12∣l0.5∣)(中间调:亮度在0.5附近权重最高)

w h ( l ) = max ⁡ ( 0 ,   2 l − 1 ) (高光:亮度越高权重越高) w_h(l) = \max(0,\ 2l - 1) \qquad \text{(高光:亮度越高权重越高)} wh(l)=max(0, 2l1)(高光:亮度越高权重越高)

三个权重之和不一定为 1,因此这是一个"叠加"操作而非归一化权重。

1.3 完整公式

设阴影/中间调/高光各自的 CMY 偏移量为 ( Δ r s , Δ g s , Δ b s ) (\Delta r_s, \Delta g_s, \Delta b_s) (Δrs,Δgs,Δbs) 等,则:

R out = clamp ( R + w s ⋅ Δ r s + w m ⋅ Δ r m + w h ⋅ Δ r h ,   0 ,   255 ) R_{\text{out}} = \text{clamp}\bigl(R + w_s \cdot \Delta r_s + w_m \cdot \Delta r_m + w_h \cdot \Delta r_h,\ 0,\ 255\bigr) Rout=clamp(R+wsΔrs+wmΔrm+whΔrh, 0, 255)

G、B 通道同理。

1.4 伪代码

函数 色彩平衡(图像 I, 阴影偏移(Δr_s,Δg_s,Δb_s),
                         中间调偏移(Δr_m,Δg_m,Δb_m),
                         高光偏移(Δr_h,Δg_h,Δb_h)):
    对每个像素 (R, G, B, A):
        # 计算归一化亮度
        l = (R + G + B) / (3 × 255)
        
        # 三区权重(分段线性近似)
        w_s = max(0, 1 - 2×l)
        w_m = max(0, 1 - 2×|l - 0.5|)
        w_h = max(0, 2×l - 1)
        
        # 按权重叠加各区域偏移
        R' = R + w_s×Δr_s + w_m×Δr_m + w_h×Δr_h
        G' = G + w_s×Δg_s + w_m×Δg_m + w_h×Δg_h
        B' = B + w_s×Δb_s + w_m×Δg_m + w_h×Δb_h
        
        输出 = (clamp(R',0,255), clamp(G',0,255), clamp(B',0,255), A)
    
    返回 输出

在这里插入图片描述
左:原图 / 右:色彩平衡(红色+40,蓝色-30)。整体偏暖,红色花朵更加鲜艳,绿色背景带明显黄调。


二、通道混合——矩阵乘法调色

2.1 核心公式

通道混合允许每个输出通道从所有输入通道线性组合:

[ R ′ G ′ B ′ ] = [ a r r a r g a r b a g r a g g a g b a b r a b g a b b ] [ R G B ] \begin{bmatrix} R' \\ G' \\ B' \end{bmatrix} = \begin{bmatrix} a_{rr} & a_{rg} & a_{rb} \\ a_{gr} & a_{gg} & a_{gb} \\ a_{br} & a_{bg} & a_{bb} \end{bmatrix} \begin{bmatrix} R \\ G \\ B \end{bmatrix} RGB = arragrabrargaggabgarbagbabb RGB

恒等矩阵(不做任何变化):

M identity = [ 1 0 0 0 1 0 0 0 1 ] M_{\text{identity}} = \begin{bmatrix} 1 & 0 & 0 \\ 0 & 1 & 0 \\ 0 & 0 & 1 \end{bmatrix} Midentity= 100010001

常用的矩阵操作示例

效果 矩阵描述
灰度化(NTSC) R ′ = G ′ = B ′ = 0.299 R + 0.587 G + 0.114 B R'=G'=B'= 0.299R + 0.587G + 0.114B R=G=B=0.299R+0.587G+0.114B
互换 R/G 通道 a r g = 1 , a g r = 1 a_{rg}=1,a_{gr}=1 arg=1,agr=1,其余对角线为 0
红色增强 a r r = 1.2 a_{rr}=1.2 arr=1.2,其他对角线不变
胶片风格(交叉冲洗) 非对角线有明显非零系数

2.2 线性代数视角

所有线性调色操作(亮度缩放、通道交换、灰度化、色温调整的线性部分)都可以表示为 3×3 矩阵乘法。多个操作的合并也只是矩阵相乘:

M total = M n ⋅ M n − 1 ⋯ M 2 ⋅ M 1 M_{\text{total}} = M_n \cdot M_{n-1} \cdots M_2 \cdot M_1 Mtotal=MnMn1M2M1

这意味着:无论链式叠加多少个线性调色操作,最终都可以合并为一次矩阵乘法执行,效率极高。

2.3 伪代码

函数 通道混合(图像 I, 3×3矩阵 M):
    对每个像素 (R, G, B, A):
        # 矩阵乘法
        R' = M[0,0]×R + M[0,1]×G + M[0,2]×B
        G' = M[1,0]×R + M[1,1]×G + M[1,2]×B
        B' = M[2,0]×R + M[2,1]×G + M[2,2]×B
        
        输出 = (clamp(R',0,255), clamp(G',0,255), clamp(B',0,255), A)
    
    返回 输出

NumPy 向量化实现(对整张图一次完成):

rgb = 图像[:,:,:3].astype(float32)            # shape: (H, W, 3)
输出 = rgb @ M.T                              # 矩阵乘法,shape 不变
输出 = clamp(输出, 0, 255).astype(uint8)

在这里插入图片描述

左:原图 / 右:通道混合(R混入30%的G,G混入20%的B,B混入20%的R)。花朵红色偏橙,绿色背景出现青调,整体色调明显偏移。


三、色温调整——暖色与冷色的数学

3.1 什么是色温?

色温(单位 K,开尔文)来自物理学:不同温度的黑体辐射不同颜色的光。低色温(2700K)是暖黄色(蜡烛光),高色温(7000K)是冷蓝色(阴天)。

数字图像中的"色温调整"是对白平衡的模拟:

  • 升高色温(变暖):增加 R,减少 B
  • 降低色温(变冷):减少 R,增加 B

3.2 简化线性模型

R out = clamp ( R + Δ T ,   0 ,   255 ) R_{\text{out}} = \text{clamp}(R + \Delta T,\ 0,\ 255) Rout=clamp(R+ΔT, 0, 255)

B out = clamp ( B − Δ T ,   0 ,   255 ) B_{\text{out}} = \text{clamp}(B - \Delta T,\ 0,\ 255) Bout=clamp(BΔT, 0, 255)

其中 Δ T > 0 \Delta T > 0 ΔT>0 变暖, Δ T < 0 \Delta T < 0 ΔT<0 变冷。G 通道通常做小幅补偿:

G out = clamp ( G + 0.1 ⋅ Δ T ,   0 ,   255 ) G_{\text{out}} = \text{clamp}(G + 0.1 \cdot \Delta T,\ 0,\ 255) Gout=clamp(G+0.1ΔT, 0, 255)

更精确的色温调整需要在 XYZ 色彩空间(设备无关的物理光色空间)中操作,通过色适应变换(Bradford 矩阵)从一个白点转到另一个白点,再转回 RGB。

3.3 伪代码

函数 色温调整(图像 I, 温度偏移 ΔT ∈ [-100, 100]):
    对每个像素 (R, G, B, A):
        R' = clamp(R + ΔT,       0, 255)   # 正值变暖
        G' = clamp(G + 0.1×ΔT,  0, 255)   # 轻微补偿
        B' = clamp(B - ΔT,       0, 255)   # 正值减蓝
        输出 = (R', G', B', A)
    
    返回 输出

左:原图 / 右:色温升高(ΔT=+60,强烈变暖)。花朵红色极度浓郁,绿色背景大幅偏黄,整体呈现强烈暖调。
在这里插入图片描述


四、自然饱和度(Vibrance)——保护已饱和颜色

4.1 普通饱和度的问题

第9篇的饱和度调整对所有像素一视同仁:无论原始饱和度高低,都均等增加。这会导致:

  • 已经高度饱和的颜色(如纯红)进一步增强,产生过饱和(霓虹感)
  • 低饱和度区域(如皮肤)变化明显,但高饱和区域反而过度

4.2 Vibrance 的保护机制

Vibrance(自然饱和度) 是 Adobe Camera Raw 引入的概念,核心思想:

当前饱和度越高,增强幅度越小;饱和度越低,增强幅度越大。

调整量与当前饱和度成反比:

Δ S = amount × ( 1 − S current ) \Delta S = \text{amount} \times (1 - S_{\text{current}}) ΔS=amount×(1Scurrent)

S current S_{\text{current}} Scurrent 越接近 1(已很饱和), Δ S \Delta S ΔS 越接近 0(几乎不增强); S current S_{\text{current}} Scurrent 接近 0(很灰), Δ S \Delta S ΔS 接近 amount(充分增强)。

4.3 伪代码

函数 自然饱和度(图像 I, 调整量 amount ∈ [-1, 1]):
    对每个像素 (R, G, B, A):
        (H, S, V) = RGB_to_HSV(R, G, B)
        
        # 保护机制:饱和度越高,增强越少
        ΔS = amount × (1 - S)
        S_new = clamp(S + ΔS, 0, 1)
        
        (R', G', B') = HSV_to_RGB(H, S_new, V)
        输出 = (R', G', B', A)
    
    返回 输出

与普通饱和度的对比

  • 普通饱和度(第9篇): S new = S + Δ S S_{\text{new}} = S + \Delta S Snew=S+ΔS(固定增量)
  • 自然饱和度: S new = S + amount × ( 1 − S ) S_{\text{new}} = S + \text{amount} \times (1 - S) Snew=S+amount×(1S)(自适应增量)

数学上,自然饱和度是一个向 S=1 方向的线性插值 S new = S + amount × ( 1 − S ) = ( 1 − amount ) × S + amount S_{\text{new}} = S + \text{amount} \times (1-S) = (1-\text{amount}) \times S + \text{amount} Snew=S+amount×(1S)=(1amount)×S+amount

在这里插入图片描述

左:原图 / 右:自然饱和度(amount=0.9)。低饱和度的绿色背景显著变鲜艳,而已高度饱和的红色花朵变化幅度明显较小,体现了自适应增量的保护机制。


五、线性调色的统一框架

5.1 仿射变换:矩阵 + 偏移

所有本篇(以及第8篇)的调色操作都属于仿射变换

[ R ′ G ′ B ′ ] = M [ R G B ] + [ b R b G b B ] \begin{bmatrix} R' \\ G' \\ B' \end{bmatrix} = M \begin{bmatrix} R \\ G \\ B \end{bmatrix} + \begin{bmatrix} b_R \\ b_G \\ b_B \end{bmatrix} RGB =M RGB + bRbGbB

其中 M M M 是 3×3 矩阵(通道混合部分), b \mathbf{b} b 是偏移向量(色彩平衡/色温部分)。

操作 M M M b \mathbf{b} b
亮度缩放 b I bI bI 0 \mathbf{0} 0
对比度 c I cI cI ( 1 − c ) × 128 ⋅ 1 (1-c) \times 128 \cdot \mathbf{1} (1c)×1281
通道混合 任意 M M M 0 \mathbf{0} 0
色温调整 I I I ( Δ T ,   0.1 Δ T ,   − Δ T ) T (\Delta T,\ 0.1\Delta T,\ -\Delta T)^T (ΔT, 0.1ΔT, ΔT)T
灰度化 NTSC 行向量重复 0 \mathbf{0} 0

5.2 合并多个操作

利用矩阵结合律, n n n 个仿射变换可以合并为一个:

T n ∘ ⋯ ∘ T 1 = { M n ⋯ M 1 ,   M n b n − 1 + ⋯ + b n } T_n \circ \cdots \circ T_1 = \{M_n \cdots M_1,\ M_n \mathbf{b}_{n-1} + \cdots + \mathbf{b}_n\} TnT1={MnM1, Mnbn1++bn}

这是 ICC 色彩配置文件LUT 预烘焙的数学基础——把复杂的调色链压缩成单次矩阵乘法或查表,实时渲染效率极高。


六、实现要点

6.1 色彩平衡的权重设计

本文给出的分段线性权重是简化版。Photoshop 实际使用的是更复杂的平滑权重(类似钟形曲线),避免三个区域交界处的突变感。若需要更精确的效果,可以用 Sigmoid 或三次 Hermite 曲线替代。

6.2 通道混合的归一化

通道混合矩阵的行之和不必为 1,但若各行之和远大于 1,会导致输出大量像素截断到 255(过曝)。常见约定是每行系数之和等于 1,保持整体亮度不变: a r r + a r g + a r b = 1 a_{rr} + a_{rg} + a_{rb} = 1 arr+arg+arb=1

6.3 自然饱和度与肤色保护

完整的 Vibrance 实现通常还包含肤色保护:检测像素是否在皮肤色相范围(H ≈ 15°–40°),若是则进一步减小增强幅度,防止人脸变橙。Adobe 的实现细节未公开,但思路是在饱和度保护基础上加色相权重。


结语

本文完成了色彩映射章节的最后一篇:

  • 色彩平衡:用亮度权重函数把调色分区到阴影/中间调/高光,实现分区调色
  • 通道混合:3×3 矩阵乘法,统一所有线性调色操作;多步骤可合并为一次矩阵乘法
  • 色温调整:R 与 B 通道的反向加减,简单线性模型即可模拟暖/冷调效果
  • 自然饱和度:自适应增量( ( 1 − S ) (1-S) (1S) 因子),保护高饱和区域,低饱和区域优先增强
  • 仿射变换框架:所有线性调色 = 矩阵乘法 + 偏移,多步操作可预烘焙

至此,色彩映射四篇(08–11)全部完成,覆盖了从最基础的点运算到专业调色工具的完整体系。下一章回到几何变换,探讨非线性位移场——漩涡、鱼眼、水波纹与球面化。


系列文章导航

标签图像处理 色彩平衡 通道混合 色温 自然饱和度 Vibrance 矩阵乘法 仿射变换 调色 Python OpenCV


本文是"有趣的图像处理"系列的第11篇,所有算法基于 Python + OpenCV + NumPy 实现,完整代码见 Github。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐