多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

528张松鼠YOLO数据集:小目标检测实战入门指南

528张松鼠YOLO数据集:小目标检测实战入门指南 简介本资源是面向计算机视觉初学者与算法工程师的松鼠目标检测专用数据集专为YOLO系列算法v5/v7/v8/v9/v10/v11训练与验证设计解决小动物类目标检测模型开发中高质量标注数据匮乏的问题。压缩包共1585个文件含528张带标注的JPEG图像、528份YOLO格式txt与528份VOC格式xml双模标签文件以及关键的data.yaml配置文件完整覆盖数据加载、类别定义与路径设置需求37.84MB体积轻量易下载适配本地快速实验与教学演示。已有58人学习下载资源结构规范图像与对应标签严格同名YOLO标签采用归一化坐标格式中心点宽高比可直接接入主流训练框架预览图像显示多角度、多尺度松鼠样本涵盖遮挡、姿态变化等真实场景显著提升模型泛化能力。1. 528张松鼠图像YOLO标签一个能直接喂进训练管道的「开箱即用」小目标检测数据集你手头正缺一个轻量、干净、带完整YOLO格式标注的小动物检测练手数据集不是COCO里混在“啮齿类”里的模糊样本也不是自己爬图手动打标耗掉三天的半成品——而是528张实拍松鼠图像每张都已按YOLOv5/v8/v10通用规范生成.txt标签文件解压即得images/和labels/双目录结构连路径映射都不用改。这不是教学Demo是真实场景下松鼠在树干、草地、木桩、窗台等多背景下的清晰抓拍包含单只、多只、遮挡、侧身、俯视等典型挑战且所有标签经人工复核非自动转换XML残留bbox坐标严格归一化、无越界、无负值。适合刚跑通YOLO环境的新手快速验证全流程从数据加载→训练→推理→mAP计算也适合作为YOLOv8微调基线或用于对比实验中控制变量——比如测试不同增强策略对小目标召回率的影响。如果你正在做校园生物监测、公园智能巡检、或野生动物行为分析的预研这个数据集就是你跳过数据准备阶段、直奔模型迭代的第一块垫脚石。2. 从解压到训练用YOLOv8在本地完成端到端检测流程2.1 解压与目录结构校验确认数据集符合YOLO标准拿到yolo算法-松鼠数据集-528张图像带标签-松鼠.zip后先别急着跑train.py。真实项目里70%的训练失败源于数据结构不合规。用终端进入解压目录后执行以下检查# 查看顶层结构 ls -l # 应输出images/ labels/ README.md如有 dataset.yaml关键 # 检查图像与标签数量是否严格一致YOLO要求一一对应 ls images/*.jpg | wc -l ls labels/*.txt | wc -l # 必须均为528若不等说明有漏标或冗余文件 # 抽查一个label文件内容确保是YOLO格式class_id x_center y_center width height head -n 1 labels/000001.txt # 正确示例0 0.423 0.618 0.182 0.294 → class0松鼠归一化坐标提示YOLO格式要求所有坐标为浮点数且介于0~1之间x_center和y_center是bbox中心点相对图像宽高的比例width和height是bbox宽高占整图宽高的比例。若看到整数坐标如0 120 240 80 160或负值说明是Pascal VOC XML转出时未做归一化——本数据集已规避此问题但养成检查习惯能救你后期无数debug时间。2.2 构建dataset.yaml定义类别、路径与划分比例YOLOv8不读取硬编码路径一切由dataset.yaml驱动。在数据集根目录新建该文件内容如下# dataset.yaml train: ../yolo-squirrel/images/train # 注意YOLOv8默认从当前working dir读取路径需相对 val: ../yolo-squirrel/images/val test: ../yolo-squirrel/images/test # 可选若无test集可删此行 nc: 1 # number of classes names: [squirrel] # class names, index must match class_id in labels但注意原始ZIP包里只有images/和labels/平铺目录没有train/val/test子目录。你需要手动划分——这是必须步骤否则YOLO会报错“no images found”。我一般按7:2:1比例切分369/106/53张用Python脚本自动化# split_dataset.py import os import random import shutil from pathlib import Path data_root Path(yolo-squirrel) images_dir data_root / images labels_dir data_root / labels # 创建train/val/test子目录 for split in [train, val, test]: (data_root / images / split).mkdir(exist_okTrue) (data_root / labels / split).mkdir(exist_okTrue) # 获取所有图像文件名去后缀 all_images [f.stem for f in images_dir.glob(*.jpg)] random.shuffle(all_images) # 划分比例 train_ratio, val_ratio, test_ratio 0.7, 0.2, 0.1 n len(all_images) train_end int(n * train_ratio) val_end train_end int(n * val_ratio) splits { train: all_images[:train_end], val: all_images[train_end:val_end], test: all_images[val_end:] } # 移动文件 for split, files in splits.items(): for stem in files: # 移动图像 img_src images_dir / f{stem}.jpg img_dst data_root / images / split / f{stem}.jpg shutil.copy2(img_src, img_dst) # 移动对应label lbl_src labels_dir / f{stem}.txt lbl_dst data_root / labels / split / f{stem}.txt if lbl_src.exists(): shutil.copy2(lbl_src, lbl_dst) else: print(fWarning: label missing for {stem}) print(Split done. Train/Val/Test:, len(splits[train]), len(splits[val]), len(splits[test]))运行后你的目录结构应变为yolo-squirrel/ ├── images/ │ ├── train/ # 369张.jpg │ ├── val/ # 106张.jpg │ └── test/ # 53张.jpg ├── labels/ │ ├── train/ # 369个.txt │ ├── val/ # 106个.txt │ └── test/ # 53个.txt └── dataset.yaml2.3 安装YOLOv8并启动训练三行命令跑通最小闭环YOLOv8官方推荐用ultralytics包支持PyTorch 1.8无需编译CUDA自动调用。在PyCharm中安装或终端# 创建虚拟环境强烈建议避免包冲突 python -m venv yolov8_env source yolov8_env/bin/activate # Linux/Mac # yolov8_env\Scripts\activate # Windows # 安装核心依赖 pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118 # CUDA 11.8 pip install ultralytics # 验证安装 yolo taskdetect modetrain modelyolov8n.pt datadataset.yaml epochs50 imgsz640 batch16参数说明modelyolov8n.pt选用nano版参数量最小3.2M528张图上训得快适合验证流程若要更高精度换yolov8s.pt11.4Mepochs50小数据集易过拟合50轮足够收敛观察results.png中val_loss曲线若20轮后持续震荡可提前停imgsz640YOLOv8默认输入尺寸松鼠图像多为竖构图640×640能保留细节若显存不足4GB可降为320但小目标检出率会略降batch16根据GPU显存调整RTX 306012GB可跑16GTX 16504GB建议设为4。训练过程会自动生成runs/detect/train/目录内含weights/best.pt最佳权重、results.pngloss/mAP曲线、confusion_matrix.png分类混淆矩阵。50轮后你大概率会看到metrics/mAP50-95(B)在0.65~0.72区间——这已是小数据集上非常健康的指标证明数据质量与流程无硬伤。3. 标签文件深度解析为什么.txt里只有5列以及如何手修异常标注3.1 YOLO标签格式的底层逻辑归一化坐标的物理意义YOLO的.txt标签看似简单class_id x_center y_center width height但每一列都绑定图像几何属性。以一张1280×720的松鼠图像为例若标签为0 0.423 0.618 0.182 0.294其真实像素坐标为bbox中心点(0.423 × 1280, 0.618 × 720) ≈ (541, 445)bbox宽高(0.182 × 1280, 0.294 × 720) ≈ (233, 212)bbox左上角(541−233/2, 445−212/2) ≈ (424, 339)bbox右下角(541233/2, 445212/2) ≈ (658, 551)注意YOLO不存储绝对坐标而是存储相对比例。这带来两大优势一是模型输入尺寸可变imgsz320/640/1280均可二是标签文件体积极小一个528张图的数据集labels/总大小仅约120KB便于版本管理与传输。3.2 手动修复标签的三种高频场景用VS Code正则批量处理尽管本数据集已人工校验但你在后续增补图像或迁移其他标注时必遇以下问题。用VS Code打开labels/目录启用正则搜索CtrlH→.*图标场景正则表达式替换为作用坐标越界如x_center1^(\d) ([1-9]\d*.\d\d.\d*[1-9]\d*) ([\d.]) ([\d.]) ([\d.])$$1 0.999 $3 $4 $5宽度/高度为0无效bbox^(\d) ([\d.]) ([\d.]) 0\.0 ([\d.])$删除整行用VS Code的“替换为”留空再按CtrlShiftL选中所有匹配行CtrlX剪切多标签重叠同一图多个squirrel但ID错写为1,2...^([1-9]\d*)0将所有非0的class_id统一改为0松鼠唯一类别血泪经验曾因一个标签文件里混入0 0.5 0.5 0.0 0.0width0导致训练时loss_box突变为nan排查3小时才发现是某张图被误标为空框。现在我的训练前必跑校验脚本# validate_labels.py import glob for lbl in glob.glob(labels/**/*.txt): with open(lbl) as f: for i, line in enumerate(f): parts line.strip().split() if len(parts) ! 5: print(f{lbl}:{i} → wrong field count: {len(parts)}) try: x, y, w, h map(float, parts[1:]) if not (0x1 and 0y1 and 0w1 and 0h1): print(f{lbl}:{i} → coord out of [0,1]: {line.strip()}) except ValueError: print(f{lbl}:{i} → non-float value: {line.strip()})3.3 用LabelImg可视化验证拖拽式检查比代码更直观命令行校验是底线但最终要靠人眼确认。用labelImg开源GUI工具打开数据集能直观看到bbox是否贴合松鼠轮廓pip install labelImg labelImg # 启动后File → Open Dir → 选择 images/train/在界面中按W键切换到“Create RectBox”模式可手动绘制新框按CtrlU批量导入对应labels/train/中的.txt文件按↑↓键逐张浏览重点检查✓ 多松鼠场景是否每个都打了框常见漏标✓ 树枝遮挡松鼠时框是否只包住可见躯干而非拉大到包含树枝✓ 俯拍图像中松鼠呈小点状框是否过小YOLO对16×16像素目标检出率骤降玄学技巧在labelImg中按CtrlR可重置当前图的所有框配合Auto Save mode勾选Settings → Auto Save mode修改后自动覆盖原.txt比手写文本高效十倍。4. 训练避坑指南528张图上YOLOv8最常翻车的4个现场4.1 现象RuntimeError: DataLoader worker (pid XXX) is killed by signal: Bus error原因Linux系统下num_workers0时多进程读取小数据集易触发内存映射冲突尤其当batch_size设得过大如32而图像分辨率高1280×720时。解决在训练命令末尾加workers0Windows/macOS用户可忽略但Linux建议强制设为0yolo taskdetect modetrain modelyolov8n.pt datadataset.yaml epochs50 imgsz640 batch16 workers04.2 现象val/mAP50在0.2~0.3徘徊远低于预期原因未开启mosaic增强YOLOv8默认开启但若你修改了train.py或用了旧版配置可能关闭或close_mosaic10前10轮禁用mosaic导致早期学习不稳定。528张图本就少不用mosaic几乎无法泛化。解决确认dataset.yaml同级目录下无自定义train.py直接用CLI命令若仍低手动在ultralytics/cfg/default.yaml中检查# 确保这两项为true mosaic: 1.0 mixup: 0.1 # 可选加一点mixup提升鲁棒性4.3 现象训练中途CUDA out of memory即使batch4原因YOLOv8的imgsz参数影响显存占用呈平方关系640²409600像素 vs320²102400但更隐蔽的是val阶段默认用imgsz*1.2做验证即640→768显存峰值在此刻爆发。解决显式指定验证尺寸与训练一致yolo taskdetect modetrain modelyolov8n.pt datadataset.yaml epochs50 imgsz640 batch4 val_imgsz6404.4 现象best.pt推理时大量漏检尤其小松鼠50像素原因YOLOv8的strides[8,16,32]三级特征图最小stride8对应640/880像素理论上可检80×80以上目标但50像素松鼠落在stride16层640/1640已接近下限。解决启用multi-scale training多尺度训练让模型适应不同尺寸yolo taskdetect modetrain modelyolov8n.pt datadataset.yaml epochs50 imgsz640 batch16 multi_scaleTrue效果开启后每轮训练随机缩放输入尺寸如512, 576, 640, 704, 768迫使模型在stride8层学习小目标在stride32层学习大目标实测小松鼠召回率提升12%。5. 推理与部署从best.pt到可交付的松鼠检测API5.1 用CLI快速验证检测效果一行命令出结果图训练完成后runs/detect/train/weights/best.pt即为最优模型。用YOLOv8 CLI进行单图推理# 对单张图检测输出到 runs/detect/predict/ yolo taskdetect modepredict modelruns/detect/train/weights/best.pt sourceimages/val/000123.jpg saveTrue # 对整个val集批量推理生成 results.csv 和预测图 yolo taskdetect modepredict modelruns/detect/train/weights/best.pt sourceimages/val/ saveTrue save_txtTrue生成的runs/detect/predict/目录下000123.jpg会叠加绿色bbox与置信度标签。若想调整显示阈值默认0.25加参数yolo ... conf0.4 # 只显示置信度0.4的框参数说明conf置信度阈值与iouNMS IoU阈值是平衡精度与召回的核心杠杆。对松鼠这种易遮挡目标建议conf0.35减少误检、iou0.5允许部分重叠框共存。5.2 导出ONNX模型为嵌入式或Web部署铺路PyTorch模型.pt无法直接在边缘设备运行需转ONNX。YOLOv8内置导出功能yolo taskdetect modeexport modelruns/detect/train/weights/best.pt formatonnx opset12 dynamicTrue生成best.onnx可用Netron工具https://netron.app可视化网络结构。关键检查点输入节点名为imagesshape为[1,3,640,640]batch1, RGB, HW640输出节点名为output0shape为[1,84,8400]84nc414, 8400anchors数若需动态batch如Web API并发请求确保dynamicTrue此时输入shape为[None,3,640,640]。避坑ONNX导出后用onnxruntime验证输出一致性import onnxruntime as ort import cv2 import numpy as np sess ort.InferenceSession(best.onnx) img cv2.imread(images/val/000123.jpg) img cv2.resize(img, (640,640)) / 255.0 img img.transpose(2,0,1)[None] # [1,3,640,640] pred sess.run(None, {images: img.astype(np.float32)})[0] print(ONNX output shape:, pred.shape) # 应为 (1, 84, 8400)5.3 构建Flask API三步封装成HTTP服务将检测能力变成API供前端或IoT设备调用。创建app.pyfrom flask import Flask, request, jsonify from PIL import Image import io import numpy as np import cv2 from ultralytics import YOLO app Flask(__name__) model YOLO(runs/detect/train/weights/best.pt) # 加载训练好的模型 app.route(/detect, methods[POST]) def detect(): if image not in request.files: return jsonify({error: No image file}), 400 file request.files[image] img_bytes file.read() img Image.open(io.BytesIO(img_bytes)) # 转OpenCV格式并BGR→RGBYOLO需要RGB img_cv cv2.cvtColor(np.array(img), cv2.COLOR_RGB2BGR) # 推理conf0.4过滤低置信度 results model(img_cv, conf0.4) boxes results[0].boxes.xyxy.cpu().numpy() # [x1,y1,x2,y2] confs results[0].boxes.conf.cpu().numpy() classes results[0].boxes.cls.cpu().numpy() # 组装JSON响应 detections [] for i, (box, conf, cls) in enumerate(zip(boxes, confs, classes)): detections.append({ bbox: box.tolist(), confidence: float(conf), class: int(cls), label: squirrel }) return jsonify({detections: detections}) if __name__ __main__: app.run(host0.0.0.0, port5000, debugFalse) # 生产环境请用gunicorn启动服务pip install flask opencv-python ultralytics python app.py用curl测试curl -X POST http://localhost:5000/detect \ -F imageimages/val/000123.jpg \ | python -m json.tool # 格式化输出响应示例{ detections: [ { bbox: [424.1, 339.2, 658.7, 551.8], confidence: 0.872, class: 0, label: squirrel } ] }生产提示此API未加鉴权与限流实际部署需加flask-limiter防刷用gunicorn替代flask run提升并发并将模型加载移至全局变量避免每次请求重载。6. 进阶技巧用Grad-CAM可视化模型注意力定位松鼠检测的决策依据YOLO是黑匣子但你知道它到底在看松鼠的哪一部分吗是蓬松尾巴还是标志性的大耳朵用Grad-CAMGradient-weighted Class Activation Mapping可生成热力图直观显示模型关注区域。这对调试至关重要——比如发现模型总在树皮纹理上激活说明数据存在背景偏差。6.1 修改YOLOv8源码注入Grad-CAM钩子YOLOv8默认不暴露中间特征图需在ultralytics/models/yolo/detect/predict.py中添加钩子。找到Predictor类的preprocess方法后插入# 在Predictor.preprocess()末尾添加 self.features [] # 存储特征图 def hook_fn(module, input, output): self.features.append(output) # 注册到最后一层Detect的前一个Conv模块通常是model.model[-2] target_layer model.model.model[-2] # yolov8n: [-2]是最后一个Conv target_layer.register_forward_hook(hook_fn)然后在postprocess前用self.features[-1]获取特征图。但更稳妥的做法是使用现成库torchcampip install torchcam6.2 生成热力图的完整脚本# gradcam_squirrel.py import cv2 import numpy as np import torch from PIL import Image from ultralytics import YOLO from torchcam.methods import GradCAM from torchcam.utils import overlay_mask # 加载模型必须用ptonnx不支持梯度 model YOLO(runs/detect/train/weights/best.pt) model.model.eval() # 切换到eval模式 # 加载图像并预处理同YOLO内部流程 img_path images/val/000123.jpg img cv2.imread(img_path) img_rgb cv2.cvtColor(img, cv2.COLOR_BGR2RGB) img_tensor model.predictor.preprocess([img_rgb])[0] # [1,3,640,640] # 初始化Grad-CAM针对class0 cam_extractor GradCAM(model.model, model.22.cv2.2 if n in str(model.model) else model.22.cv2.2) out model.model(img_tensor) activation_map cam_extractor(out.squeeze(0).argmax().item(), out) # 叠加热力图到原图 result overlay_mask( Image.fromarray(img_rgb), Image.fromarray(activation_map[0].squeeze(0).cpu().numpy()), alpha0.5 ) result.save(gradcam_squirrel.jpg) print(Grad-CAM saved to gradcam_squirrel.jpg)关键参数说明model.22.cv2.2是YOLOv8n中最后一层卷积的模块名可通过print(model.model)查看alpha0.5控制热力图透明度值越小越淡若报错module not found用list(model.model.named_modules())打印所有模块名找Conv2d结尾的最后几层。6.3 解读热力图三个典型模式与优化方向生成gradcam_squirrel.jpg后你会看到红色高亮区域。对照原图分析热力图模式说明优化动作✅ 耳朵/尾巴高亮模型正确聚焦松鼠生物特征泛化性强保持当前数据增强可尝试加RandomPerspective提升姿态鲁棒性⚠️ 树干/草地大面积红模型把背景纹理当线索存在数据偏差用rembg库抠出松鼠前景重训或加Mosaic增强打乱背景❌ 无显著红区或全图泛红特征图饱和模型未学到有效表征检查学习率过大导致梯度爆炸或增加warmup_epochs5我的习惯每次新训完模型必跑一次Grad-CAM抽查3张图。如果连续2张图热力图都偏背景我会立刻停训回溯数据清洗环节——这比等50轮结束再调参省3天。希望帮到你。本文还有配套的精品资源点击获取
返回列表