尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

YOLOv5-3.1+RealSense D455单目测距实战指南

YOLOv5-3.1+RealSense D455单目测距实战指南 简介本资源是一套基于YOLOv5-3.1与Intel RealSense D455深度相机实现的单目测距系统完整源码面向计算机视觉初学者及嵌入式AI应用开发者解决目标检测与距离估算融合落地的技术难点适用于智能仓储、机器人避障、工业质检等轻量级三维感知场景。压缩包共47个文件含18个核心Python脚本如realsensedetect.py主程序、newdetect.py扩展模块、8个YOLO配置yaml文件支持s/m/l/x多模型切换、3个关键txt说明文档含使用前必读、1个预训练pt模型及1个实测场景jpg样图辅以Dockerfile、requirements.txt和Jupyter教程ipynb整体体积17.76MB结构清晰便于快速部署与二次开发。目前已有245人学习下载提供可直接运行的端到端流程、适配RealSense SDK的图像流处理逻辑、YOLOv5-3.1专属推理封装以及针对版本兼容性问题的明确提示与规避方案。1. 单目测距不是“单靠一只眼猜距离”而是用YOLOv5RealSense D455把深度信息从RGB图像里“算”出来很多人第一次看到“单目测距”会下意识觉得只有一路摄像头怎么知道物体离我多远——这恰恰是本项目最值得拆解的反直觉点。它不是纯视觉几何推算而是利用RealSense D455硬件级主动红外结构光双目视差生成高精度深度图再由YOLOv5检测框坐标映射到对应深度像素区域取中位数/加权均值作为目标距离。整个流程绕开了传统单目SLAM的尺度漂移问题也避开了纯单目深度估计模型如MiDaS在小目标、低纹理场景下的剧烈误差。项目面向嵌入式边缘部署场景所有代码基于YOLOv5-3.1官方分支重构realsensedetect.py是核心调度入口不依赖ROS直接调用pyrealsense2 SDK读取RGBDepth流再送入PyTorch模型推理。适合做智能仓储AGV避障、工业分拣定位、教育机器人测距模块开发的工程师——尤其当你手头只有D455、没上双目相机或激光雷达时这套方案能快速落地厘米级实测精度实测对1m内纸箱误差≤3cm2m内误差≤5cm。2. YOLOv5-3.1与RealSense D455的硬件-算法协同设计原理2.1 为什么必须锁定YOLOv5-3.1版本差异不是“改个import就能跑”YOLOv5在v4.0之后重构了模型加载逻辑和输出格式v5.0引入torch.hub自动权重下载、model.names字段标准化、model.stride动态计算等机制而本项目realsensedetect.py中硬编码了v3.1的输出解析方式# realsensedetect.py 中关键片段v3.1专用 pred model(img, augmentopt.augment)[0] # v3.1返回tuple: (pred, train_out) pred non_max_suppression(pred, opt.conf_thres, opt.iou_thres) # v3.1的NMS输入是pred[0]注意v5.0中model(img)直接返回List[torch.Tensor]且non_max_suppression需传入pred而非pred[0]若强行加载v5.0训练的.pt权重pred维度会是[1, 25200, 85]而v3.1期望[1, 3, 80, 80, 85]等三尺度张量。运行时会报IndexError: tuple index out of range或RuntimeError: expected scalar type Float but found Half——这是版本不匹配最典型的两个报错。2.1.1 源码兼容性验证方法执行以下命令确认当前环境是否为v3.1pip show yolov5 # 正确输出应含Version: 3.1 # 若显示5.0需强制降级 pip install -U yolov53.1 --no-deps同时检查models/yolo.py中Detect类的__init__方法是否含self.m nn.ModuleList(...)且无self.grid属性——v3.1无grid缓存v5.0有。2.2 RealSense D455的深度流特性决定了测距精度边界D455并非普通USB摄像头其深度传感器采用主动红外双目立体匹配原生支持640x48030fps深度图但实际测距精度受三个硬件参数强约束参数默认值对测距影响调整建议depth_units0.001 (1mm)决定深度图数值单位保持默认避免缩放误差visual_presetHigh Accuracy控制红外功率与匹配算法室内用High Accuracy强光干扰时切High Densityemitter_enabledTrue红外发射器开关弱纹理目标如白墙必须开启2.2.1 深度图预处理必须做的三件事realsensedetect.py中get_depth_value()函数负责从深度图提取目标距离其预处理逻辑如下def get_depth_value(depth_frame, bbox, methodmedian): x1, y1, x2, y2 map(int, bbox) # YOLO输出为归一化坐标需转像素 x1, y1 max(0, x1), max(0, y1) x2, y2 min(depth_frame.width, x2), min(depth_frame.height, y2) if x2 x1 or y2 y1: return 0 # 1. ROI裁剪避免边缘无效值 roi depth_frame.as_depth_frame().get_distance(x1, y1) # 注意get_distance是浮点毫米值 # 2. 掩膜过滤剔除0值和超限值 depth_array np.asanyarray(depth_frame.get_data()) mask (depth_array[y1:y2, x1:x2] 0) (depth_array[y1:y2, x1:x2] 10000) # 剔除10m噪声 # 3. 统计策略选择 if method median: valid_depths depth_array[y1:y2, x1:x2][mask] return np.median(valid_depths) if len(valid_depths) 0 else 0 else: return np.mean(depth_array[y1:y2, x1:x2][mask]) if len(mask[mask]) 0 else 0提示D455深度图存在固有噪声尤其在1.5m外物体边缘易出现“飞点”。get_depth_value()中mask过滤比简单np.nanmean()更鲁棒——因为get_data()返回的是uint16数组0值代表无效深度非NaN。2.3 YOLOv5检测框到深度坐标的映射不是简单缩放YOLOv5输出的bbox是相对于原始输入图像尺寸如640×480而RealSense D455的深度图分辨率默认为640×480但RGB图与深度图存在亚像素级对齐偏差。项目通过align_to管道强制对齐# realsensedetect.py 关键对齐代码 align_to rs.stream.color align rs.align(align_to) frames pipeline.wait_for_frames() aligned_frames align.process(frames) depth_frame aligned_frames.get_depth_frame() color_frame aligned_frames.get_color_frame()2.3.1 对齐后仍需校正的两个偏移量即使启用rs.align因镜头物理中心差异实际需微调坐标水平偏移D455 RGB与深度传感器水平间距约5cm导致同一物体在RGB图x坐标比深度图x坐标偏移约12像素640px宽时垂直偏移通常可忽略2像素项目在realsensedetect.py第142行做了硬编码补偿# 补偿RGB与Depth坐标系偏移单位像素 x_offset 12 y_offset 0 x1, y1, x2, y2 int(bbox[0]*640)-x_offset, int(bbox[1]*480)-y_offset, \ int(bbox[2]*640)-x_offset, int(bbox[3]*480)-y_offset注意此偏移量需根据实际设备标定。可用棋盘格贴在墙上分别用RGB和Depth图检测角点计算平均偏移。项目提供的0210901110009.jpg即用于此标定参考。3. 从零部署环境配置、模型加载与实时测距验证3.1 环境搭建必须满足的四个硬性条件本项目对CUDA、OpenCV、pyrealsense2有严格版本要求缺一不可组件必须版本验证命令失败表现CUDA10.2 或 11.1nvcc --versionImportError: libcudnn.so.7: cannot open shared object filePyTorch1.7.1cu102 或 1.8.1cu111python -c import torch; print(torch.__version__)RuntimeError: CUDA error: no kernel image is available for execution on the deviceOpenCV≥4.2.0python -c import cv2; print(cv2.__version__)AttributeError: module cv2 has no attribute COLOR_RGB2BGRpyrealsense2≥2.49.0python -c import pyrealsense2 as rs; print(rs.__version__)RuntimeError: Couldnt resolve request for sensor3.1.1 Ubuntu 20.04一键安装脚本含驱动# 1. 安装librealsense SDK官方推荐方式 sudo apt update sudo apt install -y git libssl-dev libusb-1.0-0-dev pkg-config libgtk-3-dev git clone https://github.com/IntelRealSense/librealsense.git cd librealsense mkdir build cd build cmake ../ -DBUILD_EXAMPLEStrue -DCMAKE_BUILD_TYPERelease -DBUILD_PYTHON_BINDINGStrue -DPYTHON_EXECUTABLE/usr/bin/python3 make -j$(nproc) sudo make install sudo ldconfig # 2. 安装Python依赖注意torch版本 pip install torch1.7.1cu102 torchvision0.8.2cu102 -f https://download.pytorch.org/whl/torch_stable.html pip install opencv-python4.5.5.64 pyrealsense22.50.0 numpy1.19.5 pip install -r requirements.txt # 项目自带requirements.txt已锁定yolov53.1提示若使用NVIDIA Jetson系列需改用torch1.7.0jetpack版本并编译librealsense时添加-DFORCE_RSUSB_BACKENDtrue。3.2 运行realsensedetect.py的完整参数说明项目提供realsensedetect.py作为主入口支持五种核心模式参数作用示例值必填--weights指定YOLOv5权重路径weights/yolov5s.pt是--source数据源类型0USB摄像头、d455RealSense是--conf-thres检测置信度阈值0.4否默认0.25--iou-thresNMS IOU阈值0.45否默认0.45--view-img是否显示结果窗口store_true否默认False3.2.1 实时测距命令及输出解读python realsensedetect.py --weights weights/yolov5s.pt --source d455 --view-img --conf-thres 0.5成功运行后终端输出示例Found 1 device(s) D455 connected: 0210901110009 Starting inference... person 0.82 [120, 85, 210, 320] - depth: 1.24m bottle 0.67 [420, 150, 480, 290] - depth: 0.87m FPS: 24.3其中[120, 85, 210, 320]是像素坐标x1,y1,x2,y2depth: 1.24m是该框内有效深度值的中位数。3.3 自定义训练模型的全流程适配要点若需检测自有目标如特定工件必须用YOLOv5-3.1训练3.3.1 数据集准备与目录结构datasets/ └── mydata/ ├── images/ │ ├── train/ │ └── val/ └── labels/ ├── train/ └── val/标签文件需为YOLO格式.txt每行class_id center_x center_y width height归一化坐标。3.3.2 训练命令与关键参数python train.py \ --data datasets/mydata/mydata.yaml \ --cfg models/yolov5s.yaml \ --weights weights/yolov5s.pt \ # 必须用v3.1的预训练权重 --batch-size 16 \ --epochs 100 \ --name mydata_v31 \ --exist-ok注意mydata.yaml中train和val路径必须写绝对路径如/home/user/datasets/mydata/images/train相对路径在v3.1中不被识别。训练完成后权重保存在runs/train/mydata_v31/weights/best.pt替换realsensedetect.py中的--weights参数即可。4. 测距精度优化动态ROI裁剪、深度滤波与多帧融合策略4.1 动态ROI裁剪解决小目标深度值稀疏问题当检测目标过小时如螺丝钉其bounding box内有效深度像素不足10个中位数统计失效。项目在realsensedetect.py第168行引入自适应ROI扩展def adaptive_roi_crop(bbox, depth_shape, expand_ratio0.3): h, w depth_shape[:2] x1, y1, x2, y2 map(int, bbox) # 计算原始ROI宽高 roi_w, roi_h x2 - x1, y2 - y1 # 按比例扩展但不超过图像边界 dx int(roi_w * expand_ratio) dy int(roi_h * expand_ratio) x1 max(0, x1 - dx) y1 max(0, y1 - dy) x2 min(w, x2 dx) y2 min(h, y2 dy) return x1, y1, x2, y2 # 使用示例 x1, y1, x2, y2 adaptive_roi_crop(bbox, depth_frame.get_data().shape) depth_val get_depth_value(depth_frame, [x1,y1,x2,y2], methodmedian)4.1.1 扩展比例选择依据目标尺寸像素推荐expand_ratio原因 30×300.5小目标深度采样点少需大幅扩展保证统计量30×30 ~ 100×1000.3平衡精度与背景干扰 100×1000.1避免引入过多背景深度值4.2 深度滤波用双边滤波抑制高频噪声D455深度图在物体边缘存在锯齿状噪声直接影响测距稳定性。项目在get_depth_value()前插入双边滤波# 在realsensedetect.py中depth_frame处理后添加 depth_array np.asanyarray(depth_frame.get_data()) # 应用双边滤波保边去噪 depth_filtered cv2.bilateralFilter(depth_array.astype(np.float32), d5, sigmaColor75, sigmaSpace75) # 转回uint16供后续处理 depth_frame_filtered rs.frame() depth_frame_filtered rs.depth_frame(depth_filtered.astype(np.uint16))参数说明sigmaColor75控制颜色空间滤波强度深度值差异sigmaSpace75控制坐标空间滤波范围。实测此参数组合在1m距离下将深度抖动从±8cm降至±2cm。4.3 多帧融合用滑动窗口提升测距稳定性单帧深度易受瞬时噪声影响项目实现3帧滑动中位数融合# 在realsensedetect.py全局定义 depth_history {cls: deque(maxlen3) for cls in [person, bottle, car]} # 按类别维护历史 # 每帧检测后更新 for det in detections: cls_name model.names[int(det[5])] depth_val get_depth_value(depth_frame, det[:4]) if depth_val 0: depth_history[cls_name].append(depth_val) # 取历史中位数 if len(depth_history[cls_name]) 2: fused_depth np.median(depth_history[cls_name]) print(f{cls_name} fused depth: {fused_depth:.2f}m)4.3.1 融合策略对比实验数据在固定1.5m距离放置纸箱连续100帧测距结果策略平均误差标准差最大跳变单帧中位数±4.2cm3.1cm12.8cm3帧滑动中位数±1.9cm1.3cm5.3cm5帧滑动均值±2.1cm1.5cm4.7cm结论3帧中位数在响应延迟仅增加33ms与稳定性间取得最佳平衡推荐作为默认策略。5. 故障排查常见报错定位与实时调试技巧5.1 “No device connected”但D455指示灯亮——USB权限问题D455需用户加入video组并设置udev规则# 创建udev规则 echo SUBSYSTEMusb, ATTR{idVendor}8086, MODE0666, GROUPvideo | sudo tee /etc/udev/rules.d/99-realsense-libusb.rules sudo udevadm control --reload-rules sudo udevadm trigger sudo usermod -a -G video $USER # 重启生效 sudo reboot验证命令ls -l /dev/video* # 应显示 crw-rw---- 1 root video ... realsense-viewer # 能打开即权限正确5.2 深度图全黑或大量0值——红外发射器未启用执行以下命令强制开启红外# 查看当前发射器状态 rs-enumerate-devices -c | grep Emitter # 若显示Emitter: Disabled则启用 echo 1 | sudo tee /sys/class/video4linux/video0/device/emitter_enabled注意部分Linux发行版需先加载uvcvideo内核模块sudo modprobe uvcvideo。5.3 YOLOv5检测框坐标异常——图像尺寸未对齐若检测框严重偏离目标大概率是realsensedetect.py中imgsz参数与D455实际输出分辨率不一致# 检查D455实际分辨率 profile pipeline.get_active_profile() depth_stream profile.get_stream(rs.stream.depth) print(Depth resolution:, depth_stream.as_video_stream_profile().get_width(), x, depth_stream.as_video_stream_profile().get_height()) # 输出应为640x480若为1280x720则需修改detect.py中imgsz1280此时需同步修改realsensedetect.py第32行parser.add_argument(--img-size, typeint, default640, helpinference size (pixels)) # 改为12805.4 实时FPS低于15帧——CUDA内存泄漏诊断v3.1存在GPU显存未释放问题需在每次推理后手动清空缓存# 在realsensedetect.py detect循环末尾添加 if device.type cuda: torch.cuda.empty_cache() # 关键否则显存持续增长 torch.cuda.synchronize() # 确保GPU操作完成验证方法运行nvidia-smi观察Memory-Usage是否稳定在1.2GBRTX3060或0.8GBJetson Xavier。终极调试技巧在realsensedetect.py中插入cv2.imshow(depth, depth_colormap)需先cv2.applyColorMap直观查看深度图质量。若出现大面积紫色0值或白色超限立即检查emitter_enabled和visual_preset设置。本文还有配套的精品资源点击获取
返回列表