ARTICLE DETAIL

资讯详情

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

基于YOLOv8的鱼类检测实战:8843张数据集处理与训练调参指南

基于YOLOv8的鱼类检测实战:8843张数据集处理与训练调参指南 简介这是一份面向目标检测学习者的鱼类检测数据集适用于yolov5、yolov8、yolov9、yolov7、yolov10及yolo11等系列算法可直接用于模型训练与验证测试。数据集已按训练与验证需求划分完毕包含两种标签格式yolo格式的txt文件与voc格式的xml文件分别存放于不同文件夹中其中yolo格式采用类别索引加归一化中心点坐标与宽高的标准写法方便直接接入主流框架。压缩包共2000个文件以xml标注文件为主整体约243.91MB图像与标签一一对应省去自行标注与格式转换的环节。目前已有261人学习下载适合刚接触目标检测、需要快速跑通鱼类识别任务的初学者也适合作为课程设计或算法对比实验的基础数据。拿到后可直接替换数据路径开始训练并借助双格式标签灵活适配不同代码框架减少数据预处理成本。1. 鱼类检测数据集到手之后8843 张带标签图像到底怎么用拿到># 查看解压后的顶层结构确认 images 和 labels 是否分离 unzip -l>import os from pathlib import Path root Path.home() / fish_data imgs {p.stem for p in root.rglob(*) if p.suffix.lower() in (.jpg, .png, .jpeg)} labs {p.stem for p in root.rglob(*.txt)} print(有图无标签:, sorted(imgs - labs)[:10]) print(有标签无图:, sorted(labs - imgs)[:10]) print(配对成功:, len(imgs labs))这段逻辑很直白用文件名主干做集合运算。参数上唯一要注意的是rglob会递归所有子目录如果你的数据里混了__MACOSX这类系统目录先删掉再跑否则会误报。配对成功后再抽查一个标签文件的内容head -5 ~/fish_data/labels/xxx.txt正常输出应该是0 0.523 0.441 0.112 0.087这种五列浮点数。如果看到的是像素坐标比如523 441 112 87说明没归一化必须转换否则 YOLO 训练时损失会直接爆炸。2.2 从 VOC/COCO 转到 YOLO txt 的脚本如果标签是 XML用下面这个转换脚本逻辑是读图像宽高做归一化类别名映射到从 0 开始的整数import xml.etree.ElementTree as ET from pathlib import Path from PIL import Image classes [fish] # 按你的实际类别顺序改 def voc_to_yolo(xml_path, img_dir, out_dir): tree ET.parse(xml_path) root tree.getroot() img_name root.find(filename).text img_path Path(img_dir) / img_name w, h Image.open(img_path).size lines [] for obj in root.findall(object): cls obj.find(name).text if cls not in classes: continue cid classes.index(cls) b obj.find(bndbox) x1, y1 float(b.find(xmin).text), float(b.find(ymin).text) x2, y2 float(b.find(xmax).text), float(b.find(ymax).text) # 归一化并转为中心点宽高 xc (x1 x2) / 2 / w yc (y1 y2) / 2 / h bw (x2 - x1) / w bh (y2 - y1) / h lines.append(f{cid} {xc:.6f} {yc:.6f} {bw:.6f} {bh:.6f}) out Path(out_dir) / (Path(xml_path).stem .txt) out.write_text(\n.join(lines))参数说明classes必须和你的data.yaml里names顺序完全一致差一个位置模型就会把鱼标成背景。:.6f保留六位小数是 YOLO 官方推荐精度太少会在小目标上丢定位精度。转换完随机抽 20 张用可视化脚本叠框检查别信脚本不报错就等于对。3. 数据划分与 data.yaml8843 张怎么切才不浪费3.1 训练/验证/测试的比例与分层8843 张不算多我一般按 8:1:1 切即约 7074 训练、884 验证、885 测试。但鱼类数据有个坑如果同一段视频抽帧而来相邻帧几乎一样随机切会让验证集泄漏训练集信息指标虚高。正确做法是按来源分组切分import random from pathlib import Path from sklearn.model_selection import GroupShuffleSplit root Path.home() / fish_data imgs sorted([p for p in root.rglob(*) if p.suffix.lower() in (.jpg, .png)]) # 假设文件名前缀是视频段编号如 pondA_0001.jpg groups [p.stem.split(_)[0] for p in imgs] gss GroupShuffleSplit(n_splits1, test_size0.2, random_state42) train_idx, val_idx next(gss.split(imgs, groupsgroups)) # 再从 val 里分一半做 test val_imgs [imgs[i] for i in val_idx] test_size len(val_imgs) // 2 test_imgs, val_imgs val_imgs[:test_size], val_imgs[test_size:]GroupShuffleSplit保证同一来源的帧只出现在一个集合里random_state42固定后结果可复现。切完把文件按images/train、labels/train的目录结构软链接或复制过去YOLO 靠路径同名找标签。3.2 data.yaml 的字段与类别顺序path: /home/user/fish_data train: images/train val: images/val test: images/test nc: 1 names: [fish]nc是类别数鱼类检测多数场景只有“鱼”一类但如果你要区分鱼种names顺序必须和转换脚本里的classes一致。path用绝对路径最稳相对路径在不同工作目录下启动训练时经常找不到文件这是新手最常见的翻车点之一。提示改完data.yaml后先跑一次yolo checks或手动python -c import yaml; print(yaml.safe_load(open(data.yaml))确认 YAML 没缩进错误YAML 对空格极其敏感。4. 用 YOLOv8 跑通鱼类检测训练命令与必调参数4.1 环境与最小训练命令环境用 conda 建一个干净环境Python 3.10 PyTorch 2.x 是当前稳妥组合conda create -n fish_yolo python3.10 -y conda activate fish_yolo pip install ultralytics # 验证 GPU 可用 python -c import torch; print(torch.cuda.is_available())最小训练命令yolo detect train \ data/home/user/fish_data/data.yaml \ modelyolov8s.pt \ epochs150 \ imgsz640 \ batch16 \ device0 \ projectfish_runs \ nameexp1modelyolov8s.pt是速度和精度的平衡点8843 张用 s 足够如果鱼体很小占图面积低于 1%换yolov8m.pt并考虑imgsz960。batch16是 8GB 显存的安全值显存够可以上 32。epochs150配合早停实际常在 80~120 轮收敛。4.2 鱼类场景必须调的四个参数参数默认值鱼类场景建议原因imgsz640640 或 960小鱼目标需要更高分辨率hsv_v0.40.5水下光照变化剧烈增强亮度扰动mosaic1.00.5~1.0鱼群密集时 mosaic 提升小目标召回patience5030鱼类数据噪声大早停防过拟合增强参数在命令行里直接追加例如hsv_v0.5 mosaic0.8 patience30。hsv_v调高会让模型对暗水、浑水更鲁棒但太高会把鱼的颜色特征也破坏掉0.5 是我试过的上限。4.3 训练过程看什么指标训练日志里重点盯三个box_loss是否稳定下降、mAP50是否在验证集上持续上升、cls_loss是否异常低。如果mAP50在 0.6 左右就卡住八成是标签里有大量漏标或错标回去抽查验证集的预测可视化yolo detect predict modelfish_runs/exp1/weights/best.pt source/home/user/fish_data/images/val saveTrue看runs/detect/predict里的叠框图漏检的鱼是太小、太暗还是被遮挡对应回去补数据或调imgsz。5. 鱼类检测训练避坑五条血泪记录5.1 现象训练 loss 正常但 mAP 始终为 0原因data.yaml里names顺序和标签里的类别 id 对不上或者标签文件根本没被找到。解决用yolo detect train启动后看日志第一行打印的nc和names再随机抽一个标签文件核对 id 范围是否在[0, nc-1]内。5.2 现象验证集 mAP 很高实拍视频检测全是框原因训练集和验证集来自同一段视频数据泄漏。解决按来源分组切分确保验证集里有不同水域、不同光照条件的样本。我一般会留一个完全独立的“野外测试集”哪怕只有 200 张也比随机切出来的验证集可信。5.3 现象小目标鱼检测不到大框倒是准原因imgsz640下小鱼只有几个像素特征在 backbone 下采样后消失。解决把imgsz提到 960 或 1280同时batch降到 8 防显存溢出或者在data.yaml同级加anchors重新聚类但 YOLOv8 是 anchor-free更直接的办法是提高分辨率并增加mosaic比例。5.4 现象训练到一半 loss 变 NaN原因标签里有宽高为 0 或坐标超出 [0,1] 的脏数据。解决跑一遍清洗脚本过滤掉w0 or h0 or xc0 or xc1的行并删除对应图像。这个检查在转换脚本后立刻做别等训练崩了再回头找。5.5 现象GPU 利用率低训练慢原因batch太小或数据加载是瓶颈。解决batch提到显存允许的最大值workers设为 CPU 核数的 0.75 倍如 8 核设 6并把数据放到 SSD 上。机械硬盘读 8843 张小图会成为明显瓶颈。6. 进阶把鱼类检测模型推到可用的两个技巧6.1 用测试时增强TTA榨出最后几个点YOLOv8 支持推理时 TTA对鱼类这种小目标密集场景mAP 通常能再涨 1~2 个点yolo detect val modelfish_runs/exp1/weights/best.pt data/home/user/fish_data/data.yaml augmentTrueaugmentTrue会对每张图做多尺度翻转推理再融合。代价是推理速度慢 2~3 倍适合离线评估或对精度要求高于速度的场景。如果部署在边缘设备上这个开关不要开。6.2 导出 ONNX 并验证数值一致性训练完导出 ONNX 用于部署导出后必须做一次数值对齐否则部署端结果和训练端对不上是常事yolo export modelfish_runs/exp1/weights/best.pt formatonnx opset12 imgsz640导出后用 onnxruntime 跑一张验证图和 PyTorch 输出对比最大绝对误差正常应小于 1e-3。如果误差大检查opset版本和imgsz是否与训练一致。我习惯在导出后固定跑 10 张图做回归确认框的坐标偏差在 1 像素内才发版。这套流程走下来8843 张鱼类数据从解压到能用的模型大概两三天。真正花时间的不是训练是标签清洗和划分。我自己的习惯是每次拿到新数据集先花半天写配对检查和可视化脚本把脏数据挡在训练之前比训练崩了再回头查省事得多。希望帮到你。本文还有配套的精品资源点击获取
返回列表