色彩空间基础: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适合做颜色识别

说白了,就三个原因:

  1. 光照不变性:H通道基本不受光照影响。你换个灯泡,红色还是红色
  2. 颜色范围直观:红色就是H在0°附近,绿色在120°附近,蓝色在240°附近。调参时特别好理解
  3. 容易做阈值分割:设定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?留给显示器和摄像头去用吧。

色彩空间选择决策流程 输入图像 识别还是分析? 颜色识别 色差分析 HSV空间 Lab空间 提取H、S通道 计算欧氏距离 输出识别结果

专注资料整理