简介这是一份面向目标检测学习者的鱼类检测数据集适用于yolov5、yolov8、yolov9、yolov7、yolov10及yolo11等主流算法可直接用于模型训练与验证测试适合入门练手或课程项目、科研实验使用。压缩包共2000个文件以xml标注文件为主同时提供yolo格式的txt标签两种标注分别存放于独立文件夹便于按需选用yolo格式采用类别索引加归一化中心点与宽高的标准写法坐标范围均在0到1之间可直接接入训练流程。资源包整体约243.91MB图像与标签已按训练集、验证集划分完毕省去自行清洗与切分的步骤。目前已有261人学习下载具备一定参考热度。拿到后可直接搭建数据加载与训练脚本快速验证模型在鱼类目标上的检测效果并对比不同yolo版本的精度与速度表现。1. 鱼类检测数据集怎么选8843 张带标签图像能省掉多少标注工时做水下目标检测的同行大多有过这种经历算法代码跑通了配置文件改好了结果卡在数据上——要么找不到足够多的鱼类图像要么标注格式对不上要么训练集和验证集划分得乱七八糟。这次拆的这份资源标题写得很直白yolo算法-鱼类检测数据数据集-8843张图像带标签-data-tvlbr.zip核心就是 8843 张已经打好标签的鱼类图像同时给了 YOLO 格式的 txt 和 VOC 格式的 xml 两套标注目录也提前划分好了。它解决的不是算法问题而是「数据从哪来、标签怎么对齐、划分怎么省事」这三个最耗时的前置环节。适合正在做水下检测、养殖监测、渔业资源统计这类课题的人也适合想拿一份真实数据集练手 YOLOv5 到 YOLO11 全系列训练流程的工程师。下面按「这份数据长什么样 → 怎么接进训练管线 → 哪些地方容易翻车」的顺序拆开讲。2. 数据集结构与标签格式txt 和 xml 两套标注怎么对应2.1 目录组织与文件命名规律拿到压缩包解压后第一件事不是急着写训练脚本而是把目录结构看清楚。从项目正文给出的文件名样本看图像和标注是成对出现的命名规则类似img_0858_5331.xml前缀img_0858应该是批次或场景编号后面的5331是帧序号或图像序号。这种命名方式的好处是排序稳定不会因为文件系统差异导致图像和标签错位。常见做法是把数据整理成下面这种结构YOLO 训练脚本基本都认这一套dataset/ ├── images/ │ ├── train/ │ └── val/ ├── labels/ │ ├── train/ │ └── val/ └── annotations_xml/ # VOC 格式备份不参与 YOLO 训练 ├── train/ └── val/这里有个关键点YOLO 格式的标签文件名必须和图像文件名严格一致只是扩展名从.jpg换成.txt。如果原始包里 txt 和 xml 是分两个文件夹放的整理时要把 txt 按 train/val 分别归位xml 单独留一份做备份或转其他框架用。我一般会先跑一遍文件名比对确认图像和标签一一对应缺一个都会在训练时被静默跳过最后 mAP 莫名其妙偏低。2.2 YOLO 格式与 VOC 格式的字段差异摘要里把 YOLO 格式写得很清楚class x_center y_center width height五个字段坐标全部归一化到 0 到 1 之间。这是 YOLOv5 之后所有版本的通用输入格式v8、v9、v10、v11 都兼容。而 VOC 格式的 xml 里存的是绝对像素坐标xmin、ymin、xmax、ymax类别用name标签写字符串。两者的换算关系是理解标签的核心字段YOLO txtVOC xml换算方式类别class 索引从 0 开始name字符串需要类别映射表中心 xx_center归一化(xminxmax)/2/图像宽除以图像宽度中心 yy_center归一化(yminymax)/2/图像高除以图像高度宽width归一化(xmax-xmin)/图像宽除以图像宽度高height归一化(ymax-ymin)/图像高除以图像高度如果这份数据里 xml 的类别名是中文或非标准英文转 YOLO 时一定要先建一个classes.txt把类别顺序固定下来。顺序错了模型学到的就是错位的类别训练 loss 看着在降实际检测结果全乱。这是血泪经验别问我是怎么知道的。2.3 用脚本验证标签完整性在正式训练前建议先跑一段校验脚本检查每个 txt 是否符合五字段格式、坐标是否越界、类别索引是否超出预期范围。下面这段可以直接抄import os import glob def check_yolo_labels(label_dir, num_classes): bad_files [] for txt_path in glob.glob(os.path.join(label_dir, *.txt)): with open(txt_path, r) as f: lines f.readlines() for line_no, line in enumerate(lines, 1): parts line.strip().split() # YOLO 格式必须是 5 个字段 if len(parts) ! 5: bad_files.append((txt_path, line_no, 字段数不是5)) continue cls, x, y, w, h parts # 类别索引必须在 [0, num_classes-1] if not (0 int(cls) num_classes): bad_files.append((txt_path, line_no, f类别越界: {cls})) # 归一化坐标必须在 [0,1] for val in [x, y, w, h]: if not (0.0 float(val) 1.0): bad_files.append((txt_path, line_no, f坐标越界: {val})) return bad_files if __name__ __main__: bad check_yolo_labels(dataset/labels/train, num_classes1) print(f发现 {len(bad)} 处异常) for item in bad[:20]: print(item)逻辑说明遍历标签目录下所有 txt逐行拆分先查字段数再查类别索引范围最后查四个坐标是否落在 0 到 1 之间。参数num_classes要根据实际类别数传鱼类检测如果只分「鱼」一类就传 1如果分多种鱼就传对应数量。跑完如果异常数为 0说明标签基本干净如果有异常优先看是不是某些行多了空格或少了字段这类问题在手工标注转格式时很常见。3. 接进 YOLOv8/v11 训练管线data.yaml 配置与训练命令3.1 data.yaml 的字段含义与写法YOLO 系列从 v5 开始就用 yaml 描述数据集路径和类别v8 之后字段基本没变。这份数据已经划分好 train 和 val配置起来很直接# data_fish.yaml path: /home/user/dataset # 数据集根目录绝对路径最稳 train: images/train # 相对 path 的训练图像目录 val: images/val # 相对 path 的验证图像目录 nc: 1 # 类别数按实际改 names: # 类别名顺序必须和标签索引一致 0: fish这里有几个参数容易写错。path建议用绝对路径相对路径在不同工作目录下启动训练时会找不到文件。train和val是相对path的路径不是相对 yaml 文件本身。nc和names的数量必须一致names 的键从 0 开始连续。如果这份数据实际有多类鱼把nc改成对应数字names 按类别索引逐个写。3.2 从命令行启动一次基线训练配置写好后用 YOLOv8 或 YOLO11 的官方命令就能跑起来。下面以 v8 为例v11 把模型名换成yolo11n.pt即可yolo detect train \ datadata_fish.yaml \ modelyolov8n.pt \ epochs100 \ imgsz640 \ batch16 \ device0 \ projectruns/fish \ namebaseline参数说明data指向刚写的 yamlmodel用预训练权重n 版最轻适合先跑通流程epochs先设 100 看收敛趋势不够再加imgsz是输入尺寸640 是通用起点鱼类目标如果偏小可以试 960 或 1280但显存占用会明显上升batch根据显存调16 是 8G 显存左右的保守值device0指定第一块 GPUCPU 训练把这里改成cpu。训练日志里重点看mAP50和mAP50-95两个指标前者宽松后者严格如果 mAP50 高但 mAP50-95 低通常是框的位置不够准可以考虑加数据增强或换更大的模型。3.3 验证与推理确认标签没接错训练完先别急着导出模型用验证集跑一遍确认标签对应关系没错yolo detect val \ modelruns/fish/baseline/weights/best.pt \ datadata_fish.yaml \ imgsz640如果验证 mAP 和训练时最后一轮的数值差距很大比如训练 0.8、验证 0.2大概率是 train 和 val 的标签格式不一致或者 val 目录里混进了没有对应 txt 的图像。推理单张图可以用yolo detect predict \ modelruns/fish/baseline/weights/best.pt \ sourcedataset/images/val \ saveTrue \ conf0.25conf是置信度阈值0.25 是默认值鱼类检测如果误检多可以往上调到 0.4 左右漏检多就往下调。saveTrue会把画框结果存到runs/detect/predict下肉眼扫一遍比看指标更直观。4. 避坑与排查鱼类检测数据集训练中最容易翻车的五件事4.1 现象训练 loss 正常下降但 mAP 始终接近 0原因类别索引和 names 顺序对不上或者标签里的 class 全部是同一个值但 names 写了多个类别。鱼类数据如果只标了一类names 却写了三四种鱼模型学到的全是错位映射。解决打开几个 txt 看第一列的实际取值统计一下有哪些 class 值然后让nc和names严格匹配这个集合。改完重新训练不要接着旧权重继续。4.2 现象验证时提示找不到标签文件原因YOLO 默认按图像路径把images替换成labels再找同名 txt。如果目录结构不是标准的images/和labels/并列或者 txt 扩展名写成了.TXT就会找不到。解决确认目录层级是dataset/images/train对应dataset/labels/train文件名除了扩展名完全一致。Linux 下大小写敏感.TXT和.txt是两回事。4.3 现象坐标越界导致训练报错或框跑到图像外原因VOC 转 YOLO 时如果图像宽高读错或者标注时框超出了图像边界归一化后会出现大于 1 或小于 0 的值。解决用第 2.3 节的校验脚本先扫一遍把越界的行找出来。轻微越界可以裁剪到 [0,1]严重越界说明标注本身有问题建议回到原图重新标。4.4 现象显存爆了batch 降到 1 还是 OOM原因imgsz设得太大或者模型选了 l/x 大版本加上鱼类图像本身分辨率高预处理后占用暴涨。解决先把imgsz降到 640模型换 n 或 s 版batch设 8 试。如果还不行检查是不是开了cacheTrue把整个数据集缓存进内存关掉它。4.5 现象训练集和验证集指标都很好实际拍的新图检测很差原因这份数据的 8843 张图可能来自有限的水域或光照条件模型过拟合到特定场景。鱼类检测里水质、光照、拍摄角度变化很大同分布验证集说明不了泛化能力。解决留一部分完全不同场景的图做测试集不要混进 train 或 val。训练时开mosaic、mixup、hsv增强提升对光照和颜色的鲁棒性。如果条件允许补拍一些目标水域的图像做微调。5. 从 8843 张到可用模型类别平衡检查与增强策略调参数据量看着不小但鱼类检测有个隐蔽问题如果某些类别样本极少模型会偏向多数类。先跑一段统计脚本看每个类别的框数量import glob from collections import Counter counter Counter() for txt in glob.glob(dataset/labels/train/*.txt): with open(txt) as f: for line in f: if line.strip(): counter[int(line.split()[0])] 1 for cls_id, count in sorted(counter.items()): print(f类别 {cls_id}: {count} 个框)如果发现某个类别框数不到总数的 5%训练时可以考虑对含该类的图像做过采样或者用copy_paste增强。YOLOv8 之后的版本支持在 yaml 里配augment参数但更细粒度的控制还是靠自定义 dataloader。另一个实用技巧是调整imgsz和rect参数。鱼类目标如果普遍偏小640 下可能只有十几个像素特征提取会吃力。把imgsz提到 960同时开rectTrue做矩形训练减少 padding 浪费显存换精度。我一般会跑两组对比640 基线一组960 一组看 mAP50-95 提升是否值得多出来的训练时间。最后说个习惯。从那以后我每次拿到新数据集不管对方说划分得多好都强制走一遍「文件名比对 → 标签格式校验 → 类别分布统计 → 小样本过拟合测试」这四步。小样本测试就是拿 20 张图训练 50 轮如果能过拟合到接近 1.0说明标签和管线没问题再上全量数据。这一步能挡掉八成低级错误省下的返工时间远比跑一次测试多。希望帮到你。本文还有配套的精品资源点击获取