色彩空间基础:RGB、HSV、Lab色彩空间介绍
做套色标记识别,说白了就是让计算机看懂颜色。但计算机看颜色的方式和我们人眼完全不同。我刚开始接触这个领域时,也踩过不少坑——明明肉眼看着很明显的色差,换到代码里就是死活识别不出来。
为什么会这样?因为计算机看到的只是数字。一张彩色图片,在它眼里就是三个数字矩阵的堆叠。今天我们就来聊聊这三个最常见的色彩空间:RGB、HSV、Lab。
RGB色彩空间
RGB是最基础、最常用的色彩模型。R是红,G是绿,B是蓝。每个通道取值0到255,三个通道组合起来就能表示1600多万种颜色。
举个例子,纯红色就是(255, 0, 0),纯绿色是(0, 255, 0),纯蓝色是(0, 0, 255)。黄色呢?红色加绿色,也就是(255, 255, 0)。
RGB的核心问题:它和人对颜色的感知方式不匹配。你想想看,我们说「这个苹果是红色的」,但RGB里没有「红色」这个概念,只有R、G、B三个数值的组合。
我在项目中遇到过这样一个场景:要识别红色标签,光照稍微一变,原本(200, 30, 20)的红色就变成了(150, 40, 30)。三个数值全变了,但人眼看起来还是红色。这就是RGB的致命弱点——它对光照变化太敏感了。
HSV色彩空间
HSV就是来解决这个问题的。它把颜色拆成三个维度:
- H(Hue,色调):描述颜色的种类,比如红、绿、蓝。取值范围0°到360°
- S(Saturation,饱和度):描述颜色的纯度。0%是灰色,100%是最鲜艳
- V(Value,明度):描述颜色的明暗程度。0%是黑色,100%是最亮
你看,HSV把「颜色是什么」和「颜色有多亮」分开了。这意味着什么?
嗯,这里要注意:光照变化主要影响V通道,对H通道影响很小。所以用HSV做颜色识别,稳定性比RGB好得多。
我的经验:做套色标记识别时,我一般只关注H和S两个通道。V通道直接扔掉,或者做归一化处理。这样光照变化再大,识别结果也不会跑偏。
Lab色彩空间
Lab是另一个好东西。它设计得更接近人眼感知:
- L(Lightness,亮度):从黑到白的亮度值
- a:从绿色到红色的分量
- b:从蓝色到黄色的分量
Lab最大的特点是「感知均匀」。什么意思?就是两个颜色在Lab空间里的距离,和人眼感觉到的色差基本一致。这在做颜色相似度判断时特别有用。
我曾经做过一个项目,需要判断两个标签颜色是否「看起来一样」。用RGB算欧氏距离,结果一塌糊涂。换成Lab空间后,准确率直接翻倍。
| 色彩空间 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| RGB | 简单直观,硬件友好 | 光照敏感,感知不均匀 | 图像显示、存储 |
| HSV | 分离色调和亮度,光照鲁棒 | H通道在低饱和度时不稳定 | 颜色识别、分割 |
| Lab | 感知均匀,色差计算准确 | 计算复杂,取值范围大 | 颜色匹配、质量检测 |
为什么HSV适合做颜色识别
说白了,就三个原因:
- 光照不变性:H通道基本不受光照影响。你换个灯泡,红色还是红色
- 颜色范围直观:红色就是H在0°附近,绿色在120°附近,蓝色在240°附近。调参时特别好理解
- 容易做阈值分割:设定H的范围就能锁定目标颜色,S和V用来过滤干扰
避坑指南:我曾经犯过一个错误——直接用OpenCV的默认HSV范围。结果发现,不同摄像头拍出来的同一张红色卡片,H值能差20多度。后来我学乖了,每次换设备都要重新标定HSV范围。
举个实际例子。假设我们要识别红色套色标记:
import cv2
import numpy as np
# 读取图像
img = cv2.imread('mark.jpg')
# 转HSV
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
# 红色范围(H: 0-10 和 170-180)
lower_red1 = np.array([0, 50, 50])
upper_red1 = np.array([10, 255, 255])
lower_red2 = np.array([170, 50, 50])
upper_red2 = np.array([180, 255, 255])
# 生成掩码
mask1 = cv2.inRange(hsv, lower_red1, upper_red1)
mask2 = cv2.inRange(hsv, lower_red2, upper_red2)
mask = cv2.bitwise_or(mask1, mask2)
# 提取红色区域
result = cv2.bitwise_and(img, img, mask=mask)
你看,代码很简单。但这里有个细节——红色在HSV里是跨0°的,所以要分两个区间。我刚开始做时没注意这个,结果红色总是识别不全。
三种空间的转换关系
实际项目中,我们经常需要在不同色彩空间之间切换。OpenCV提供了现成的转换函数:
# RGB转HSV
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
# RGB转Lab
lab = cv2.cvtColor(img, cv2.COLOR_BGR2LAB)
# HSV转RGB
rgb = cv2.cvtColor(hsv, cv2.COLOR_HSV2BGR)
记住:OpenCV默认用BGR顺序,不是RGB。很多新手在这里翻车——用RGB的值去调HSV参数,结果怎么调都不对。
我个人习惯的做法是:先用RGB显示图像,确认目标颜色。然后转HSV,用鼠标取点采样,统计H、S、V的分布范围。最后根据统计结果设定阈值。这样调出来的参数,基本一次到位。
好了,色彩空间的基础就聊到这里。记住一句话:做颜色识别,首选HSV;做色差分析,首选Lab。RGB?留给显示器和摄像头去用吧。