ARTICLE DETAIL

资讯详情

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

基于YOLOv5的船舶检测识别项目:从数据集到树莓派部署全流程

基于YOLOv5的船舶检测识别项目:从数据集到树莓派部署全流程 简介本资源为基于YOLOv5的船舶检测识别完整项目包面向计算机视觉学习者、课程设计及期末大作业需求者帮助快速搭建可运行的船舶目标检测系统。包内共203个文件以52个Python源码、47个YAML配置、35张PNG图像及5个pt权重文件为主另含txt说明、sh脚本、xml标注与jpg样例等压缩包约124.75MB目录结构清晰覆盖训练、推理与界面展示全流程。项目提供PyQt5检测界面运行show_0文件夹下的pyqt.py即可可视化查看检测效果权重位于shipdata/resultWeights/best.pt代码完整下载可用确保能够运行。目前已有440人学习下载适合需要船舶检测数据集、模型权重与可复现代码的读者参考可据此完成模型训练、界面调试与结果验证快速理解YOLOv5在船舶识别任务中的落地方式。1. 船舶检测这套 YOLOv5 方案为什么期末大作业选它最稳带过几届毕业设计之后我发现一个规律选船舶检测做期末大作业的人往往不是冲着船去的而是冲着这个方向能跑通、能出图、能写报告去的。港口监控、航道管理、海上执法这些场景里船舶目标检测是刚需但真正让这个题目在课程设计里站稳脚跟的是 YOLOv5 这套工程化程度极高的框架——配置文件清晰、训练脚本开箱即用、推理可视化现成配合一份标注好的船舶检测数据集从环境配置到跑出第一张带框的检测图熟练的话一个下午就能搞定。这也是为什么yolov5训练自己的数据集常年挂在搜索热词上而yolov5环境配置更是新手绕不过去的第一道坎。这篇文章要拆的就是基于 YOLOv5 的船舶检测识别项目从源码到模型再到数据集这一整条链路。我会按实际动手的顺序讲数据集长什么样、怎么转格式、配置文件怎么改、训练参数怎么设、推理脚本怎么跑、部署到树莓派这类边缘设备要注意什么。适合两类人一类是课程设计或期末大作业需要快速出成果的学生另一类是想把船舶检测落地到实际监控场景、但被数据标注和模型调参卡住的工程师。不吹精度天花板只讲能复现的路径和会翻车的地方。2. 船舶检测数据集从原始标注到 YOLOv5 可训练格式2.1 船舶数据集通常长什么样类别怎么定船舶检测数据集和通用 COCO、VOC 最大的区别在于目标尺度跨度极大。近景的渔船可能占满半个画面远景的货轮在 1920×1080 的监控画面里可能只有 30×20 像素。这就决定了你在定类别的时候不能贪多。常见做法是先把类别压到 3 到 5 类比如货船、渔船、客船、其他或者干脆只分船和非船两类。类别越少标注一致性越高模型收敛越快期末大作业的周期内更容易出可展示的结果。数据集的组织结构一般是这样一个 images 目录放原图一个 labels 目录放同名 txt 标注文件外加一个 data.yaml 描述路径和类别名。如果你拿到的原始数据是 VOC 格式的 XML或者标注工具导出的 JSON第一步就是转成 YOLO 需要的归一化中心点格式。下面这个脚本处理 VOC 转 YOLO 的典型场景。import xml.etree.ElementTree as ET import os # 类别映射根据你的数据集实际类别修改 classes [cargo, fishing, passenger, other] def convert_annotation(xml_path, img_w, img_h, out_path): tree ET.parse(xml_path) root tree.getroot() with open(out_path, w) as f: for obj in root.iter(object): cls_name obj.find(name).text if cls_name not in classes: continue # 跳过未定义类别避免训练时报索引越界 cls_id classes.index(cls_name) bbox obj.find(bndbox) xmin float(bbox.find(xmin).text) ymin float(bbox.find(ymin).text) xmax float(bbox.find(xmax).text) ymax float(bbox.find(ymax).text) # YOLO 格式中心点 x,y 和宽高全部除以图像尺寸归一化到 0-1 x_center (xmin xmax) / 2.0 / img_w y_center (ymin ymax) / 2.0 / img_h w (xmax - xmin) / img_w h (ymax - ymin) / img_h f.write(f{cls_id} {x_center:.6f} {y_center:.6f} {w:.6f} {h:.6f}\n)这段代码的关键点有三个。第一classes列表的顺序必须和 data.yaml 里的 names 完全一致否则训练出来的模型会把货船识别成渔船。第二归一化除法用的是图像真实宽高不是标注框的宽高很多人在这里写反导致框全部偏移。第三if cls_name not in classes这个过滤不能省VOC 数据集里经常混着boat和ship两种写法不统一就会在训练时抛异常。2.2 data.yaml 配置与数据集划分的实操参数转换完标注之后下一步是写 data.yaml 并划分训练集、验证集。YOLOv5 官方推荐的比例是 8:1:1 或 7:2:1但船舶数据集如果样本量本身就不大比如 2000 张以内我一般会用 8:2 只分训练和验证把测试集从验证集里临时抽。原因是小数据集下三份划分会让验证集样本太少mAP 波动大看不出真实效果。# data/ship.yaml path: ../datasets/ship_data # 数据集根目录 train: images/train # 训练集图片相对路径 val: images/val # 验证集图片相对路径 nc: 4 # 类别数量必须和 classes 长度一致 names: [cargo, fishing, passenger, other]这里有个容易被忽略的坑path写的是相对路径时YOLOv5 是相对于你运行 train.py 时的工作目录来解析的不是相对于 yaml 文件位置。所以如果你在项目根目录跑训练path 就要按根目录来写。我见过太多人 yaml 写得没问题但一跑就报找不到图片九成是路径基准搞错了。稳妥做法是直接写绝对路径或者用os.path.abspath在脚本里动态生成。划分脚本本身很简单但要注意图片和标注文件必须同步移动不能只挪 images 不挪 labels。另外文件名里的空格和中文最好提前批量替换掉YOLOv5 的 dataloader 在某些系统上对中文路径支持不稳定这是血泪经验。3. YOLOv5 环境配置与训练参数怎么设才不白跑3.1 环境配置conda 建环境到依赖装齐yolov5环境配置是搜索量最高的长尾词之一说明卡在这一步的人最多。我的建议是永远用 conda 建独立环境不要往 base 环境里装。YOLOv5 对 PyTorch 和 torchvision 的版本匹配比较敏感混装很容易出现 CUDA 版本不匹配或者 numpy 版本冲突。# 创建环境python 版本选 3.8 或 3.9兼容性最好 conda create -n ship_yolo python3.9 -y conda activate ship_yolo # 安装 PyTorch根据你的 CUDA 版本去官网查对应命令 # 这里以 CUDA 11.8 为例 pip install torch2.0.1 torchvision0.15.2 --index-url https://download.pytorch.org/whl/cu118 # 克隆 YOLOv5 源码后安装依赖 git clone https://github.com/ultralytics/yolov5 cd yolov5 pip install -r requirements.txt装完之后一定要验证 GPU 是否可用跑一行python -c import torch; print(torch.cuda.is_available())输出 True 才算环境通了。如果输出 False先别急着跑训练检查 CUDA 版本和 PyTorch 版本是否对应这一步不解决后面训练会慢到让你怀疑人生。requirements.txt 里有时候会指定特定版本的 opencv如果装完 import cv2 报错单独pip install opencv-python覆盖一下通常能解决。3.2 训练参数batch size、学习率和 epochs 的取舍YOLOv5 的训练命令看起来简单但参数设不对就是白跑。下面是一条我常用的训练命令针对船舶数据集做过调整。python train.py \ --data data/ship.yaml \ --weights yolov5s.pt \ --img 640 \ --batch 16 \ --epochs 100 \ --hyp data/hyps/hyp.scratch-low.yaml \ --name ship_exp1 \ --cache逐个说参数。--weights yolov5s.pt用的是官方预训练权重船舶数据集样本量不大的话从预训练权重微调比从头训练收敛快得多这是迁移学习的基本操作。--img 640是输入分辨率船舶目标普遍偏小理论上 1280 能提升小目标召回但显存占用翻倍8G 显存以下建议先跑 640 看效果。--batch 16是批大小显存不够就降到 8 或 4但 batch 太小会让 BN 层统计不稳定精度可能掉一两个点。--epochs 100对船舶这种类别少的数据集通常够用如果验证集 mAP 在 60 轮之后还在涨可以加到 150。--cache是把图片缓存到内存数据集不大的话能明显加快每个 epoch 的速度但内存小于 16G 且图片超过 5000 张时慎用。--hyp指定超参数文件新手直接用默认的 hyp.scratch-low.yaml 就行等你对数据分布有感觉了再去调学习率和数据增强。这里提一句yolov5超参数很多人一上来就想改 lr0 和 lrf其实对船舶检测影响最大的是 mosaic 增强的比例默认 1.0 意味着每张图都做马赛克拼接对小目标检测有帮助但如果你的数据集里船本身就很小mosaic 可能让目标更碎可以试着降到 0.5。训练过程中重点看三个指标box_loss 是否稳定下降、mAP0.5 是否在涨、验证集的 precision 和 recall 是否平衡。如果 loss 震荡厉害先把 batch 调大或者学习率调小。如果 mAP 卡在某个值不动了检查标注质量船舶数据集最常见的标注问题是漏标——远景的小船没标模型学到的就是有些船不用检测召回率自然上不去。4. 推理、验证与树莓派部署从跑通到跑稳4.1 推理脚本与结果验证训练完之后用 detect.py 跑推理是最直接的验证方式。命令如下python detect.py \ --weights runs/train/ship_exp1/weights/best.pt \ --source data/samples/ \ --img 640 \ --conf 0.25 \ --iou 0.45 \ --save-txt--conf 0.25是置信度阈值低于这个值的框不显示。船舶检测里这个值不要设太高0.25 到 0.3 比较合适设到 0.5 会漏掉很多远景小船。--iou 0.45是 NMS 的 IoU 阈值控制重叠框的合并程度船舶密集停靠的场景可以适当调高到 0.5 减少误删。--save-txt会把检测结果存成 txt方便你后续做统计或者和标注对比。验证模型好坏不能只看几张推理图要用 val.py 跑一遍验证集看 mAP0.5 和 mAP0.5:0.95 两个指标。船舶检测的 mAP0.5 能到 0.85 以上就算不错了如果只有 0.6 左右大概率是数据量不够或者标注有问题。另外建议单独抽一批远景小目标的图做测试因为整体 mAP 会被近景大目标拉高掩盖小目标检测差的问题。4.2 树莓派 5 上部署自己训练的 YOLOv5 模型树莓派5上部署自己训练的yolov5模型是近期的热词说明边缘部署的需求在涨。树莓派 5 的算力比 4 强不少但直接跑 PyTorch 原版 YOLOv5 还是吃力帧率可能只有 2 到 3 FPS。我的做法是先导出 ONNX再用 onnxruntime 推理帧率能提到 5 到 8 FPS如果对精度要求不那么极致可以导出 NCNN 格式速度更快。# 导出 ONNX 模型 python export.py --weights runs/train/ship_exp1/weights/best.pt --include onnx --img 640 # 在树莓派上安装 onnxruntime pip install onnxruntime # 推理脚本核心逻辑 import onnxruntime as ort import cv2 import numpy as np session ort.InferenceSession(best.onnx) img cv2.imread(test.jpg) img cv2.resize(img, (640, 640)) img img[:, :, ::-1].transpose(2, 0, 1) # BGR 转 RGB 并调整通道顺序 img np.expand_dims(img, axis0).astype(np.float32) / 255.0 outputs session.run(None, {session.get_inputs()[0].name: img})树莓派部署最大的坑是内存和散热。YOLOv5s 的 ONNX 模型大概 28MB推理时内存占用在 500MB 左右树莓派 5 的 4G 版本够用但如果你同时跑摄像头采集和网络传输就要注意别把内存吃满。另外树莓派 5 满载跑推理温度会到 70 度以上不加散热片会降频帧率直接腰斩。建议加个主动散热风扇成本不高但效果立竿见影。5. 避坑与排查船舶检测训练中最容易翻车的 5 个地方5.1 训练 loss 不降反升现象训练开始后 box_loss 从 0.1 涨到 0.5 甚至更高mAP 一直是 0。原因通常是学习率设太大或者标注格式不对导致模型学的是噪声。解决先把学习率降到 0.001 试一轮如果 loss 开始降说明是学习率问题如果还是不动用python utils/check_dataset.py检查标注文件重点看有没有坐标超出 0-1 范围或者类别索引越界。5.2 验证集 mAP 很高但实际推理漏检严重现象val.py 跑出来 mAP0.5 有 0.9但拿新图片推理时很多船没框出来。原因是验证集和训练集分布太接近模型过拟合了。解决重新划分数据集确保验证集里有不同场景、不同光照、不同距离的图片。另外检查推理时的 conf 阈值是不是设太高了默认 0.25 对船舶检测比较合适。5.3 训练到一半报 CUDA out of memory现象前几个 epoch 正常突然报显存不足。原因通常是 dataloader 的 worker 数太多或者图片尺寸不统一导致某些 batch 显存峰值超标。解决把--workers降到 4 或 2--batch降到 8如果还不行就加--img 512降低输入分辨率。另外--cache在内存紧张时也会加剧问题可以先去掉这个参数。5.4 树莓派上推理结果和 PC 上不一致现象同一个模型PC 上检测正常树莓派上框的位置偏移或者类别错乱。原因是预处理不一致最常见的是 RGB 和 BGR 通道顺序搞反或者归一化方式不同。解决把 PC 上的预处理代码原封不动搬到树莓派上逐行对比输入张量的数值确保完全一致。ONNX 导出时也要注意 opset 版本树莓派上的 onnxruntime 版本较老时opset 不要超过 12。5.5 数据集里混入非船舶图片导致误检率飙升现象模型在岸边场景把建筑物或者车辆识别成船。原因是数据集中混入了不含船舶的负样本但标注时没做处理模型学到了错误的特征关联。解决要么把这些图片删掉要么在标注时明确标为背景类。YOLOv5 支持背景类但需要在 data.yaml 里单独加一个 background 类别并给这些图片生成空标注文件。更简单的做法是直接剔除船舶检测数据集里负样本的比例控制在 5% 以内比较安全。6. 把 mAP 再往上推一档船舶小目标检测的针对性技巧前面讲的都是跑通和跑稳这一章说一个具体技巧怎么针对船舶小目标把 mAP 往上提。船舶检测的难点从来不是大船而是远景里那些几十像素的小目标。我试过几种方法最有效的是三个组合拳。第一提高输入分辨率。把--img从 640 提到 1024 或 1280小目标的像素信息保留得更多。代价是显存和训练时间增加但船舶数据集通常不大多花几个小时换几个点的 mAP 是值得的。如果显存不够可以用--multi-scale让 YOLOv5 在训练时随机缩放输入尺寸间接提升尺度鲁棒性。第二调整 anchor 尺寸。YOLOv5 默认的 anchor 是基于 COCO 数据集聚类的对船舶这种长宽比偏大的目标不一定最优。可以用python utils/autoanchor.py在你的船舶数据集上重新聚类 anchor命令是python train.py --data data/ship.yaml --weights yolov5s.pt --img 640 --batch 16 --epochs 1 --noautoanchor先跑一轮看默认 anchor 的匹配率如果低于 0.9 就值得重新聚类。第三在验证阶段用 TTATest Time Augmentation。推理时加--augment参数YOLOv5 会对图片做翻转、缩放等多尺度增强后再合并结果小目标的召回率通常能提升 2 到 3 个点。代价是推理速度慢一倍左右适合对精度要求高、对实时性要求不高的场景。方法mAP0.5 提升幅度推理速度影响适用场景提高输入分辨率到 10243~5 个点慢 2 倍离线检测、精度优先重新聚类 anchor1~2 个点无影响所有场景推理时加 TTA2~3 个点慢 1 倍验证和报告展示组合使用5~8 个点慢 3 倍期末大作业冲高分最后说个我自己的习惯每次改完参数跑完训练不管结果好坏都把 runs 目录下的 results.csv 和混淆矩阵截图存一份按日期和参数命名。船舶检测这个方向调参的直觉是靠对比积累出来的光看一次结果记不住什么参数组合有效。我见过太多人跑完一次训练过两天想复现却忘了当时改了什么只能从头再来。这个习惯帮我省了很多后悔药。希望帮到你。本文还有配套的精品资源点击获取
返回列表