第11篇:色彩平衡与通道混合
第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(1−l)⋅1+e10(l−0.25)1⋅4
更简洁的实现(Photoshop 风格的分段线性近似):
w s ( l ) = max ( 0 , 1 − 2 l ) (阴影:亮度越低权重越高) w_s(l) = \max(0,\ 1 - 2l) \qquad \text{(阴影:亮度越低权重越高)} ws(l)=max(0, 1−2l)(阴影:亮度越低权重越高)
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, 1−2∣l−0.5∣)(中间调:亮度在0.5附近权重最高)
w h ( l ) = max ( 0 , 2 l − 1 ) (高光:亮度越高权重越高) w_h(l) = \max(0,\ 2l - 1) \qquad \text{(高光:亮度越高权重越高)} wh(l)=max(0, 2l−1)(高光:亮度越高权重越高)
三个权重之和不一定为 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} R′G′B′ = 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=Mn⋅Mn−1⋯M2⋅M1
这意味着:无论链式叠加多少个线性调色操作,最终都可以合并为一次矩阵乘法执行,效率极高。
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×(1−Scurrent)
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×(1−S)(自适应增量)
数学上,自然饱和度是一个向 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×(1−S)=(1−amount)×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} R′G′B′ =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} (1−c)×128⋅1 |
| 通道混合 | 任意 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\} Tn∘⋯∘T1={Mn⋯M1, Mnbn−1+⋯+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) (1−S) 因子),保护高饱和区域,低饱和区域优先增强
- ✅ 仿射变换框架:所有线性调色 = 矩阵乘法 + 偏移,多步操作可预烘焙
至此,色彩映射四篇(08–11)全部完成,覆盖了从最基础的点运算到专业调色工具的完整体系。下一章回到几何变换,探讨非线性位移场——漩涡、鱼眼、水波纹与球面化。
系列文章导航:
- 📖 当前位置:第11篇 - 色彩平衡与通道混合
- ➡️ 下一篇:第12篇 - 非线性位移场:漩涡、鱼眼、水波纹与球面化
- 🔙 上一篇:第10篇 - 曲线与直方图:色调重映射的两种方式
- 🔙 系列首页:总览篇
标签:图像处理 色彩平衡 通道混合 色温 自然饱和度 Vibrance 矩阵乘法 仿射变换 调色 Python OpenCV
本文是"有趣的图像处理"系列的第11篇,所有算法基于 Python + OpenCV + NumPy 实现,完整代码见 Github。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)