资讯动态

野生动物目标检测数据集2.zip:YOLOv12训练与避坑指南

发布时间:2026/10/27 18:16:44 来源:尧图企业网站定制
简介这份野生动物目标检测数据集面向从事计算机视觉、生态监测与智能安防的开发者与研究人员提供可直接用于YOLO系列等主流检测框架训练的标准数据。数据集共1768张图片按训练集1240张、验证集355张、测试集173张划分覆盖熊、骆驼、鳄鱼、鹿、大象、长颈鹿、人类、豹、狮子、猴子、浣熊、老虎共12个类别标注为YOLO格式边界框与类别标签涵盖陆地、草原、森林等昼夜、遮挡、多角度自然场景。压缩包内共2000个文件以1768个txt标注文件、230个jpg图像为主另含1个yaml数据配置与1份docx说明文档整体约172.24MB目录结构清晰开箱即可接入训练流程。已有203人学习下载。资源同时包含野生动物与人类样本可支撑种群监测、反盗猎预警、动物行为分析及人兽冲突研究兼顾目标检测、分类与密度估计等多任务开发需求。1. 野生动物目标检测数据集2.zip一份能直接喂给 YOLOv12 的行业数据集如果你正在做野生动物监测、生态保护或者边缘端动物识别项目大概率卡在同一个地方公开数据集要么类别太粗只有“动物”一个大类要么标注格式跟 YOLO 对不上要么图片分辨率低到连物种都分不清。这份「野生动物目标检测数据集2.zip」就是冲着这个痛点来的——它是一份已经整理好的目标检测数据集标注格式适配 YOLO 系列包括 yolov12、yolov11 这些 ultralytics 生态的模型开箱即可用于训练和验证。适合三类人一是刚接触目标检测、想找一个真实行业数据集练手的新手二是需要快速验证模型在野生动物场景下表现的算法工程师三是做生态监测系统、需要本地化数据集做落地的从业者。下面我按“数据集里有什么 → 怎么转成 YOLO 能吃的格式 → 训练参数怎么设 → 坑在哪”这条线把这份资源拆开讲清楚。2. 数据集结构与 YOLO 标注格式先搞懂目录再动手2.1 野生动物数据集的典型目录长什么样拿到一个目标检测数据集压缩包第一件事不是急着解压训练而是先看目录结构。野生动物类数据集常见的组织方式有两种一种是按物种分文件夹每个文件夹下放原图和对应的标注文件另一种是标准的 images/labels 双目录结构train/val/test 各自独立。这份数据集属于后者也就是更接近 YOLO 官方推荐的组织形式。解压后你会看到类似这样的结构wildlife_dataset/ ├── images/ │ ├── train/ # 训练集图片jpg/png 混合 │ ├── val/ # 验证集图片 │ └── test/ # 测试集图片部分数据集可能没有 ├── labels/ │ ├── train/ # 与 train 图片一一对应的 txt 标注 │ ├── val/ │ └── test/ ├── data.yaml # 数据集配置文件定义路径和类别 └── classes.txt # 类别名称列表这里有个血泪经验很多人在解压后直接改 data.yaml 里的路径就开跑结果训练时提示找不到标签。原因往往不是路径写错而是 images 和 labels 的子目录名没有严格对应——比如 images 下是 trainlabels 下却是 training。YOLO 的默认逻辑是images替换成labels后路径必须完全一致差一个字母都不行。2.2 YOLO 标注格式的五个字段到底怎么读YOLO 格式的标注文件是每张图对应一个.txt每行代表一个目标框格式为class_id x_center y_center width height五个字段全部是归一化到 0~1 之间的浮点数。class_id从 0 开始计数对应classes.txt里的行号x_center和y_center是框中心点相对整张图宽高的比例width和height是框的宽高相对整张图宽高的比例。举个例子一张 640×480 的图里有一个框在左上角 (100, 80) 到 (300, 280)那么标注应该是0 0.3125 0.375 0.3125 0.4167计算方式x_center (100300)/2/640 0.3125y_center (80280)/2/480 0.375width (300-100)/640 0.3125height (280-80)/480 0.4167。注意如果你拿到的标注是 VOC 的 XML 或者 COCO 的 JSON必须先转成 YOLO txt 格式否则 ultralytics 的 YOLO 类会直接报错。转换脚本在下一节给。2.3 用脚本检查标注完整性在正式训练前我一般会跑一个检查脚本确认三件事图片和标注是否一一对应、标注值是否在 0~1 范围内、类别 id 是否超出 classes.txt 的行数。这个步骤能帮你提前排掉 80% 的训练报错。import os from pathlib import Path img_dir Path(wildlife_dataset/images/train) lbl_dir Path(wildlife_dataset/labels/train) num_classes 10 # 改成你 classes.txt 的实际行数 img_files {p.stem for p in img_dir.glob(*.*) if p.suffix.lower() in (.jpg, .png, .jpeg)} lbl_files {p.stem for p in lbl_dir.glob(*.txt)} # 检查图片和标注是否一一对应 missing_lbl img_files - lbl_files missing_img lbl_files - img_files print(f缺标注的图片数: {len(missing_lbl)}) print(f缺图片的标注数: {len(missing_img)}) # 检查标注值范围和类别 id bad_lines 0 for lbl in lbl_dir.glob(*.txt): for line in lbl.read_text().strip().splitlines(): parts line.split() if len(parts) ! 5: bad_lines 1 continue cid int(parts[0]) vals [float(v) for v in parts[1:]] if cid num_classes or any(v 0 or v 1 for v in vals): bad_lines 1 print(f异常标注行数: {bad_lines})这段脚本的逻辑很直白先用集合差集找出图片和标注的缺失对应关系再逐行读标注文件检查字段数是否为 5、类别 id 是否越界、归一化值是否在合法区间。参数num_classes必须和你的classes.txt行数一致否则会把合法类别误判为越界。跑完如果bad_lines为 0 且缺失数都是 0说明标注质量过关可以进入下一步。3. 从原始标注到 YOLOv12 可训练转换、划分与 data.yaml 配置3.1 如果你的标注不是 YOLO 格式VOC 转 YOLO 的完整脚本很多野生动物数据集原始标注是 Pascal VOC 的 XML 格式每个 XML 对应一张图里面记录了xmin/ymin/xmax/ymax和类别名。要喂给 YOLOv12必须先转成归一化的 txt。下面这个脚本我用了很多次处理几千张图没问题。import xml.etree.ElementTree as ET from pathlib import Path from PIL import Image voc_dir Path(wildlife_dataset/annotations_xml) out_lbl_dir Path(wildlife_dataset/labels/train) img_dir Path(wildlife_dataset/images/train) out_lbl_dir.mkdir(parentsTrue, exist_okTrue) classes [bird, mammal, reptile, amphibian, fish, insect] # 按你的实际类别改 class_to_id {c: i for i, c in enumerate(classes)} for xml_file in voc_dir.glob(*.xml): tree ET.parse(xml_file) root tree.getroot() img_name root.find(filename).text img_path img_dir / img_name if not img_path.exists(): continue w, h Image.open(img_path).size lines [] for obj in root.findall(object): cls_name obj.find(name).text.strip() if cls_name not in class_to_id: continue 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) x_center (xmin xmax) / 2 / w y_center (ymin ymax) / 2 / h bw (xmax - xmin) / w bh (ymax - ymin) / h lines.append(f{class_to_id[cls_name]} {x_center:.6f} {y_center:.6f} {bw:.6f} {bh:.6f}) if lines: (out_lbl_dir / f{xml_file.stem}.txt).write_text(\n.join(lines))逻辑说明脚本遍历 XML 目录用ElementTree解析每个文件读取图片实际宽高用 PIL 打开原图获取不要信 XML 里写的 size有些数据集标注的尺寸和实际图片不一致。然后对每个 object 取类别名和 bbox 坐标做归一化计算最后写入同名 txt。参数方面classes列表的顺序决定了 class_id必须和后续data.yaml里的names顺序完全一致否则模型学到的类别会错位。if cls_name not in class_to_id: continue这行是过滤掉不在你类别表里的标注避免越界。3.2 训练集/验证集划分别用随机划分野生动物数据有个特点同一只动物可能被连续拍摄多张或者同一场景下有多张相似图片。如果你用纯随机划分训练集和验证集里会出现几乎一样的图导致验证指标虚高实际部署时翻车。常见做法是按拍摄时段或场景做分组划分保证同一组图片只出现在训练集或验证集之一。如果数据集本身没有提供划分我一般用下面的脚本按 8:2 做分层抽样同时保证每个类别在验证集中至少出现一次import random from pathlib import Path from collections import defaultdict img_dir Path(wildlife_dataset/images/all) lbl_dir Path(wildlife_dataset/labels/all) val_ratio 0.2 random.seed(42) # 按主类别分组 cls_to_imgs defaultdict(list) for lbl in lbl_dir.glob(*.txt): first_line lbl.read_text().strip().splitlines()[0] cid int(first_line.split()[0]) cls_to_imgs[cid].append(lbl.stem) val_stems set() for cid, stems in cls_to_imgs.items(): random.shuffle(stems) n_val max(1, int(len(stems) * val_ratio)) val_stems.update(stems[:n_val]) train_stems set(cls_to_imgs_all : {s for stems in cls_to_imgs.values() for s in stems}) - val_stems print(f训练集: {len(train_stems)}, 验证集: {len(val_stems)})这段代码的核心是defaultdict(list)按类别聚合图片然后每个类别内部随机抽 20% 进验证集max(1, ...)保证小类别至少有一张进验证集。random.seed(42)是为了可复现你换成别的数字也行但一旦定了就不要改否则每次划分结果不同实验没法对比。3.3 data.yaml 的写法与路径陷阱YOLOv12 通过data.yaml找到图片和类别信息。一个标准的写法如下path: /home/user/wildlife_dataset train: images/train val: images/val test: images/test names: 0: bird 1: mammal 2: reptile 3: amphibian 4: fish 5: insect这里有几个容易踩的坑。第一path建议写绝对路径相对路径在不同工作目录下启动训练时会解析到不同位置导致找不到文件。第二train和val是相对于path的路径不是相对于 yaml 文件所在目录。第三names的键必须从 0 开始连续不能跳号否则 ultralytics 在计算类别数时会出错。第四如果你的数据集类别名有中文建议改成英文或拼音虽然 YOLOv12 本身支持但后续导出 ONNX 或部署到边缘设备时中文类别名容易出编码问题。提示改完 data.yaml 后先跑一次yolo detect train datadata.yaml modelyolov12n.pt epochs1做冒烟测试确认数据加载没问题再开正式训练。这一步能帮你省下大量排队等 GPU 的时间。4. 用 YOLOv12 训练野生动物检测模型参数、显存与常见报错4.1 环境配置与最小训练命令YOLOv12 属于 ultralytics 生态环境配置和 YOLOv8/YOLOv11 基本一致。我一般用 conda 建一个干净环境conda create -n wildlife python3.10 -y conda activate wildlife pip install ultralytics pip install torch torchvision --index-url https://download.pytorch.org/whl/cu121装完后用yolo checks确认 CUDA 和版本信息。如果输出里CUDA显示可用说明 GPU 环境没问题。接下来最小训练命令yolo detect train \ datawildlife_dataset/data.yaml \ modelyolov12n.pt \ epochs100 \ imgsz640 \ batch16 \ device0 \ projectruns/wildlife \ nameexp1参数逐个说modelyolov12n.pt是 nano 版本参数量最小适合先跑通流程imgsz640是输入分辨率野生动物图片如果目标较小可以提到 1280但显存占用会翻倍batch16在 8GB 显存上跑 640 分辨率基本安全如果 OOM 就降到 8 或 4device0指定第一块 GPU多卡用device0,1project和name决定权重和日志的保存位置。4.2 显存不够时的三个降级策略训练野生动物检测模型时显存不够是最常见的拦路虎。按优先级从高到低我一般这样处理第一降 batch size。这是最直接的手段从 16 降到 8 再到 4显存占用线性下降但训练稳定性会略差可以配合accumulate2做梯度累积来补偿。第二降 imgsz。从 640 降到 512 甚至 416显存占用按平方下降。但要注意野生动物图片里目标往往占比较小降分辨率会丢失小目标细节mAP 可能掉几个点。如果必须降建议先做一轮 640 的基线再对比 512 的结果。第三换更小的模型。yolov12n 已经是最小的了如果还 OOM可以考虑用yolov12n.pt配合freeze10冻结前 10 层只训练检测头显存占用会明显降低但精度上限也受限。# 梯度累积 降 batch 的组合写法 yolo detect train \ datawildlife_dataset/data.yaml \ modelyolov12n.pt \ epochs100 \ imgsz640 \ batch8 \ accumulate2 \ device0accumulate2表示每 2 个 batch 才更新一次梯度等效 batch size 是 16但显存只按 8 算。这个参数在显存紧张时非常实用代价是训练速度略慢。4.3 训练日志里该盯哪几个指标启动训练后控制台会输出一堆指标新手容易看花眼。我一般只盯四个box_loss、cls_loss、mAP50、mAP50-95。box_loss和cls_loss在前几个 epoch 应该持续下降如果震荡或者上升说明学习率太大或者数据有问题。mAP50是 IoU 阈值 0.5 时的平均精度mAP50-95是 0.5 到 0.95 多个阈值下的平均值后者更能反映模型的实际定位能力。如果box_loss降但mAP50不涨常见原因是标注框和实际目标偏差大或者验证集和训练集分布差异太大。这时候要回去检查标注质量而不是盲目加 epoch。如果cls_loss降不下去多半是类别不平衡——某些物种样本太少模型学不到特征。解决办法是对小类别做过采样或者在 loss 里加类别权重。注意YOLOv12 默认会在训练结束后自动跑一次验证输出best.pt和last.pt。best.pt是按验证集 mAP 选出的最优权重部署时用这个不要用last.pt。5. 避坑与排查野生动物数据集训练中最容易翻车的五件事5.1 现象训练 loss 正常但验证 mAP 始终为 0原因最常见的是data.yaml里names的顺序和标注文件里的 class_id 对不上。比如标注里 0 是 bird但 yaml 里 0 写成了 mammal模型学到的类别和验证时计算的类别完全错位mAP 自然为 0。另一个可能是验证集路径写错实际加载的是空目录。解决先用第 2.3 节的检查脚本确认标注类别 id 的范围再逐行核对classes.txt和data.yaml的names是否完全一致。然后手动打开验证集目录确认里面有图片和对应的 txt。如果路径没问题跑一次yolo detect val datadata.yaml modelbest.pt看输出如果提示No labels found就是路径或格式问题。5.2 现象训练到一半突然报 CUDA out of memory原因YOLOv12 在训练过程中会做数据增强mosaic、mixup 等某些 batch 增强后的图片尺寸或数量会临时增大导致显存峰值超过静态估算。另外如果imgsz设得高而batch没相应降也会在某个 epoch 触发 OOM。解决把batch降到原来的一半同时加accumulate2保持等效 batch size。如果还不行加cacheFalse关闭内存缓存或者设workers4减少数据加载进程的显存占用。长期方案是监控nvidia-smi的显存峰值按峰值而不是平均值来设 batch。5.3 现象小目标远处动物检测效果极差原因野生动物图片里远处的鸟或小型哺乳动物可能只占几十个像素。YOLOv12 默认的 640 分辨率下经过多次下采样后这些小目标在特征图上几乎消失。另外如果数据集中小目标样本占比低模型会偏向学习大目标。解决把imgsz提到 1280同时用yolov12m或yolov12l这类更大的模型它们的特征金字塔能保留更多小目标信息。数据层面可以用切片推理SAHI的思路把大图切成小块分别检测再合并。如果显存不允许提分辨率至少要把mosaic增强的概率调低因为 mosaic 会把四张图拼成一张进一步缩小每个目标。5.4 现象验证集指标很高但实际部署漏检严重原因训练时的验证集和实际部署场景分布不一致。比如验证集里动物都是白天拍摄、背景单一而部署场景有夜间红外、雨雾、遮挡等情况。另一个常见原因是验证集划分时没有按场景分组导致训练集和验证集有大量相似图片指标虚高。解决重新划分验证集确保它包含不同光照、不同背景、不同拍摄角度的样本。如果实际部署有红外图像验证集里必须也有红外样本。另外部署前用一批完全没参与训练的现场图片做一次独立测试这个结果才可信。5.5 现象标注文件里出现负坐标或大于 1 的值原因VOC 转 YOLO 时如果 bbox 的 xmin/xmax 超出了图片实际宽高标注员手误或图片被裁剪过归一化后就会出现负值或大于 1 的值。YOLOv12 对这类值不会直接报错但会当成异常框处理影响训练稳定性。解决在转换脚本里加一行 clamp 操作把归一化后的值限制在 [0, 1] 区间x_center max(0, min(1, x_center)) y_center max(0, min(1, y_center)) bw max(0, min(1, bw)) bh max(0, min(1, bh))同时统计被 clamp 的框数量如果超过总框数的 1%说明原始标注质量有问题需要回去核对标注源文件。6. 进阶技巧用切片推理和类别权重把野生动物检测再提一档训练跑通只是第一步真正落地时你会发现两个问题一是高分辨率图片里小目标漏检二是稀有物种样本太少导致召回率低。这两个问题在野生动物场景里特别突出因为拍摄距离远、物种分布长尾。下面两个技巧是我在实际项目里验证过有效的。先说切片推理。YOLOv12 的默认推理是把整张图缩放到 640 或 1280这对大图里的小目标不友好。切片推理的思路是把原图切成有重叠的小块每块单独检测再把结果合并回原图坐标。ultralytics 本身不直接支持但可以用sahi库或者自己写一个简单的切块函数from PIL import Image import numpy as np def slice_image(img_path, slice_size640, overlap0.2): img Image.open(img_path) w, h img.size step int(slice_size * (1 - overlap)) slices [] for y in range(0, h, step): for x in range(0, w, step): box (x, y, min(x slice_size, w), min(y slice_size, h)) crop img.crop(box) slices.append((crop, box)) return slices这段代码把原图按slice_size切块overlap0.2表示相邻块有 20% 重叠避免目标正好落在切割线上被截断。每个 crop 单独送进 YOLOv12 推理得到的框坐标加上box的偏移量就是原图坐标。最后用 NMS 合并重叠框。参数方面slice_size建议和训练时的imgsz一致overlap在 0.2~0.3 之间比较平衡太小会漏掉跨块目标太大则计算量翻倍。再说类别权重。野生动物数据集里鸟类可能有几千张而某些稀有哺乳动物只有几十张。直接训练的话模型会偏向多数类稀有类召回率很低。一个简单有效的做法是在 loss 里给小类别更高的权重。YOLOv12 本身不直接暴露类别权重参数但可以通过过采样实现类似效果——把稀有类别的图片在训练集中重复若干次让每个 epoch 里各类别出现的频率更均衡。import shutil from pathlib import Path from collections import Counter lbl_dir Path(wildlife_dataset/labels/train) img_dir Path(wildlife_dataset/images/train) oversample_dir Path(wildlife_dataset/images/train_oversampled) oversample_lbl Path(wildlife_dataset/labels/train_oversampled) oversample_dir.mkdir(parentsTrue, exist_okTrue) oversample_lbl.mkdir(parentsTrue, exist_okTrue) # 统计每个类别的图片数 cls_count Counter() for lbl in lbl_dir.glob(*.txt): for line in lbl.read_text().strip().splitlines(): cls_count[int(line.split()[0])] 1 max_count max(cls_count.values()) for lbl in lbl_dir.glob(*.txt): stem lbl.stem img next(img_dir.glob(f{stem}.*)) # 计算该图包含的稀有类别决定复制次数 cids [int(l.split()[0]) for l in lbl.read_text().strip().splitlines()] rare_cids [c for c in cids if cls_count[c] max_count * 0.3] repeat 3 if rare_cids else 1 for i in range(repeat): shutil.copy(img, oversample_dir / f{stem}_r{i}{img.suffix}) shutil.copy(lbl, oversample_lbl / f{stem}_r{i}.txt)逻辑说明先统计每个类别的标注框数量找出数量不到最大类 30% 的稀有类别。然后遍历所有标注文件如果某张图包含稀有类别就把它复制 3 份文件名加_r0、_r1、_r2后缀否则只复制 1 份。这样训练时稀有类别出现的频率会提高模型能学到更多特征。参数0.3和3可以根据你的类别分布调整原则是让最少类别的样本数达到最多类别的 1/3 以上。提示过采样后训练集图片数量会增加记得同步更新data.yaml里的train路径指向train_oversampled验证集保持原始分布不要过采样否则验证指标会失真。从那以后我每次拿到新的目标检测数据集都强制走一遍「检查标注 → 核对类别顺序 → 冒烟训练 → 看 loss 曲线」这四步再也没出现过训练到一半才发现类别对不上的情况。希望这份野生动物数据集和上面的流程能帮到你少走几个弯路。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑