欢迎来到 嗅灵易学

零基础也能上手的脚本技术课,一对一答疑带你入门

OpenCV 从零学习 · 第 3 讲:色彩空间转换 cvtColor(为什么抠"红色物体"要转到 HSV)

OpenCV 从零学习 · 第 3 讲:色彩空间转换 cvtColor

上节课我们用 BGR 三通道做处理。但如果你试过"把照片里红色的杯子抠出来",会发现用 BGR 直接判断颜色非常麻烦——同一只红杯子,在阳光下和阴影里,BGR 三个值全变了。这一讲教你用 cv2.cvtColor 换一套"描述颜色的方式",让按颜色抠图变得简单可靠。

1. 函数签名

dst = cv2.cvtColor(src, code)
# src : 输入图 (uint8)
# code: 转换方式, 如 cv2.COLOR_BGR2GRAY
# dst : 转换后的图
常用 code含义
cv2.COLOR_BGR2GRAYBGR → 灰度
cv2.COLOR_BGR2HSVBGR → HSV(色相/饱和度/明度)
cv2.COLOR_BGR2RGBBGR → RGB(给 matplotlib/PIL 用)
cv2.COLOR_GRAY2BGR灰度 → BGR(升回三通道)
cv2.COLOR_HSV2BGRHSV → BGR(处理结果转回显示)
新手必踩坑:OpenCV 里 H(色相) 范围是 0~179,不是 0~360!
8 位图放不下 360,OpenCV 把色相压缩到 0~179。写颜色阈值时别照着网上的 0~360 来。

2. BGR → GRAY 灰度化:降维、去干扰

场景案例 A:OCR / 人脸检测前的标准动作
很多算法(如人脸检测、文字识别)只需要"亮度信息"不需要颜色。先灰度化能少算 2/3 的数据量,还能去掉颜色噪声:
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
print(gray.shape)     # (高, 宽)  —— 注意通道维没了!
灰度图是单通道 (h,w),不能直接和彩色图做运算。要再转回三通道才兼容显示/合成:gray3 = cv2.cvtColor(gray, cv2.COLOR_GRAY2BGR)

3. 为什么抠"红色物体"要用 HSV,而不是 BGR?

HSV 把颜色拆成三部分:

  • H(Hue 色相):到底是什么颜色(红/绿/蓝),0~179;
  • S(Saturation 饱和度):颜色浓不浓,0~255;
  • V(Value 明度):亮不亮,0~255。
关键差异:同一只红杯子,光照一变,BGR 三个通道值全跟着变;但 H(色相)基本不动。所以"按颜色找东西"用 HSV 的 H 通道来卡范围,比在 BGR 里卡三个通道稳得多。
场景案例 B:从照片里只保留"红色"的杯子
步骤:转 HSV → 用 cv2.inRange 圈出红色范围得到掩膜 → 用掩膜把红色部分抠出来:
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

# 红色在 HSV 里"跨过 0 度": 一段在 0~10, 一段在 170~179, 所以要取两个区间的并集
lower1 = np.array([0,   100, 100]);  upper1 = np.array([10,  255, 255])
lower2 = np.array([170, 100, 100]);  upper2 = np.array([179, 255, 255])
mask = cv2.bitwise_or(cv2.inRange(hsv, lower1, upper1),
                      cv2.inRange(hsv, lower2, upper2))

red_only = cv2.bitwise_and(img, img, mask=mask)   # 只保留红色区域, 其余变黑
对比一下:如果直接用 BGR 写 cv2.inRange(img, (0,0,200), (80,80,255)) 去卡红色,阴影里的红杯子(偏暗、B/G 略高)会大量漏掉;HSV 方案几乎不会。这就是"换色彩空间"带来的实质性差别。
场景案例 C:绿幕抠像(chroma key)
视频/直播里的绿幕,本质是"把某一片颜色换成透明"。用 HSV 卡住绿色范围做掩膜即可:
lower_green = np.array([35, 43, 46]);  upper_green = np.array([77, 255, 255])
mask = cv2.inRange(hsv, lower_green, upper_green)   # 绿幕区域为 255
fg = cv2.bitwise_and(img, img, mask=mask)           # 只留前景(非绿幕)

4. 常见色彩空间该用在哪(对照表)

色彩空间典型用途
GRAY(灰度)OCR、人脸检测、边缘检测等前处理;减少计算量
HSV按颜色追踪/抠图、绿幕、皮肤检测、交通灯识别
LAB颜色校正、白平衡、肉眼感知更均匀的颜色比较
RGB给 matplotlib / PIL 显示(OpenCV 读进来是 BGR,要先转)
新手必踩坑:用 matplotlib 显示前必须转 RGB!
OpenCV 读的是 BGR,matplotlib 按 RGB 画,直接 plt.imshow(img) 颜色会发蓝。正确做法:plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))

5. 本讲要点清单

  • cv2.cvtColor(src, code) 负责色彩空间转换,code 决定转成什么。
  • 灰度化 BGR2GRAY:检测/OCR 前处理首选,省算力。
  • 按颜色抠图用 HSV:H 通道对光照稳定,远强于 BGR 三通道硬卡。
  • HSV 的 H 范围是 0~179,红色跨 0 度要取两段并集。
  • cv2.inRange 出掩膜,再用 cv2.bitwise_and 抠图。
  • 给 matplotlib 显示前记得 BGR2RGB
✅ 下一讲预告:图片尺寸不对、拍歪了、需要镜像怎么办?第 4 讲:几何变换 resize / flip / 旋转

注意:上传附件及图片大小不得大于30M。

⚠️ 版权声明:
本博客所有内容(含教程、源码、工具)仅供个人技术学习与研究交流使用,严禁商用、倒卖、二次分发及非法用途
未经作者书面授权,任何组织或个人不得转载、复制或用于其他平台,违者将追究相关责任。

0 0 0 举报
复制成功