你可能已经对RGB颜色模型非常熟悉了,但在图像处理,特别是颜色检测与分割任务中,HSV(色相、饱和度、明度)模型往往更直观、更实用。它的设计更贴近人眼感知色彩的方式,因此许多实际项目在开始阶段就会将图像从RGB转换到HSV空间进行处理。
HSV 的基本参数
HSV的三个分量各有其独特特性:
- 色相(Hue, H):用角度表示,范围为0°到360°,从红色开始逆时针旋转。红色位于0°,绿色120°,蓝色240°;补色也很容易记住——黄色60°,青色180°,紫色300°。
- 饱和度(Saturation, S):简单来说,就是颜色的“纯净程度”。一种颜色可以看作是光谱色与白色混合的结果,光谱色占比越高,饱和度就越高,颜色就越鲜艳浓郁。当完全不含白光时,饱和度达到100%(即纯光谱色),取值通常为0%~100%。
- 明度(Value, V):表示颜色的明亮程度。对于光源色,明度与发光体的光亮度有关;对于物体色,则取决于物体的透射比或反射比,光照对其影响最大。取值从0%(黑色)到100%(白色)。
OpenCV 中的转换与二值化
OpenCV中读取图片默认采用BGR格式(而非RGB),因此转换时需要使用 cv2.COLOR_BGR2HSV。具体实现代码非常简洁:

转换完成后,通常需要借助 cv2.inRange 进行二值化处理。这个函数比 threshold() 更加灵活——threshold 只能处理单通道图像,而 inRange 可以直接对多通道图像(如HSV的三通道)进行操作。
cv2.inRange 的用法
调用格式非常简单:img = cv2.inRange(hsv, lower, upper)
- 第一个参数是待处理的HSV图像;
- 第二个参数
lower是下界——低于该值的像素会被置为0; - 第三个参数
upper是上界——高于该值的像素同样会被置为0。
换句话说,落在lower 和 upper 之间的像素变为255(白色),范围之外的像素变为0(黑色)。如果原始图像是彩色三维数组,那么 lower 和 upper 也必须为数组类型,每个分量分别对应 H、S、V 的阈值范围。
处理完成后得到一张二值图像——你要提取的颜色区域显示为白色,其余区域显示为黑色,后续就可以专门对白色区域进行形态学处理、轮廓提取等操作。
举个实际例子
下面这张图中,我们希望提取水杯(黑色部分):

经过 inRange 处理后得到的结果:

可以看到杯子基本被分离出来了,但由于猫耳朵和背景角落也存在黑色区域,加上杯子本身的黑色不够纯净(含有一些白点),结果中会出现少量噪点。这属于正常现象,后续可以通过开闭运算或滤波操作来消除这些噪点。
为什么颜色检测更倾向于使用 HSV 而非 RGB
在实际项目中,光照变化是最常见的棘手问题之一。如果场景中存在阴影或亮斑,RGB三个分量的值都会发生剧烈波动,调整参数时需要逐个通道反复调试,效果往往也不理想。
而HSV模型的核心优势在于:色相 H 基本不受光照影响(阴影或亮斑通常不会改变物体本身的色相),真正受光照影响的主要是明度 V。因此,当遇到光源不稳定、场景明暗变化大的情况时,你只需要重点调整 V 的阈值范围,就能较好地适应光照变化,比调整RGB三个通道省时省力,而且效果更加稳定。
总的来说,HSV是颜色检测领域中的“老朋友”,深入理解这三个维度的含义后,处理起来会得心应手很多。
