4、颜色阈值分割:利用HSL/HSV颜色空间提取白色和黄色车道线的方法
在上一节中,我们完成了图像灰度化和高斯模糊处理,但灰度图像中车道线与路面背景的对比度仍然有限,尤其是在阴影、强光或沥青路面颜色不均的场景下。本节将引入颜色阈值分割技术,利用HSL/HSV颜色空间对白色和黄色车道线进行精确提取。与RGB空间相比,HSL/HSV将颜色信息分解为色相(Hue)、饱和度(Saturation)和亮度(Lightness/Value)三个独立维度,能够更稳定地应对光照变化和阴影干扰,是车道线识别系统中承上启下的关键环节。
上图展示了颜色阈值分割的整体流程:从BGR图像出发,经过颜色空间转换后,分别对白色和黄色生成掩码,再通过按位或合并得到最终的二值掩码图。下面我们将深入探讨HSL/HSV颜色空间的原理、阈值选取方法、实战案例以及常见误区。
4.1 核心原理:为什么选择HSL/HSV而非RGB
RGB颜色空间由红、绿、蓝三个通道组成,三个通道高度相关,且对光照变化极其敏感。例如,一条白色车道线在阴影下可能呈现RGB(180,180,180),而在阳光下为RGB(240,240,240),两者在RGB空间中的欧氏距离很大,难以用固定阈值同时覆盖。而HSL(色相、饱和度、亮度)和HSV(色相、饱和度、明度)将颜色信息解耦:色相H表示颜色的本质属性(如红色、黄色),饱和度S表示颜色的纯净程度(灰度为0,纯色为255),亮度L/明度V表示颜色的明暗程度。这种解耦使得我们可以针对车道线的颜色本质进行分割,而不受光照强度变化的直接影响。
具体而言,白色车道线的特征是高亮度、低饱和度,无论H值是多少,只要L足够高且S足够低,就可以判定为白色。黄色车道线的特征是色相集中在30°附近(OpenCV中H范围为0-180,对应色相环0-360°),且饱和度和亮度都较高。这种基于颜色属性的判断方式,比RGB空间中的"三个通道同时满足条件"要稳健得多。
4.2 判断方法:阈值选取与掩码生成操作流程
在OpenCV中,颜色阈值分割通常遵循以下操作流程。首先,使用cv2.cvtColor()将BGR图像转换为HSL或HSV空间。然后,通过cv2.inRange()函数为每种颜色定义阈值范围,生成二值掩码。最后,使用cv2.bitwise_or()合并白色和黄色掩码。
import cv2
import numpy as np
def extract_lane_colors(img_bgr):
# 1. 转换为HSL空间
img_hsl = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2HLS)
# 2. 白色掩码:高亮度,低饱和度
lower_white = np.array([0, 200, 0]) # H任意, L≥200, S任意
upper_white = np.array([180, 255, 30]) # H任意, L≤255, S≤30
mask_white = cv2.inRange(img_hsl, lower_white, upper_white)
# 3. 黄色掩码:色相窄带,高饱和度,中等亮度
lower_yellow = np.array([15, 150, 80]) # H 15-35, L≥150, S≥80
upper_yellow = np.array([35, 255, 255])
mask_yellow = cv2.inRange(img_hsl, lower_yellow, upper_yellow)
# 4. 合并掩码
mask_combined = cv2.bitwise_or(mask_white, mask_yellow)
# 5. 可选:形态学操作去除噪点
kernel = np.ones((3,3), np.uint8)
mask_clean = cv2.morphologyEx(mask_combined, cv2.MORPH_OPEN, kernel)
return mask_clean
阈值选取的核心原则是"宁宽勿窄,宁漏勿错"。在初始调试阶段,可以适当放宽阈值范围,确保车道线完整保留;后续再根据误检情况逐步收紧。具体操作时,建议使用OpenCV的滑动条(Trackbar)动态调整阈值,观察掩码效果,而不是一次性设定固定值。
| 颜色目标 | HSL阈值范围(H, L, S) | HSV阈值范围(H, V, S) | 适用场景 |
|---|---|---|---|
| 白色车道线 | H: 0-180, L: 200-255, S: 0-30 | H: 0-180, V: 200-255, S: 0-30 | 白天、阴天、阴影较少 |
| 白色(阴影下) | H: 0-180, L: 170-255, S: 0-40 | H: 0-180, V: 170-255, S: 0-40 | 树荫、建筑物阴影 |
| 黄色车道线 | H: 15-35, L: 150-255, S: 80-255 | H: 20-35, V: 150-255, S: 80-255 | 标准黄色标线 |
| 黄色(偏暗) | H: 15-35, L: 120-255, S: 60-255 | H: 20-35, V: 120-255, S: 60-255 | 黄昏、隧道内 |
4.3 案例拆解:高速公路强光与阴影交替场景
我们以一段真实的高速公路行车记录仪视频为例。该路段两侧有密集的树木,阳光透过树叶形成斑驳阴影,同时路面为深色沥青,部分路段有反光。初始使用RGB阈值分割时,白色车道线在阴影下被漏检,而反光区域被误检为白色。切换到HSL空间后,我们进行了以下调试过程:
- 初始参数设定:白色L下限设为220,S上限设为25;黄色H范围20-30,S下限100,L下限180。结果发现阴影下的白色车道线大量漏检,掩码覆盖率仅约60%。
- 分析判断:通过直方图统计发现,阴影区域的白色车道线L值降至180-200之间,而S值升高至40-60(因为阴影使颜色变灰,饱和度相对升高)。
- 参数调整:将白色L下限降至180,S上限放宽至50;同时将黄色L下限降至140,S下限降至70。调整后,掩码覆盖率提升至92%,但出现了少量误检——路面反光区域被误判为白色。
- 优化处理:引入形态学开运算(3×3核)去除孤立噪点,并利用ROI区域排除天空和路肩干扰。最终掩码准确率达到95%以上,漏检率低于3%。
这个案例说明,阈值参数不是一成不变的,需要根据实际场景的光照分布进行动态调整。在工程实现中,可以设计一个简单的自适应策略:统计图像上半部分的平均亮度,若低于某个阈值(如100),则自动降低L下限20-30个单位。
4.4 常见误区与总结复盘
在实际项目开发中,以下误区最为常见:
- 误区一:直接使用RGB阈值。RGB空间对光照变化极度敏感,同一颜色在不同亮度下RGB值差异巨大,固定阈值无法适应环境变化。
- 误区二:混淆HSL和HSV的通道顺序。OpenCV中
COLOR_BGR2HLS返回的通道顺序是H、L、S,而COLOR_BGR2HSV返回的是H、S、V。如果搞混顺序,阈值设置将完全失效。 - 误区三:忽略H通道的环形特性。H值在0和180之间是连续的(0和180都代表红色),如果黄色阈值跨越了0/180边界(例如H从170到10),需要拆分为两个区间分别处理。
- 误区四:阈值固定不变。一天中光照色温变化显著(清晨偏暖、正午偏冷、黄昏偏红),固定阈值在早晚可能失效。建议根据时间或图像统计特征动态调整。