2. 色彩空间基础:RGB、HSV、Lab 色彩空间介绍
做图像处理这么多年,我越来越觉得:选对色彩空间,项目就成功了一半。尤其是光照校正这个方向,很多人一上来就对着 RGB 猛调,结果越调越乱。
今天咱们就把三种最常用的色彩空间掰开揉碎讲清楚。特别是 HSV,为什么它在光照处理里这么吃香?
2.1 RGB 色彩空间——最熟悉,也最不听话
RGB 就是红绿蓝三通道叠加。显示器、摄像头、手机屏幕,全用这套。每个像素三个值,范围 0-255,组合出 1600 多万种颜色。
听起来很完美对吧?但实际用起来,问题就来了。
RGB 的核心缺陷:三个通道高度耦合。你调亮度,三个通道一起变;你调颜色,亮度也跟着跑。说白了,RGB 把「亮度」和「颜色」搅在一起了。
举个例子。一张照片偏暗,你想提亮。在 RGB 里,你得把 R、G、B 三个值都乘个系数。结果呢?亮度是上去了,但颜色也变了——原本的红色可能变得发白,蓝色变得发紫。
我在项目中遇到过这种情况:用 RGB 做直方图均衡化,处理完的图像颜色完全失真,客户直接打回来重做。后来换成 HSV,一次通过。
| 特性 | RGB | HSV | Lab |
|---|---|---|---|
| 亮度与颜色耦合度 | 高度耦合 | 分离 | 完全分离 |
| 光照变化敏感度 | 非常敏感 | 不敏感(V 通道) | 不敏感(L 通道) |
| 人眼感知一致性 | 差 | 中等 | 好 |
| 计算复杂度 | 低 | 中 | 高 |
| 工程常用场景 | 显示、存储 | 光照校正、目标跟踪 | 颜色分析、色彩管理 |
2.2 HSV 色彩空间——光照处理的王牌
HSV 把颜色拆成三个分量:Hue(色调)、Saturation(饱和度)、Value(明度)。
- H(色调):0°-360°,决定是什么颜色。红色、蓝色、绿色,全在这里。
- S(饱和度):0-1,决定颜色有多纯。0 是灰色,1 是纯色。
- V(明度):0-1,决定有多亮。0 是全黑,1 是全亮。
关键来了:V 通道只负责亮度,跟颜色无关。你调整 V 通道,H 和 S 完全不受影响。
为什么会这样?因为 HSV 的设计初衷就是把「颜色是什么」和「颜色有多亮」分开。你想想看,这简直就是为光照校正量身定做的。
我的习惯做法:做光照校正时,先把 RGB 转成 HSV,然后只动 V 通道。直方图均衡化、Gamma 校正、对比度拉伸,全在 V 通道上操作。处理完再转回 RGB 显示。效果稳得很。
我曾经接手过一个项目,需要在不同光照条件下检测交通标志。白天、傍晚、隧道里,光照变化极大。用 RGB 做阈值分割,参数调了三天都搞不定。换成 HSV,只对 H 通道做范围筛选,S 和 V 稍微过滤一下,半天就上线了。
2.3 Lab 色彩空间——人眼级别的颜色感知
Lab 是 CIE 组织搞出来的色彩空间,目标是模拟人眼对颜色的感知方式。
- L(亮度):0-100,从黑到白。
- a(绿到红):-128 到 127,负值偏绿,正值偏红。
- b(蓝到黄):-128 到 127,负值偏蓝,正值偏黄。
Lab 最大的优势是感知均匀。什么意思?就是你在 Lab 空间里移动相同的距离,人眼感受到的颜色变化是差不多的。RGB 和 HSV 都做不到这一点。
但 Lab 也有短板:计算量大,而且 a、b 通道的取值范围没有直观的物理意义。你很难像 HSV 那样直接说「把 H 设在 120° 就是绿色」。
注意:Lab 空间在做颜色迁移、色彩分析时非常强大。但如果你只是做光照校正,HSV 的性价比更高。别为了炫技硬上 Lab,工程上讲究的是「够用就好」。
2.4 为什么 HSV 更适合光照处理?
一句话总结:HSV 把光照信息独立出来了。
在 RGB 里,光照变化会同时影响三个通道。在 HSV 里,光照变化主要影响 V 通道,H 和 S 基本不变。这意味着你可以放心大胆地调整亮度,不用担心颜色跑偏。
我给你们看个实际对比。假设一张图片的某个像素在 RGB 里是 (200, 100, 50)。光照变暗后变成 (100, 50, 25)。你算算,R/G/B 的比例完全变了,颜色肯定变。
但同样的像素在 HSV 里,光照变暗只是 V 值从 0.78 降到 0.39,H 和 S 几乎不变。颜色还是那个颜色。
工程建议:只要你的任务涉及光照变化——不管是校正、增强还是归一化——优先考虑 HSV。这是我在几十个项目里踩坑踩出来的经验。
2.5 三种色彩空间的转换关系
实际工程中,我们经常需要在 RGB、HSV、Lab 之间来回切换。OpenCV 提供了现成的函数,但理解背后的转换逻辑很重要。
RGB → HSV 的核心思路:
- 把 RGB 归一化到 0-1 范围。
- V = max(R, G, B)
- S = (V - min(R, G, B)) / V(如果 V=0,则 S=0)
- H 的计算稍微复杂一点,根据哪个通道最大来决定基准角度,再偏移。
import cv2
import numpy as np
# RGB 转 HSV
img_rgb = cv2.imread('example.jpg')
img_hsv = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2HSV)
# 只对 V 通道做直方图均衡化
h, s, v = cv2.split(img_hsv)
v_eq = cv2.equalizeHist(v)
img_hsv_eq = cv2.merge([h, s, v_eq])
# 转回 RGB 显示
img_result = cv2.cvtColor(img_hsv_eq, cv2.COLOR_HSV2BGR)
嗯,这里要注意:OpenCV 的 HSV 范围跟理论值不一样。H 是 0-179,S 和 V 是 0-255。别搞混了,我刚开始用的时候就因为这个踩过坑。
2.6 知识体系总览
下面这张图把三种色彩空间的核心逻辑和适用场景串起来了。你可以把它当作本章的「思维导图」。
2.7 避坑指南
最后分享几个我踩过的坑,希望能帮你省点时间。
坑 1:OpenCV 的 HSV 范围不是标准的 0-360/0-100/0-100。H 是 0-179,S 和 V 是 0-255。做阈值分割时一定要换算清楚。
坑 2:HSV 转 RGB 再转 HSV,会有精度损失。别来回转,尽量在一个色彩空间里完成所有操作。
坑 3:Lab 空间的 L 通道虽然独立,但 a、b 通道的取值范围跟图像内容有关。做归一化时别用固定阈值,用统计值更靠谱。
我曾经在一个项目里,用 HSV 做肤色检测。一开始直接拿标准 HSV 范围去筛,结果亚洲人和欧洲人的肤色完全筛不到一起。后来发现,光照不同导致 V 通道差异太大。解决办法是先把 V 通道归一化到固定范围,再筛 H 和 S。效果立竿见影。
嗯,色彩空间这块就讲这么多。记住一句话:选对色彩空间,比调参更重要。