十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

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

YOLOv13无人机俯视舰船检测实战:数据集与部署全解析

YOLOv13无人机俯视舰船检测实战:数据集与部署全解析 简介目标检测是计算机视觉领域的核心任务旨在从图像中定位并识别物体。传统地面视角检测中目标尺度大、背景简单而无人机俯拍改变了成像视角使舰船目标呈现尺寸小、任意旋转、海面反光干扰复杂等新挑战对模型的泛化能力提出更高要求。YOLOv13作为新一代单阶段检测器通过可变形卷积、解耦检测头等改进增强了俯视场景下的特征提取与定位能力。基于该模型构建的俯视舰船检测项目整合了标注数据集与预训练权重覆盖货船、渔船、快艇等多类目标可快速应用于海上搜救、港口监管、生态监测等实际场景。项目结构、模型原理、训练配置与部署细节均包含工程化适配为无人机视角下的舰船目标检测提供了一套开箱即用的可行方案。 无人机视角下的舰船目标检测这几年在海上搜救、港口监管、渔业管理、海洋生态监测这些场景里需求特别大。普通的地面摄像头拍的舰船是水平视角目标大、背景干净检测难度不高但换成无人机俯拍之后情况完全变了——船变成了一堆形状各异的色块、阴影混杂在水面和波浪反光里再加上目标尺寸小、分布密集、角度任意旋转常规检测模型很容易翻车。这个 yolov13-main-sts-boat-drone-vis-data 项目解决的就是这个场景下的实际问题它把 YOLOv13 模型和一批俯视舰船数据集、训练好的权重打包在一起开箱即用省去了自己找数据、标数据、从零训练的漫长过程。我拿到这个压缩包之后拆开看了一下里面东西挺全YOLOv13 的完整工程代码、一套俯视视角舰船检测数据集还有已经训练好的模型权重。意味着你不用理解底层结构也能直接用它跑推理如果你想自己微调数据、脚本、配置也都给你备好了。这篇文章我打算从项目设计思路、核心细节、训练实操、踩坑记录四个角度展开把我实际跑通这个项目的整个过程和经验都写清楚。1. 项目整体设计与思路拆解1.1 为什么俯视视角是舰船检测的一个分水岭很多做目标检测的朋友习惯了水平视角的图片觉得舰船检测不就是识别个船吗但到了俯视视角问题就变得很不一样。水平视角下船的特征非常明确船体、船舱、桅杆、烟囱这些结构肉眼可辨。可无人机从上面往下拍的时候你看到的基本是船的甲板平面加上船体轮廓特征信息大幅度减少而且船的形状在不同角度、不同船型下差异极大——货轮是长方形的渔船是窄长条的快艇是个小三角还有密密麻麻停在一起的成排渔船人眼辨别都费劲。这版 YOLOv13 在检测头和解码策略上针对这类柔性目标做了优化。它延续了 YOLO 系列 anchor-free 的思路不再依赖预设的锚框尺寸而是让模型直接从特征图上回归物体的中心和边界。这对舰船检测特别有意义因为船的长宽比变化范围实在太大了从 1:1 的小快艇到 1:8 以上的长货轮都有如果还用固定比例的 anchor 去覆盖得设置几十组尺度才够用而且召回率还不一定高。俯视场景还有一个隐藏难点——目标朝向的任意性。同一艘船船头朝北和朝东在图像上就是完全不同的姿态。YOLOv13 的数据增强策略里加入了随机旋转增强把训练图片按任意角度旋转强制模型学到旋转不变性。我试过把旋转增强关掉之后训练同一批测试集上的 mAP 大概掉了 4-5 个点说明这个策略在俯视场景里不是可有可无的而是直接影响精度的关键项。1.2 YOLOv13 相对上一代模型改进在哪儿如果你熟悉 YOLOv10 或者 YOLOv11 的结构再翻开这套代码会发现主干网络部分看着眼熟但细节上有几处明显的调整。首先是主干中的 C2f 模块做了进一步改造增加了可变形卷积DCNv2的可选分支对几何形变目标的特征提取更友好。舰船在俯视图中存在透视收缩、波浪遮挡造成的局部变形普通卷积对这类形变不太敏感可变形卷积会主动调整感受野的位置相当于给特征提取加了个自适应对准的能力。其次是检测头部分YOLOv13 采用了轻量化的解耦头设计把分类和回归分支彻底分开同时把边框回归从传统的直接回归宽高改成了基于中心点距离和尺度比例的联合预测。这种设计对检测结果的定位精度提升非常明显尤其是对边缘模糊的目标比如船和海水交界处对比度低的时候回归误差能小不少。从训练策略上看这套代码默认开启了 Mosaic 和 MixUp 联合增强把多张图拼在一起训练让模型在训练时能看到更多的小目标样本。俯视舰船数据集的难点恰恰就是小目标多——一艘几十米长的船在 640x640 的输入图像里可能只占 20x20 像素。如果不用 Mosaic 这种拼接增强小目标出现的频率太低模型很容易直接忽略掉它们。不过 Mosaic 用的比例在这里被特意调低了我看了下代码里的配置mixup 和 mosaic 的概率都控制在 0.5 左右不像很多通用检测项目直接开到 1.0。这个改动我推测是为了防止过度增强导致船体纹理失真毕竟俯视舰船本身的纹理信息就少再被拼接切块搞几下特征就彻底糊了。1.3 压缩包里究竟有什么先盘一遍再动手解压 yolov13-main-sts-boat-drone-vis-data.zip 之后第一层目录结构如下yolov13-main/ ├── configs/ # 模型配置参数 ├── data/ # 数据集存放目录 ├── weights/ # 训练好的模型权重 ├── utils/ # 工具函数 ├── train.py # 训练入口脚本 ├── detect.py # 推理检测脚本 ├── val.py # 验证评估脚本 └── requirements.txt # 依赖环境清单weights 目录里有多个 pt 文件名字带了精度和训练轮次标识比如best.pt、last.pt还有用不同输入尺寸训练出来的版本。我优先推荐直接用best.pt这是按验证集 mAP 挑选出来的最优权重。如果你要部署到算力有限的设备上可以试试目录里那个经过通道剪枝压缩的小模型体积大概是原版的 60%精度只掉了不到 2 个点性价比很高。数据集这块压缩包内嵌了一套已经标注好的俯视舰船数据集我没细数是几千张但标注文件用的是 YOLO 的 txt 格式每行对应一个目标class_id x_center y_center width height坐标值全部归一化到 0~1这样不依赖具体的图像尺寸训练时不用做额外的坐标换算。类别方面数据集基本涵盖了常见的舰船类型货船、渔船、邮轮、快艇、橡皮艇都有标注不过各类别的样本量并不均匀——货船和渔船数量占了大头快艇和橡皮艇相对少一些训练时可以考虑对尾部类别做过采样不然模型容易把少见类别学成稀有类推理时漏检率会偏高。2. 核心细节解析与实操要点2.1 瞄准俯视场景的预处理链路这套项目的推理和训练流程在预处理阶段有意识地针对俯视舰船图做了适配不是简单的 resize 完事。你打开utils/datasets.py能看到加载图片之后会先做一次自适应对比度增强用的是 CLAHE限制对比度自适应直方图均衡化把海水区域和船体之间的对比度拉开。这个细节在普通数据集上影响不大但在俯视海面上非常关键——阴天时光线均匀海水和船身的灰度值非常接近不做对比度增强的话船体边缘在特征图上几乎提不出有效响应。尺寸调整方面项目默认把输入图片缩放到 640x640同时保持长宽比不变剩余区域用灰色填充。这个操作和很多分类项目里那种直接拉伸变形不一样直接拉伸会把船的长宽比搞坏模型学到的是一个变形过的船型特征推理时遇到正常的船反而识别不准。我看到很多舰船检测的分享帖都会忽略这一点实际上这个细节对精度影响很大尤其是狭长型的货轮拉伸之后本来是 1:6 的长宽比变成 1:4特征分布完全变了。推理时的 NMS非极大值抑制参数也做了调整。YOLOv13 默认的 NMS 阈值是 0.45但在这个项目里被改成了 0.35。原因是俯视场景下船和船容易紧紧挨着停靠目标框高度重叠如果 IOU 阈值设得高重叠框不会被抑制会出现一艘船被同时画出三四个框的情况调低阈值之后重叠的框会被更积极地去重实际测试下来密集靠泊场景下的误检率降低了约三成。2.2 数据标注格式与类别体系如果你打算往这套框架里加自己的数据需要严格按照 YOLO 格式来组织。数据集目录是data/ ├── images/ │ ├── train/ │ └── val/ ├── labels/ │ ├── train/ │ └── val/ └── data.yamldata.yaml指定类别数和类别名这个项目里类别名是[cargo, fishing, passenger, speedboat, rubber]这样的顺序类别顺序必须和标注文件里的 class_id 一一对应一旦顺序错了模型会完全学歪。我自己曾经犯过这个错数据文件里把 cargo 标为 0yaml 里却把 passenger 排在第一训练过程中 loss 一直不降后来检查发现是类别顺序错位了。还有个小细节值得留意标注框的最小尺寸。训练时如果某个目标的宽或高小于 2 像素YOLO 系列通常直接过滤掉因为这么小的目标在特征图上连一个像素都覆盖不了硬塞进去只会给 loss 增加噪声。这套项目里也保留了类似逻辑所以在自建数据集时尽量保证目标框像素尺寸不小于 5x5过小标签宁可删除也不要保留。2.3 训练好的模型该怎么用四种方式各有取舍拿到best.pt权重之后用法不是只有一种我建议根据你的实际场景来选直接推理单张图片跑detect.py指定权重路径和输入图片路径适合快速验证效果。批量推理整个文件夹detect.py支持传入目录自动遍历所有图片适合离线处理一批历史影像。视频流实时检测代码里封装了VideoStreamDetector类支持从摄像头或视频文件读取帧逐帧推理可以在输出的画面上绘制检测框和置信度。我实际测了一下在 RTX 3060 上能做到大概 45 FPS满足实时监控的基本要求。迁移继续训练train.py里使用--weights weights/best.pt作为预训练权重继续微调适合新增类别或适配新的拍摄环境。如果你要把它接到自己的 C 或嵌入式项目里最省事的做法是先通过 ONNX 把模型导出代码里有export.py再用 OpenCV 的 DNN 模块加载 ONNX 文件推理。这一步我在后面实操部分会细讲导出时有个坑就是 opset 版本和动态轴设置搞不定的话导出的模型无法处理任意尺寸输入。3. 实操过程与核心环节实现3.1 环境搭建与依赖安装老规矩先准备一个干净的 Python 虚拟环境建议 Python 3.9 或 3.10太新的 3.12 版本有些 PyTorch 轮子还不稳定容易踩编译坑。创建一个新的虚拟环境conda create -n yolo13 python3.10 -y conda activate yolo13然后安装 PyTorch。我用的 CUDA 11.8 版本如果你是 30 系或 40 系显卡直接装官方推荐的轮子就行pip install torch2.1.0 torchvision0.16.0 --index-url https://download.pytorch.org/whl/cu118再装项目要求的依赖pip install -r requirements.txtrequirements.txt 里主要就是 numpy、opencv-python、tqdm、pyyaml、matplotlib 这些常规库没有特别冷门的东西安装过程一般不会有什么意外。注意一点如果系统里已经有旧版本的 opencv建议先卸载再装避免和 torchvision 的 libjpeg 版本冲突否则训练时偶尔会报一些莫名其妙的图片解码错误。3.2 准备数据集并修改配置压缩包里自带的数据集已经放在了data/目录理论上解压之后直接就能跑。但如果你加了新数据或者想换一套自己的数据需要改data/data.yaml里的路径和类别信息。举一个例子假设你的数据放在D:/my_boat_data/图片和标签分别放在images/和labels/下配置可以写成path: D:/my_boat_data train: images/train val: images/val nc: 5 names: [cargo, fishing, passenger, speedboat, rubber]path路径一定要用绝对路径尤其是 Windows 系统上用相对路径很容易找不到文件。Linux 服务器上跑的话相对路径问题小一些但为了保险我依然建议写绝对路径。接下来是模型配置。打开configs/yolov13.yaml里面有几个关键参数可以调nc: 5 # 类别数必须和 data.yaml 一致 depth_multiple: 0.33 # 网络深度缩放 width_multiple: 0.50 # 网络宽度缩放depth_multiple 和 width_multiple 控制模型大小。默认值 0.33/0.50 是一个 lightweight 版本速度快但精度稍低。如果算力足够可以把 depth_multiple 调到 0.67、width_multiple 调到 0.75模型的表达能力会更强舰船检测的细节特征能学得更充分。我在 3090 上试过这个组合训练时间大约增加 40%但 mAP 提升约 2.1 个点划算。3.3 训练超参数设置实操训练命令看起来不复杂核心就一行python train.py --data data/data.yaml --cfg configs/yolov13.yaml --weights weights/best.pt --batch-size 16 --epochs 100 --img-size 640但这里面的超参数值得逐个说清楚batch-size默认 16如果你的显存只有 8GB建议降到 8 或 4。显存不够的时候不要硬扛PyTorch 会报 CUDA out of memory你只能干瞪眼。另外要注意batch-size 不要频繁改因为学习率调度和 batch-size 是挂钩的中途改了 batch-size最好把学习率也重新调整。epochs这个项目训练集规模不大100 个 epoch 基本够用。如果 loss 曲线还在明显下降可以加到 150但超过 200 大概率过拟合因为舰船数据集的多样性有限模型学太多反而会把波浪纹理当成船的特征。img-size训练输入尺寸。640 是速度和精度的均衡点如果你的检测目标以小型快艇为主可以试试 960 甚至 1280小目标的分辨率会大幅提升。前提是你显存扛得住960x960 输入下 batch-size 16 在 24GB 显存上也接近极限了。学习率初始学习率 0.01 是默认值配合余弦退火调度。实际训练中如果 loss 从一开始就不降先别急着调学习率检查一下数据路径有没有配错之前讲过类别顺序错乱也会有同样的表现。训练过程日志里会打印每个 epoch 的 box_loss、cls_loss、dfl_loss以及 precision、recall、mAP50、mAP50-95 等指标。重点关注 mAP50-95这个指标对边框定位精度更敏感俯视场景下舰船边缘和背景反差小mAP50-95 通常比普通数据集偏低不要慌这是正常的。3.4 模型评估与推理演示训练完之后runs/train/exp/weights/下会生成best.pt和last.pt。先跑一遍验证集看指标python val.py --data data/data.yaml --weights runs/train/exp/weights/best.pt --img-size 640输出结果会包含每类的 AP 值。我这次跑下来货船和渔船的 AP 都在 0.9 以上但橡皮艇的 AP 只有 0.61原因就是样本量太少。如果实际项目中橡皮艇是重要目标建议专门补充这个类别的数据。推理验证一张图python detect.py --source test.jpg --weights weights/best.pt --conf-thres 0.35 --iou-thres 0.35conf-thres是置信度阈值默认 0.25但俯视场景虚线多、误检也多建议调到 0.35 以上。置信度阈值设太高会漏检小目标设太低会画一堆多余的框我一般先拿一张有代表性的图试几个阈值找到视觉上最均衡的点再批量跑。检测完成后结果图存放在runs/detect/exp/目录里每艘船会用带颜色的框标出来左上角显示类别和置信度直接可以拿去做汇报展示。3.5 导出 ONNX 部署模型把 PyTorch 权重部署到生产环境通常走 ONNX 中间格式。项目里自带了export.pypython export.py --weights weights/best.pt --imgsz 640 --opset 12一个常见坑导出的 ONNX 模型默认只有静态的输入尺寸640x640如果部署时输入图像尺寸不固定就会报错。解决办法是导出时带上动态轴参数在代码里把 input_names 和 dynamic_axes 设置正确让 ONNX 允许输入尺寸动态变化。导出完可以用 onnxruntime 验证一下import onnxruntime as ort import numpy as np from PIL import Image session ort.InferenceSession(best.onnx, providers[CUDAExecutionProvider, CPUExecutionProvider]) img np.array(Image.open(test.jpg).resize((640, 640))).astype(np.float32) / 255.0 img img.transpose(2, 0, 1)[None, ...] outputs session.run(None, {session.get_inputs()[0].name: img}) print(outputs[0].shape)输出 shape 是(1, 5, 8400)这种形式的对应(batch, 5 class_num, anchor_num)前 4 行是框坐标第 5 行是目标置信度剩下的行是各类别置信度解析方式和 YOLOv8 之后版本一致。4. 常见问题与排查技巧实录4.1 高频问题速查表我把自己在跑这个项目过程中踩过、以及帮朋友排查过的典型问题整理成一张表问题现象可能原因排查与解决CUDA out of memorybatch-size 过大降低 batch-size 到 4 或 2或缩小 img-sizeloss 在训练初期不下降类别顺序错乱 / 学习率过低核对 data.yaml 和标注 class_id尝试 lr0.01验证集小目标全部漏检输入尺寸太小/旋转增强缺失增大 img-size 到 960确认旋转增强已开启训练 50 轮后 mAP 仍为 0标签文件为空或路径错误检查 labels/ 目录下 txt 文件确认坐标值在 0~1推理时一张图跑很久使用了 CPU 推理确认 PyTorch 装的是 CUDA 版本用torch.cuda.is_available()验证导出 ONNX 后尺寸不兼容动态轴未设置重新导出设置 dynamic_axes海上场景误检大量波浪训练数据缺少反例增加纯海面、无船的负样本图片参与训练4.2 训练不收敛的排查顺序很多人遇到 loss 居高不下就慌了马上开始调学习率、换优化器一顿操作猛如虎最后发现是数据路径写错了。我建议按以下顺序排查第一确认数据加载正常。在训练脚本里打印一个 batch 的图片和标签可视化结果检查框是不是标在正确位置、类别对不对。这一步花五分钟能省下后面五个小时的瞎折腾。第二检查标注文件是否有空文件或异常值。比如某张图的标签文件存在但内容是空的模型可以从这张图上学到没有目标的负反馈但如果大量图片都是空的模型就会学会对什么都输出低置信度mAP 自然上不去。第三再考虑超参数。确认类别数nc是否一致主干网络的 pretrained 权重是否加载成功。很多情况下用了不匹配的预训练权重会让模型初始状态就很差后面怎么调都费劲。第四最后才动学习率。如果初始学习率 0.01 下 loss 先降后停滞可以试试 0.005 甚至 0.001配合 warmup 轮数适当加大让模型在前期不要学得太猛。4.3 数据增强的参数调优心得俯视舰船检测的数据增强几个关键开关对最终效果影响很大我单独拿出来说说旋转增强角度范围默认是正负 30 度。但无人机飞行时不一定总是平行于海面有时会有较大的横滚角拍出来的船会偏转更多角度。如果你的无人机经常做大角度机动建议把旋转范围扩大到正负 45 度。代价是训练时间变长因为旋转后的图片需要重新计算标注框坐标但精度收益明显。HSV 增强色调、饱和度、亮度的随机扰动在俯视场景下要格外谨慎。海水的颜色比较稳定如果色调扰动范围太大会把蓝色海水扰动成奇怪的绿色模型就会学到绿色可能是船这种错误关联。我试过把 hsv_h 从 0.015 改成 0.05误检率翻了好几倍后来老老实实改回 0.01 以下。翻转变换水平翻转和垂直翻转对舰船检测完全适用舰船不像是数字识别里有方向歧义。YOLOv13 默认开启随机翻转这个保持默认就好不用动。4.4 实际场景测试港口密集停泊 vs 开阔海域最后说两个实际场景的测试感受。密集停泊的港口场景船一艘挨着一艘遮挡严重检测难度最高。我拿训练好的模型跑了一组港口无人机影像货船、渔船的检测效果很好但小船和橡皮艇容易被相邻的大船遮挡召回率掉得比较明显。这种情况下除了考虑更高分辨率输入之外还可以尝试把 NMS 的 iou-thres 进一步调低到 0.3让模型在拥挤场景下更激进地去重。开阔海域场景则相反船少、背景单纯主要难点在于船体尺度变化大。同样一艘 50 米长的船在 120 米高度拍摄和在 400 米高度拍摄像素尺寸能差出两倍多。这个场景下多尺度推理测试时同时跑 640 和 960 两种输入尺寸融合结果能有效提升对极端尺寸目标的检出率代价是推理耗时约增加一倍。如果对实时性要求高可以在检测脚本里做按需切换远距离巡检用 960 输入近距离作业监控用 640 输入。这个项目的整体完成度相当高无论是拿来做研究还是直接落地都省去了不少工程化的脏活累活。我觉得最有参考价值的是它对俯视场景做的那些小改动——对比度增强、旋转策略、NMS 阈值这些看起来不起眼的参数调整恰恰是实际效果拉开差距的地方。我做了几次项目之后最大的体会是通用检测模型放到特定垂直场景里真正值钱的往往不是网络结构本身而是针对场景特性做的那一圈适配工程。本文还有配套的精品资源点击获取
返回列表