2.7 HSV 颜色检测
总目录:1.1 OpenCV介绍与学习路线 | 第二章:基础图像处理 | 编号:2.7
← 上一节:2.6 形态学处理 | 下一节:3.1 Canny边缘检测 →
2.7 HSV 颜色检测
假设我们要找橙色小车。最直观的办法不是告诉电脑“这看起来很橙”,而是规定:H、S、V 都落在某个范围里的像素留下,其余全部丢掉。
一、颜色检测其实是范围筛选
BGR 原图
↓ cvtColor
HSV 图像
↓ inRange(lower, upper)
黑白蒙版 mask
↓ bitwise_and
只保留目标颜色的结果图
HSV 各通道范围见 四、HSV:把颜色种类和明暗拆开。
二、inRange:生成颜色蒙版
hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
lower = np.array([5, 120, 100], dtype=np.uint8)
upper = np.array([25, 255, 255], dtype=np.uint8)
mask = cv2.inRange(hsv, lower, upper)
注意输入应当是 hsv,原笔记中一处写成了 cv2.inRange(img, ...),那会拿 BGR 数字套 HSV 阈值,结果当然乱跑。
mask 是单通道二值图:
范围内 → 255(白)
范围外 → 0(黑)
三、bitwise_and:把目标颜色抠出来
result = cv2.bitwise_and(image, image, mask=mask)
同一张原图参与按位与,mask 决定哪些位置允许保留。白色位置保留原图,黑色位置变黑。

如果最终目的是找轮廓,其实可以直接对 mask 做形态学和 findContours;result 主要用于给人看。
四、用滑动条寻找阈值
import cv2
import numpy as np
def nothing(_):
pass
cv2.namedWindow("Trackbars", cv2.WINDOW_NORMAL)
cv2.createTrackbar("H min", "Trackbars", 0, 179, nothing)
cv2.createTrackbar("H max", "Trackbars", 179, 179, nothing)
cv2.createTrackbar("S min", "Trackbars", 0, 255, nothing)
cv2.createTrackbar("S max", "Trackbars", 255, 255, nothing)
cv2.createTrackbar("V min", "Trackbars", 0, 255, nothing)
cv2.createTrackbar("V max", "Trackbars", 255, 255, nothing)
while True:
image = cv2.imread("resources/car.png")
if image is None:
raise FileNotFoundError("resources/car.png")
hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
lower = np.array([
cv2.getTrackbarPos("H min", "Trackbars"),
cv2.getTrackbarPos("S min", "Trackbars"),
cv2.getTrackbarPos("V min", "Trackbars"),
])
upper = np.array([
cv2.getTrackbarPos("H max", "Trackbars"),
cv2.getTrackbarPos("S max", "Trackbars"),
cv2.getTrackbarPos("V max", "Trackbars"),
])
mask = cv2.inRange(hsv, lower, upper)
result = cv2.bitwise_and(image, image, mask=mask)
cv2.imshow("Mask", mask)
cv2.imshow("Result", result)
if cv2.waitKey(1) & 0xFF == ord("q"):
break
cv2.destroyAllWindows()
原笔记里滑动条代码主要以截图存在,新版已经还原成可复制代码。
五、红色为什么经常需要两段范围
色相是一个圆环。红色落在 H 的起点附近,也会绕到末端附近,所以常分两段:
lower_1 = np.array([0, 120, 80])
upper_1 = np.array([10, 255, 255])
lower_2 = np.array([170, 120, 80])
upper_2 = np.array([179, 255, 255])
mask_1 = cv2.inRange(hsv, lower_1, upper_1)
mask_2 = cv2.inRange(hsv, lower_2, upper_2)
mask = cv2.bitwise_or(mask_1, mask_2)
六、颜色阈值怎样保存和验证
不要只在一张图上调到“完美”:
- 采集白天、晚上、强光、阴影和不同距离的样本;
- 记录阈值,而不是每次打开滑动条重调;
- 检查漏检和误检;
- 先固定相机曝光和白平衡,再谈稳定阈值;
- 对 mask 做轻度 开闭运算,不要用巨大核掩盖阈值错误。
可以把阈值写成清楚的配置:
ORANGE_HSV = {
"lower": np.array([5, 120, 100], dtype=np.uint8),
"upper": np.array([25, 255, 255], dtype=np.uint8),
}

这张图适合保留,因为它同时展示了原图、HSV、蒙版、结果和滑动条,比单独的代码截图更能说明流程。
← 上一节:2.6 形态学处理 | 下一节:3.1 Canny边缘检测 →
留言区
不收集任何个人信息;昵称只绑定浏览器里的随机 Cookie。