ARTICLE DETAIL

资讯详情

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

YOLOv5 ROS部署版行人与红绿灯识别实战指南

YOLOv5 ROS部署版行人与红绿灯识别实战指南 简介这是一份基于YOLOv5在ROS环境下完成行人与红绿灯识别部署的完整工程包适合计算机、电子信息工程、数学等专业学生用于课程设计、期末大作业或毕业设计参考。包内除源码外还提供训练权重、模型配置文件与说明文档从环境搭建、模型结构到注意力机制改进均有涉及便于有Python与ROS基础的学习者快速上手或二次开发。资源共123个文件涵盖yaml配置、py源码、shell脚本、Dockerfile部署文件、ipynb教程、pt权重与说明文档等83.87MB压缩包目录清晰可按需取用。已有1933人学习下载。借助这套资料使用者能够熟悉YOLOv5与ROS节点间协同流程理解红绿灯检测中的图像处理与模型调用逻辑并基于现有权重快速验证识别效果为后续功能扩展或论文实验提供扎实起点。1. YOLOv5 ROS部署版行人和红绿灯识别先看清这个包解决了什么问题在机器人项目里视觉检测最花时间的往往不是模型精度而是把模型接进ROS节点里让它稳定地跑。你手里的“YOLOv5 ROS部署版源码权重说明文档”本质上是把“读图—推理—出框—发布话题”这条链路封装好的一套工程产物。它解决的核心问题是把YOLOv5原生推理的输出变成带时间戳、可订阅、可被下游决策节点直接消费的ROS话题消息。适合顺着这个标题往下走的人是正在做服务机器人、园区无人车或实验平台需要识别行人和红绿灯的开发者。你不需要从零搭通信框架也暂时不用深究YOLOv5的训练细节你要做的是理解包内代码结构、环境组合和排查路径。先说一个容易误导人的判断这类部署方向权重只占三成价值通信和部署代码占七成。把这句话想明白再解压看代码效率会高很多。2. YOLOv5与ROS之间的协作架构节点、话题与消息流2.1 检测节点为什么必须独立成节点而不是和摄像头写在一起新手最容易犯的错是把摄像头读取和YOLOv5推理写进同一个Python脚本以“图省事”开始以“改一处崩三处”结束。真实部署里摄像头驱动、检测节点、决策节点是三个独立进程分别对应ROS节点。usb_cam或realsense节点负责发布sensor_msgs/Image话题YOLOv5检测节点订阅图像话题推理完成后发布检测结果话题决策节点再订阅检测结果去控制底盘或机械臂。这个模型的最大好处是边界清晰换摄像头不用改检测代码换模型不用动摄像头节点。有人会问检测节点里的推理循环不就是一个while True吗在ROS里不是这么写的。ROS节点用回调函数响应订阅话题处理节奏由消息到达驱动而不是自己循环。检测节点收到一张图像就推理一次推理期间摄像头节点持续发布新图像如果回调队列设置不当内存占用会逐渐涨上去。关于ROS1和ROS2的通信关系这里先提一句这类部署包大多基于ROS1 Noetic写的ROS2的节点、话题、消息定义都要重写迁移成本远高于想象。如果你的底盘驱动和传感器只有ROS1版本直接用Noetic最稳。2.2 自定义Detection.msg还是复用标准消息带源码的部署版多数习惯在msg目录里定义轻量的Detection.msg典型字段如下std_msgs/Header header string class_name int32 class_id float32 confidence float32 xmin float32 ymin float32 xmax float32 ymax这里不用vision_msgs/BoundingBox2D的原因是它只存中心点和尺寸下游逻辑需要x1y1x2y2时还得再换算。自定义消息把格式一次定死代码里直接取xmin、xmax省一道工序。代价是别的包要用这个消息必须在package.xml里声明依赖并且先catkin_make生成好消息模块。如果你只想做可视化不想管下游逻辑也可以直接发visualization_msgs/MarkerArray但让控制节点用Marker消息做逻辑判断是给自己埋坑。2.3 把检测框画进rvizMarker消息的坐标陷阱rviz里显示检测框常见的做法是检测节点同时发布Marker话题。核心代码from visualization_msgs.msg import Marker marker Marker() marker.header.frame_id camera_link marker.header.stamp rospy.Time.now() marker.type Marker.CUBE marker.action Marker.ADD marker.pose.position.x (msg.xmin msg.xmax) / 2.0 marker.pose.position.y (msg.ymin msg.ymax) / 2.0 marker.pose.position.z 0.0 marker.scale.x msg.xmax - msg.xmin marker.scale.y msg.ymax - msg.ymin marker.scale.z 0.1 marker.color.a 0.5 marker.color.r 1.0 marker.color.g 1.0 marker.color.b 0.0 marker_pub.publish(marker)这段代码的坑在frame_id必须和图像话题的frame一致。如果图像frame是camera_linkMarker也写camera_link否则rviz里框会飘在莫名其妙的位置。scale.z取0.1只是为了有立体感不代表真实深度做避障决策时不能拿这个z值去算距离。2.4 时间戳与坐标系两件极易被忽略的事图像消息的header.stamp表示采集时刻检测节点不能擅自把它替换成推理结束时间。控制节点依赖时间戳做延迟补偿改掉会导致整个系统时钟偏移。规范写法是det_msg.header.stamp image_msg.header.stamp如果确实要记录推理耗时就在消息里单独加float32 inference_time字段跟header.stamp分开。另一个问题是传感器间同步激光雷达、图像、检测结果是否在同一坐标系下由tf树决定。部署版通常在launch里加静态变换把camera_link和base_link连起来node pkgtf2_ros typestatic_transform_publisher namecamera_broadcaster args0.12 0 0.3 0 0 0 base_link camera_link/这段参数依次是x、y、z平移量和roll、pitch、yaw旋转量必须跟你实际安装的相机位置一致写错了在rviz里看就是框全部偏移。2.5 先看rqt_graph再动手改代码环境里不止一个节点时靠读代码推关系容易漏。启动系统后跑一下实时话题图rosrun rqt_graph rqt_graph图中能看到话题从哪个节点发出、被谁订阅。有经验的开发者会先看这幅图再动代码因为通信层错误多半这时候就暴露了。一个正常工作的部署版图里至少有一条“图像发布节点 → yolov5检测节点 → 可视化或决策节点”的通路。如果检测节点没有订阅到图像话题要么话题名写错要么消息类型对不上要么摄像头节点根本没启动。3. 环境准备与版本对齐Ubuntu、ROS、CUDA、PyTorch怎么组合3.1 版本对齐表最卡人的不是YOLOv5是ROS和显卡驱动部署环境八成报错来自版本错位。拿到一个Noetic版的ROS部署包直接套用老教程在Ubuntu 16.04上装ROS Kinetic第一关就过不去。给出参考组合组件推荐版本备注Ubuntu18.04 / 20.04对应ROS Melodic / NoeticROSNoetic默认Python 3.8部署脚本多按Python 3写CUDA11.x先跑nvidia-smi看驱动支持的版本PyTorch1.8及以上YOLOv5 v6.0后对PyTorch版本有最低要求Python3.8不要另装3.10当默认解释器判断“这份部署包对应的YOLOv5版本”启动节点时会打印项目版本信息或者在requirements.txt里能看到核心依赖。YOLOv5-5.0、v6.0、v7.0差异很大v6.0后把模型结构改过权重不能直接跨版本加载。用v5.0代码加载v6.0训练的权重轻则报警告重则输出全是空的。3.2 用鱼香ROS一键安装脚本搭好ROS省掉手动改源Ubuntu上手动装ROS要配源、配密钥、装几十个包容易在加源这步卡半天。现在很多人直接用鱼香ROS的一键安装脚本wget http://fishros.com/install -O fishros . fishros脚本执行后选“ROS1 Noetic”会自动配置软件源并安装ros-noetic-desktop-full。脚本只负责安装ROS本体YOLOv5的Python依赖要自己装。装完验证一下source /opt/ros/noetic/setup.bash echo $ROS_DISTRO输出noetic即可。以后每次开新终端都要重新source建议把这句追加到~/.bashrc末尾免得反复手敲。3.3 YOLOv5的Python环境conda还是venvROS Noetic自带Python 3.8而YOLOv5还要装PyTorch、torchvision、opencv-python。直接在系统环境里装容易把cv_bridge的OpenCV依赖搅乱我的习惯是单独建环境。常见做法是用condaconda create -n yolov5ros python3.8 -y conda activate yolov5ros pip install torch1.8.2cu111 torchvision0.9.2cu111 pip install -r requirements.txt但这里有个典型坑conda环境和ROS Noetic的系统Python是两套解释器。用catkin_make编译生成的自定义消息模块默认装进系统site-packagesconda环境里import不到。解决办法是把工作空间的devel目录显式加进PYTHONPATHexport PYTHONPATH/path/to/catkin_ws/devel/lib/python3/dist-packages:$PYTHONPATH或者更省心一点不用conda直接用Python自带的venv让ROS和YOLOv5共用同一套Python 3.8。很多“找不到cv2”“找不到cv_bridge”的报错本质上都是环境混用造成的。选一种方式用到底别同时开conda和venv。3.4 GPU与嵌入式平台的权重验证确认环境是否正常先跑一张图和ROS没关系import torch model torch.hub.load(./yolov5, custom, pathconfig/best.pt, sourcelocal) results model(test.jpg) results.show()如果这一步能出框说明PyTorch和权重没问题问题只可能出在ROS衔接层。卡住的情况多半是sourcelocal的仓库路径指错或者网络不通去GitHub拉代码。注意像rk3588这类带NPU的嵌入式平台PyTorch权重不能直接吃到NPU里需要rknn-toolkit先把模型转换导出再用NPU推理接口替换YOLOv5的原始推理部分。这个工作量和重新部署差不多不要指望一份PyTorch权重到处通用。4. 把部署包跑起来目录结构、检测节点与launch文件4.1 压缩包里一般有哪些目录不论你拿到的是.rar还是.zip解压后通常能看到这样的工作空间结构catkin_ws/src/yolov5_ros/ ├── launch/ │ ├── yolov5_detect.launch │ └── yolov5_show.launch ├── msg/ │ └── Detection.msg ├── scripts/ │ ├── detector_node.py │ └── rviz_marker_node.py ├── config/ │ ├── yolov5s.pt │ └── best.pt └── package.xml重点核对四样东西launch里有没有启动入口msg里有没有自定义消息定义scripts或src里有没有检测节点代码config里有没有权重文件。缺任何一样都得先补上再谈运行。还要检查best.pt和训练时的类别顺序红绿灯一般有red、green、yellow行人单独一类类别数在推理时应输出3到4个类别而不是COCO的80类。4.2 检测节点的骨架代码打开检测节点Python文件核心逻辑一般长这样#!/usr/bin/env python3 import rospy import torch from sensor_msgs.msg import Image from cv_bridge import CvBridge from yolov5_ros.msg import Detection class YoloDetector: def __init__(self): rospy.init_node(yolov5_detector) self.bridge CvBridge() self.model torch.hub.load(yolov5, custom, pathconfig/best.pt, sourcelocal) self.model.conf 0.35 self.model.iou 0.45 self.pub rospy.Publisher(detections, Detection, queue_size10) rospy.Subscriber(image_raw, Image, self.image_cb, queue_size1, buff_size2**24) def image_cb(self, msg): cv_image self.bridge.imgmsg_to_cv2(msg, bgr8) results self.model(cv_image) df results.pandas().xyxy[0] for _, row in df.iterrows(): det Detection() det.header.stamp msg.header.stamp det.header.frame_id msg.header.frame_id det.class_name row[name] det.confidence float(row[confidence]) det.xmin float(row[xmin]) det.ymin float(row[ymin]) det.xmax float(row[xmax]) det.ymax float(row[ymax]) self.pub.publish(det) if __name__ __main__: YoloDetector() rospy.spin()逻辑说明queue_size1表示图像消息处理不过来时直接丢旧帧而不是排队等这符合实时控制的需求buff_size2**24是为了避免大分辨率图像在订阅时被截断。self.model.conf和self.model.iou是训练后的推理参数不是训练超参数改这两行就是调现场灵敏度。4.3 launch文件与三个必调参数启动节点用launch文件统一管理参数launch node nameyolov5_detector pkgyolov5_ros typedetector_node.py outputscreen param nameimage_topic value/usb_cam/image_raw/ param nameconf_thres value0.35/ param nameiou_thres value0.45/ param nameimg_size value640/ /node /launchimage_topic要和摄像头节点发布的话题一致conf_thres是置信度阈值iou_thres是NMS的IoU阈值img_size是推理缩放尺寸。起步值我一般用conf0.35iou0.45。红绿灯目标小conf设太高会漏检远处的绿灯img_size从640提到1280能明显提升小目标召回但推理时间几乎翻倍。先跑640确认全链路通顺再调尺寸。4.4 订阅话题验证结果跑起来之后先不急着看画面用命令行确认话题在出数据rostopic list rostopic echo /detectionsrostopic list能看到检测结果话题存在echo能看到具体消息内容。如果一直等不到输出下一步就去查图像话题有没有数据rostopic hz /usb_cam/image_raw这个命令每秒打印一次图像的发布频率。摄像头话题没数据检测节点再正常也是空转。确认图像在推、检测节点在线但echo还没输出基本就是消息类型或话题名不匹配。4.5 摄像头与检测节点的组合没有现成摄像头驱动时可以用ROS自带的usb_cam包roslaunch usb_cam usb_cam_node.launch它默认发布/usb_cam/image_raw发布的话题名和图像分辨率可以用launch参数改。要确认摄像头真的在出图打开独立窗口看rosrun image_view image_view image:/usb_cam/image_raw能实时看到画面再回去看检测话题排查范围一下子就缩小了。图像有、检测没结果问题在检测节点图像都没有问题在摄像头驱动或权限。5. 常见部署问题排查与避坑六个真实踩坑记录5.1 catkin_make编译报找不到自定义消息现象编译工作空间时报Could not find the required component yolov5_ros或类似错误。原因工作空间里多个包互相依赖但package.xml没有正确声明依赖或者消息包没有被先编译。解决先把含Detection.msg的包放进来catkin_make会按依赖顺序编译。同时在依赖方的package.xml里加上build_dependyolov5_ros/build_depend exec_dependyolov5_ros/exec_depend再重新编译。如果还不行删掉build和devel目录重来比找错误日志快。5.2 import cv_bridge 就报错现象检测节点启动即退出错误指向cv_bridge模块。原因conda环境的Python版本和系统ROS的Python版本不一致或系统里同时存在多套OpenCV。解决统一用同一个Python环境。我一般直接不用conda用系统Python 3.8加venv然后单独pip装YOLOv5依赖。装完之后用以下命令验证cv_bridge能正常导入python -c from cv_bridge import CvBridge; print(ok)这条命令输出的ok比任何教程都可靠。5.3 检测节点无话题输出但图像话题正常现象rostopic hz /usb_cam/image_raw有20Hz但/detections没输出。原因节点没有匹配到图像话题或推理还没走完回调就异常退出了。解决先看节点终端有没有报错堆栈。没有报错就看launch里的image_topic和摄像头实际话题是否一致用rostopic list核对一遍。还有一种冷门原因图像消息的编码不是bgr8而是yuv422imgmsg_to_cv2转换失败。把desired_encoding改成passthrough再转一次试试。5.4 显存持续增长最终进程被杀现象系统运行半小时后检测节点被系统killnvidia-smi显示显存占满。原因回调里把每帧结果累积到一个list或队列没有及时释放或者图像消息积压导致缓存暴涨。解决检查代码里是否用了append累积检测结果推理结束后手动释放大对象results self.model(cv_image) # 只取需要的字段 boxes results.pandas().xyxy[0] del results另外把订阅端的queue_size压到1避免图像堆积。5.5 置信度阈值不合适导致“看不见红灯”现象近距离行人能检测远处红灯不报或者早上逆光时误检一大堆。原因conf_thres没有按场景调小目标在低分辨率下置信度本就不高。解决conf_thres从0.35往下调到0.2试一轮看红灯漏检率是否下降。注意conf降太低会让“红色圆形物体”全变成红灯此时需要配合类别判断只在红绿灯区域做二次过滤。实车场景里倒计时数字小的红灯容易漏提高img_size比降conf更有效。5.6 时间戳不一致决策节点拿到的检测框是旧的现象控制节点做轨迹预测时检测框和当前画面明显错位。原因检测节点发布消息时重新打了时间戳没有沿用图像采集时间。解决改成用输入图像的时间戳det.header.stamp msg.header.stamp如果消息里额外记录了推理耗时下游可以自行补偿不要把耗时混进时间戳。这个错误很隐蔽因为rqt_graph看不出异常只有做多传感器融合时才会暴露。6. 从“有框”到“能用”实车验证、延迟标定与置信度校准部署包跑通只是第一步真正常用的系统要在现场做校准。第一步是延迟标定在画面里放一个秒表同时录检测话题视频对比秒表刻度和检测框时间戳算出端到端延迟。对红绿灯识别来说延迟超过500毫秒就意味着停车决策慢半拍很危险。延迟主要来自推理耗时其次是图像传输可以先看rostopic hz /detections的输出频率如果低于5Hz优先考虑缩小img_size或换轻量权重。第二步是看混淆案例。把检测节点的输出做成日志统计行人被分成红灯、红灯被分成人行的样本。这类错位往往会出现在同框场景行人穿红衣服站在红灯下。此时的调参方向不是继续调conf_thres而是给红绿灯检测单独加一个ROI区域只允许在画面上半部分出红绿灯类别行人只在画面下半部分出框。这个约束在部署里非常实用比换模型成本低得多。第三步是现场验证决策闭环。给决策节点订阅检测结果让它读到red类别且置信度大于0.5时执行停车。在实车测试前先跑仿真rosbag录一段路口数据回放给检测节点再用rqt_graph和rostopic echo同时观察确认决策节点在红灯帧到达后限时停车。我可是在这个环节吃过亏的仿真里一切正常真车一上就撞了护栏原因是相机装歪了camera_link的静态tf参数没更新检测框全部偏移到路沿上。所以每次换相机位置第一件事就是改launch里的静态变换参数。ZUI后把部署思路明确下来先跑通最小链路再量延迟再调场景参数最后加决策逻辑。每一步都有反馈指标就不会把时间耗在“代码明明能跑但就是不对劲”的玄学里。希望这篇能帮你少走一段弯路把YOLOv5在ROS里的部署做扎实。本文还有配套的精品资源点击获取
返回列表