资讯详情

资讯详情

智慧牧场牛羊检测数据集3538张:VOC/YOLO/JSON三种标签格式选型与训练实战

简介这份智慧牧场牛羊检测数据集面向从事目标检测学习、课程作业、学科设计、竞赛及实际项目开发的人员聚焦牛、羊两类家畜的识别与计数需求可服务于智慧农场系统、牛羊群检测计数等场景。数据集共3538张图片分布均匀、标注精准、背景丰富算法拟合效果较好标签同时提供vocxml、yolotxt与json三种格式主流目标检测算法可直接接入训练。压缩包内文件总数约2000个以jpg图像、xml标注、txt标签及json文件为主整体约706.2MB目录结构清晰便于按格式快速取用。目前已有473人学习下载。对于需要高质量家畜检测数据的研究者与开发者而言该资源省去自行采集与标注成本可直接用于模型训练、对比实验与项目落地验证是较为省心的数据基础。1. 智慧牧场牛羊检测数据集3538 张三种标签格式到底怎么选牧场里装了几路摄像头想数牛、找走失的羊、判断栏舍里有没有异常聚集第一道坎往往不是模型而是数据。你手里可能已经有一段监控视频也可能刚拿到一批标注好的图片但打开压缩包一看voc 的 xml、yolo 的 txt、json 三种标签各一份3538 张图到底该用哪套、怎么切分、怎么喂给训练脚本这就是「智慧牧场-牛羊检测数据集-3538张-含voc(xml)yolo(txt)json三种格式标签」这个标题真正要解决的问题。它适合三类人一是做畜牧智能化、想快速验证牛羊检测可行性的算法同学二是接了牧场项目、需要拿现成标注数据先跑通 baseline 的工程同学三是手里有数据但被格式转换卡住、不确定 voc 和 yolo 差异的开发者。三种格式不是让你全用而是对应不同训练框架和下游任务Pascal VOC 的 xml 偏通用标注交换yolo 的 txt 直接对接 Darknet/Ultralytics 系训练json 更适合做数据管理、可视化或转 COCO。选错格式不会报错但会让你在类别映射和坐标换算上多花半天。下面按「先认清格式 → 再动手转换与训练 → 最后避坑」的顺序讲透。2. 三种标签格式的差异与选型xml、txt、json 各自适合谁2.1 VOC xml 的结构与读取方式Pascal VOC 格式用一张图对应一个 xml 文件核心节点是filename、size、object。每个object里有name类别名、bndboxxmin/ymin/xmax/ymax绝对像素坐标。它的好处是可读性强、工具链老牌LabelImg 默认就导出这个。缺点是文件多、解析慢训练框架一般不直接吃 xml需要先转。import xml.etree.ElementTree as ET def parse_voc(xml_path): tree ET.parse(xml_path) root tree.getroot() size root.find(size) w int(size.find(width).text) h int(size.find(height).text) boxes [] for obj in root.iter(object): cls obj.find(name).text 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) boxes.append((cls, xmin, ymin, xmax, ymax)) return w, h, boxes这段代码把 xml 里的宽高和每个框读出来。注意size节点必须存在有些标注工具会漏写读不到就会NoneType报错。类别名建议先做一次全量统计确认牛羊两类没有写成「cow」「牛」「cattle」混用否则后面映射会乱。2.2 YOLO txt 的归一化坐标与类别索引YOLO 格式每张图对应一个 txt每行是class_id x_center y_center width height全部是相对图像宽高的归一化值0~1。它没有类别名字段类别靠一个classes.txt或data.yaml里的names列表按索引对应。这是训练时最省事的格式Ultralytics 的 YOLOv8/v11 直接读。def voc_to_yolo(w, h, boxes, class_map): lines [] for cls, xmin, ymin, xmax, ymax in boxes: cid class_map[cls] xc (xmin xmax) / 2.0 / w yc (ymin ymax) / 2.0 / h bw (xmax - xmin) / w bh (ymax - ymin) / h # 裁剪到 [0,1]防止标注越界导致训练报错 xc, yc min(max(xc, 0), 1), min(max(yc, 0), 1) bw, bh min(max(bw, 0), 1), min(max(bh, 0), 1) lines.append(f{cid} {xc:.6f} {yc:.6f} {bw:.6f} {bh:.6f}) return linesclass_map必须固定比如{cow:0, sheep:1}。归一化前一定要用原图真实宽高不要用缩放后的尺寸否则框会整体偏移。裁剪那两行是血泪经验标注时手抖画出边界不裁剪训练时可能直接抛异常或产生无效框。2.3 json 标签的用途与转换场景json 格式没有唯一标准常见的是 COCO 风格的images/annotations/categories三段式也有每图一个 json 的简单结构。它最大的价值是方便做数据统计、可视化、和 COCO 生态对接。如果你要做实例分割或后续接多模态分析json 更容易扩展字段。import json def load_coco_json(json_path): with open(json_path, r, encodingutf-8) as f: data json.load(f) img_map {img[id]: img for img in data[images]} cat_map {c[id]: c[name] for c in data[categories]} records [] for ann in data[annotations]: img img_map[ann[image_id]] records.append({ file: img[file_name], w: img[width], h: img[height], cls: cat_map[ann[category_id]], bbox: ann[bbox] # COCO 是 [x,y,w,h] 左上角宽高 }) return records注意 COCO 的 bbox 是[x_min, y_min, width, height]和 VOC 的[xmin,ymin,xmax,ymax]不一样转换时最容易在这里翻车。json 文件用什么打开都行但别用记事本硬看大文件用json.load或编辑器格式化更稳。2.4 选型建议按训练框架和下游任务决定格式坐标类别适合场景VOC xml绝对像素字符串名标注交换、老工具链YOLO txt归一化索引Ultralytics/Darknet 训练json视标准视标准数据管理、COCO 对接、可视化如果你只是要跑 YOLO 检测直接用 txt如果要做数据分析或转 COCO用 jsonxml 留作备份和人工核对。三种格式同源时先确认它们标注是否一致别默认完全等价。3. 从零跑通牛羊检测目录组织、转换脚本与训练命令3.1 数据集目录该怎么摆不管用哪种格式训练前都要把目录固定下来。常见做法是dataset/ images/ train/ val/ labels/ train/ val/ classes.txt data.yamlimages/train和labels/train里的文件名必须一一对应只是后缀不同.jpg 对 .txt。如果原始数据是 xml先批量转成 txt 再按 8:2 或 7:3 切分。切分要按图切不能按框切否则同一张图的框会分散到训练和验证集造成泄漏。import os, random, shutil def split_dataset(img_dir, lbl_dir, out_root, ratio0.8): files [f for f in os.listdir(img_dir) if f.endswith((.jpg,.png))] random.seed(42) random.shuffle(files) n int(len(files) * ratio) for phase, subset in [(train, files[:n]), (val, files[n:])]: for f in subset: stem os.path.splitext(f)[0] shutil.copy(os.path.join(img_dir, f), os.path.join(out_root, images, phase, f)) shutil.copy(os.path.join(lbl_dir, stem .txt), os.path.join(out_root, labels, phase, stem .txt))random.seed(42)保证每次切分一致方便复现。如果某张图没有对应 txtshutil.copy会直接报错这其实是好事能帮你发现漏标。3.2 批量转换脚本与类别映射把 xml 批量转 yolo关键是先扫一遍所有类别名生成固定映射。import os, glob from xml_parser import parse_voc, voc_to_yolo # 前面定义的函数 def build_class_map(xml_files): names set() for x in xml_files: _, _, boxes parse_voc(x) for b in boxes: names.add(b[0]) return {n: i for i, n in enumerate(sorted(names))} def convert_all(xml_dir, out_lbl_dir, class_map): os.makedirs(out_lbl_dir, exist_okTrue) for x in glob.glob(os.path.join(xml_dir, *.xml)): w, h, boxes parse_voc(x) lines voc_to_yolo(w, h, boxes, class_map) stem os.path.splitext(os.path.basename(x))[0] with open(os.path.join(out_lbl_dir, stem .txt), w) as f: f.write(\n.join(lines))sorted(names)让类别索引稳定避免每次运行顺序不同。转换完一定要抽查几张用可视化脚本把框画回图上确认没有整体偏移或镜像。3.3 data.yaml 与训练命令Ultralytics 系训练需要data.yamlpath: /abs/path/dataset train: images/train val: images/val names: 0: cow 1: sheep然后一条命令开跑yolo detect train modelyolov8n.pt datadata.yaml epochs100 imgsz640 batch16imgsz640是常见起点牛羊目标通常较大640 够用如果远景小目标多可以上 960 但显存翻倍。batch16按显存调爆显存就减半。训练完看runs/detect/train/下的results.csv重点看 mAP50 和召回别只看 loss。3.4 验证与推理确认模型真的认牛羊训练完先跑验证集yolo detect val modelruns/detect/train/weights/best.pt datadata.yaml再拿单张图推理把框画出来肉眼看yolo detect predict modelbest.pt sourcetest.jpg saveTrue如果 mAP 正常但实际画面漏检多半是训练集和现场光照、角度差异大。这时候别急着加 epoch先补几十张现场图重新标注比调参有效得多。4. 避坑与排查格式转换和训练里最容易翻车的 5 个点4.1 现象训练 loss 正常但 mAP 一直是 0原因通常是类别索引错位。txt 里的class_id从 0 开始而data.yaml的names如果写成从 1 开始模型学到的类别和验证时对不上。解决确认names的 key 和 txt 里的 id 完全一致牛羊两类就是 0 和 1。4.2 现象框整体偏移或缩到一角原因是归一化时用了错误的宽高比如用了缩放后尺寸或把 VOC 的 xmax 当成了宽。解决归一化必须用原图width/height且bw (xmax - xmin) / w不是xmax / w。转换后务必可视化抽查。4.3 现象报错「No labels found」原因是 images 和 labels 路径没对应或 txt 文件名和图片名不一致。解决检查data.yaml里train/val指向的是 images 目录Ultralytics 会自动把images替换成labels找标签。文件名只差后缀别多空格或大小写不一致。4.4 现象json 转 yolo 后框全错原因是 COCO 的 bbox 是[x,y,w,h]直接当[xmin,ymin,xmax,ymax]用就错了。解决先转成xmax x w、ymax y h再走归一化。这个坑几乎每个第一次接 COCO 的人都踩过。4.5 现象验证集指标虚高上线就崩原因是切分时同一张图或同一段视频的相邻帧同时进了训练和验证。解决按视频源或时间段切分而不是随机按图切。牧场场景里连续帧高度相似随机切分会让验证集泄漏指标好看但没意义。5. 进阶技巧用 json 做数据体检与难例挖掘三种格式里json 最适合做数据质量体检因为它能一次性加载全部标注做统计。我一般会先跑一个分布检查每类框的数量、宽高比、面积分布找出异常样本。import json from collections import Counter def data_health(json_path): data json.load(open(json_path, encodingutf-8)) cat {c[id]: c[name] for c in data[categories]} cnt Counter() areas [] for ann in data[annotations]: cnt[cat[ann[category_id]]] 1 x, y, w, h ann[bbox] areas.append(w * h) # 标记极小框可能是误标 if w * h 100: print(tiny box:, ann[image_id], ann[bbox]) print(类别分布:, cnt) print(平均框面积:, sum(areas) / len(areas)) return cnt这段代码能快速告诉你牛羊两类是否严重不均衡。如果牛 3000 框、羊 300 框直接训练模型会偏向牛。常见做法是对羊类做过采样或在损失里给类别权重。极小框打印出来人工复核很多是标注时误点的噪点。另一个技巧是用训练后的模型在验证集上跑推理把置信度低但真实存在的框挑出来这就是难例。把这些图重新标注后加入训练集往往比盲目加数据提升明显。我自己的习惯是每轮训练后固定做一次难例回捞尤其是夜间或遮挡场景模型翻车基本都在这些地方。最后提醒一句数据集里的三种格式只是同一批标注的不同表达别把它们当成三份独立数据混着用否则重复样本会让验证指标失真。先定一套主格式训练用 yolo txtxml 和 json 留作核对与扩展流程就顺了。希望帮到你。本文还有配套的精品资源点击获取
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →