ARTICLE DETAIL

资讯详情

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

YOLOv5+Tello TT无人机实战:目标检测与追踪测距全流程指南

YOLOv5+Tello TT无人机实战:目标检测与追踪测距全流程指南 简介基于YOLOv5与大疆教育无人机Tello TT联合开发的目标识别检测与追踪测距完整工程定位面向毕业设计、期末课程设计及K12人工智能实践。压缩包内置可运行的Python源码、已标注数据集、训练好的模型权重与图文说明手册代码附有注释新手也能按步骤完成部署并复现识别、追踪与测距功能。资源压缩包共1672个文件大小约269.35MB主要包含758个jpg图像样本、694个txt标注文件、94个yaml配置、50个py脚本、9个pt模型权重以及xml、sh、md、dockerfile等辅助文件覆盖数据准备、模型训练、推理部署全流程。内容预览中可见大量tfevents训练日志便于查看训练进度与参数调优记录。项目已有461人学习下载常用于毕业设计选题参考和课程设计高分项目。资源提供的完整数据链路和预训练权重可直接迁移到不同目标检测场景说明文档结合目录结构梳理了运行方法帮助使用者快速上手并进行二次开发。1. 为什么是yolov5Tello TT一套能落地到教室的检测追踪方案先说结论用 yolov5 带着大疆教育无人机 Tello TT 做目标识别检测再叠加追踪测距最近两年已经成为不少高校实验室、中小学科创课和无人机竞赛队的标准入门路线。原因不复杂——Tello TT 有可编程的SDK、能直接拿到视频流和姿态数据而 yolov5 是生态最成熟、训练自己的数据集门槛最低的目标检测模型之一两者一拼不需要自研飞控也不用从零写视觉算法就能在教室里跑出「识别到红色锥桶并锁定距离」的完整闭环。这套方案适合谁适合已经会一点Python、想绕过复杂课程设计的人你要的不是发论文而是把模型跑起来、把无人机飞起来、把数据测出来。它能解决三个痛点第一教学场景里缺的是低成本且能出效果的实验平台第二很多开源项目只给了推理代码没给数据集和训练好的权重导致复现第一步就卡死第三追踪测距的精度到底怎么调很少有文档讲透。这篇笔记就按「环境 → 数据集 → 训练 → 推理 → 追踪测距 → 避坑」的顺序把完整落地路径说清楚。2. 把环境与数据集备齐yolov5环境配置与TT图像采集的3个前置步骤2.1 conda建环境与依赖版本yolov5环境配置里最容易翻车的点不管你是拿到现成源码压缩包还是从GitHub拉 yolov5 主分支第一步都是在 conda 里独立建一个环境。我见过太多新手图省事直接往 base 环境里 pip install -r requirements.txt结果把系统里其他项目的 torch 版本冲掉回头哭都来不及。常见做法是新建一个专门跑 yolov5 的 conda 环境Python 版本选 3.8 或 3.9。yolov5 在 3.9 下表现稳定往上到 3.11 会有一些旧版依赖的坑。命令如下conda create -n yolov5_tt python3.9 -y conda activate yolov5_tt cd yolov5 # 进入yolov5源码目录 pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple这里有个关键点requirements.txt 里锁定的 torch 是 CPU 版还是 GPU 版取决于你的机器。如果你只有 NVIDIA 显卡想在训练时启用 CUDA不要直接用 requirements 里默认的 torch建议先装 cuda 版 torch再装其余依赖。我一般会先执行pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118然后再跑 requirements.txt。原因很简单yolov5 的后处理和追踪推理在 CPU 上也能跑但训练自己的数据集时没有 GPU一个 epoch 可能要等几十分钟你根本没法调超参数。装完之后验证环境是否正常用一行命令python -c import torch; print(torch.__version__, torch.cuda.is_available())如果输出2.0.1cu118 True说明环境没问题。如果cuda.is_available()是False先别急着重装检查驱动和 nvcc 版本是否匹配这也是我后面要单列的一个踩坑点。2.2 采集TT图像并做标注用Tello TT拍出符合yolov5训练要求的数据集很多同学拿到「完整数据集」压缩包后直接开始训练但你要明白那只是作者在特定场景下拍的样本换到你自己的教室、光线、目标物准确率会明显下降。所以「基于yolov5Tello TT」这个方案真正值钱的部分不是那几千张图片而是你能自己采集数据、自己标注、自己反复迭代的能力。Tello TT 采集图像有两条路一是用官方 Tello App 飞一圈拍视频然后抽帧二是直接用 yolo 源码里的 detect.py 配合 Tello 的 SDK 实时保存。更推荐第二条路因为视频帧率和分辨率可控还能记录无人机姿态。常见做法是用一个 Python 脚本连接 Tello TT 的 SDK拿到每一帧 H.264 视频再用 OpenCV 解码后保存成 jpg。from djitellopy import Tello import cv2 tello Tello() tello.connect() tello.streamon() count 0 while count 200: # 保存200帧 frame tello.get_frame_read().frame if frame is None: continue cv2.imwrite(fdataset/images/tello_{count:04d}.jpg, frame) count 1 tello.streamoff()这段代码的逻辑很简单循环拉流每帧存一张图。重点是参数设置——解析度默认是 960x720对 yolov5 训练来说足够但如果你要识别的是很小的目标比如30像素以内的交通锥建议先记住tello.set_video_resolution(Tello.RESOLUTION_720P)这样的设置不要让图被压缩得过狠。另外存图时不要只拍悬停画面要涵盖不同高度、不同角度、不同光照这样训练出来的模型才有泛化能力。标注工具我推荐用 LabelImg 或 Label Studio输出格式选 YOLO 格式——也就是每个图片对应一个 txt里面每一行写class_id x_center y_center width height坐标都是归一化到0-1的。如果你拿到的数据集里已经有 label 文件夹建议花十分钟随机抽几张把 txt 内容和图片目测对应一下防止坐标单位不一致有的工具输出是像素值yolov5 要的是归一化值。这一步是很多「数据集跑不通」的根源。2.3 训练好的模型与权重文件的组织方式标题里有「训练好的模型」这个描述很宽泛。在 yolov5 语境下训练好的模型通常指best.pt和last.pt两个权重文件。best.pt是验证集上 mAP 最高的权重last.pt是最后一个 epoch 保存的权重。追踪测距阶段我们一定用best.pt因为它的泛化能力通常更好。拿到别人给的项目源码时先看权重文件的后缀。.pt是 PyTorch 权重可以直接加载.engine是 TensorRT 序列化后的权重需要配套的推理环境.onnx是开放格式可以用 OpenCV 或 ONNX Runtime 加载。在 Tello TT 这种边缘设备上.engine更快但生成它需要先把.pt转成.onnx再转成.engine。后面第 4 章会展开讲部署。还有一个小细节数据集的data.yaml里train和val的路径必须是绝对路径或者相对路径但位置正确。很多项目压缩包解压后训练命令直接报FileNotFoundError就是因为 yaml 里写死的是作者机器的路径。我一般会改成相对路径train: dataset/images/train val: dataset/images/val nc: 2 names: [cone, person]这里的nc是类别数names列表的索引要和标注 txt 里的class_id一一对应。如果顺序错了训练不会报错但识别结果会张冠李戴——这也是让你怀疑数据集质量的最隐蔽坑之一。3. 训练自己的数据集yolov5超参数与训练脚本的调参笔记3.1 数据集格式与yaml配置VOC转yolov5格式的3个边界坑不管你手里的数据集是 COCO 格式还是 VOC 格式最终都要转成 yolov5 需要的 YOLO 格式。网上现成转换脚本很多但你要注意三个边界坑。第一VOC 的坐标是xmin ymin xmax ymax转成 YOLO 需要做归一化而且必须除以图片实际宽高不能除以默认值。如果图片是 960x720而你除的是 720x720目标框位置整体右偏训练时 loss 会异常升高但模型仍然能收敛最后推理时框总是偏一点。第二类别映射。VOC 的类别名和 YOLO 的 class_id 是按字母序排列的——yolov5 源码里默认按文件名排序生成标注。比如你有cone和person两类cone排在前面class_id 是 0person是 1。如果你的 txt 文件里写反了训练出来的模型就永远分不清谁是谁。第三数据集拆分。我习惯按train:val 9:1做随机拆分但必须保证同一段连续视频抽出的帧不被分到两个集合里——否则训练集和验证集里的图片极其相似验证 mAP 高得离谱一到真实场景就露馅。所以先按视频片段分组再在组内做划分而不是把所有图片打乱直接分。这里给一段我常用的 VOC 转 YOLO 脚本核心逻辑只贴关键部分import os import xml.etree.ElementTree as ET def voc2yolo(xml_file, img_w, img_h, class_dict): tree ET.parse(xml_file) root tree.getroot() lines [] for obj in root.iter(object): name obj.find(name).text if name not in class_dict: continue box obj.find(bndbox) xmin float(box.find(xmin).text) ymin float(box.find(ymin).text) xmax float(box.find(xmax).text) ymax float(box.find(ymax).text) # 关键用真实宽高归一化 x_center (xmin xmax) / 2 / img_w y_center (ymin ymax) / 2 / img_h width (xmax - xmin) / img_w height (ymax - ymin) / img_h lines.append(f{class_dict[name]} {x_center:.6f} {y_center:.6f} {width:.6f} {height:.6f}) return lines参数说明img_w和img_h从图片实际尺寸读取不要从 XML 的size节点取——因为有些标注工具的size字段写的是缩放前的值。class_dict是「类别名 → id」的映射手动配置即可。3.2 训练命令与关键超参数yolov5超参数如何影响小目标检测Tello TT 的相机架在高处往下看目标比如地面交通锥在画面里通常很小因此训练超参数要往「小目标友好」方向调。yolov5 默认的hyp.scratch-low.yaml是通用参数直接拿来训练能出结果但小目标召回率往往偏低。我一般会改三个地方mosaic保持默认 1.0因为马赛克增强能模拟远景小目标被拼接的效果copy_paste提到 0.3 以上特别是目标比较小的时候这个增强能把目标从一个图复制粘贴到另一个图等效于扩充小目标样本scale从 0.5 改成 0.9允许训练时对图片做更大幅度的随机缩放让模型看到更多不同尺度的目标。训练命令标准写法如下python train.py \ --data dataset/data.yaml \ --weights yolov5s.pt \ --epochs 100 \ --batch-size 8 \ --img 640 \ --hyp hyp.scratch-low.yaml \ --device 0参数说明--weights yolov5s.pt是预训练权重用小模型起步。V100 或 3080 上 100 个 epoch 大概一两个小时如果你只有 CPU建议把--epochs改成 20 先跑通再考虑加预算。--batch-size 8对 8GB 显存比较安全如果你的显卡只有 4GB改成 4。--img 640是训练输入尺寸如果 Tello TT 画面里的目标太小可以试--img 960但训练和推理速度都会变慢后面部署到树莓派5这种设备上会吃力。训练完成后在runs/train/exp目录里看results.png重点关注val/box_loss和val/obj_loss是否持续下降。如果两个 loss 在最后 20 个 epoch 还在明显波动说明学习率没来得及衰减可以适当增加--epochs或修改hyp里的lr0。这些就是 yolo 玩家常说的「基础笔记」——不是高端理论而是每个项目都必须重复检查的基线指标。3.3 后处理NMS与置信度阈值在TT追踪场景里的调整训练完只是第一步。真正放到 Tello TT 上跑的时候你会发现同一个目标在连续几帧里会被模型检测出多个框——尤其是目标小且边缘模糊时。这就是后处理要解决的问题。yolov5 的推理阶段默认用 NMS非极大值抑制去掉重叠框但你可以在推理脚本里调整两个关键阈值conf_thres和iou_thres。常见做法是先在离线图片上做一轮遍历找到适合你场景的阈值。比如from pathlib import Path import torch model torch.hub.load(./yolov5, custom, pathweights/best.pt, sourcelocal) model.conf 0.25 model.iou 0.45 results model(test_images/test_01.jpg) results.print()这段代码用 torch.hub 加载本地权重设置置信度阈值 0.25、NMS IoU 阈值 0.45。在 Tello TT 的俯视视角下如果目标是明显的红色锥桶conf可以放到 0.35因为这类目标特征太明显低置信度的框大概率是误检但如果你要识别的是学生或行人目标姿态变化大conf降到 0.15 能找回很多框代价是误检增加。iou保持 0.45 左右太大容易把两个紧挨着的同类目标合并成一个框太小又会让同一个目标产生多个重叠框。追踪测距时多个重叠框会导致距离跳变——后面会详细说。4. 在Tello TT上做目标识别检测与追踪测距从权重到实时推理4.1 用yolov5推理TT视频流的代码骨架当你在本地实验跑通了检测下一步就是让 Tello TT 的实时视频流进入 yolov5 推理循环。有一个绕不开的问题TT 视频流是 H.264 编码yolov5 的预处理期望的是 BGR 的 numpy 数组所以必须用 OpenCV 解码每一帧再送入模型。一个最小可跑的推理循环参考如下from djitellopy import Tello import cv2 import torch tello Tello() tello.connect() tello.streamon() # 加载训练好的权重 model torch.hub.load(./yolov5, custom, pathweights/best.pt, sourcelocal) model.conf 0.30 model.iou 0.45 model.max_det 10 # 每帧最多同时追踪10个目标 while True: frame tello.get_frame_read().frame if frame is None: continue results model(frame, size640) rendered results.render()[0] # 在图像上画框 cv2.imshow(Tello TT Detection, rendered) if cv2.waitKey(1) 0xFF ord(q): break tello.streamoff() cv2.destroyAllWindows()逻辑说明results.render()返回的是画好检测框的图片列表取[0]就是当前帧。model(frame, size640)内部会做 letterbox 缩放保持长宽比并填充灰边所以不用手动 resize。关键参数是model.conf和model.iou这两个值在实时场景里比训练超参数更敏感——TT 飞行时画面抖动如果conf设太高检测框会一闪一闪设太低又会出现很多假框。我建议从 0.25 开始调。4.2 追踪测距单目测距与PID追踪的简化做法「追踪测距」这个标题里的第二关键词在真实项目里指的是两件事一是用视觉锁定目标并让无人机跟随追踪二是估算无人机与目标的距离测距。Tello TT 没有深度相机也没有激光雷达所以测距只能用单目视觉的近似方法。最常见做法是已知目标的真实高度或宽度然后用相似三角形计算距离。比如红色交通锥的真实高度是 30cm在图像中检测框的高度是 120 像素相机焦距是 920 像素Tello TT 的水平视场角约 82 度可以通过标定得到那么距离 ≈ (30 / 120) * 920 230cm。这个公式我建议封装成函数def estimate_distance(real_height_cm, box_height_pixel, focal_px): return (real_height_cm / box_height_pixel) * focal_px参数说明real_height_cm是目标真实尺寸需要你自己量box_height_pixel是检测框的height乘以图像高度因为 yolo 输出是归一化的focal_px是焦距像素值可以用 OpenCV 标定棋盘格拿到。这个方法误差在 10%~20% 左右但胜在简单不需要额外硬件。至于追踪常见做法是 PID 控制器。先计算目标中心与图像中心的偏差然后把偏差作为 PID 的输入输出给 Tello 的左右、前后、上下通道。一个简化的比例控制代码示例def pid_control(dx, dy, kp0.01): left_right kp * dx up_down -kp * dy return left_right, up_down注意这个示例只写了 P 分量实际飞行时如果没有 D 分量TT 会在目标附近振荡。我会在循环里维护上一帧偏差计算误差变化率加到输出上。另外TT 的 SDK 指令有频率限制建议控制在 10~20Hz太高会出现指令堆积无人机会突然抽搐。4.3 部署注意算力受限时的推理加速如果你把训练好的模型放到树莓派5上部署——这是很多竞赛队伍的常规做法——那你要面对的是实时性问题。树莓派5 的算力比普通 PC 弱很多yolov5s 在 640 分辨率下可能只有 2~4 FPS直接做追踪会让无人机反应迟钝。我一般会做三件事。第一把推理分辨率从 640 降到 416 或 320Latency 能下降 40% 以上代价是小目标检测率下降。第二用 ONNX Runtime 代替 PyTorch 推理因为 ONNX Runtime 对 ARM 平台有优化。转换命令很简单python export.py --weights weights/best.pt --include onnx --img 320第三如果你有 NVIDIA Jetson 设备导出成 TensorRT engine 后帧率可以到 20 FPS 以上。但没有 GPU 的树莓派ONNX 加 320 输入是性价比最高的组合。部署时还有一个隐藏坑树莓派上如果同时跑 Tello 的 WiFi 接收和 OpenCV 解码CPU 会爆满建议把视频解码用硬件加速树莓派5 可以用cvv4l2之类的 GStreamer 管道。5. Tello TT实战避坑5个让新手反复重跑的现象与对策5.1 现象训练损失正常但识别不到TT视角下的小目标模型在验证集上的 mAP 明明不低但一放到 Tello TT 的实时画面上小目标经常漏检。原因很直接TT 飞行时的运动模糊和俯视角度带来的目标形变和训练集里的静态图差太多。解决思路不是盲目加大训练集而是做两步第一训练时打开--augment参数让模型适应随机光照、旋转、缩放第二在采集阶段就有意识地把无人机飞到不同高度和偏离角度制造更多「不完美」的样本。这是很多项目文档都不写但是实际最影响效果的一条。5.2 现象推理帧率只有3 FPS追踪发飘PC 上跑得好好的换到树莓派后整个追踪系统像慢动作。原因通常是模型输入太大且没有做后处理上的帧间复用。我试过把检测结果用简单卡尔曼滤波跟踪这样即使模型推理只有 5 FPS控制输出也能平滑到 20Hz。另一个原因是 OpenCV 的视频解码线程和推理线程没有分开导致解码阻塞推理。解决方式是开两个线程一个只负责读帧一个只负责推理中间用 queue 传递。5.3 现象TT飞近后目标丢失测距跳变很多人在追踪时发现无人机越靠近目标目标越容易飞出画面测距数值突然变得很大。这不一定是模型问题而是你的追踪策略只有「往中心飞」没有限速和边界保护。我给出的对策是在控制回路里加一个死区——当目标中心偏差小于 20 像素时不输出水平控制同时当估计距离小于 50cm 时强制停止前飞并略微后退。这个策略很简单但能把整个系统的稳定性提升一个档次。5.4 现象conda环境装好后torch与cuda不匹配明明按 requirements 装好了torch.cuda.is_available()还是 False。最常见原因是 PyTorch 装成了 CPU 版。排查时先看torch.__version__是否带cu后缀如果没有卸载重装pip uninstall torch torchvision -y pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118注意cu118对应 CUDA 11.8你的显卡驱动必须支持该版本。可以用nvidia-smi看到驱动支持的最高 CUDA 版本如果只支持到 11.4就改用cu113。这是环境配置里最隐蔽但是最不值得浪费时间的坑。5.5 现象数据集里有大量重复背景导致过拟合我拿到过一份别人整理的 Tello TT 数据集里面 80% 的图片是从一段悬停视频里连续抽帧出来的背景几乎一样只有目标位置微微移动。训练出来的模型在自己的测试集上 mAP 很高换到新环境立刻崩。解决方法是做视频抽帧时限制采样率比如每 10 帧取一帧同时把不同飞行路线的视频分开存放确保训练和验证集来自不同路线。如果你自己也打算做数据集一定不要偷懒连续抽帧。6. 让整套系统更耐用的进阶技巧模型量化与追踪控制回路的验证方法到了这个阶段你已经能跑通检测、追踪、测距了。但如果要在竞赛场上稳定比赛我强烈建议再做两件事模型量化和控制回路验证。模型量化方面如果你实在没有 GPU在树莓派5上部署可以把训练好的权重先导出成 int8 量化的 ONNX 模型。常见的做法是用 ONNX Runtime 自带的动态量化工具from onnxruntime.quantization import quantize_dynamic, QuantType quantize_dynamic( model_inputbest.onnx, model_outputbest_int8.onnx, weight_typeQuantType.QUInt8 )参数说明QuantType.QUInt8是无符号 8 位量化对精度影响比QInt8小。量化后模型体积缩小到原来的四分之一推理速度提升 1.5~2 倍但检测框的置信度会普遍下降 0.05 左右。应对方式是把推理时的conf阈值调低 0.05而不是对量化模型修改训练参数。追踪控制回路的验证我习惯用日志方式记录每一帧的目标中心坐标、距离估计、控制输出。跑完一次飞行后把这三组数据画成曲线——如果水平控制输出曲线呈等幅振荡说明 P 项增益太大如果目标中心偏差一直收敛不到 0说明有恒定误差需要加一点积分项。这个验证方法不需要额外硬件比凭空调 PID 参数可靠得多。最后说一个我自己的习惯每次改动数据集或者训练超参数前先把旧的best.pt复制一份带日期备份。因为你在第 3 轮调参会把模型调坏而重训一次的成本往往是一两个小时有备份就等于有后悔药。做无人机项目的血泪经验是视觉模型的表现有很强的「玄学」成分你永远不知道哪次数据增强会让 mAP 掉 3 个点。所以不求一次到位而是按版本管理数据和权重每一步都可回滚。希望这些方法能帮到你让你的 Tello TT 目标识别检测和追踪测距项目少走弯路。本文还有配套的精品资源点击获取
返回列表