1. 色彩空间基础:RGB、BGR、HSV、Lab、YUV 的概念与区别

做图像处理这些年,我见过不少新手一上来就对着像素值猛调,结果效果一塌糊涂。说白了,就是没搞懂色彩空间这回事。你想想看,RGB 适合显示器,但不适合做颜色分析。选错色彩空间,就像用锤子拧螺丝——费劲还容易坏。

今天我们就来聊聊 OpenCV 里最常见的几种色彩空间。我会结合自己的踩坑经历,帮你理清它们的区别和适用场景。

1.1 RGB 与 BGR:OpenCV 的“反直觉”设计

RGB 大家最熟悉了。红绿蓝三通道,每个通道 0-255。但 OpenCV 默认用的是 BGR,不是 RGB。我第一次用 OpenCV 显示图片时,发现人脸是蓝色的,吓我一跳。

⚠️ 避坑指南: 我曾经在项目里直接用 matplotlib 显示 OpenCV 读取的图片,结果颜色全乱套。因为 matplotlib 默认用 RGB,而 OpenCV 用 BGR。解决办法很简单:用 cv2.cvtColor(img, cv2.COLOR_BGR2RGB) 转换一下。

为什么 OpenCV 要这么设计?历史原因。早期摄像头硬件厂商偏爱 BGR 排列,OpenCV 为了兼容就沿用了下来。你记住一点:读图用 BGR,显示用 RGB,就不会出问题。

import cv2
import matplotlib.pyplot as plt

# 读取图片(BGR 格式)
img = cv2.imread('photo.jpg')

# 转成 RGB 再显示
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
plt.imshow(img_rgb)
plt.show()

1.2 HSV:更适合做颜色分割

HSV 把颜色拆成三个维度:色调(H)、饱和度(S)、明度(V)。我个人习惯用 HSV 做颜色检测,因为它对光照变化不敏感。

举个例子。你想从图片里找出红色的物体。在 RGB 空间里,红色可能是 (200, 30, 30),也可能是 (180, 20, 20),阈值很难定。但在 HSV 空间里,红色的 H 值基本在 0-10 和 170-180 之间,S 和 V 只要不太低就行。这样阈值就好设多了。

💡 实用技巧: 我在做交通标志识别项目时,就用 HSV 提取红色和蓝色区域。效果比 RGB 好太多。记住:颜色分割首选 HSV
# BGR 转 HSV
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

# 红色范围(OpenCV 中 H 范围是 0-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)

1.3 Lab:人眼感知最均匀的色彩空间

Lab 色彩空间的设计初衷是模拟人眼对颜色的感知。L 代表亮度,a 代表红绿色,b 代表黄蓝色。它的特点是:两个颜色之间的欧氏距离,大致等于人眼感知到的颜色差异

这有什么用?做颜色相似度比较时特别准。我记得有一次做产品色差检测,用 RGB 算距离,结果深红和浅红被判成完全不同的颜色。换成 Lab 空间后,准确率直接提升到 95% 以上。

📌 我的建议: 如果你要做颜色匹配、图像分割中的颜色聚类,或者需要抵抗光照变化,Lab 空间比 HSV 更稳定。缺点是计算量稍大。
# BGR 转 Lab
lab = cv2.cvtColor(img, cv2.COLOR_BGR2LAB)

# 提取亮度通道
l_channel = lab[:, :, 0]

# 直方图均衡化(只对亮度做,避免颜色失真)
l_eq = cv2.equalizeHist(l_channel)
lab[:, :, 0] = l_eq

# 转回 BGR
img_enhanced = cv2.cvtColor(lab, cv2.COLOR_LAB2BGR)

1.4 YUV:视频压缩的老朋友

YUV 最早是为电视广播设计的。Y 是亮度,U 和 V 是色度。人眼对亮度敏感,对颜色不敏感。所以视频压缩时,可以保留完整的 Y,但把 UV 的分辨率降低一半,人眼几乎察觉不到。

你在看视频时,其实大部分数据都是 Y 通道。UV 通道被压缩得很厉害。这就是为什么同样码率下,视频比图片小很多的原因。

色彩空间 通道含义 主要用途 我的评价
RGB/BGR 红、绿、蓝 显示、存储 最直观,但不适合分析
HSV 色调、饱和度、明度 颜色分割、物体跟踪 颜色检测首选
Lab 亮度、红绿、黄蓝 颜色匹配、图像增强 感知均匀,精度高
YUV 亮度、蓝色差、红色差 视频编码、传输 压缩效率高

1.5 如何选择?我的经验总结

说了这么多,到底该用哪个?我根据项目经验给你几个建议:

  • 只是显示图片:用 RGB,记得从 BGR 转过来。
  • 做颜色检测或分割:用 HSV,阈值好设,抗光照干扰。
  • 做颜色相似度比较:用 Lab,感知均匀,结果更符合人眼。
  • 处理视频或压缩:用 YUV,效率高。
  • 做图像增强:用 Lab 或 YUV,只处理亮度通道,避免颜色失真。
🔑 核心要点: 没有最好的色彩空间,只有最合适的。我建议你每个都试试,看看哪个效果最符合你的需求。OpenCV 提供了 cv2.cvtColor() 函数,转换起来很方便。

嗯,色彩空间的基础就讲到这里。下一章我们会深入每个空间的转换原理,以及如何用它们做出各种滤镜效果。到时候我会分享一些我在项目中用过的“骚操作”,保证让你大开眼界。