1、色彩空间基础:RGB、HSV、Lab、YUV色彩空间的定义与区别
色彩空间,说白了就是描述颜色的数学模型。我刚开始做图像处理时,总觉得这东西太理论了,不就是红绿蓝嘛。直到有一次做工业检测项目,在特定光照下怎么也提取不出目标区域,折腾了两天才发现——换个色彩空间,问题直接解决。
嗯,今天我们就来聊聊四种最常用的色彩空间。我会结合自己的踩坑经历,帮你理解它们各自适合什么场景。
1.1 RGB色彩空间——最直观,但最不「直觉」
RGB 就是红、绿、蓝三原色。每个像素用三个数值表示,范围通常是 0-255。显示器、摄像头、手机屏幕,底层全是 RGB。
定义:RGB 是一种加色模型。光越多,颜色越亮。三个通道全 255 是白色,全 0 是黑色。
核心特点:
- 硬件友好:显示器直接使用
- 通道高度相关:改变亮度,三个通道都得调
- 不适合人眼感知:你想想看,我说「RGB(180, 120, 60)」,你能想象出是什么颜色吗?
我在项目中遇到过一个问题:用 RGB 做颜色分割,光照一变,阈值全得重调。为什么?因为 RGB 把亮度信息和颜色信息混在一起了。你调亮度,颜色也跟着变。
1.2 HSV色彩空间——更符合人眼直觉
HSV 把颜色拆成三个分量:色相(Hue)、饱和度(Saturation)、明度(Value)。
我个人习惯用 HSV 做颜色识别。举个例子,你要识别红色物体。在 RGB 里,红色可能是 (200, 30, 20),也可能是 (180, 50, 40),范围很散。但在 HSV 里,红色的 H 值就在 0-10 和 170-180 附近,非常集中。
| 分量 | 含义 | 范围(OpenCV) |
|---|---|---|
| H | 色相,决定是什么颜色 | 0-179 |
| S | 饱和度,颜色纯度 | 0-255 |
| V | 明度,亮度 | 0-255 |
避坑指南:我曾经在 OpenCV 里直接用 HSV 范围做皮肤检测,结果发现 V 值太低时(比如阴影区域),皮肤全被滤掉了。后来我加了 V 值的下限阈值,效果才稳定。
1.3 Lab色彩空间——感知均匀,适合颜色比较
Lab 的设计目标是:数值上的差异,等于人眼感知的差异。L 是亮度,a 是红绿轴,b 是黄蓝轴。
说白了,RGB 里两个颜色差 10,人眼可能觉得差很多。但 Lab 里差 10,人眼感觉就是差 10。这个特性在做颜色相似度计算时特别有用。
适用场景:
- 颜色匹配、色差检测
- 图像增强(只调 L 通道,不影响颜色)
- 打印、印刷行业
注意:Lab 空间不是线性的,而且转换计算量比 HSV 大。实时处理时要注意性能。我有个项目就是因为每帧都转 Lab,导致帧率掉了一半,后来改成了 HSV。
1.4 YUV色彩空间——视频压缩的功臣
YUV 把亮度(Y)和色度(U、V)分开。人眼对亮度变化敏感,对颜色变化不敏感。所以视频编码时,Y 通道保留高分辨率,U、V 通道可以降采样——这就是为什么视频能压缩那么小。
我记得第一次接触 YUV 是在做视频采集卡驱动时。摄像头输出的原始数据就是 YUV422 格式,每个像素 16 位,比 RGB24 省了三分之一带宽。
| 格式 | 说明 | 常见场景 |
|---|---|---|
| YUV420 | U、V 分辨率是 Y 的 1/4 | H.264/H.265 视频 |
| YUV422 | U、V 分辨率是 Y 的 1/2 | 摄像头、采集卡 |
| YUV444 | 无压缩,每个像素完整 | 专业视频编辑 |
1.5 四种色彩空间对比总结
你想想看,选哪个色彩空间,完全取决于你要做什么。
- 显示、存储:用 RGB,硬件直接支持
- 颜色识别、分割:用 HSV,光照鲁棒性好
- 颜色比较、增强:用 Lab,感知均匀
- 视频编码、传输:用 YUV,压缩效率高
我的建议:新手先掌握 RGB 和 HSV 的互转。这两个在实际项目中占了 80% 的使用场景。Lab 和 YUV 遇到具体需求时再学,完全来得及。
1.6 代码示例:OpenCV 色彩空间转换
下面这段代码,我几乎每个项目都会用到。你直接复制就能跑。
import cv2
import numpy as np
# 读取图像(默认是 BGR,OpenCV 的 RGB 顺序是反的)
img = cv2.imread('test.jpg')
# RGB 转 HSV
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
# RGB 转 Lab
lab = cv2.cvtColor(img, cv2.COLOR_BGR2Lab)
# RGB 转 YUV
yuv = cv2.cvtColor(img, cv2.COLOR_BGR2YUV)
# 查看各通道
h, s, v = cv2.split(hsv)
l, a, b = cv2.split(lab)
y, u, v = cv2.split(yuv)
# 显示结果
cv2.imshow('Hue', h)
cv2.imshow('Saturation', s)
cv2.imshow('Value', v)
cv2.waitKey(0)
cv2.destroyAllWindows()
小技巧:OpenCV 里默认是 BGR 顺序,不是 RGB。我第一次用的时候没注意,结果颜色全乱了。记住:cv2.imread() 读出来的是 BGR,转其他空间时用 COLOR_BGR2xxx。
好了,色彩空间的基础就这些。下一章我们会深入讲 HSV 的阈值选择技巧,以及如何用滑动条动态调试——这可是我做项目时最常用的调试手段。