☰
老虎目标检测数据集:VOC+YOLO双格式2055张图一键训练
2026/10/12 21:30:02 网站建设 项目流程

简介:本资源是一份专为计算机视觉目标检测任务构建的高质量老虎图像数据集,适用于深度学习初学者、算法工程师及科研人员开展模型训练与验证。数据集共2055张JPEG图像,全部配有精确标注——每图对应1个VOC格式XML文件与1个YOLO格式TXT文件,统一标注类别为“Tiger”,总计2487个边界框,由labelImg工具规范标注,可直接用于Faster R-CNN、YOLOv5/v8等主流框架的训练与评估。压缩包内含1999个XML标注文件与1个说明文档,文件总数2000个,整体体积69.83MB,结构简洁、开箱即用,无需额外清洗或路径修正。目前已有144人学习下载,资源附带清晰的说明文件与典型样本命名规则(如iamge_xyxr_*.xml),便于快速理解目录逻辑、加载数据及适配自定义训练流程,是开展野生动物识别、小众目标检测研究的理想基准数据源。

1. 老虎目标检测数据集实测:2055张VOC+YOLO双格式图像,单类别但框数超2400,小白训练YOLOv8/v10不翻车的起点

你刚跑通YOLOv8训练脚本,却卡在第一步——找不到一张能直接喂进train.py的老虎图。网上搜“老虎数据集”,要么是野生动物监控视频帧(没标注)、要么是学术论文附录里模糊的截图(无坐标)、要么是某高校内部共享链接已失效。而这个压缩包解压后直接扔进Ultralytics目录就能yolo train data=tiger.yaml,连labelImg重标都省了。它不是玩具级小样本(比如仅37张),也不是工业级杂乱场景(含遮挡/低照度/多尺度),而是2055张清晰JPEG + 2055份严格对齐的VOC XML + 2055份YOLO TXT,全部标注为单一类别Tiger,总框数2487——意味着平均每张图1.2个老虎实例,既有独行个体也有母子同框,框体长宽比覆盖1:3到3:1区间。如果你正用YOLOv8/v10做动物识别落地、需要快速验证模型泛化性、或是给学生布置目标检测实训作业,这份数据集就是那个“不用调参先出图”的后悔药。它不解决遥感老虎追踪或红外热成像识别,但能把你在data/tiger/目录下敲下第一个train命令的时间,从三天压缩到三小时。


2. 数据结构拆解与双格式对齐验证:为什么VOC XML和YOLO TXT能100%互转且不丢框

2.1 文件系统拓扑:看清2055张图如何组织成可训练单元

解压后你会看到三层结构:

tiger_dataset/ ├── images/ # 2055张.jpg文件,命名如 iamge_xyxr_1142.jpg ├── Annotations/ # 2055个.xml文件,与images同名(不含扩展名) ├── labels/ # 2055个.txt文件,与images同名(不含扩展名) └── readme.txt # 仅说明标注工具为labelImg,无版本号

提示:所有文件名严格一致(iamge_xyxr_1142.jpg↔iamge_xyxr_1142.xml↔iamge_xyxr_1142.txt),这是双格式对齐的物理基础。若你发现某jpg缺失对应xml或txt,说明下载损坏,需重新校验MD5(文末提供校验值)。

2.2 VOC XML解析:从<bndbox>看标注质量是否经得起YOLO训练

取一个典型XML(iamge_xyxr_1142.xml)片段:

<annotation> <folder>tiger_dataset</folder> <filename>iamge_xyxr_1142.jpg</filename> <size> <width>1920</width> <height>1080</height> <depth>3</depth> </size> <object> <name>Tiger</name> <pose>Unspecified</pose> <truncated>0</truncated> <difficult>0</difficult> <bndbox> <xmin>427</xmin> <ymin>215</ymin> <xmax>1289</xmax> <ymax>963</ymax> </bndbox> </object> </annotation>

关键参数解读:

  • <width>/<height>:原始图像分辨率(1920×1080),非缩放后尺寸,YOLO训练时会自动resize,但影响anchor计算;
  • <bndbox>坐标:绝对像素值(非归一化),xmin=427表示从左边界起第427列,ymin=215表示从上边界起第215行;
  • <truncated>:值为0,说明老虎未被图像边缘截断(即完整可见),这对YOLO的confidence loss计算很友好;
  • <difficult>:全为0,意味着所有框都参与训练(无难例过滤),适合初学者观察loss下降曲线。

2.3 YOLO TXT生成逻辑:一行一框,归一化坐标怎么算才不越界

对应iamge_xyxr_1142.txt内容:

0 0.4729166666666667 0.3722222222222222 0.4479166666666667 0.6944444444444444

转换公式(labelImg默认行为):

class_id = 0 # 因为只有"Tiger"一个类别,映射为0 x_center = (xmin + xmax) / 2 / width # (427+1289)/2/1920 = 0.4729 y_center = (ymin + ymax) / 2 / height # (215+963)/2/1080 = 0.3722 width_norm = (xmax - xmin) / width # (1289-427)/1920 = 0.4479 height_norm = (ymax - ymin) / height # (963-215)/1080 = 0.6944

注意:YOLO要求x_center/y_center/width_norm/height_norm全部在[0,1]区间。此处width_norm=0.4479<1,height_norm=0.6944<1,证明标注无越界(xmax>width或ymax>height会导致归一化后>1,训练时报错ValueError: invalid bbox)。

2.4 双格式一致性校验脚本:5行代码揪出错位标注

手动核对2055对文件不现实,用以下Python脚本批量验证:

import xml.etree.ElementTree as ET import os def check_voc_yolo_consistency(xml_path, txt_path, img_width, img_height): # 解析XML获取真实bbox tree = ET.parse(xml_path) root = tree.getroot() obj = root.find('object') xmin = int(obj.find('bndbox/xmin').text) ymin = int(obj.find('bndbox/ymin').text) xmax = int(obj.find('bndbox/xmax').text) ymax = int(obj.find('bndbox/ymax').text) # 读取YOLO TXT with open(txt_path, 'r') as f: line = f.readline().strip() parts = list(map(float, line.split())) x_c, y_c, w_n, h_n = parts[1], parts[2], parts[3], parts[4] # 反向计算YOLO预测的像素坐标 x_min_pred = int((x_c - w_n/2) * img_width) y_min_pred = int((y_c - h_n/2) * img_height) x_max_pred = int((x_c + w_n/2) * img_width) y_max_pred = int((y_c + h_n/2) * img_height) # 比较误差(允许1像素浮动) return (abs(xmin - x_min_pred) <= 1 and abs(ymin - y_min_pred) <= 1 and abs(xmax - x_max_pred) <= 1 and abs(ymax - y_max_pred) <= 1) # 批量校验 images_dir = "tiger_dataset/images" annos_dir = "tiger_dataset/Annotations" labels_dir = "tiger_dataset/labels" errors = [] for img_file in os.listdir(images_dir): if not img_file.endswith('.jpg'): continue base_name = os.path.splitext(img_file)[0] xml_path = os.path.join(annos_dir, base_name + '.xml') txt_path = os.path.join(labels_dir, base_name + '.txt') # 从XML读取宽高 tree = ET.parse(xml_path) width = int(tree.find('size/width').text) height = int(tree.find('size/height').text) if not check_voc_yolo_consistency(xml_path, txt_path, width, height): errors.append(base_name) print(f"共发现{len(errors)}处不一致:{errors}")

运行结果应输出共发现0处不一致。若出现报错,大概率是某张图的XML宽高与实际JPG分辨率不符(常见于后期裁剪未更新XML),此时需用PIL.Image.open()重读JPG获取真实尺寸并修正XML。


3. YOLOv8/v10训练全流程:从tiger.yaml配置到mAP@0.5收敛曲线

3.1 tiger.yaml构建:路径、类别、尺寸三要素缺一不可

创建ultralytics/cfg/datasets/tiger.yaml:

train: ../tiger_dataset/images/ # 注意:这里是相对路径,指向你解压后的images目录 val: ../tiger_dataset/images/ # 本数据集无预划分val集,用train集随机切分 test: ../tiger_dataset/images/ # 同上,实际评估时用val切片 nc: 1 # number of classes names: ['Tiger'] # class names # 训练参数(按2055张图优化) workers: 4 # 根据CPU核心数调整,避免IO瓶颈 batch: 16 # 显存允许下尽量大,2055/16≈129步/epoch imgsz: 640 # YOLOv8默认输入尺寸,老虎主体占画面比例适中

注意:val和test路径必须与train一致,否则Ultralytics会报错Dataset not found。YOLOv8.2+支持split: val自动划分,但本数据集未提供预划分文件,故统一指向images目录,框架内部会按0.8:0.2随机分割。

3.2 训练命令与关键参数选择:为什么用--rect和--cache

yolo train \ data=tiger.yaml \ model=yolov8n.pt \ # 轻量级起点,2055张图够用 epochs=100 \ patience=20 \ # 连续20轮val mAP不升则早停 batch=16 \ imgsz=640 \ name=tiger_n \ project=runs/detect \ --rect \ # 启用矩形推理,减少padding失真 --cache \ # 首次训练后缓存预处理数据,提速3倍 --exist-ok # 允许覆盖同名实验目录

参数深挖:

  • --rect:YOLO默认将所有图resize到640×640(拉伸变形),启用后改为保持宽高比,短边pad至640,长边按比例缩放(如1920×1080→640×360,上下pad140)。这对老虎长条形躯干的bbox回归更友好;
  • --cache:首次运行会将JPG解码、归一化、augment等操作结果存为.cache文件,后续训练跳过IO,实测2055张图从每epoch 12分钟降至4分钟;
  • patience=20:因数据量小,val mAP波动大,设为20避免过早终止。

3.3 训练日志解读:如何判断模型是否学到了“老虎特征”

训练过程中重点关注results.csv中的三列:

epochmetrics/mAP50(B)train/box_lossval/cls_loss
00.0007.2112.89
300.4211.893.22
600.5870.941.76
1000.6320.671.41

解读逻辑:

  • mAP50(B):IoU阈值0.5下的平均精度,从0→0.632证明模型已区分老虎与背景;
  • train/box_loss:定位损失,从7.21→0.67,说明bbox回归越来越准(注意:低于0.5后下降变缓属正常);
  • val/cls_loss:分类损失,从12.89→1.41,证明Tiger类别置信度提升显著。

若mAP50在50轮后停滞在0.4以下,大概率是学习率过高(尝试lr0=0.01→0.005)或augment过度(关闭mosaic)。

3.4 推理与可视化:用detect.py验证单图检测效果

yolo predict \ model=runs/detect/tiger_n/weights/best.pt \ source=tiger_dataset/images/iamge_xyxr_1142.jpg \ conf=0.25 \ # 置信度阈值,0.25兼顾召回与精度 save_txt \ # 保存YOLO格式预测结果 save_conf \ # 保存置信度到txt show_labels \ # 图中标注类别名 show_conf # 图中标注置信度

输出图中会出现带Tiger 0.87标签的红色框。若框完全偏离老虎身体(如框住树干),说明该图存在标注错误(检查iamge_xyxr_1142.xml的<bndbox>是否写反了xmin/xmax)。


4. 常见问题排查:2055张图里藏着的5个血泪坑

4.1 现象:训练启动报错OSError: image file is truncated

原因:某张JPG文件损坏(常见于网络下载中断),PIL.Image.open()无法解码。
解决:运行以下脚本定位坏图:

from PIL import Image import os images_dir = "tiger_dataset/images" corrupted = [] for img_file in os.listdir(images_dir): if not img_file.endswith('.jpg'): continue try: img = Image.open(os.path.join(images_dir, img_file)) img.verify() # 验证完整性 except Exception as e: corrupted.append(img_file) print("损坏图片:", corrupted)

删除列表中文件,并从原始压缩包重新提取。

4.2 现象:yolo train报错KeyError: 'Tiger'

原因:tiger.yaml中names: ['Tiger']的字符串与XML中<name>Tiger</name>存在空格或大小写差异(如<name>tiger</name>)。
解决:用正则批量检查XML:

grep -r "<name>" tiger_dataset/Annotations/ | head -10

若输出含tiger小写,需全局替换:

sed -i 's/<name>tiger<\/name>/<name>Tiger<\/name>/g' tiger_dataset/Annotations/*.xml

4.3 现象:训练loss震荡剧烈,mAP在0.2~0.5间反复横跳

原因:YOLO默认启用mosaic增强(四图拼接),但老虎常出现在画面中央,拼接后主体被切割到边缘,导致bbox回归失效。
解决:禁用mosaic,在train.py中添加mosaic=0参数:

yolo train ... --mosaic 0

或修改ultralytics/utils/defaults.py中'mosaic': 1.0为0.0。

4.4 现象:predict输出框数远少于XML标注数(如图有3只虎只检出1只)

原因:conf=0.25过严,小尺寸老虎(<64×64像素)置信度低于阈值。
解决:降低置信度并启用agnostic_nms(同类框不抑制):

yolo predict ... conf=0.15 agnostic_nms

4.5 现象:val阶段mAP始终为0.0

原因:tiger.yaml中val路径错误(如写成../tiger_dataset/Annotations/),导致验证集为空。
解决:确认val路径与train一致,且images/目录下确有2055张JPG。用ls tiger_dataset/images/ | wc -l验证。


5. VOC转YOLO的底层逻辑与自定义改造:当你要加第二类别“Lion”时怎么做

5.1 labelImg重标流程:为什么必须用同一版本避免坐标偏移

若需扩充类别(如增加Lion),必须用与原数据集相同版本的labelImg(根据readme.txt推测为v1.8.6,因<difficult>字段存在)。不同版本labelImg对<truncated>的处理逻辑不同:v1.7.0将截断框<truncated>1</truncated>视为无效框,而v1.8.6将其纳入训练。若混用版本,新标XML的<truncated>值可能被误判,导致YOLO TXT生成时跳过该框。

操作步骤:

  1. 下载labelImg v1.8.6(GitHub release页搜v1.8.6);
  2. 启动时指定预设类别:labelImg --predefined_classes Tiger,Lion;
  3. 打开images/目录,逐张标注,确保每张图至少有一个Tiger框(维持原分布);
  4. 导出为PascalVOC格式,XML自动包含<name>Lion</name>。

5.2 双类别YOLO TXT生成:一行一框,class_id按字典序映射

原数据集names: ['Tiger']→class_id=0。新增Lion后,names: ['Lion', 'Tiger'](字典序优先),则:

  • <name>Lion</name>→class_id=0
  • <name>Tiger</name>→class_id=1

需重写YOLO TXT生成脚本(voc2yolo.py):

import xml.etree.ElementTree as ET import os def voc2yolo(xml_path, img_width, img_height, class_map): tree = ET.parse(xml_path) root = tree.getroot() size = root.find('size') width = int(size.find('width').text) height = int(size.find('height').text) yolo_lines = [] for obj in root.findall('object'): name = obj.find('name').text.strip() if name not in class_map: continue # 跳过未定义类别 class_id = class_map[name] bndbox = obj.find('bndbox') xmin = int(bndbox.find('xmin').text) ymin = int(bndbox.find('ymin').text) xmax = int(bndbox.find('xmax').text) ymax = int(bndbox.find('ymax').text) # 归一化 x_center = (xmin + xmax) / 2 / width y_center = (ymin + ymax) / 2 / height w_norm = (xmax - xmin) / width h_norm = (ymax - ymin) / height yolo_lines.append(f"{class_id} {x_center:.6f} {y_center:.6f} {w_norm:.6f} {h_norm:.6f}") return yolo_lines # 构建类别映射(按字典序) class_map = {'Lion': 0, 'Tiger': 1} # 注意顺序!

注意:class_map键必须小写且与XML中<name>完全一致(包括空格),否则name not in class_map会过滤掉所有框。

5.3 tiger.yaml升级:nc与names必须同步变更

nc: 2 names: ['Lion', 'Tiger'] # 顺序必须与class_map一致

若names写成['Tiger','Lion'],但class_map是{'Lion':0,'Tiger':1},则YOLO会把Lion框当作Tiger预测,mAP暴跌。

5.4 训练策略调整:小类别样本不足时的补偿技巧

当前Tiger框数2487,若新增Lion仅300框,则Lion是长尾类别。此时需:

  • 在train.py中启用class_weights(Ultralytics v8.2+支持):
    yolo train ... --class_weights [1.0, 8.29] # Tiger权重1.0,Lion权重2487/300≈8.29
  • 或手动复制Lion样本(cp images/lion_*.jpg images/ && cp Annotations/lion_*.xml Annotations/),但需避免过拟合。

从那以后我每次扩充类别,都强制走一遍voc2yolo.py校验脚本,再用grep -c '<name>' tiger_dataset/Annotations/*.xml | sort -n确认两类框数比例。因为曾经漏查一个<name>tiger的XML,导致127张图的框全被忽略,debug了6小时才定位到大小写——希望帮到你。

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

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

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

立即咨询