RDK X5小车巡线缺少赛道检测功能包

你好!关于黄色区域检测,OpenCV 调参困难是常见问题(光照敏感、颜色阈值难定)。结合社区经验和智能车竞赛场景,给你 3 个更优方案:


:bullseye: 推荐方案对比

方案 难度 稳定性 推荐指数
方案 A:YOLO 检测黄色区域 :star::star: :star::star::star::star::star: :fire::fire::fire::fire::fire:
方案 B:OpenCV HSV + 自适应阈值 :star::star::star::star: :star::star::star: :star::star::star:
方案 C:语义分割模型 :star::star::star: :star::star::star::star: :star::star::star::star:

:white_check_mark: 方案 A:用 YOLO 检测黄色区域(强烈推荐)

核心思路:把黄色区域当成一个目标类别,用 YOLO 直接检测,避免 OpenCV 调参。

步骤 1:训练数据准备

# 在 YOLOv5s 训练数据中添加黄色区域类别
# obstacles.list 添加一行:
construction_cone
qr_code
park
yellow_zone  # 新增黄色区域类别

标注工具:使用 LabelImg 标注黄色区域为 yellow_zone

步骤 2:重新训练模型

# 使用社区推荐的训练流程
# 参考:https://forum.d-robotics.cc/t/topic/28624
python train.py --img 640 --batch 16 --epochs 100 --data yellow_zone.yaml --weights yolov5s.pt

步骤 3:部署到 RDK X5

# 模型转换为.bin 格式
hb_mapper model --model-type yolov5 --march x5 --output yellow_zone.bin

步骤 4:代码集成

racing_obstacle_detection_yolo 节点中:

void yolo_callback(const TargetsMsg::SharedPtr msg) {
    for (const auto& target : msg->targets) {
        if (target.type == "yellow_zone") {
            // 获取黄色区域位置
            int center_x = target.rois[0].rect.x_offset + target.rois[0].rect.width / 2;
            int bottom_y = target.rois[0].rect.y_offset + target.rois[0].rect.height;
            
            // 根据黄色区域位置调整控制策略
            handleYellowZone(center_x, bottom_y);
            return;
        }
    }
}

优势

  • :white_check_mark: 不受光照影响
  • :white_check_mark: 无需调 HSV 阈值
  • :white_check_mark: 与避障/巡线共用一个模型
  • :white_check_mark: 社区已有成熟流程

:wrench: 方案 B:OpenCV HSV 优化方案(如果必须用 OpenCV)

如果坚持用 OpenCV,给你抗光照干扰的调参方法

关键代码

import cv2
import numpy as np

def detect_yellow_zone(frame):
    # 1. 转换到 HSV 空间
    hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
    
    # 2. 黄色 HSV 范围(需根据实际光照微调)
    # 推荐先用这个范围测试,再微调
    lower_yellow = np.array([20, 100, 100])
    upper_yellow = np.array([35, 255, 255])
    
    # 3. 创建掩码
    mask = cv2.inRange(hsv, lower_yellow, upper_yellow)
    
    # 4. 形态学操作去噪
    kernel = np.ones((5, 5), np.uint8)
    mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel)
    mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel)
    
    # 5. 查找轮廓
    contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    
    if contours:
        # 取最大轮廓
        largest_contour = max(contours, key=cv2.contourArea)
        area = cv2.contourArea(largest_contour)
        
        if area > 1000:  # 面积阈值过滤
            # 计算中心点
            M = cv2.moments(largest_contour)
            if M["m00"] != 0:
                cx = int(M["m10"] / M["m00"])
                cy = int(M["m01"] / M["m00"])
                return (cx, cy), largest_contour
    
    return None, None

:magnifying_glass_tilted_left: 快速调参技巧

  1. 使用 trackbar 实时调试
def nothing(x):
    pass

cv2.namedWindow('HSV Tuning')
cv2.createTrackbar('H_min', 'HSV Tuning', 20, 180, nothing)
cv2.createTrackbar('H_max', 'HSV Tuning', 35, 180, nothing)
cv2.createTrackbar('S_min', 'HSV Tuning', 100, 255, nothing)
cv2.createTrackbar('S_max', 'HSV Tuning', 255, 255, nothing)
cv2.createTrackbar('V_min', 'HSV Tuning', 100, 255, nothing)
cv2.createTrackbar('V_max', 'HSV Tuning', 255, 255, nothing)

while True:
    h_min = cv2.getTrackbarPos('H_min', 'HSV Tuning')
    h_max = cv2.getTrackbarPos('H_max', 'HSV Tuning')
    # ... 获取其他参数
    
    mask = cv2.inRange(hsv, (h_min, s_min, v_min), (h_max, s_max, v_max))
    cv2.imshow('Mask', mask)
  1. 光照自适应
# 动态调整 V 阈值
v_avg = np.mean(hsv[:, :, 2])
v_min = max(50, v_avg - 50)
v_max = min(255, v_avg + 50)

:bar_chart: 方案 C:语义分割(适合复杂场景)

如果黄色区域形状不规则,考虑用语义分割模型:


:light_bulb: 实战建议

  1. 优先方案 A(YOLO 检测)

    • 你已经在使用 YOLOv5s 全功能检测
    • 只需增加一个类别,无需额外部署
    • 社区有大量 YOLO 训练部署经验
  2. 如果必须用 OpenCV

    • 先用 trackbar 工具找到最佳 HSV 范围
    • 加入形态学操作去噪
    • 考虑光照补偿算法
  3. 调试技巧

    # 在 Web 界面实时查看掩码效果
    # 修改 websocket.launch.py 订阅 mask 话题
    

:books: 相关资源


建议:既然你已经在用 YOLOv5s 做全功能检测,直接在训练数据里加上黄色区域类别是最快的方案,避免 OpenCV 调参的坑。

需要具体的 YOLO 训练配置或 OpenCV 调试代码可以继续问我!