☰
YOLO老鼠数据集实战:2295张带标签图像训练与避坑指南
2026/10/4 1:00:56 网站建设 项目流程

简介:这是一份面向YOLO系列目标检测学习者的老鼠目标检测数据集,适合正在做小目标识别、动物检测或课程设计、毕业设计的同学直接上手训练与验证。数据集已按训练与验证需求划分完毕,兼容yolov5、yolov8、yolov9、yolov7、yolov10及yolo11等主流版本,无需额外整理即可投入模型训练。压缩包共约2000个文件,整体约119.3MB,其中1610个xml文件为VOC格式标注,390个txt文件为YOLO格式标注,两种标签分别存放于独立文件夹,便于按框架灵活切换。YOLO格式采用类别索引加归一化中心点与宽高的标准写法,坐标范围均在0到1之间,可直接被训练脚本读取。目前已有143人学习下载,资源提供图像与对应标签的完整配对,能帮助读者省去标注与格式转换环节,把精力集中在模型调参、效果对比与检测精度提升上,也便于复现和扩展自己的检测方案。

1. 老鼠数据集 2295 张带标签:这套 YOLO 组合包到底能解决什么问题

实验室里要做一个鼠类行为识别或者鼠害监测的项目,最卡脖子的往往不是模型结构,而是手里没有一批标注干净、类别明确的老鼠图像。公开数据集里猫狗、行人、车辆一抓一大把,老鼠这种小目标、多姿态、易被遮挡的对象反而稀缺。这个标题里的「yolo算法-老鼠数据集-2295张图像带标签-组合鼠标.zip」,本质就是一份面向 YOLO 目标检测训练的老鼠图像数据集,2295 张图像配对应标签文件,打包成一个压缩包,拿来就能接进 YOLO 训练流程。它适合三类人:刚入门 YOLO 想找一个真实小目标数据集练手的新手、做鼠情监测或动物行为研究需要快速起一个 baseline 的从业者、以及想验证自己数据增强和调参策略是否有效的老手。2295 张不算大,但足够跑通从数据检查、格式转换、训练到推理的完整链路,也足够暴露小目标检测里那些玄学问题。下面我按自己实际处理这类数据集的顺序,把每一步拆开讲清楚。

2. 拿到压缩包先别急着训练:数据体检与标签格式确认

2.1 为什么 2295 张必须先做体检

很多人拿到数据集第一反应是直接yolov8 train,结果训练 loss 不降或者 mAP 一直趴在地上,回头才发现标签里有大量空文件、坐标越界、类别编号从 1 开始而不是 0。老鼠数据集这类小目标数据尤其容易出问题:标注时鼠标点偏一点,框就可能只有几个像素;有些图像里老鼠只露出尾巴或耳朵,标注员干脆漏标。2295 张里哪怕只有 5% 的脏数据,也足以让模型学到一个错误的先验。所以第一步不是训练,是把压缩包解压后做一次结构化体检,确认图像数量、标签数量、类别分布、框的尺寸分布这四件事。

2.2 解压后的目录结构与标签格式核对

常见做法是解压后得到images/和labels/两个目录,或者JPEGImages/配Annotations/的 VOC 结构。YOLO 训练需要的是每张图对应一个同名.txt,每行class_id x_center y_center width height,且坐标是归一化到 0~1 的。先用下面这段脚本把家底摸清楚。

import os from pathlib import Path from collections import Counter img_dir = Path("images") lbl_dir = Path("labels") img_exts = {".jpg", ".jpeg", ".png", ".bmp"} imgs = [p for p in img_dir.rglob("*") if p.suffix.lower() in img_exts] print(f"图像总数: {len(imgs)}") missing, empty, bad_coord = [], [], [] cls_counter = Counter() box_sizes = [] for img in imgs: lbl = lbl_dir / (img.stem + ".txt") if not lbl.exists(): missing.append(img.name) continue lines = [l.strip() for l in lbl.read_text().splitlines() if l.strip()] if not lines: empty.append(img.name) continue for line in lines: parts = line.split() if len(parts) != 5: bad_coord.append((img.name, line)) continue c, x, y, w, h = int(parts[0]), *map(float, parts[1:]) cls_counter[c] += 1 box_sizes.append((w, h)) if not (0 <= x <= 1 and 0 <= y <= 1 and 0 < w <= 1 and 0 < h <= 1): bad_coord.append((img.name, line)) print(f"缺失标签: {len(missing)}") print(f"空标签文件: {len(empty)}") print(f"坐标异常行: {len(bad_coord)}") print(f"类别分布: {dict(cls_counter)}") if box_sizes: ws = sorted(w for w, _ in box_sizes) hs = sorted(h for _, h in box_sizes) print(f"框宽中位数: {ws[len(ws)//2]:.4f}, 框高中位数: {hs[len(hs)//2]:.4f}")

这段脚本做四件事:统计图像总数、找出没有对应标签的图、找出空标签文件、校验每行坐标是否归一化且在合法范围,同时输出类别分布和框尺寸中位数。参数上img_dir和lbl_dir按你解压后的实际路径改,img_exts覆盖常见图像后缀。跑完重点看两个数:框宽高中位数如果低于 0.05,说明这是典型小目标数据集,后面训练必须调小 anchor 或改用更适合小目标的检测头;类别分布如果严重倾斜,比如某一类占 90%,就要考虑过采样或类别加权。

2.3 把 VOC 或 COCO 标签转成 YOLO 格式

如果压缩包里给的是 XML 或 JSON,就得先转。VOC 转 YOLO 的核心是把xmin,ymin,xmax,ymax转成中心点加宽高再归一化。下面这个转换函数我一般直接复用。

import xml.etree.ElementTree as ET from PIL import Image def voc_to_yolo(xml_path, img_path, class_map): tree = ET.parse(xml_path) root = tree.getroot() w, h = Image.open(img_path).size lines = [] for obj in root.findall("object"): name = obj.find("name").text if name not in class_map: continue cid = class_map[name] bnd = obj.find("bndbox") xmin = float(bnd.find("xmin").text) ymin = float(bnd.find("ymin").text) xmax = float(bnd.find("xmax").text) ymax = float(bnd.find("ymax").text) # 裁剪到图像边界,防止标注越界 xmin, ymin = max(0, xmin), max(0, ymin) xmax, ymax = min(w, xmax), min(h, ymax) xc = (xmin + xmax) / 2 / w yc = (ymin + ymax) / 2 / h bw = (xmax - xmin) / w bh = (ymax - ymin) / h lines.append(f"{cid} {xc:.6f} {yc:.6f} {bw:.6f} {bh:.6f}") return lines

class_map是你自己定义的类别名到 0 起始编号的映射,比如{"mouse": 0}。注意这里做了边界裁剪,因为标注越界是 VOC 数据里最常见的脏数据之一,不裁的话归一化后会出现大于 1 的坐标,YOLO 训练时直接报错或静默丢弃。转换完再跑一遍 2.2 的体检脚本确认干净。

3. 用 YOLOv8 在 2295 张老鼠图上跑通第一个 baseline

3.1 数据集配置文件与目录组织

YOLO 训练不直接吃散图,需要按train/val划分并写一个data.yaml。2295 张我一般按 8:2 切,验证集留 450 张左右,保证每个类别在验证集里都有足够样本。目录结构建议这样组织:

dataset/ images/ train/ # 约1836张 val/ # 约459张 labels/ train/ val/ data.yaml

data.yaml内容如下,路径写绝对路径最稳,避免训练时工作目录变化导致找不到文件。

path: /abs/path/to/dataset train: images/train val: images/val nc: 1 names: ["mouse"]

nc是类别数,老鼠数据集通常就一类,如果压缩包里区分了不同鼠种或姿态,按实际类别数改,names顺序必须和标签里的class_id严格对应,错一位整个训练就废了。

3.2 训练命令与关键参数怎么设

baseline 先用yolov8n或yolov8s,别一上来就上大模型,2295 张撑不起大参数量,过拟合风险高。命令如下:

yolo detect train \ data=dataset/data.yaml \ model=yolov8s.pt \ epochs=100 \ imgsz=640 \ batch=16 \ lr0=0.01 \ lrf=0.01 \ patience=20 \ cache=True \ project=runs/mouse \ name=baseline

逐个说参数:imgsz=640是输入分辨率,老鼠是小目标,理论上可以提到 960 或 1280,但显存和速度会明显上升,先用 640 看 baseline;batch=16按显存调,8G 显存跑yolov8s640 大概能到 16;lr0=0.01是初始学习率,小数据集可以降到 0.005 更稳;patience=20是早停,验证指标 20 轮不涨就停,省时间;cache=True把图像缓存到内存,2295 张不大,开了之后每轮省不少 IO。训练完看runs/mouse/baseline/results.csv,重点看metrics/mAP50-95和val/box_loss两条曲线,如果 box_loss 震荡不降,多半是学习率太大或标签有问题。

3.3 小目标检测的针对性调整

老鼠在图像里往往只占几十个像素,默认 anchor 和检测头对小目标不友好。三个调整方向:第一,把imgsz提到 960,让老鼠在特征图上多占几个像素;第二,用yolov8s-p2这类带 P2 小目标检测层的变体,P2 层 stride 是 4,对小目标响应更强;第三,开 Mosaic 和 CopyPaste 增强,mosaic=1.0默认开,copy_paste=0.3可以增加小目标的出现频率。我一般先跑 640 baseline,再跑 960 对比,如果 mAP50-95 提升超过 3 个点,就说明分辨率是瓶颈,值得为它牺牲推理速度。

4. 训练完别只看 mAP:推理验证与坏案例排查

4.1 用验证集跑推理并可视化

训练结束模型权重在runs/mouse/baseline/weights/best.pt,先别急着部署,拿验证集跑一遍推理,把预测框画出来人眼看。

yolo detect predict \ model=runs/mouse/baseline/weights/best.pt \ source=dataset/images/val \ conf=0.25 \ iou=0.5 \ save=True \ project=runs/mouse \ name=val_pred

conf=0.25是置信度阈值,低于它的框不显示;iou=0.5是 NMS 的 IoU 阈值,重叠超过 0.5 的框会被合并。跑完去runs/mouse/val_pred看可视化结果,重点找三类坏案例:漏检(老鼠在但没框)、误检(背景被当成老鼠)、框不准(框住了但偏移大)。漏检多说明召回不够,可以降conf到 0.1 再看;误检多说明模型把背景纹理当成了老鼠,需要补负样本或提高conf。

4.2 从混淆矩阵和 PR 曲线定位问题

YOLO 训练完会自动生成confusion_matrix.png和PR_curve.png。混淆矩阵里如果background那一列数值高,说明大量背景被误检成老鼠;如果mouse行里background高,说明漏检严重。PR 曲线看曲线下的面积,曲线越靠右上越好。2295 张的数据量,mAP50 能到 0.85 以上算正常,如果只有 0.5 左右,先回去查标签,八成是格式或类别编号问题,而不是模型不行。

4.3 导出 ONNX 做一次跨框架验证

训练框架里指标好看不代表部署没问题,我习惯导出 ONNX 再用 onnxruntime 跑一张图,确认输出形状和数值对得上。

import onnxruntime as ort import numpy as np from PIL import Image sess = ort.InferenceSession("best.onnx") img = Image.open("test.jpg").resize((640, 640)) x = np.array(img).transpose(2, 0, 1)[None].astype(np.float32) / 255.0 outs = sess.run(None, {sess.get_inputs()[0].name: x}) print(outs[0].shape) # 期望 (1, 4+nc, 8400)

输出形状里4+nc是框坐标加类别分数,8400是三个尺度特征图展平后的候选框数。如果形状不对,多半是导出时opset或dynamic参数没设对,回去用yolo export model=best.pt format=onnx opset=12重新导。

5. 老鼠数据集训练避坑:5 个血泪踩坑记录

5.1 标签类别编号从 1 开始导致全盘皆输

现象:训练 loss 正常下降,但 mAP 始终接近 0,推理时一个框都不出。原因:标注工具默认类别从 1 开始,而 YOLO 要求从 0 开始,模型学到的类别索引和data.yaml里的names对不上。解决:跑 2.2 的体检脚本看cls_counter的 key,如果有 1 没有 0,把所有标签文件的第一个数字减 1,或者改data.yaml的names前面补一个占位类。这个坑我踩过两次,每次都是训练了半天才发现。

5.2 空标签文件被当成负样本

现象:验证集误检率异常高,背景里到处是框。原因:部分图像确实没有老鼠,标注时生成了空.txt,YOLO 会把空标签文件当成「这张图没有目标」的负样本,但如果空文件比例过高(比如超过 30%),模型会倾向于预测背景,反而在真有老鼠的图上漏检。解决:统计空标签比例,如果过高,要么补充正样本,要么在训练时用close_mosaic提前关掉增强,让模型在后期专注正样本。

5.3 图像和标签文件名大小写不一致

现象:训练时报No labels found,但明明标签文件都在。原因:图像是Mouse_001.JPG,标签是mouse_001.txt,Linux 下大小写敏感,匹配不上。解决:写个脚本统一转小写,或者用Path.stem匹配时统一lower()。这个坑在 Windows 上开发、Linux 上训练时特别常见。

5.4 小目标框归一化后宽高接近 0

现象:训练时警告ignoring degenerate boxes,部分目标学不到。原因:老鼠只占几个像素,标注框宽高归一化后小于 0.001,YOLO 在生成 anchor 时直接丢弃。解决:提高输入分辨率到 960 或 1280,让框的绝对像素变大;或者改用带 P2 层的模型;实在不行把极小框合并或剔除,别让它们污染训练。

5.5 验证集和训练集图像重复

现象:验证集 mAP 高得离谱,部署后效果断崖式下跌。原因:2295 张里可能有连拍或近似帧,随机划分时同一只老鼠的相邻帧同时进了训练集和验证集,造成数据泄漏。解决:按图像相似度或拍摄时间分组后再划分,保证验证集里的老鼠和训练集不重叠。用imagehash做感知哈希去重是个快办法。

6. 把 2295 张用到极致:小数据集上的增强与半监督技巧

2295 张在目标检测里属于小数据集,想再往上提点,光调参不够,得在数据层面做文章。我一般会做两件事:一是离线增强扩样本,二是用训练好的模型去伪标注未标注图像做半监督。离线增强不是简单开 Mosaic,而是针对老鼠的姿态和光照做定向增强:随机旋转 ±30 度模拟不同拍摄角度,随机调整亮度对比度模拟昼夜,随机遮挡模拟老鼠被杂物挡住。用 Albumentations 写一个增强管道,把 2295 张扩到 8000 张左右再训练,mAP 通常能涨 2 到 4 个点。

import albumentations as A import cv2 transform = A.Compose([ A.RandomRotate90(p=0.3), A.Rotate(limit=30, p=0.5), A.RandomBrightnessContrast(0.3, 0.3, p=0.5), A.CoarseDropout(max_holes=8, max_height=32, max_width=32, p=0.3), A.HorizontalFlip(p=0.5), ], bbox_params=A.BboxParams(format="yolo", label_fields=["class_ids"])) img = cv2.imread("mouse.jpg") with open("mouse.txt") as f: boxes = [list(map(float, l.split())) for l in f if l.strip()] bboxes = [b[1:] for b in boxes] class_ids = [int(b[0]) for b in boxes] out = transform(image=img, bboxes=bboxes, class_ids=class_ids)

BboxParams里format="yolo"告诉 Albumentations 输入是归一化的xcycwh,它会自动同步变换框。CoarseDropout模拟遮挡,Rotate模拟角度变化,这两个对老鼠这种姿态多变的目标准确率提升最明显。增强后的数据单独存一份,别覆盖原图,方便对比增强前后的效果。

半监督的做法是:先用 2295 张训练一个 baseline,拿它去推理你手头其他未标注的老鼠图像,把置信度高于 0.7 的预测框当伪标签,和原数据混在一起再训一轮。这一步能把有效样本量翻倍,但要注意伪标签的噪声,置信度阈值别设太低,0.7 是个比较稳的起点。我自己的习惯是每轮半监督后都拿固定验证集测一次,涨了就保留,掉了就回退,别盲目堆数据。这套流程跑下来,2295 张老鼠数据集足够撑起一个能用的检测模型,剩下的就是根据你的实际场景调阈值和部署了。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询