ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

YOLOv5 ROS部署实战:行人检测与红绿灯识别的完整工程链路

YOLOv5 ROS部署实战:行人检测与红绿灯识别的完整工程链路 简介基于YOLOv5的机器人操作系统ROS部署版本实现行人与红绿灯识别面向计算机、电子信息工程、数学等专业学生的课程设计、期末大作业或毕业设计参考。方案覆盖从模型配置、权重加载到ROS节点封装的完整流程适合有一定深度学习与机器人操作系统基础、希望对照源码理解、调试和二次开发的读者。压缩包共123个文件整体约83.87MB主要以配置文件、Python脚本、训练权重、说明文档和环境构建文件为主并附带示例图片、shell脚本与Jupyter笔记等按目录分类便于快速定位。目前已有1934人浏览学习。借助源码、权重与说明文档可掌握目标检测在ROS环境下的数据流、配置思路与节点部署技巧配套的网络结构与注意力机制报告则有助于理解模型改进方向适合作为项目起步模板。1. 基于YOLOv5 ROS部署版做行人和红绿灯识别先想清楚“检测”和“决策”之间的那段路拿到一个“基于YOLOv5 ROS部署版实现行人和红绿灯识别”的源码包很多人的第一反应是赶紧把模型跑起来然后看到摄像头画面里出现框。实际上这类把源码、权重和说明文档打包在一起的方案真正要解决的不是“模型能不能认出目标”而是“检测结果怎么变成 ROS 系统里下游决策能直接消费的消息”。我在 yolo ros 无人小车这类项目上反复折腾过最反直觉的结论是精度问题一般不是瓶颈真正让部署翻车的几乎都集中在图像转换、话题延迟、权重路径这些不被当回事的工程细节上。这套方案适合手里有 ROS 基础、想快速在无人小车或巡检机器人上验证行人避障和红绿灯感知的开发者也适合准备把模型搬到树莓派、Jetson 等边缘盒子上做量产验证的团队。建议你在动手前先建立一条完整认知摄像头负责取流检测节点负责把每一帧变成检测框决策节点负责让底盘做出反应。下面沿着这条链路往下拆并在关键位置给出踩坑记录。2. YOLOv5 的检测逻辑与两类目标差异先看懂原理再碰部署包2.1 单阶段回归与后处理YOLOv5 为什么适合实时 ROS 场景YOLOv5 本质上是一个单阶段回归模型目标检测被看作回归问题一次前向推理同时输出目标框的位置、大小、置信度和类别概率不需要像两阶段模型那样先提候选区域再逐区域分类。这种结构让它在嵌入式平台上的实时性优势非常明显这也是大量 ROS 部署包选它而不是更重模型的原因。网上热门的“yolov5网络结构图”看着分层很多部署阶段只需要抓住三点Backbone 负责提特征Neck 负责把多尺度特征融合起来Head 在 P3、P4、P5 三个尺度上输出预测结果。三个输出头分别对应小、中、大三种目标这一点对红绿灯特别关键。P5 特征图分辨率最低、感受野最大负责大目标行人这种占画面比例高的目标主要靠它红绿灯在远处可能只占几十个像素更多时候要靠 P3 和 P4 的浅层特征。部署时不需要改结构但调阈值之前你得知道模型对远近不同目标给出的置信度分布是不一样的。远处红绿灯的置信度普遍低于近处行人用同一套阈值过滤结果一定是行人保留得多、红绿灯漏得多。后处理是部署版里最容易忽略的部分。网络输出的原始张量要经过置信度阈值过滤、非极大值抑制NMS两步才变成我们看到的框。NMS 的作用是把同一个目标上的多个重叠框合并成一个避免一个行人被框两三次。常见部署包里的后处理参数是 conf_thres0.25、iou_thres0.45 这类默认值实际使用时要看场景调。行人密集的十字路口IoU 阈值太低会把前后重叠的行人合并成一个框阈值太高又会把同一个人拆成两个框。后处理参数属于典型的“yolov5超参数”在部署包里经常被当成不重要的默认项但它对下游决策质量的影响比很多网络结构改动都大。2.2 行人与红绿灯在 anchor 设计上的差异两类目标不能共用同一套直觉YOLOv5 使用 anchor 机制来预定义目标框的形状。官方预训练模型默认提供三组 anchor对应三个检测尺度但部署版本的目标只有行人和红绿灯anchor 的分布必须能覆盖这两类目标的形状差异。行人大多是竖长框宽高比往往在 0.3 到 0.6 之间红绿灯更接近正方形尤其远处只露出灯头时框会非常小。如果拿一套只针对行人的权重去检测红绿灯很可能出现红绿灯置信度很低、漏检严重的现象这不是模型坏了而是 anchor 分布压根没照顾到这类目标。这里给一个常见的 YOLOv5 自定义模型配置文件片段可以对照理解部署权重里的关键字段# yolov5s_custom.yaml 节选 nc: 2 depth_multiple: 0.33 width_multiple: 0.50 anchors: - [10,13, 16,30, 33,23] - [30,61, 62,45, 59,119] - [116,90, 156,198, 373,326]逻辑说明nc 是类别数这里等于 2对应行人和红绿灯。depth_multiple 和 width_multiple 控制网络深度和宽度0.33 和 0.50 是 YOLOv5s 的常见取值。部署时如果追求速度可以换更小的 n 版本追求精度可以换 m 或 l但边缘设备上一般还是 s 更稳。参数说明anchors 这一行是官方模型的初始值实际训练时 YOLOv5 会根据训练集自动重新计算这就是常说的 autoanchor。你不需要手工抠 anchor但要注意一个现象如果训练集里行人占绝大多数、红绿灯样本很少autoanchor 算出来的结果会偏向行人红绿灯的召回率会变得很难看。解决办法不是拿到部署包后硬调 anchor而是回到训练环节做类别平衡这也是“yolov5训练自己的数据集”时最常被忽略的一步。2.3 拿到部署包的权重先别急着跑先做三个检查部署包的完整度从标题看是“源码权重说明文档”三件套但不同作者的打包习惯差别很大。我一般拿到 .rar 解压后先不看代码按三个步骤检查权重是否可用省得后面把时间浪费在错误方向上。第一步确认类别数。下面的小脚本能直接看到模型结构import torch model torch.hub.load(ultralytics/yolov5, custom, pathweights/best.pt, force_reloadFalse) print(model.names)逻辑说明这里的 path 要指向你解压后的实际权重路径相对路径的坑在第五章专门讲。model.names 会输出类别索引到名称的映射比如 {0: person, 1: traffic_light}。如果输出只有 person说明权重只训练了行人红绿灯要另想办法如果输出是 [person, traffic_light] 而不是 [red_light, green_light]说明模型做的是“有没有红绿灯”的检测灯色还要靠后处理来判断也就是第六章要展开的内容。第二步拿一张典型街景图跑一次推理看置信度分布import cv2 results model(cv2.imread(street.jpg), size640) df results.pandas().xyxy[0] print(df[[name, confidence, xmin, ymin, xmax, ymax]])逻辑说明size640 是常见推理输入尺寸模型会把输入图等比缩放后送进网络。如果行人的置信度普遍在 0.7 以上红绿灯只有 0.3 以下说明训练样本不平衡。靠降低 conf_thres 去捞红绿灯会带来大量误检不如先确认训练数据构成。第三步看一眼说明文档里的训练集描述这是判断权重边界最省事的方法。有些训练集全是白天、晴天和正视角有些包含夜间和逆光。夜间场景下红绿灯灯体过曝行人对比度低如果文档里没提夜间数据就该预期这套方案在夜间的表现明显下降而不是在部署后抱怨权重是坏的。搞清楚这些边界再把权重接到 ROS 节点上才会少很多“玄学”问题。3. 跑通最小 ROS 部署 demousb_cam 摄像头取流 检测节点的完整流程3.1 环境准备ROS 版本、Python 与 cv_bridge 三件套多数 YOLOv5 部署包设计在 ROS 1 环境下运行Ubuntu 20.04 ROS Noetic Python3 是常见组合。如果是 Ubuntu 22.04很多人会直接上 ROS 2但旧部署包的节点代码往往还是 rospy 写法迁到 ROS 2 后要改话题接口和时间戳处理工作量不小。我的建议是先按 README 指定的 ROS 1 版本跑通再考虑迁移。装 ROS 基础环境时如果只有一台新机器用一键安装脚本要比手动编译省心很多这也是社区里“鱼香ros一键安装”这类脚本流行起来的原因。我早期手动装过三台机器后来给新同事配环境就优先用一键脚本再用 rosdep 补齐剩余依赖。环境验证三步直接在终端里执行python3 -c import rospy; print(rospy ok) python3 -c import cv2; print(cv2.__version__) python3 -c import torch; print(torch.__version__)参数说明第一行确认 rospy 在 Python3 环境下可用第二行确认 cv2 存在这里有个高发坑pip 安装的 opencv-python 会和 ROS 自带的 cv_bridge 冲突第五章专门讲第三行确认 PyTorch 正确加载。这三样不齐检测节点基本启动不起来。之后创建工作空间。常见做法是mkdir -p ~/catkin_ws/src cd ~/catkin_ws catkin_make source devel/setup.bash逻辑说明把部署包里的功能包解压到 ~/catkin_ws/src 下再在 catkin_ws 根目录执行 catkin_make。如果编译报错多半是缺少某个 ROS 依赖包用 rosdep install --from-paths src --ignore-src -r -y 一次性安装缺失依赖。注意不要用 sudo 执行 catkin_make权限问题会导致 devel 目录属主混乱后续每次 source 都可能报错。这里再提醒一句没把包解压到 src 目录命令执行多少遍都没有用。3.2 摄像头与检测节点的最小 launch用 ROS 打开电脑自带摄像头部署方案里检测节点通常以 ROS 节点方式运行而不是一个独立 python 脚本。摄像头取流最常见的是 usb_cam 这个 ROS 包。先测一下摄像头设备号用 ls /dev/video* 确认笔记本自带摄像头一般是 /dev/video0但也可能被虚拟摄像头抢占。确认后用下面这个 launch 文件把摄像头和检测节点一起拉起来launch node nameusb_cam pkgusb_cam typeusb_cam_node outputscreen param namevideo_device value/dev/video0/ param namepixel_format valueyuyv/ param nameimage_width value640/ param nameimage_height value480/ param nameframerate value15/ /node node nameyolo_detector pkgyour_pkg typedetect_node.py outputscreen param nameweights_path value$(find your_pkg)/weights/best.pt/ param nameconf_thres value0.35/ /node /launch逻辑说明usb_cam 节点把摄像头图像发布到 /camera/image_raw 话题detect_node.py 订阅该话题做推理。pixel_format 用 yuyv 是因为 usb_cam 在大部分 UVC 摄像头下对 yuyv 支持最稳定mjpeg 在部分设备上会出现花屏和帧率波动。640x480 是部署阶段比较保守的分辨率既保证行人在画面里有足够像素又不会让推理时间长得无法接受。画面明显卡顿的话先把 framerate 降到 10不要一上来就换模型。参数说明conf_thres0.35 是第一个需要重点关注的部署参数它直接决定哪些检测结果会下发到决策节点。0.35 是行人识别场景的常见折中太低会看到大量误检框太高会漏掉远处行人。红绿灯小目标在默认阈值下容易被过滤如果发现红绿灯经常不出现优先把这个参数往下降。部署包默认可能给的是 0.25 或 0.3运行前至少显式写一次方便后面对比效果。启动命令roslaunch your_pkg yolo_min.launch这条命令是启动入口。如果 roslaunch 直接报找不到包先确认 source 过 devel/setup.bash如果报找不到 launch 文件则是包路径没放对。启动成功后在新终端执行 rosnode list应该能看到 /usb_cam 和 /yolo_detector 两个节点。3.3 验证检测输出没有显示器也要能看到画面验证环节最容易出现的情况是节点日志没有报错但调试画面看不到。很多开发机没有接显示器还有的是通过 SSH 远程操作无人小车。rqt_image_view 是最快的验证方式但它必须在有图形界面的环境里打开。远程场景下我一般用下面这个订阅脚本把画好框的检测结果保存成图片import rospy, cv2 from sensor_msgs.msg import Image from cv_bridge import CvBridge bridge CvBridge() def cb(msg): frame bridge.imgmsg_to_cv2(msg, bgr8) cv2.imwrite(/tmp/ros_preview.jpg, frame) rospy.loginfo(saved %dx%d, frame.shape[1], frame.shape[0]) rospy.init_node(save_preview) rospy.Subscriber(/yolo/debug_image, Image, cb, queue_size1, buff_size2**24) rospy.spin()逻辑说明这里的 /yolo/debug_image 话题一般由检测节点发布内容是把检测框和置信度画在原始图像上。imgmsg_to_cv2 的第二个参数 bgr8 表示把 ROS 图像消息转成 OpenCV 的 BGR 格式不要省略默认的 passthrough 在部分相机节点下会给单通道图。buff_size 设置为 2**24 是为了让大分辨率图像订阅不丢数据这是个特别容易踩的缓冲坑默认 buff_size 偏小订阅 1080p 图像时经常出现“图像卡住”但日志无报错的现象。验证完成后手上应该有一张带检测框的实际图像。下一步是把视频输入源从 usb_cam 扩展到 rosbag 回放、本地视频、海康相机 RTSP 流这些更贴合落地场景的输入。常见做法是先把 RTSP 流转成 ROS 图像话题再让检测节点订阅同一个话题检测节点本身不用改代码。这一步跑通之前先别急着改输入源后面所有调试都要依赖这个最小环境。4. ROS 话题与消息设计检测框从检测节点流向决策模块的工程细节4.1 节点结构与数据流图像取流、检测推理、速度指令分三段部署包跑通不是终点你得让检测结果真正服务于下游决策。最常见的机器人感知链路是摄像头节点把图像发布到 /camera/image_raw检测节点订阅图像推理出行人和红绿灯的框再发布两类话题一类是可视化用的 /yolo/debug_image一类是结构化检测结果如 /detector/bounding_boxes决策节点订阅结构化结果后输出速度指令到 /cmd_vel。整个过程是三个节点、三个话题各司其职。这种设计最大的好处是解耦。摄像头节点不需要知道后面是 YOLO 还是别的模型检测节点不需要知道底盘是差速还是阿克曼决策节点可以先在仿真环境里用 Gazebo 配合 ROS 小车自主导航仿真调逻辑再切换到真机。坏处是话题关系一多出错后不好定位图像没发布、检测没输出、决策没订阅三种情况的日志都长得差不多。所以我养成了一个习惯每个节点启动后用 rostopic hz /话题名 看频率用 rostopic echo 看消息内容比盯着 log 有效得多。说到真实场景很多部署会把检测放到 Jetson 这类边缘设备上把决策放到另一台性能机上。多机通信配置的要点就是 ROS_MASTER_URI 和 ROS_IP 必须配对正确。主机 roscore 在哪台机器所有节点就把 ROS_MASTER_URI 指向哪里ROS_IP 要写各机器自己的局域网地址不能留空。我见过太多 CAN 通讯正常、但图像话题一直 CONNECT 不上的局面最后发现是 ROS_IP 配成了 127.0.0.1。4.2 自定义检测消息与 cv_bridge坐标转换是部署版最容易出错的界面结构化检测结果适合用自定义消息承载而不是把框画进图像里让下游去解析像素。自定义消息的定义一般长这样# BoundingBox.msg Header header string class_name float32 score float32 xmin float32 ymin float32 xmax float32 ymax逻辑说明Header 里有时间戳对决策节点做延迟判断特别重要。class_name 是类别名score 是置信度。xmin、ymin、xmax、ymax 是像素坐标系里的检测框注意这个约定是 xyxy不是 YOLO 训练时常用的 xywh也不是归一化坐标。不同来源的部署包在这里约定差别很大如果代码里用的是 COCO 格式的 xywh下游节点必须做一次转换否则框会画到画面外或者画偏。我的做法是在检测节点里统一转成 xyxy 像素坐标再发布下游消费时不再关心模型内部是什么格式。发布端一个典型的代码片段from your_pkg.msg import BoundingBox, BoundingBoxes box BoundingBox() box.class_name person box.score 0.92 box.xmin, box.ymin 120, 200 box.xmax, box.ymax 340, 540 msg BoundingBoxes() msg.bounding_boxes [box] pub.publish(msg)逻辑说明BoundingBoxes 是包含一个检测框列表的自定义消息用于承载一帧所有检测结果。发布话题前可以用 rosmsg show BoundingBoxes 检查字段是否与 .msg 文件一致字段名不对在编译期间就会暴露。发布频率建议跟随图像帧率不要单独起一个更快的线程去刷话题否则下游会收到大量重复帧决策节点的滤波逻辑会被打乱。cv_bridge 在这里扮演图像转换角色。它的坑在于ROS 编译时绑定了系统自带的 OpenCV而 Python 环境下很可能装了另一个版本的 OpenCV。两个库同时存在时检测节点同时 import cv2 和 from cv_bridge import CvBridge加载顺序稍微不对就会出现段错误。常见规避办法是让 cv_bridge 用的 cv2 与系统版本保持一致而不是把系统卸掉用 pip 版这点在第五章详细展开。4.3 多节点同时发速度指令时底盘节点到底听谁的无人小车项目里“ros 多个节点发布移动指令话题时底盘节点如何取舍”是社区里反复出现的问题。很多人写避障节点时直接向 /cmd_vel 发布速度导航节点也这么做结果机器人被两个节点来回拉扯表现为抖动、来回抽动、甚至原地转圈。底盘节点只有一个它订阅到的 /cmd_vel 是多个发布者混在一起的消息流谁抢到最后一条谁就生效。比较可靠的取舍方式是在所有上层节点和底盘之间加一个仲裁节点或者用现成的 twist_mux 这类管理器。上层节点把速度指令发布到各自命名话题比如 /nav_vel、/avoid_vel、/yolo_stop_vel仲裁节点按优先级决定最终 /cmd_vel。视觉检测的优先级在行人避障场景里应该最高一旦检测到行人在安全距离内就锁死其他速度指令强制减速或停车。仲裁逻辑的优先级参数是部署时真正要花时间调的东西而不是在检测节点里简单写一个 pub.publish(0,0)。4.4 Rosbag 复用让部署调试不再依赖真机实跑想重复利用一次真机采集的数据来做调试rosbag record 是最常见的做法rosbag record /camera/image_raw /yolo/debug_image /cmd_vel rosbag play record.bag --loop逻辑说明record 把指定话题的数据包记录下来play 把数据重新发布回 ROS 话题。这样改检测节点代码时不需要一次次推着车到路边实跑直接回放数据就能回归验证。注意 --loop 会把 bag 循环播放配合固定的输入流可以稳定复现“偶发漏检”这类问题。如果输入源是海康相机这类 RTSP 设备也可以先把 RTSP 拉流后的图像话题录成 rosbag再把 bag 当输入来调检测效率和稳定性都会高很多。5. 部署避坑五条真实踩坑记录与排查方法5.1 检测节点启动即崩cv_bridge 与 OpenCV 版本打架现象roslaunch 一键启动后节点还没开始取流就直接闪退终端里报 undefined symbol 或 GLIBC 版本不匹配往往出现在 cv2 相关模块。原因系统里装了两套 OpenCV。ROS 自带的 cv_bridge 编译时链接到 /opt/ros/noetic/lib 下的系统库而部署包在 requirements.txt 里要求 pip 安装 opencv-python这个包把新版 OpenCV 动态链接库放进了 site-packages。两个库同时加载后符号冲突Python 解释器直接段错误。解决先确认当前环境用的是哪个 OpenCV执行 python3 -c import cv2; print(cv2.version, cv2.file)。如果路径在 site-packages而 /opt/ros/noetic/lib 下存在另一个版本优先卸载 pip 版执行 pip uninstall opencv-python opencv-contrib-python然后重启节点。如果卸载后还有其他包依赖 pip 版 OpenCV改用虚拟环境把 ROS 的 Python 路径和虚拟环境隔离别在同一个解释器里硬凑。这个坑换 Python 版本或重装 ROS 后特别容易复发。5.2 画面延迟和检测框跳变话题队列和帧率没对齐现象可视化话题里的检测框一秒跳一次或者检测框在目标上大范围抖动但摄像头原始画面是流畅的。如果在 30fps 的原始相机话题上看检测节点输出的频率明显低于预期。原因检测节点订阅图像时用了较大队列推理速度跟不上图像发布速度ROS 会在队列里积压旧帧。积压的帧在处理器空闲时被快速消费形成“一阵快一阵慢”的检测节奏另外旧帧带有旧时间戳决策节点用错时间戳还会把过期的框当成当前状态。解决订阅图像时把 queue_size 设为 1并让检测节点丢弃时间戳早于上一帧的图像只处理最新的一帧。另一个有效做法是把相机 framerate 降到 10 到 15匹配模型推理速度这比升级硬件解决得更快。回放 rosbag 时建议按原速播放不要加速否则同样会复现这个现象。5.3 权重路径找不到roslaunch 的工作目录坑现象直接在终端里 python3 detect_node.py 跑得通但 roslaunch 启动后报找不到 weights/best.ptFileNotFoundError 指向的路径是 ~/.ros/weights/best.pt。原因roslaunch 默认会把工作目录切换到用户的 ~/.ros 目录而不是功能包所在目录。代码里写的相对路径 weights/best.pt在终端里执行时以当前工作目录为基准在 roslaunch 环境里就变成了 ~/.ros/weights/best.pt。解决不要用相对路径。常见做法是把权重路径做成 launch 参数在 launch 文件里用 $(find your_pkg)/weights/best.pt 指明绝对路径节点代码里用 rospy.get_param(~weights_path) 获取。同样的问题也会出现在中文路径场景如果解压路径带了中文目录名OpenCV 的 imread 和 PyTorch 的 torch.load 在部分环境下会失败最好统一改成英文目录。5.4 嵌入式设备上跑不动Jetson 和树莓派的显存与算力限制现象部署包在 PC 上满帧运行放到 Jetson 或树莓派上推理时间从 30ms 变成 300ms 甚至更低画面直接变成幻灯片稍大分辨率下还会报 CUDA out of memory。原因边缘设备 GPU 显存普遍有限Jetson 的 GPU 与 CPU 共享内存640x640 输入加上 batch 和动态图开销很容易撑爆显存。树莓派没有可用的 CUDA 加速纯 CPU 推理同一模型的速度基本没有工程可用性。这里说的“树莓派4b部署yolov5”不是不行是必须把输入尺寸和模型版本一起降下来。解决第一步把推理输入尺寸从 640 降到 416 或 320很多部署包在代码里直接用默认 640改动入口往往是 detect_node.py 里 preprocess 函数的 size 参数。第二步对 Jetson 这类带 TensorRT 加速的平台把权重转换成 TensorRT 的 engine 文件常见工具是官方仓库的 export.py转换后推理延迟通常比原生 PyTorch 降一个量级。第三代 Jetson Orin 性能余量大不少但老平台和树莓派建议优先走量化路线这跟 rk3588 部署 yolov8 时先做 RKNN 量化的思路是相通的。提示量化后权重精度下降是正常现象不要在量化版上追求和 FP16 完全一致的指标你要对比的是部署后的端到端延迟和漏检率。5.5 一个行人被框两次多模型并行时的重复检测问题现象部署包同时发布了两个检测结果话题一个行人被两个框重复包围置信度一个高一个低红绿灯也一样。下游决策节点拿到重复框容易产生重复计数和误判。原因很多部署包为了让行人和红绿灯都有较好表现分别用两个权重做推理。两个模型都检测到同一个目标时不可避免产生重叠框如果代码里没对两个模型的输出做融合重复框会直接进入决策逻辑。解决把两个模型的结果在检测节点内部统一做一次 NMS。具体做法是把两个模型的输出合并到一个框列表按类别分开对同一类别按 IoU 阈值 0.5 融合保留置信度高的框融合后再发布结构化话题。更干净的方案是重新训练一个 nc2 的权重让模型用同一个输出头同时检测行人和红绿灯只在训练时需要保证数据集里两类样本都足够。如果暂时不能重训融合 NMS 是成本最低的兜底方案。6. 框出来之后的最后一公里红绿灯颜色判定与 rosbag 回归自测6.1 从检测框到灯色状态HSV 空间下抠出灯体YOLO 检测结果给出的 traffic_light 框并不等于红灯或绿灯。部署级红绿灯识别还需要判断灯色状态。在 ROS 部署版里我不会把颜色判断交给一个重型分类网络而是直接在检测框内做 HSV 颜色统计。取检测框裁剪出灯体区域去掉暗色背景分别统计红色和绿色像素占比。def judge_light(crop_bgr): hsv cv2.cvtColor(crop_bgr, cv2.COLOR_BGR2HSV) red1 cv2.inRange(hsv, (0, 70, 120), (10, 255, 255)) red2 cv2.inRange(hsv, (170, 70, 120), (180, 255, 255)) green cv2.inRange(hsv, (40, 70, 100), (80, 255, 255)) red_px cv2.countNonZero(red1) cv2.countNonZero(red2) green_px cv2.countNonZero(green) return red if red_px green_px else green逻辑说明红色在 HSV 色相环上跨越 0 与 180 两个边界所以要分两段取值。灯的像素通常有较高饱和度与亮度因此把饱和度下限设为 70、亮度下限设为 120用来排除灰暗背景。这个阈值只能算经验值遇到强逆光或灯体过曝时需要上调亮度下限。运行这个后处理前先把检测框按 1.2 倍左右向外扩一点因为 YOLO 的框可能会贴着灯体切掉边缘的高亮像素。6.2 让改动落地rosbag 回放做回归自测灯色判断逻辑改完后不能直接上车跑。我养成的习惯是把真机采集的 5 分钟 rosbag 存下来改进任何感知或后处理逻辑后先用 rosbag play 回放数据反复验证。回放时同时订阅 /detector/bounding_boxes 和 /detector/debug_image检查灯色判定是否稳定比实车测试省时间得多也能复现偶发问题。回放命令和 4.4 节一致区别在于要录的是自定义检测话题。这个部署方向值不值得投入我的判断标准是如果目标只是验证行人避障逻辑把 YOLOv5 部署版跑通并配合颜色后处理是成本最低的一步如果目标是量产级红绿灯识别检测框之后的路还很长灯色、倒计时、方向箭头和夜间泛光都要逐个处理。踩过的坑里对我帮助最大的是把所有检测结果先落到 rosbag 和结构化话题上再来调参而不是每次都依赖肉眼盯实时画面。希望这套“检测 工程链路 颜色后处理”的走法能帮你少走几步弯路。本文还有配套的精品资源点击获取
返回列表