颜色空间:HSV 不万能
cvtColor 转 HSV 后 inRange 阈值在阴影和白平衡漂移下大面积失效;受控光照下才有用,否则应归一化或学习检测。

1. 产线换班次后,绿色 indicator 全漏检
固定光源下 HSV inRange 数红绿指示器,白班 OK。夜班 ambient 变、相机 auto WB 一锁,同一 (h_min, h_max) 把阴影里的金属反光判成「绿」,真 indicator 反而出界。HSV 把 hue 从亮度里拆出来只是 近似——阴影、低饱和、sensor WB 都会搬移 hue bucket。问题不是 morphology 不够,是颜色模型与部署域不匹配。运维若只看到「阈值 yaml 没改却坏了」,多半漏看了光照与 WB 契约。
2. OpenCV 转换契约
hsv = cv2.cvtColor(bgr, cv2.COLOR_BGR2HSV)
mask = cv2.inRange(hsv, (h_min, s_min, v_min), (h_max, s_max, v_max))
lab = cv2.cvtColor(bgr, cv2.COLOR_BGR2LAB)OpenCV 读图是 BGR;matplotlib 是 RGB——cvtColor 常量写错是最低级也最致命的 bug。HSV 的 H 范围 0–180(8bit),S/V 0–255。NN 预处理 blobFromImage(..., swapRB=True) 必须与训练一致。16-bit 或 depth 图转 HSV 前先 normalize 到 8bit,否则 inRange 阈值没有物理意义。团队里应把「颜色空间 + 数值范围」写进 code review checklist,而不是只靠个人记忆。
3. 何时 HSV 够用
受控光源、锁 WB/曝光、色块对比强(产线 indicator、分拣红绿件);简单 blob 计数且误检代价低;阈值可在 ROI 内用直方图标定,且跨班次抽检稳定。三条同时满足才值得维护 HSV yaml。若任一条动摇(例如加了夜班或换了相机驱动默认 WB),应触发阈值重标流程,而不是先加 morphology 核大小。
4. 何时不够、替代路径
户外日光阴影、金属高光 sat→0、跨相机色偏——固定阈值必崩。替代:CLAHE 在 Lab 的 L 通道再 threshold;灰度+梯度;CNN detector。Lab 对阴影略友好,仍非物理 color constancy。
lab = cv2.cvtColor(bgr, cv2.COLOR_BGR2Lab)
l, a, b = cv2.split(lab)
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8, 8))
l2 = clahe.apply(l)HSV 不稳定区:低 S 或低 V 时 H 噪声大——阈值前常设 S>40, V>40 gate,减少灰色区域误分割。
5. 实践:标定阈值而非堆 morphology
阈值前在 ROI 内画 H/S 直方图,看 bimodal 是否跨帧/跨相机稳定。morphologyEx 去噪救不了 wrong color model。Auto WB 改变 BGR→HSV 映射;锁 WB 和锁 exposure 一样重要。产线优先硬件光控:同一 batch 物料、同一光源角度,比软件 patch 便宜。标定集应覆盖「最暗班次 + 最亮班次」各一段录像,而不是只在工程师调试的白天采图。
6. 与 NN 检测的 pipeline 分工
HSV 适合 快速粗筛 或 规则兜底;泛化交给 detector。仍用 HSV 做主路径时,record 失败帧进 hard example,定期重标阈值。训练 detector 时 augment 含 color jitter,部署又用 HSV,等于两套颜色假设打架——pick one primary。若业务要求 HSV 兜底 NN,应明确 NN 失败时才 fallback,并单独验收 fallback 路径 recall。
7. 多相机与 color constancy
同型号相机 serial 不同,默认 WB curve 可差一截。多机位产线每台独立标 (h,s,v) 区间,或统一 gray-world 只是 heuristic。YCrCb 肤色老方案在 diverse tone 上 fail;需要泛化时用 learned detector + 正常曝光。换镜头或改光圈后,即使型号不变也要抽检直方图 drift。
8. 失败模式
| 现象 | 原因 |
|---|---|
| 阴影下 hue 跳 | H 与 V 耦合 |
| 高光 sat→0 | 退化成无信息 |
| 跨相机色偏 | 无 color constancy |
| NN 与 OpenCV 不一致 | BGR/RGB 或 normalize 错 |
9. 验收
跨时段/跨相机 recall;误检 mask 可视化。对比固定阈值 vs CLAHE/自适应在同一光照变化 clip 上的表现。部署前记录光源型号、WB 模式、阈值 YAML 版本——换相机或换灯必须重标。业务侧接受误检率上限写进 SOP,别用 overall detection rate 掩盖 minority failure。每周抽检一张失败 mask 归档,便于追溯是光照 drift 还是阈值过期。
10. 案例:反光区不是调宽 H 能救
某分拣线红件误检集中在输送带反光区——HSV 里反光 sat 低、hue 随机,加宽 (h_min,h_max) 只会放进更多背景。最终改为 ROI 内灰度 Otsu + 形状 filter,HSV 只做预筛。教训:先画失败 mask 的空间分布,再决定换颜色空间还是换 ROI。颜色分割 PR 应附失败 mask 图,而不是只报 overall precision。
颜色是线索之一,不是稳定物理量。部署域光照不可控时,别在 HSV 阈值上堆 morphology 补丁。
相关
也可以看看
johan's blog