尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

黑熊检测数据集:COCO转YOLO格式,1009张图训练全指南

黑熊检测数据集:COCO转YOLO格式,1009张图训练全指南 简介一套面向黑熊bear目标检测任务的数据集从COCO2017数据集中筛选并提取相关图像整理为可直接用于YOLO等主流检测算法的标准格式。压缩包共3028个文件大小约214.28MB其中包含1009张jpg原图、1009个xml标注文件以及1010个txt标注文件。txt标签内包含类别与目标框坐标适合YOLO系列直接读取xml标签采用VOC格式记录图像尺寸与目标位置便于在Faster R-CNN、SSD等框架中灵活切换。两种标注格式各有侧重免去开发者自行编写转换脚本的麻烦。数据集类别统一为bear图片源自真实场景尺寸与背景多样适合目标检测初学者练习单类别检测也可用于算法效果对比或补充缺少黑熊样本的项目数据。目前已有155人学习资源按原图与标签分类存放结构清晰下载解压后即可快速接入常见检测流程。1. 黑熊检测数据集1009张图、txtxml双格式拿来就能训这份黑熊检测数据集是我见过比较省事的野生动物检测训练素材。它从COCO2017里把bear这一类全部抽出来图片还是COCO原始的jpg文件标注则单独转成了txt和xml两种格式数量1009张类别名统一叫bear。也就是说你不用再写转换脚本、不用自己爬图下载解压后按YOLO的目录要求摆好改一下data.yaml就能开训。适合这几类人第一次跑YOLO目标检测、想用现成数据走通全流程的新手做野生动物监测、熊类识别项目但缺标注数据的从业者以及想验证YOLOv5或YOLOv8在自己显卡上效果如何的玩家。下面我从文件结构、标签格式、训练参数到踩坑记录把这套数据从头到尾拆给你看。2. 数据文件与标注格式COCO原始标注如何落成bear标签2.1 从文件名到目录先搞清这份数据长什么样解压后你会看到大量类似000000091844.jpg这种命名的图片这是COCO官方的补零命名法12位数字编号不需要也没必要改名。图片全部来自COCO2017的train2017和val2017数据集作者已经按bear类过滤好了所以直接看内容就是各种场景下的熊树林里的、雪地里的、远处的、近景的光照和遮挡情况都比较丰富。目录组织一般长这样bear_dataset/ ├── images/ │ ├── train/ │ │ ├── 000000091844.jpg │ │ └── ... │ └── val/ │ ├── 000000361341.jpg │ └── ... ├── labels/ │ ├── train/ │ │ ├── 000000091844.txt │ │ └── ... │ └── val/ │ └── ... └── annotations/ ├── bear_train.xml └── bear_val.xmlimages和labels是按train/val子目录对应的txt和jpg文件名一致这是YOLO系工具默认的读取方式。如果你拿到的压缩包不是这个结构也简单自己写两行脚本按文件名前缀归类就行。要特别注意图片和标签文件名必须严格同名后缀可以不同但主名一旦对不上训练时会直接跳过这张图而且不报错这个我后面避坑章节会细讲。2.2 txt与xml两种标签格式的字段对照同一份标注为什么给两种格式因为不同工具链吃的格式不一样。YOLO系列v5/v8原生读txt每行一个目标而VOC系的工具、部分可视化脚本和标注平台只认xml。下面这张表能把两种格式的差异看清楚项目YOLO txtVOC xml文件后缀.txt.xml坐标基准归一化范围0~1像素绝对值目标格式每行一个目标object块类别表示类别id数字类别名字符串中心点写法x_center y_center左上角右下角xmin ymin xmax ymax适用场景YOLO训练、推理预处理数据可视化、VOC工具链、二次标注txt的每一行固定是五个数顺序是类别id、中心点x、中心点y、框宽、框高。这五个数全部除以图片宽高做了归一化所以无论原图是1920还是640训练时都不用管绝对像素。xml则是标准的PASCAL VOC结构name标签里写的是bear这个字符串bndbox里是四个绝对像素坐标。你如果要做样本校验或者框可视化xml读起来更直观如果要喂给YOLOtxt更直接。这份数据集最省事的地方在于你不需要从零写转换器两种格式都给你备好了。但我的建议是训练用txt可视化检查用xml各取所长。2.3 COCO json转YOLO txt一个可复用的转换脚本虽然这份数据已经转好了但实际项目中你大概率还要往数据里补充自己的熊类图片那就要自己写转换。我从COCO官方json里抽取bear类并转成YOLO txt的脚本如下直接可跑import json import os from pathlib import Path def coco_to_yolo(coco_json, img_dir, out_label_dir, cat_names[bear]): with open(coco_json, r) as f: coco json.load(f) # 建立category名称 - 新id的映射这里只有bear一种新id恒为0 cat_id_map {} target_ids set() for cat in coco[categories]: if cat[name] in cat_names: target_ids.add(cat[id]) cat_id_map[cat[id]] 0 # 单类统一映射到0 if not target_ids: raise ValueError(没有找到目标类别) # 先按image_id建索引 img_info {img[id]: img for img in coco[images]} anns_by_img {} for ann in coco[annotations]: if ann[category_id] not in target_ids: continue image_id ann[image_id] if image_id not in anns_by_img: anns_by_img[image_id] [] anns_by_img[image_id].append(ann) os.makedirs(out_label_dir, exist_okTrue) for image_id, anns in anns_by_img.items(): img img_info[image_id] img_path os.path.join(img_dir, img[file_name]) if not Path(img_path).exists(): continue w, h img[width], img[height] txt_path os.path.join(out_label_dir, Path(img[file_name]).stem .txt) lines [] for ann in anns: cx, cy, bw, bh ann[bbox] # coco的bbox是[x, y, width, height] # 转成归一化坐标并做边界裁剪 x_center max(0.0, min(1.0, (cx bw / 2) / w)) y_center max(0.0, min(1.0, (cy bh / 2) / h)) box_w max(0.0, min(1.0, bw / w)) box_h max(0.0, min(1.0, bh / h)) lines.append(f0 {x_center:.6f} {y_center:.6f} {box_w:.6f} {box_h:.6f}) with open(txt_path, w) as f: f.write(\n.join(lines)) coco_to_yolo(instances_train2017.json, train2017, labels_train)这段脚本的核心是三个步骤先建类别映射把COCO原始的category_id统一改成新编号0再遍历所有标注只保留目标类别最后把COCO的[x, y, width, height]格式换算成YOLO的[x_center, y_center, width, height]并除以图片宽高。参数说明coco_json是COCO的标注文件路径img_dir是图片目录out_label_dir是txt输出目录cat_names传你想提取的类别名列表默认只取bear。注意COCO的bbox坐标是左上角起点不是中心点很多新手在这里翻车换算时要记得加上宽高的一半。xml的生成逻辑其实类似只是要拼VOC的XML结构用xml.etree.ElementTree就能写。这部分的重点只有一个坐标不要除错。COCO的宽高和YOLO的宽高都指框本身但COCO是像素值YOLO是比例值换算时分子分母都必须来自同一张图片的实际宽高。3. 用YOLOv5训练黑熊检测目录组织、配置与训练命令3.1 数据集目录与data.yaml配置拿到了txt标签和jpg图片接下来把它们组织成YOLOv5能直接读的格式。我一般会在YOLOv5项目根目录下新建一个bear_data文件夹然后把数据集按下面的目录结构摆放bear_data/ ├── images/ │ ├── train/ │ └── val/ ├── labels/ │ ├── train/ │ └── val/ ├── bear.yaml └── test/train和val的比例官方默认是--train和--val两个参数分开指定没有强制比例。我建议按9:1或8:2划1009张图不算多验证集留100张左右就够看效果留太多训练数据会不够用。划分时用随机抽样但要注意同一个场景的连续帧最好别同时出现在train和val里否则你的验证分数会偏乐观。然后写数据集配置文件bear.yaml# bear.yaml train: bear_data/images/train val: bear_data/images/val nc: 1 names: [bear]这里nc表示类别数量黑熊检测只有bear一类所以是1。names列表里的顺序必须和txt标签里的类别id对应因为我们的txt里全部写的是0所以names的第一位就是bear。如果你的标签里出现了1、2这样的id说明类别数不止一个这个后面避坑部分会再说。注意YOLOv5里路径可以写绝对路径也可以写相对于项目根目录的路径但不要用~/这种符号容易解析出错。3.2 训练命令与关键参数配置写好后直接用train.py启动训练python train.py \ --data bear_data/bear.yaml \ --weights yolov5s.pt \ --img 640 \ --batch 16 \ --epochs 200 \ --workers 4 \ --project runs/bear_train \ --name exp1命令行参数说明如下--data指向刚写的yaml文件--weights填预训练权重这里用yolov5s.pt如果你的显卡显存小于6G可以换yolov5n.pt精度略降但显存占用少一半--img是训练分辨率640是默认值COCO原图大多在500到800像素之间640不需要改--batch根据显存调整8G显存跑16没问题8G以下建议降到8--epochs在数据量少时拉长到200甚至300因为单类检测收敛快但更多epoch有助于稳定--workers是数据加载线程数Windows下建议设成0否则容易报DataLoader worker错误。训练过程中重点看两个东西一是loss曲线是不是持续下降二是每个epoch结束时的mAP0.5有没有明显爬升。如果跑了50个epoch mAP还是零先别怪数据大概率是标签出了问题跳去第4章排查。3.3 迁移学习的作用1009张图怎么训出稳定模型1009张图对目标检测来说不算多尤其是熊这种在画面中占比变化极大的目标直接从头训练很容易过拟合。这里的关键是迁移学习COCO预训练权重里本来就见过bear这个类COCO 80类包含bear换句话说模型已经知道熊长什么样我们做的只是在熊的子集上微调。我用yolov5s实测下来预训练权重起训前50个epoch mAP就会快速爬升到0.8以上而随机初始化从头训的话50个epoch可能还在0.5附近挣扎。如果你的场景不是纯黑熊而是需要区分棕熊、黑熊、北极熊那建议把nc改成对应类别数并重新整理txt标签模型仍能利用预训练权重里的通用特征。另外一个很实用的小技巧显存不足时可以打开--multi-scale参数让YOLO在训练时随机使用0.5到1.5倍的分辨率缩放。这个参数对1000张量级的小数据集特别有帮助相当于免费做了多尺度数据增强能明显缓解小目标熊漏检的问题代价是训练速度下降约两三成。4. 避坑黑熊数据训练中的五个常见问题4.1 类别id错位训练不报错但mAP一直为零现象训练过程正常loss也在降但每个epoch的mAP都是0验证集一张熊都检测不出来logs里还偶尔出现Target is out of bounds的警告。原因COCO原始标注里bear的category_id是22按COCO的80类编号有人顺手把这个22直接写进了txt。但你的yaml里nc: 1模型只认为有类别0于是id22的标签要么越界被丢弃要么被强行当成背景处理模型根本学不到有效目标。解决把数据集里所有txt的第一列强制改成0用一条命令搞定sed -i s/^[0-9]* /0 / labels/train/*.txt。或者回到转换脚本在写txt前统一做cat_id_map[ann[category_id]] 0。我拿到任何数据集的第一件事就是抽查3到5个txt文件看类别id有没有超出nc-1范围。4.2 图片无对应标签导致训练中断或loss异常现象训练跑到一半报assert ... labels.shape (n, 5)错误或者某几个epoch loss突然变成nan。原因COCO2017里并不是每张含有bear的图都有有效的bear标注有些图里的熊被严重遮挡标注时被过滤掉了于是出现了只有jpg没有txt的情况。YOLOv5在做数据加载时会读取同名的txt发现文件不存在或内容为空就会在缓存里报错。解决训练前先做一次标签完整性检查用脚本把所有只有图片没有txt的文件剔除from pathlib import Path for split in [train, val]: img_dir Path(fbear_data/images/{split}) lbl_dir Path(fbear_data/labels/{split}) for img in img_dir.glob(*.jpg): txt_path lbl_dir / (img.stem .txt) if not txt_path.exists() or txt_path.stat().st_size 0: img.unlink() print(fremoved {img.name})检查完再删除runs目录下的缓存文件重新训练。这一步对从COCO提取的子集特别重要COCO官方标注里有不少空标注或极端尺寸的框不清理干净迟早会咬你一口。4.3 小目标熊检测不到现象验证集mAP0.5能到0.9但你拿一张熊在画面远处、占比很小的图去推理结果什么都没框出来。原因1009张图里大尺度的熊占多数模型对中小目标的召回率天然偏低。另外YOLOv5默认的anchor是基于COCO整体统计出来的对“熊占画面比例极小”的场景并不适配。解决训练时加上--multi-scale做多尺度训练推理时把--img从640提到960或1280小目标特征会更明显。还可以在训练后跑一次python utils/anchors.py --data bear_data/bear.yaml --img-size 640重新聚类anchor把默认anchor换成基于你数据集统计的尺寸对这张图集实际效果很明显。4.4 验证集loss反复震荡现象训练曲线里验证集loss像锯齿一样上下跳动训练集loss却稳定下降mAP波动幅度超过5个点。原因1009张图按9:1划分后验证集只有100来张样本方差太大每个epoch抽到的验证batch质量各不相同loss自然会震荡。另一个常见原因是学习率太高默认的0.01在数据量小时偏激进。解决把验证集比例提高到20%大约200张同时把--lr0降到0.005或0.001。loss震荡本身不可怕可怕的是你看不出趋势所以建议用TensorBoard观察val loss的滑动平均而非原始曲线。200张验证图放在1000张的量级上既不影响训练也能让评估指标稳定不少。4.5 黑熊棕熊的命名混淆现象你下载这份数据是想做黑熊检测但翻开图片发现里面棕熊、黑熊都有有的图连熊都分不清品种标签统一叫bear。原因COCO2017的bear类别本身没有细分亚种所有熊科动物都归在bear这一个类下。数据集名字虽然叫黑熊检测但标注是COCO原生的没有做品种重标注。解决如果你只要黑熊我的建议是用这份数据做预训练然后准备一两百张纯黑熊图片微调或者用主动学习筛选出黑熊样本重新标注。如果你要同时区分黑熊、棕熊、北极熊那这份数据只能提供通用熊类特征需要你把标签细分后重训别指望拿来即用。5. 验证与进阶从mAP到误检分析的完整闭环5.1 用val.py跑一次评估看懂Precision、Recall与mAP训练结束后光看训练日志不够我会单独用val.py在验证集上正经跑一次评估python val.py \ --data bear_data/bear.yaml \ --weights runs/bear_train/exp1/weights/best.pt \ --img 640 \ --batch 16 \ --conf-thres 0.001 \ --iou-thres 0.5按上面的参数跑完终端会输出Precision、Recall、mAP0.5、mAP0.5:0.95四行数据。怎么解读Precision是模型框出来的目标里真正是熊的比例Recall是真实熊里被框出来的比例两者在conf阈值变化时此消彼长。mAP0.5是IoU阈值0.5下的平均精度做工程落地主要看这个mAP0.5:0.95是更严格的指标对框的位置精度敏感适合用来调优但不作为业务验收标准。单类检测时mAP0.5大于0.9属于正常水平0.8到0.9说明可用但有小幅误检低于0.8就要回头查数据了。我把conf阈值设为0.001而不是默认的0.25是为了把低置信度预测也纳入评估这样能看清模型的完整召回能力。想省事的话直接python val.py --data bear_data/bear.yaml --weights best.pt跑默认参数也行但低阈值跑出来的指标更有参考价值。5.2 混淆矩阵与误检分析不止看mAPmAP只是一个数字真正告诉你模型哪里不行的是混淆矩阵。训练完在runs/bear_train/exp1/目录下会生成confusion_matrix.png单类检测时重点看两类一是bear这一类别的召回率二是background类别被预测成bear的比例。背景误检率超过10%时说明模型把树桩、岩石、深色衣物当成了熊这在野生动物监控场景里很致命。我的习惯是再从验证集里抽三四十张图用detect.py批量推理保存结果然后人工翻一遍python detect.py \ --weights runs/bear_train/exp1/weights/best.pt \ --source bear_data/images/val \ --img 640 \ --conf 0.25 \ --save-txt \ --save-conf--save-txt会把推理结果存成txt方便你对比预测框和真实框的差异--save-conf会附上每个框的置信度。翻图时重点找两类问题熊被框成两半的说明NMS后处理没合并好以及背景被框出来的说明模型学到的特征里混入了环境纹理。这些人工分析比盯着mAP看要实在得多也是数据集后续扩充时的方向指引。5.3 数据增强与多尺度有限数据下的稳定性1009张图训一个单类检测器数据增强就不是锦上添花而是必要手段。YOLOv5训练时默认开启了mosaic、random_perspective、hsv_augment等增强这些配置在hyp.scratch.yaml里。我在这个数据集上会把mosaic的mosaic_scale从默认的0.5到1.5改成0.3到1.8让熊在拼接图里的尺寸变化更大对远近尺度不同的熊更友好。如果训练环境显存够大12G以上我推荐把--img设成800而不是640。这个数据集里的熊很多是远距离拍摄占画面比例小800分辨率下小目标对应的像素区域更大训练出来的模型在实际检测中更稳。代价是训练速度下降约40%但1000张图的体量多跑半小时换来几个点的mAP提升我认为是划算的。数据增强参数不建议一次改太多。先只开--multi-scale跑一个对比组再改mosaic参数跑一个对比组用验证集指标决定去留。这个数据集体量小一个epoch就一两分钟多跑几个对比实验的成本很低但你能清楚地知道每个增强手段到底贡献了多少。6. 训练前先做标签可视化一个能省一天排错时间的小习惯前面说了这么多有一个动作我强烈建议你每次拿到新数据集都做一遍把txt标签画回图片上看一眼。很多人标签格式对不对、坐标有没有除错直到训练完才发现然后回去查转换逻辑一天就没了。标签可视化只要十几行代码却能提前暴露绝大多数标注问题import cv2 def draw_yolo_boxes(img_path, txt_path, class_names[bear]): img cv2.imread(img_path) h, w img.shape[:2] with open(txt_path, r) as f: lines f.readlines() for line in lines: parts line.strip().split() cls_id, cx, cy, bw, bh int(parts[0]), float(parts[1]), float(parts[2]), float(parts[3]), float(parts[4]) x1 int((cx - bw / 2) * w) y1 int((cy - bh / 2) * h) x2 int((cx bw / 2) * w) y2 int((cy bh / 2) * h) cv2.rectangle(img, (x1, y1), (x2, y2), (0, 0, 255), 2) cv2.putText(img, class_names[cls_id], (x1, y1 - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2) cv2.imshow(label check, img) cv2.waitKey(0) cv2.destroyAllWindows() draw_yolo_boxes(bear_data/images/train/000000091844.jpg, bear_data/labels/train/000000091844.txt)这段代码将归一化的中心点坐标还原成像素坐标画框并标注类名按空格键逐张翻图。检查重点是框是否紧贴熊的身体而不是只框了头或半个身子是否存在大量宽高比异常的长条框以及标签值和图片内容是否对得上。我一般随机抽20到30张覆盖远景、近景、遮挡几种情况全部正常才启动训练。从那以后我拿到任何数据集的第一件事都是先可视化标签再谈训练。这个习惯帮我避掉过类别id写错、坐标用成了像素值没归一化、txt和jpg文件名后缀不匹配等至少五种问题每次省下的都是实打实的半天时间。希望你能把这套数据集玩明白也把这个检查习惯带进自己的项目里希望帮到你。本文还有配套的精品资源点击获取
返回列表