第3篇:色彩空间原理与转换——从RGB到HSI、HSV、LAB

第3篇:色彩空间原理与转换------从RGB到HSI、HSV、LAB

系列导语:本文是"有趣的图像处理"系列的第3篇。我们将深入探讨颜色空间的数学原理:为什么RGB不适合颜色调整?HSI、HSV、HSL、LAB颜色空间是如何定义的?它们之间的转换公式是什么?理解颜色空间,是掌握色彩校正、饱和度调整、图像分割等高级技术的关键。


导语

在第1篇和第2篇中,我们学习了像素操作和卷积运算。但你可能注意到一个问题:

在RGB空间调整颜色非常不直观!

  • 想让颜色更鲜艳?不知道该改R、G、B哪个通道
  • 想让图像变亮?调整RGB后颜色会偏色
  • 想提取红色区域?RGB中红色的定义很模糊

原因:RGB是面向硬件的颜色空间(显示器用),不是面向人类感知的。

解决方案 :使用更符合人类感知的颜色空间------HSI、HSV、HSL、LAB

本文将带你理解:

  • 为什么需要不同的颜色空间?
  • RGB ↔ HSI 的数学推导与转换公式
  • RGB ↔ HSV/HSL 的六区间分段算法
  • RGB ↔ CIE LAB 的色彩科学基础
  • 各颜色空间的应用场景

一、颜色空间的基础概念

1.1 什么是颜色空间?

**颜色空间(Color Space)**是一种用数学方法描述颜色的系统。

不同的颜色空间用不同的"坐标"来定义颜色:

  • RGB:用红、绿、蓝三原色的强度
  • HSV:用色相(颜色种类)、饱和度(纯度)、明度(亮度)
  • LAB:用亮度、红绿轴、黄蓝轴

1.2 RGB颜色空间的局限性

**RGB(Red, Green, Blue)**是最常用的颜色空间,但它有两个根本缺陷:

缺陷1:通道耦合

RGB三个通道不是独立的。改变一个通道会同时影响:

  • 颜色的色相(Hue)
  • 颜色的饱和度(Saturation)
  • 颜色的亮度(Intensity)

示例:将R通道加倍

复制代码
原始: (R=100, G=100, B=100) → 灰色
加倍R: (R=200, G=100, B=100) → 偏红的暖色

结果:不仅变亮了,色相也变了!

缺陷2:不符合人类感知

人眼对绿色的敏感度远高于蓝色,但RGB将三个通道视为平等。

人眼敏感度: 绿色 > 红色 > 蓝色

灰度公式: Gray = 0.299 R + 0.587 G + 0.114 B \text{Gray} = 0.299R + 0.587G + 0.114B Gray=0.299R+0.587G+0.114B

1.3 为什么需要其他颜色空间?

颜色空间 优势 典型应用
RGB 面向硬件,显示友好 图像存储、显示器
HSI 符合人类颜色描述 颜色分析、分割
HSV/HSL 直观的颜色调整 颜色选择器、调色板
LAB 感知均匀,设备无关 颜色科学、色差测量

二、RGB ↔ HSI 转换

2.1 HSI颜色空间的定义

HSI将颜色分解为三个独立的分量:

  • H(Hue,色调):颜色的种类(红、橙、黄、绿、蓝、紫)
  • S(Saturation,饱和度):颜色的纯度(0=灰色,1=纯色)
  • I(Intensity,强度):颜色的亮度(0=黑,1=白)

2.2 RGB → HSI 的数学推导

步骤1:归一化

将RGB值从 [0, 255] 归一化到 [0, 1]

复制代码
r = R / 255
g = G / 255
b = B / 255
步骤2:计算强度(Intensity)

强度是三个通道的算术平均值

I = r + g + b 3 I = \frac{r + g + b}{3} I=3r+g+b

物理意义:颜色的整体亮度。

步骤3:计算饱和度(Saturation)

饱和度定义为:

S = 1 − 3 × min ⁡ ( r , g , b ) r + g + b S = 1 - \frac{3 \times \min(r, g, b)}{r + g + b} S=1−r+g+b3×min(r,g,b)
推导过程

r = g = b 时(灰色),min(r,g,b) = r = g = b,则:

复制代码
S = 1 - 3r / (3r) = 1 - 1 = 0  # 完全去色

当某一通道为0时(如 b = 0,纯黄色):

复制代码
S = 1 - 0 / (r+g) = 1  # 最大饱和度
步骤4:计算色调(Hue)

色调的计算基于反余弦公式

首先计算分子和分母:

numerator = ( r − g ) + ( r − b ) \text{numerator} = (r - g) + (r - b) numerator=(r−g)+(r−b)
denominator = 2 × ( r − g ) 2 + ( r − b ) ( g − b ) \text{denominator} = 2 \times \sqrt{(r - g)^2 + (r - b)(g - b)} denominator=2×(r−g)2+(r−b)(g−b)

然后计算角度:

θ = arccos ⁡ ( numerator denominator ) \theta = \arccos\left(\frac{\text{numerator}}{\text{denominator}}\right) θ=arccos(denominatornumerator)

最终色调

复制代码
        θ / (2π),              if b ≤ g
H = 
        (2π - θ) / (2π),       if b > g

为什么需要判断 bg

因为 arccos 的值域是 [0, π],只能覆盖半圈。通过判断 bg 的大小,可以将色调扩展到完整范围 [0, 2π]

2.3 RGB → HSI 转换算法

Algorithm 1: RGB2HSI

输入:彩色图像 I I I( H × W × 3 H \times W \times 3 H×W×3), R G B ∈ 0 , 255 RGB \in 0, 255 RGB∈0,255

输出: H ∈ 0 , 1 H \in 0, 1 H∈0,1, S ∈ 0 , 1 S \in 0, 1 S∈0,1, I ∈ 0 , 1 I \in 0, 1 I∈0,1

1 归一化:

| r = I : , : , 0 / 255 r = I:,:,0 / 255 r=I:,:,0/255;

| g = I : , : , 1 / 255 g = I:,:,1 / 255 g=I:,:,1/255;

| b = I : , : , 2 / 255 b = I:,:,2 / 255 b=I:,:,2/255;

2 计算强度:

| I o u t = ( r + g + b ) / 3 I_{out} = (r + g + b) / 3 Iout=(r+g+b)/3;

3 计算饱和度:

| m i n _ v a l = min ⁡ ( r , g , b ) min\_val = \min(r, g, b) min_val=min(r,g,b);

| s u m _ v a l = r + g + b sum\_val = r + g + b sum_val=r+g+b;

| for each 像素 ( i , j ) (i, j) (i,j) do

| | if s u m _ v a l i , j > 0 sum\_vali,j > 0 sum_vali,j>0:

| | | S i , j = 1 − 3 × m i n _ v a l i , j / s u m _ v a l i , j Si,j = 1 - 3 \times min\_vali,j / sum\_vali,j Si,j=1−3×min_vali,j/sum_vali,j;

| | else:

| | | S i , j = 0 Si,j = 0 Si,j=0;

| end

4 计算色调:

| for each 像素 ( i , j ) (i, j) (i,j) do

| | n u m = ( r − g ) + ( r − b ) num = (r - g) + (r - b) num=(r−g)+(r−b);

| | d e n = 2 × ( r − g ) 2 + ( r − b ) ( g − b ) + ε den = 2 \times \sqrt{(r-g)^2 + (r-b)(g-b) + \varepsilon} den=2×(r−g)2+(r−b)(g−b)+ε ;

| | if d e n > 0 den > 0 den>0:

| | | θ = arccos ⁡ ( clip ( n u m / d e n , − 1 , 1 ) ) \theta = \arccos(\text{clip}(num/den, -1, 1)) θ=arccos(clip(num/den,−1,1));

| | | if b i , j ≤ g i , j bi,j \leq gi,j bi,j≤gi,j:

| | | | H i , j = θ / ( 2 π ) Hi,j = \theta / (2\pi) Hi,j=θ/(2π);

| | | else:

| | | | H i , j = ( 2 π − θ ) / ( 2 π ) Hi,j = (2\pi - \theta) / (2\pi) Hi,j=(2π−θ)/(2π);

| | else:

| | | H i , j = 0 Hi,j = 0 Hi,j=0;

| end

5 return H , S , I o u t H, S, I_{out} H,S,Iout;

2.4 HSI → RGB 反向转换

反向转换的核心思想:根据色调所在的区间,使用不同的公式还原RGB。

三个区间

区间1:0° ≤ H ≤ 120°(红→绿)

复制代码
b = (1 - S) × I
σ = (H × 360° - 60°) × π / 180  # 转换为弧度
t = tan(σ) / √3

g = (1.5 + 1.5t) × I - (0.5 + 1.5t) × b
r = 3I - g - b

区间2:120° < H ≤ 240°(绿→蓝)

复制代码
r = (1 - S) × I
σ = (H × 360° - 180°) × π / 180
t = tan(σ) / √3

b = (1.5 + 1.5t) × I - (0.5 + 1.5t) × r
g = 3I - r - b

区间3:240° < H ≤ 360°(蓝→红)

复制代码
g = (1 - S) × I
σ = (H × 360° - 300°) × π / 180
t = tan(σ) / √3

r = (1.5 + 1.5t) × I - (0.5 + 1.5t) × g
b = 3I - r - g

特殊情况 :当 S < ε(接近灰色)时:

复制代码
r = g = b = I

2.5 HSI → RGB 转换算法

Algorithm 2: HSI2RGB

输入: H ∈ 0 , 1 H \in 0, 1 H∈0,1, S ∈ 0 , 1 S \in 0, 1 S∈0,1, I ∈ 0 , 1 I \in 0, 1 I∈0,1

输出: R G B ∈ 0 , 1 RGB \in 0, 1 RGB∈0,1

1 将色调转为角度: H d e g = H × 360 H_{deg} = H \times 360 Hdeg=H×360;

2 for each 像素 ( i , j ) (i, j) (i,j) do

3 | if S i , j < ε Si,j < \varepsilon Si,j<ε:

4 | | r = g = b = I i , j r = g = b = Ii,j r=g=b=Ii,j;

5 | else if 0 ≤ H d e g ≤ 120 0 \leq H_{deg} \leq 120 0≤Hdeg≤120:

6 | | b = ( 1 − S ) × I b = (1-S) \times I b=(1−S)×I;

7 | | σ = ( H d e g − 60 ) × π / 180 \sigma = (H_{deg} - 60) \times \pi/180 σ=(Hdeg−60)×π/180;

8 | | t = tan ⁡ ( σ ) / 3 t = \tan(\sigma)/\sqrt{3} t=tan(σ)/3 ;

9 | | g = ( 1.5 + 1.5 t ) × I − ( 0.5 + 1.5 t ) × b g = (1.5+1.5t)\times I - (0.5+1.5t)\times b g=(1.5+1.5t)×I−(0.5+1.5t)×b;

10 | | r = 3 I − g − b r = 3I - g - b r=3I−g−b;

11 | else if 120 < H d e g ≤ 240 120 < H_{deg} \leq 240 120<Hdeg≤240:

12 | | r = ( 1 − S ) × I r = (1-S) \times I r=(1−S)×I;

13 | | σ = ( H d e g − 180 ) × π / 180 \sigma = (H_{deg} - 180) \times \pi/180 σ=(Hdeg−180)×π/180;

14 | | t = tan ⁡ ( σ ) / 3 t = \tan(\sigma)/\sqrt{3} t=tan(σ)/3 ;

15 | | b = ( 1.5 + 1.5 t ) × I − ( 0.5 + 1.5 t ) × r b = (1.5+1.5t)\times I - (0.5+1.5t)\times r b=(1.5+1.5t)×I−(0.5+1.5t)×r;

16 | | g = 3 I − r − b g = 3I - r - b g=3I−r−b;

17 | else:

18 | | g = ( 1 − S ) × I g = (1-S) \times I g=(1−S)×I;

19 | | σ = ( H d e g − 300 ) × π / 180 \sigma = (H_{deg} - 300) \times \pi/180 σ=(Hdeg−300)×π/180;

20 | | t = tan ⁡ ( σ ) / 3 t = \tan(\sigma)/\sqrt{3} t=tan(σ)/3 ;

21 | | r = ( 1.5 + 1.5 t ) × I − ( 0.5 + 1.5 t ) × g r = (1.5+1.5t)\times I - (0.5+1.5t)\times g r=(1.5+1.5t)×I−(0.5+1.5t)×g;

22 | | b = 3 I − r − g b = 3I - r - g b=3I−r−g;

23 end

24 合并通道: R G B = stack ( r , g , b ) RGB = \text{stack}(r, g, b) RGB=stack(r,g,b);

25 裁剪: R G B = Clip ( R G B , 0 , 1 ) RGB = \text{Clip}(RGB, 0, 1) RGB=Clip(RGB,0,1);

26 return R G B RGB RGB;


三、RGB ↔ HSV 转换

3.1 HSV颜色空间的定义

HSV与HSI类似,但定义略有不同:

  • H(Hue,色相):颜色的种类(与HSI类似)
  • S(Saturation,饱和度):颜色的纯度
  • V(Value,明度):颜色的最大亮度

3.2 RGB → HSV 的转换公式

步骤1:计算最大值和最小值
复制代码
max_val = max(r, g, b)
min_val = min(r, g, b)
C = max_val - min_val  # 色度(Chroma)
步骤2:计算明度(Value)
复制代码
V = max_val

与HSI的区别:HSI的强度是平均值,HSV的明度是最大值。

步骤3:计算饱和度(Saturation)
复制代码
        C / max_val,  if max_val > 0
S = 
        0,            otherwise
步骤4:计算色调(Hue)

基于六区间分段

复制代码
            ((g - b) / C) % 6,     if max_val = r
H_sector =  (b - r) / C + 2,       if max_val = g
            (r - g) / C + 4,       if max_val = b

H = H_sector / 6  # 归一化到 [0, 1]

六区间的含义

区间 H范围 颜色
0 0°-60° 红→黄
1 60°-120° 黄→绿
2 120°-180° 绿→青
3 180°-240° 青→蓝
4 240°-300° 蓝→品红
5 300°-360° 品红→红

3.3 RGB → HSV 转换算法

Algorithm 3: RGB2HSV

输入:彩色图像 I I I( H × W × 3 H \times W \times 3 H×W×3), R G B ∈ 0 , 255 RGB \in 0, 255 RGB∈0,255

输出: H ∈ 0 , 1 H \in 0, 1 H∈0,1, S ∈ 0 , 1 S \in 0, 1 S∈0,1, V ∈ 0 , 1 V \in 0, 1 V∈0,1

1 归一化:

| r = I : , : , 0 / 255 r = I:,:,0 / 255 r=I:,:,0/255;

| g = I : , : , 1 / 255 g = I:,:,1 / 255 g=I:,:,1/255;

| b = I : , : , 2 / 255 b = I:,:,2 / 255 b=I:,:,2/255;

2 计算最大值、最小值、色度:

| m a x _ v a l = max ⁡ ( r , g , b ) max\_val = \max(r, g, b) max_val=max(r,g,b);

| m i n _ v a l = min ⁡ ( r , g , b ) min\_val = \min(r, g, b) min_val=min(r,g,b);

| C = m a x _ v a l − m i n _ v a l C = max\_val - min\_val C=max_val−min_val;

3 计算明度:

| V = m a x _ v a l V = max\_val V=max_val;

4 计算饱和度:

| for each 像素 ( i , j ) (i, j) (i,j) do

| | if m a x _ v a l i , j > 0 max\_vali,j > 0 max_vali,j>0:

| | | S i , j = C i , j / m a x _ v a l i , j Si,j = Ci,j / max\_vali,j Si,j=Ci,j/max_vali,j;

| | else:

| | | S i , j = 0 Si,j = 0 Si,j=0;

| end

5 计算色调:

| for each 像素 ( i , j ) (i, j) (i,j) do

| | if C i , j = = 0 Ci,j == 0 Ci,j==0:

| | | H i , j = 0 Hi,j = 0 Hi,j=0;

| | else if m a x _ v a l i , j = = r i , j max\_vali,j == ri,j max_vali,j==ri,j:

| | | H i , j = ( ( g i , j − b i , j ) / C i , j )   m o d   6 Hi,j = ((gi,j - bi,j) / Ci,j) \bmod 6 Hi,j=((gi,j−bi,j)/Ci,j)mod6;

| | else if m a x _ v a l i , j = = g i , j max\_vali,j == gi,j max_vali,j==gi,j:

| | | H i , j = ( b i , j − r i , j ) / C i , j + 2 Hi,j = (bi,j - ri,j) / Ci,j + 2 Hi,j=(bi,j−ri,j)/Ci,j+2;

| | else:

| | | H i , j = ( r i , j − g i , j ) / C i , j + 4 Hi,j = (ri,j - gi,j) / Ci,j + 4 Hi,j=(ri,j−gi,j)/Ci,j+4;

| | end

| | H i , j = H i , j / 6 Hi,j = Hi,j / 6 Hi,j=Hi,j/6;

| end

6 return H , S , V H, S, V H,S,V;

3.4 HSV → RGB 反向转换

反向转换的核心:根据色调所在的区间,使用线性插值还原RGB。

Algorithm 4: HSV2RGB

输入: H ∈ 0 , 1 H \in 0, 1 H∈0,1, S ∈ 0 , 1 S \in 0, 1 S∈0,1, V ∈ 0 , 1 V \in 0, 1 V∈0,1

输出: R G B ∈ 0 , 1 RGB \in 0, 1 RGB∈0,1

1 将 H , S , V H, S, V H,S,V 转换到 OpenCV 的范围:

| H c v = H × 180 H_{cv} = H \times 180 Hcv=H×180;

| S c v = S × 255 S_{cv} = S \times 255 Scv=S×255;

| V c v = V × 255 V_{cv} = V \times 255 Vcv=V×255;

2 合并为 HSV 图像: H S V = stack ( H c v , S c v , V c v ) HSV = \text{stack}(H_{cv}, S_{cv}, V_{cv}) HSV=stack(Hcv,Scv,Vcv);

3 使用 OpenCV 转换: R G B = cv2.cvtColor ( H S V , cv2.COLOR_HSV2BGR ) RGB = \text{cv2.cvtColor}(HSV, \text{cv2.COLOR\_HSV2BGR}) RGB=cv2.cvtColor(HSV,cv2.COLOR_HSV2BGR);

4 归一化: R G B = R G B / 255 RGB = RGB / 255 RGB=RGB/255;

5 return R G B RGB RGB;

注意:HSV转RGB的实现较为复杂,涉及多段线性插值,通常直接使用OpenCV内置函数。


四、RGB ↔ HSL 转换

4.1 HSL颜色空间的定义

HSL与HSV非常类似,但明度(Lightness)的定义不同:

  • H(Hue,色相):与HSV相同
  • S(Saturation,饱和度):定义略有不同
  • L(Lightness,亮度):最大值和最小值的平均

4.2 RGB → HSL 的转换公式

步骤1:计算最大值和最小值
复制代码
max_val = max(r, g, b)
min_val = min(r, g, b)
步骤2:计算亮度(Lightness)
复制代码
L = (max_val + min_val) / 2

与HSV的区别:HSV的明度是最大值,HSL的亮度是平均值。

步骤3:计算饱和度(Saturation)

分段定义

复制代码
          0,                           if max_val = min_val
S =       d / (max_val + min_val),     if L < 0.5
          d / (2 - max_val - min_val), if L ≥ 0.5

其中 d = max_val - min_val 是色度。

步骤4:计算色调(Hue)

与HSV的色调计算完全相同

4.3 HSL → RGB 反向转换

核心思想 :使用 hue_to_rgb 辅助函数,通过分段线性插值将色相映射回RGB。

辅助函数

复制代码
函数: hue_to_rgb(p, q, t)
输入: p, q (插值参数), t (色调偏移)
输出: 插值结果

开始
  ① 处理周期性:
     if t < 0: t += 1
     if t > 1: t -= 1
  
  ② 分段计算:
     if t < 1/6:
       return p + (q - p) × 6 × t
     if t < 1/2:
       return q
     if t < 2/3:
       return p + (q - p) × (2/3 - t) × 6
     return p
结束

Algorithm 5: HSL2RGB

输入: H ∈ 0 , 1 H \in 0, 1 H∈0,1, S ∈ 0 , 1 S \in 0, 1 S∈0,1, L ∈ 0 , 1 L \in 0, 1 L∈0,1

输出: R G B ∈ 0 , 1 RGB \in 0, 1 RGB∈0,1

1 for each 像素 ( i , j ) (i, j) (i,j) do

2 | if S i , j = = 0 Si,j == 0 Si,j==0:

3 | | r = g = b = L i , j r = g = b = Li,j r=g=b=Li,j;

4 | else:

5 | | if L i , j < 0.5 Li,j < 0.5 Li,j<0.5:

6 | | | q = L i , j × ( 1 + S i , j ) q = Li,j \times (1 + Si,j) q=Li,j×(1+Si,j);

7 | | else:

8 | | | q = L i , j + S i , j − L i , j × S i , j q = Li,j + Si,j - Li,j \times Si,j q=Li,j+Si,j−Li,j×Si,j;

9 | | end

10 | | p = 2 × L i , j − q p = 2 \times Li,j - q p=2×Li,j−q;

11 | | r i , j = hue_to_rgb ( p , q , H i , j + 1 / 3 ) ri,j = \text{hue\_to\_rgb}(p, q, Hi,j + 1/3) ri,j=hue_to_rgb(p,q,Hi,j+1/3);

12 | | g i , j = hue_to_rgb ( p , q , H i , j ) gi,j = \text{hue\_to\_rgb}(p, q, Hi,j) gi,j=hue_to_rgb(p,q,Hi,j);

13 | | b i , j = hue_to_rgb ( p , q , H i , j − 1 / 3 ) bi,j = \text{hue\_to\_rgb}(p, q, Hi,j - 1/3) bi,j=hue_to_rgb(p,q,Hi,j−1/3);

14 end

15 合并通道: R G B = stack ( r , g , b ) RGB = \text{stack}(r, g, b) RGB=stack(r,g,b);

16 return R G B RGB RGB;


五、RGB ↔ CIE LAB 转换

5.1 为什么需要LAB颜色空间?

CIE LAB(也称 L*a*b*)是国际照明委员会(CIE)定义的颜色空间,具有以下优势:

  1. 感知均匀:相同数值变化产生相同的感知差异
  2. 设备无关:不依赖于显示器或打印机的特性
  3. 完整覆盖人眼可见色域

5.2 LAB颜色空间的定义

  • L*(Lightness,亮度):0(黑)到 100(白)
  • a*:从绿色(负值)到红色(正值)
  • b*:从蓝色(负值)到黄色(正值)

5.3 RGB → LAB 的转换流程

转换分为两步:RGB → XYZ → LAB

步骤1:RGB → XYZ

使用D65标准光源的线性变换矩阵:

复制代码
[x]   [0.5767309  0.1855540  0.1881852] [r]
[y] = [0.2973769  0.6273491  0.0752741] × [g]
[z]   [0.0270343  0.0706872  0.9911085] [b]

矩阵说明

  • 这个矩阵是基于sRGB颜色空间和D65白点计算得出的
  • 确保输入RGB是归一化的 [0, 1] 范围
步骤2:XYZ → LAB

非线性校正函数

复制代码
            t^(1/3),                if t > 0.008856
f(t) = 
            7.787 × t + 16/116,     otherwise

阈值 0.008856 的来源

这是CIE标准定义的转折点,确保函数在转折处连续且平滑:

  • t > 0.008856 时,使用立方根(感知均匀)
  • t ≤ 0.008856 时,使用线性函数(避免原点处的无穷大斜率)

LAB计算公式

复制代码
L* = 116 × f(Y) - 16
a* = 500 × (f(X) - f(Y))
b* = 200 × (f(Y) - f(Z))

系数说明

  • 11616:将L*映射到 [0, 100] 范围
  • 500:放大a*轴,增强红绿差异的敏感度
  • 200:放大b*轴,增强黄蓝差异的敏感度

5.4 RGB → LAB 转换算法

Algorithm 6: RGB2LAB

输入:彩色图像 I I I( H × W × 3 H \times W \times 3 H×W×3), R G B ∈ 0 , 255 RGB \in 0, 255 RGB∈0,255

输出: L ∈ 0 , 100 L \in 0, 100 L∈0,100, a ∈ − 128 , 127 a \in -128, 127 a∈−128,127, b ∈ − 128 , 127 b \in -128, 127 b∈−128,127

1 归一化:

| r = I : , : , 0 / 255 r = I:,:,0 / 255 r=I:,:,0/255;

| g = I : , : , 1 / 255 g = I:,:,1 / 255 g=I:,:,1/255;

| b = I : , : , 2 / 255 b = I:,:,2 / 255 b=I:,:,2/255;

2 RGB → XYZ(线性变换):

| X = 0.5767309 × r + 0.1855540 × g + 0.1881852 × b X = 0.5767309 \times r + 0.1855540 \times g + 0.1881852 \times b X=0.5767309×r+0.1855540×g+0.1881852×b;

| Y = 0.2973769 × r + 0.6273491 × g + 0.0752741 × b Y = 0.2973769 \times r + 0.6273491 \times g + 0.0752741 \times b Y=0.2973769×r+0.6273491×g+0.0752741×b;

| Z = 0.0270343 × r + 0.0706872 × g + 0.9911085 × b Z = 0.0270343 \times r + 0.0706872 \times g + 0.9911085 \times b Z=0.0270343×r+0.0706872×g+0.9911085×b;

3 定义校正函数 f ( t ) f(t) f(t):

| if t > 0.008856 t > 0.008856 t>0.008856:

| | return t 1 / 3 t^{1/3} t1/3;

| else:

| | return 7.787 × t + 16 / 116 7.787 \times t + 16/116 7.787×t+16/116;

4 XYZ → LAB:

| for each 像素 ( i , j ) (i, j) (i,j) do

| | L i , j = 116 × f ( Y i , j ) − 16 Li,j = 116 \times f(Yi,j) - 16 Li,j=116×f(Yi,j)−16;

| | a i , j = 500 × ( f ( X i , j ) − f ( Y i , j ) ) ai,j = 500 \times (f(Xi,j) - f(Yi,j)) ai,j=500×(f(Xi,j)−f(Yi,j));

| | b i , j = 200 × ( f ( Y i , j ) − f ( Z i , j ) ) bi,j = 200 \times (f(Yi,j) - f(Zi,j)) bi,j=200×(f(Yi,j)−f(Zi,j));

| end

5 return L , a , b L, a, b L,a,b;

5.5 LAB → RGB 反向转换

反向流程:LAB → XYZ → RGB

由于 XYZ → RGB 需要矩阵求逆,且 f ( t ) f(t) f(t) 的反函数计算复杂,通常直接使用 OpenCV 内置函数

Algorithm 7: LAB2RGB

输入: L ∈ 0 , 100 L \in 0, 100 L∈0,100, a ∈ − 128 , 127 a \in -128, 127 a∈−128,127, b ∈ − 128 , 127 b \in -128, 127 b∈−128,127

输出: R G B ∈ 0 , 1 RGB \in 0, 1 RGB∈0,1

1 合并为 LAB 图像: L A B = stack ( L , a , b ) LAB = \text{stack}(L, a, b) LAB=stack(L,a,b);

2 调整到 OpenCV 的范围:

| L A B : , : , 0 = L × 255 / 100 LAB:,:,0 = L \times 255 / 100 LAB:,:,0=L×255/100;

| L A B : , : , 1 = a + 128 LAB:,:,1 = a + 128 LAB:,:,1=a+128;

| L A B : , : , 2 = b + 128 LAB:,:,2 = b + 128 LAB:,:,2=b+128;

3 使用 OpenCV 转换: R G B = cv2.cvtColor ( L A B , cv2.COLOR_LAB2BGR ) RGB = \text{cv2.cvtColor}(LAB, \text{cv2.COLOR\_LAB2BGR}) RGB=cv2.cvtColor(LAB,cv2.COLOR_LAB2BGR);

4 归一化: R G B = R G B / 255 RGB = RGB / 255 RGB=RGB/255;

5 return R G B RGB RGB;


六、颜色空间对比与应用场景

6.1 四种颜色空间的对比

特性 RGB HSI HSV/HSL LAB
直观性 很好 很好
计算复杂度 -
感知均匀性 一般 一般 很好
通道独立性
适用场景 显示存储 颜色分析 颜色调整 色彩科学

6.2 应用场景详解

场景1:饱和度调整

  • RGB空间:不知道该改哪个通道
  • HSV空间:直接调整S通道,简单直观

Algorithm 8: SaturationAdjust

输入:RGB 图像 I I I,饱和度因子 f a c t o r factor factor

输出:调整后的图像 I ′ I' I′

1 RGB → HSV: ( H , S , V ) = RGB2HSV ( I ) (H, S, V) = \text{RGB2HSV}(I) (H,S,V)=RGB2HSV(I);

2 调整饱和度: S ′ = Clip ( S × f a c t o r , 0 , 1 ) S' = \text{Clip}(S \times factor, 0, 1) S′=Clip(S×factor,0,1);

3 HSV → RGB: I ′ = HSV2RGB ( H , S ′ , V ) I' = \text{HSV2RGB}(H, S', V) I′=HSV2RGB(H,S′,V);

4 return I ′ I' I′;

场景2:颜色分割(提取红色区域)

  • RGB空间:红色的定义模糊(R>G且R>B?阈值多少?)
  • HSI空间 :色调在 0 ° − 30 ° 0°-30° 0°−30° 或 330 ° − 360 ° 330°-360° 330°−360° 之间即为红色

Algorithm 9: ExtractRed

输入:RGB 图像 I I I

输出:红色区域掩码 M a s k Mask Mask

1 RGB → HSI: ( H , S , I ) = RGB2HSI ( I ) (H, S, I) = \text{RGB2HSI}(I) (H,S,I)=RGB2HSI(I);

2 转换为角度: H d e g = H × 360 H_{deg} = H \times 360 Hdeg=H×360;

3 判断红色区域: M a s k = ( H d e g ≤ 30 ) ∨ ( H d e g ≥ 330 ) Mask = (H_{deg} \leq 30) \lor (H_{deg} \geq 330) Mask=(Hdeg≤30)∨(Hdeg≥330);

4 return M a s k Mask Mask;

场景3:颜色校正与色差测量

  • RGB空间:欧氏距离不能反映感知差异

  • LAB空间:欧氏距离直接对应感知差异

    色差: ΔE = √[(L₁-L₂)² + (a₁-a₂)² + (b₁-b₂)²]

ΔE < 2.3 时,人眼通常无法区分两个颜色(Just Noticeable Difference)。


七、性能优化与实现要点

7.1 逐像素循环 vs 向量化运算

问题:颜色空间转换涉及大量逐像素的条件判断,难以直接向量化。

解决方案

方案1:使用NumPy的条件索引

复制代码
# 慢:Python循环
for i in range(height):
    for j in range(width):
        if sum_val > 0:
            S[i,j] = 1 - 3*min_val/sum_val

# 快:NumPy向量化
S = np.where(sum_val > 0, 1 - 3*min_val/sum_val, 0)

方案2:使用OpenCV内置函数

复制代码
# 手工实现(慢)
H, S, V = RGB2HSV(image)

# OpenCV实现(快100倍+)
hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)

7.2 性能对比

转换 手工实现 OpenCV 性能提升
RGB→HSV 0.8s (512×512) 0.008s 100×
RGB→LAB 1.2s (512×512) 0.012s 100×
RGB→HSI 1.0s (512×512) N/A -

建议

  • HSV、LAB转换:直接使用OpenCV
  • HSI转换:OpenCV未提供,需手工实现(但可向量化优化)

八、参数调优指南

8.1 饱和度调整

空间 参数 效果 适用场景
HSV factor=1.3 轻微鲜艳 风景照
HSV factor=1.5 明显鲜艳 食物摄影
HSV factor=0.5 降低饱和 忧郁氛围
HSV factor=0.0 完全去色 黑白效果

8.2 色调调整(改变颜色)

在HSV空间,可以直接调整色调:

复制代码
H' = (H + shift) % 1.0  # shift ∈ [0, 1]
偏移值 效果
+0.08 红→橙
+0.17 红→黄
+0.33 红→绿
+0.50 红→青(互补色)

九、扩展阅读

9.1 其他颜色空间

  • CMYK:印刷用的减色模型(青、品红、黄、黑)
  • YUV/YCbCr:视频编码常用的亮度-色度分离空间
  • XYZ:CIE定义的基础颜色空间,LAB的前置步骤

9.2 颜色空间转换的数学基础

  • 线性代数:矩阵乘法(RGB↔XYZ)
  • 三角函数:反余弦、正切(RGB↔HSI)
  • 分段函数:f(t)校正函数(XYZ↔LAB)

9.3 参考文献

  1. Gonzalez, R. C., & Woods, R. E. (2018). Digital Image Processing (4th ed.). Pearson. 第6章:彩色图像处理
  2. CIE (1986). Colorimetry (2nd ed.). CIE Publication No. 15.2.
  3. OpenCV Documentation - Color conversions. https://docs.opencv.org/

十、完整代码

所有算法的完整Python实现已开源:

📦 GitHub仓库: 待添加


结语

本文深入探讨了四种颜色空间的数学原理:

  • HSI:基于反余弦公式的色调计算,适合颜色分析
  • HSV/HSL:六区间分段算法,直观的颜色调整
  • LAB:感知均匀的色彩科学空间,用于色差测量
  • 转换公式:完整的正向与反向转换算法

理解颜色空间是掌握色彩校正、饱和度调整、图像分割等高级技术的关键基础

在下一篇文章中,我们将探索图层混合模式完全解析,深入理解Photoshop中18种混合模式的数学公式与算法实现。


系列文章导航

标签颜色空间 RGB HSI HSV HSL LAB 色彩科学 颜色转换 图像处理 Python OpenCV


本文是"图像特效与滤镜技术"系列的第3篇,共15篇。所有算法都基于Python+OpenCV+NumPy实现,完整代码开源在GitHub。

相关推荐
周周爱喝粥呀19 小时前
4个AI 大模型排行榜的对比
人工智能·ai
昇腾CANN19 小时前
从一张查找表到 4GB/s:HiFloat8 Cast 算子的工程化之路
人工智能·开源·昇腾·cann
老H科研技术19 小时前
第 01 篇:MCP 概念与架构 —— AI 世界的“USB-C“
c语言·人工智能·chatgpt·架构·aigc·agi
衫水19 小时前
关于 AI 工程化 Harness 的一些笔记(2026/6/5)
人工智能·笔记
大模型最新论文速读19 小时前
06-05 · LLM 最新论文速览
论文阅读·人工智能·深度学习·机器学习·自然语言处理
闻道参看19 小时前
2026企业GEO选型指南:主流AI优化服务商对比
大数据·人工智能
FIT2CLOUD飞致云19 小时前
里程碑丨MaxKB开源企业级智能体平台v2.10 LTS版本发布
人工智能·ai·开源·智能体·maxkb
论迹19 小时前
【LangChain-AI】聊天模型--调用工具
人工智能·langchain
Elastic 中国社区官方博客19 小时前
13.7万人,零人工决策:使用 Elasticsearch 实现智能体驱动的灾害响应系统
大数据·数据库·人工智能·elasticsearch·搜索引擎·ai·全文检索
北京耐用通信19 小时前
耐达讯自动化 Modbus RTU转Profibus 网关产品技术说明书
人工智能·物联网·网络协议·自动化·信息与通信