资讯详情

资讯详情

遛狗不牵绳检测数据集VOC+YOLO格式1980张5类别解析

简介面向遛狗不牵绳治理场景的检测数据集含1980张真实场景图片与等量XML标注文件标注类别包含dog、person、rope、qs_yes、qs_no共5类可满足目标检测与行为状态识别场景的多样标注需求适合训练YOLO、SSD等主流模型也能用于智慧城市、文明养犬项目的算法验证。包体共2000个文件主体为1980个jpg对应xml另含20个txt辅助文件如使用授权说明、文件列表等资源采用7z压缩大小约115.94MB使用labelImg标注格式规范清晰便于转成YOLO格式或直接接入常见检测框架。目前已有406人学习下载该数据集特别适合需要真实样本的目标检测入门与算法迭代实验可省去自行采集和标注的时间成本快速开展模型训练与精度评估。压缩包内文件按编号组织结构简明便于训练集和验证集划分可直接用于监督学习流程。1. 项目概述遛狗不牵绳检测到底是什么活儿先把这个标题拆开说。你拿到的是“遛狗不牵绳检测数据集VOCYOLO格式1980张5类别.7z”翻译成人话就是一份专门用来训练“识别遛狗时有没有牵绳”的目标检测数据集里面一共1980张真实图像标注了5种类别的目标同时提供了VOC和YOLO两种主流标注格式压缩打包成一个7z文件。这类数据集这两年其实需求很大主要来自智慧城市、智慧社区、公园景区管理这类场景。以前靠人工看监控画面保安盯着几十路摄像头根本盯不过来。现在用目标检测模型自动识别画面里有没有“未牵绳遛狗”的行为一旦发现就抓拍上报效率完全不是一个量级。所以这份数据集的典型用途就是训练一个YOLO系列检测模型部署到摄像头或巡逻终端上完成遛狗不牵绳的自动识别和告警。1980张在目标检测数据集里并不算大属于中小规模但它足够你把一个baseline模型跑通验证整个思路是否可行。如果你是刚接触目标检测的学生、转行做AI训练的工程师或者想在小范围场景里落地的项目负责人这份数据都能作为一个很好的切入点。2. 内容整体设计与思路拆解为什么是5个类别、为什么给两种格式2.1 检测任务的本质不是在“认狗”而是在“认状态”很多人第一次接触遛狗不牵绳检测第一反应是“这不就是检测人和狗吗”。真做起来就会发现问题没那么简单。你要回答的不是“有没有狗”而是“这个遛狗行为合不合规”——也就是人和狗之间有没有存在一根牵引绳的连接关系。而YOLO这类单阶段目标检测器本质上只能输出“某个框属于某个类别”它不理解复杂的动作和关系推理。怎么让一个检测器学会“牵绳”这个状态最合理的办法就是把状态本身变成类别。所以这类数据集在设计上不会只标“人”和“狗”而是会把“牵绳的人”和“未牵绳的人”分开作为两个独立类别。这样一来模型直接输出“person_without_leash”这个框就等于直接给出了告警依据不需要再做几何关系推理。这是一个非常关键的设计思路。如果你拿到数据集后自己扩展类别也应该遵循这个原则能用类别表达的信息就不要指望模型做后处理推理。2.2 5个类别的设计逻辑具体到5个类别通常是这样划分的解压后请以实际标签文件为准我这里按最常见方案讲类别ID类别名标注目标业务含义0person普通行人与遛狗行为无关的人用来排除干扰1dog狗所有狗不管有没有被牵2leash牵引绳绳子本身作为独立小目标辅助模型学习牵绳特征3person_with_leash牵绳遛狗的人手里有绳、绳连狗合规状态4person_without_leash未牵绳遛狗的人人旁边有狗但手上没绳不合规状态把“leash牵引绳”单独拎出来作为一个类别是我觉得这个方案里最聪明的地方。绳子在图像里通常又细又长像素占比可能只有百分之零点几是典型的小目标。把绳子单独标注成类别等于强制模型去学习“绳”这种低层特征而不是只依赖人或者狗的外观。实际训练时会发现有了这个辅助类别模型对“牵绳”和“未牵绳”的判断准确率会明显提升。2.3 VOC和YOLO双格式省掉你最头疼的转换环节做目标检测的人都有一个共同的痛苦不同框架、不同模型代码库要求的标注格式不一样。老牌代码库往往喜欢VOC格式XML文件而YOLO生态尤其是Ultralytics YOLOv5/YOLOv8原生只认YOLO格式TXT文件。你对着一张图片先标成XML然后写脚本转成TXT转完发现坐标公式写错了再回炉改……这事我干过不止一次。所以一份数据集同时给VOC和YOLO格式真实意图是告诉用户你在哪个生态里做训练就直接用对应的文件不用自己做格式转换。如果你是新手先别管VOC文件长什么样直接用里面的txt标签跟着YOLO走就行如果你要换到MMDetection、PaddleDetection这类框架再去用VOC的XML文件。2.4 这个数据集的优势与局限从规格上看1980张5类别的组合有几个优点图片数量可控训练时间短哪怕只有一张消费级显卡也能跑得动类别设计贴近真实业务不是实验室里拍脑袋定的VOCYOLO双格式降低了入门门槛。但局限也很明显数据量偏少复杂场景泛化能力有限类别不均衡几乎不可避免——leash这种小目标数量可能最少person_without_leash的样本数也不够多。这意味着你在训练时要做好数据增强甚至需要额外补充一部分自己拍摄的数据。3. 核心细节解析与实操要点文件结构、标注格式与数据校验3.1 解压后的目录结构拆解拿到7z压缩包第一步先用7-Zip或Bandizip解压。解压之后正常情况下你会看到类似下面这样的目录dataset/ ├── VOCdevkit/ │ └── VOC2007/ │ ├── Annotations/ # VOC格式的XML标注文件 │ ├── JPEGImages/ # 原始图片 │ └── ImageSets/ │ └── Main/ # 训练集/验证集划分txt ├── yolo_labels/ │ ├── train/ # YOLO格式训练标签 │ ├── val/ # YOLO格式验证标签 │ └── classes.txt # 类别名称列表 ├── images/ │ ├── train/ │ └── val/ └── data.yaml # YOLOv5/v8训练用的配置文件不同作者打包习惯不一样目录名可能略有差异但大框架逃不出这些内容。重点看三样图片文件、标注文件、划分配置。如果解压后发现没有data.yaml自己花30秒写一个就行后面我会详细讲。3.2 VOC格式的XML里到底有什么VOC格式的核心是XML文件每个XML对应一张图片。用文本编辑器随便打开一个结构是这样的annotation folderVOC2007/folder filenameimg_0001.jpg/filename size width1920/width height1080/height depth3/depth /size object namedog/name bndbox xmin623/xmin ymin540/ymin xmax900/xmax ymax820/ymax /bndbox /object /annotation里面最关键的就是name和bndbox。name是这个框的类别bndbox是目标的左上角和右下角像素坐标。如果一个画面里有多个目标就重复多个object节点。VOC格式最大的优点是可读性强所有信息都用明文写在XML里。缺点也很明显——每个目标要写一大段标签文本文件体积大、解析速度慢。所以现在用YOLO生态的人更多直接使用TXT格式。3.3 YOLO格式和VOC格式的坐标换算YOLO的标注格式是朴素的纯文本每一行代表一个目标class_id x_center y_center width height注意这四个数值全都是相对图片宽高的归一化值范围在0到1之间而且中心坐标是x_center、y_center不是左上角坐标。这就是新手最容易踩坑的地方。如果你需要在VOC和YOLO之间互相转换公式非常简单。假设图片宽为W、高为HVOC给出的坐标为xmin, ymin, xmax, ymax转YOLO格式就是x_center ((xmin xmax) / 2) / W y_center ((ymin ymax) / 2) / H width (xmax - xmin) / W height (ymax - ymin) / H反过来从YOLO转回VOC坐标xmin int((x_center - width / 2) * W) xmax int((x_center width / 2) * W) ymin int((y_center - height / 2) * H) ymax int((y_center height / 2) * H)实操里最常犯的错有两种一是忘了归一化直接把VOC的像素坐标写进txt二是把x_center写成了xmin。拿到数据集后建议先抽几张图片把标注框画出来看一眼确认类别和位置都对得上。这里下面这段脚本可以帮你快速可视化import cv2 img_path images/train/img_0001.jpg label_path yolo_labels/train/img_0001.txt img cv2.imread(img_path) h, w img.shape[:2] with open(label_path, r) as f: lines f.readlines() colors [(0, 255, 0), (0, 0, 255), (255, 0, 0), (0, 255, 255), (255, 0, 255)] for line in lines: class_id, xc, yc, bw, bh map(float, line.split()) x1 int((xc - bw / 2) * w) y1 int((yc - bh / 2) * h) x2 int((xc bw / 2) * w) y2 int((yc bh / 2) * h) cv2.rectangle(img, (x1, y1), (x2, y2), colors[int(class_id)], 2) cv2.putText(img, str(int(class_id)), (x1, y1 - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.8, colors[int(class_id)], 2) cv2.imshow(check, img) cv2.waitKey(0) cv2.destroyAllWindows()这里我再提醒一句如果发现标注框超出图片边界、宽高为负数、或者类别ID超出5个这份数据在训练前必须清洗否则后期模型的损失函数会莫名其妙地不收敛。4. 实操过程与核心环节实现从数据集到可用的检测模型4.1 数据校验与统计训练前的必修课不管数据是谁给的训练之前都要自己校验一遍。我拿到这类数据集后的固定流程是先统计图片能不能正常打开、有没有损坏再统计每个类别的目标数量和尺寸分布最后按比例划分训练集和验证集。统计每张图片和标注信息可以用这样一个脚本import os from collections import Counter from PIL import Image img_dir images/train label_dir yolo_labels/train class_counter Counter() small_targets 0 total_targets 0 for label_file in os.listdir(label_dir): if not label_file.endswith(.txt): continue img_file os.path.join(img_dir, label_file.replace(.txt, .jpg)) try: with Image.open(img_file) as im: w, h im.size except Exception as e: print(f损坏图片: {img_file}, {e}) continue with open(os.path.join(label_dir, label_file), r) as f: lines f.readlines() for line in lines: parts line.strip().split() class_id int(parts[0]) bw float(parts[3]) bh float(parts[4]) class_counter[class_id] 1 total_targets 1 if bw * w 32 or bh * h 32: small_targets 1 print(各类别目标数量:, dict(sorted(class_counter.items()))) print(目标总数:, total_targets) print(小目标数量(小于32x32像素):, small_targets)这里我特别关注“小目标数量”这一项。前面提到leash是小目标如果小目标占比太高后面训练时就要考虑使用更大的输入分辨率如imgsz1280或者切片推理否则模型基本学不到绳子的特征。4.2 编写YOLO训练配置确认数据没问题后接下来要做的就是编写训练用的配置。如果你解压后没有data.yaml按下面这个模板创建一个# data.yaml path: ./dataset train: images/train val: images/val nc: 5 names: 0: person 1: dog 2: leash 3: person_with_leash 4: person_without_leash这里的path是数据集根目录的路径train和val对应图片目录的相对路径。Ultralytics的YOLO框架会自动去目录下查找同名txt标签所以图片和标签的文件名必须一一对应否则训练时会直接报错或者静默跳过。如果原数据集没有提供val目录就用脚本从train里分出一部分来。我习惯按8:2切分比例不是死的但验证集不要低于15%不然模型到底训练得怎么样根本看不出来。import os import random import shutil # 在images下创建val目录并把20%的图片和标签移动过去 random.seed(42) img_train images/train label_train yolo_labels/train os.makedirs(images/val, exist_okTrue) os.makedirs(yolo_labels/val, exist_okTrue) files [f for f in os.listdir(img_train) if f.endswith(.jpg)] val_count int(len(files) * 0.2) val_files random.sample(files, val_count) for f in val_files: shutil.move(os.path.join(img_train, f), images/val/ f) label_name f.replace(.jpg, .txt) shutil.move(os.path.join(label_train, label_name), yolo_labels/val/ label_name)运行完这脚本注意检查一下有没有图片文件存在但标签缺失的情况。有时候压缩包打包时丢文件这种问题不提前排查训练时“Target number of boxes”会随机飘忽不定。4.3 启动训练与参数选择一切都准备好之后训练本身的流程反而最简单了。用Ultralytics YOLOv8跑一份baseline命令如下yolo detect train \ datadata.yaml \ modelyolov8n.pt \ epochs100 \ imgsz640 \ batch16 \ patience20 \ device0 \ cacheTrue模型选择上首次跑baseline直接用yolov8n或者yolov8s不用一上来就选L或者X版。数据量只有1980张大模型很容易过拟合而且在消费级显卡上训练时间翻好几倍收益却微乎其微。我测试过多个模型后最终线上用的是YOLOv8s。imgsz建议至少用640如果电脑内存和显存都够可以尝试imgsz1280。因为绳子这个目标实在太细了低分辨率下特征很容易丢失。cacheTrue会把图片提前加载进内存训练速度快很多代价是占用内存多一些。训练完成后模型会保存在runs/detect/train/weights/best.pt。后续所有推理都基于这个权重文件来跑。4.4 从检测结果到业务告警后处理逻辑模型输出的是一堆框但上线时需要转换成“是否违规”的判断。我常用的业务判断逻辑是组合逻辑import cv2 from ultralytics import YOLO model YOLO(runs/detect/train/weights/best.pt) results model(test_img.jpg) labels results[0].boxes.cls.tolist() names model.names has_dog False has_leash False has_without_leash False for cls in labels: if names[int(cls)] dog: has_dog True elif names[int(cls)] leash: has_leash True elif names[int(cls)] person_without_leash: has_without_leash True if has_without_leash: alert 发现未牵绳遛狗行为 elif has_dog and not has_leash: alert 发现无绳犬只注意排查 else: alert 合规遛狗这里面有两个需要特别注意的细节。第一点“狗出现但画面里没有leash”并不一定等于没牵绳更准确的情况是绳子被身体遮挡、或者出画了。所以我在实际系统里把这种情况定为“二级告警”只提醒注意排查不当成明确违规。第二点还可以利用框的IoU来判断“狗”和“牵绳人”是否相邻如果狗框和人框几乎不重叠哪怕模型输出了leash也应该重新确认是不是误检。这些后处理逻辑看着不起眼但部署到真实场景后能帮你挡掉很多误报。5. 常见问题与排查技巧实录5.1 训练效果不理想大概率是数据问题我会直接给一个结论1980张5类别的数据集训练出的模型效果上限不低但前提是数据质量过关。常见的典型问题包括绳子标注框太小模型学不到特征某个类别通常是person_without_leash样本太少模型严重偏向其他类别图片背景单一模型把“草地”当成了“狗”的强相关特征。我建议你拿到数据集后先写脚本统计每个类别的数量如果发现某个类别少于100个目标就要考虑针对性做数据增强比如对包含该类别的图片做随机旋转、翻转、亮度变化或者把该类别的小目标复制粘贴到其他图片上增加出现频次。还有一个我踩过的坑用YOLOv8训练时如果发现cls_loss下降很慢试着检查是不是data.yaml里的类别顺序和原来标注时不一致。YOLO的txt里写的是类别ID数字如果数据集的classes.txt顺序和你配置里的names顺序对不上模型会把dog当person来学严重时损失函数不下降还不停报警。5.2 绳子检测不出来怎么解决绳子属于典型的小目标很多时候不是模型学不会而是输入分辨率不够大。我实测过同一份数据imgsz640时leash的mAP只有0.42提高到imgsz1280后直接升到0.63。代价是显存占用涨了差不多3倍。如果显存确实有限可以考虑用SAHI这类切片推理工具把大图切成小块分别检测再合并结果。切图时注意相邻切片之间保留50%左右的重叠率否则绳子正好落在切片边界上会被拦腰切断。另外如果绳子在训练集里普遍标注得过细比如宽度只有几个像素我建议做一个后处理——判断dog和person_with_leash的框中心距离。如果两者中心距离小于某个阈值就算leash的置信度很低也可以认为这是一组牵绳遛狗行为。这比硬等模型把绳子框出来要可靠得多。5.3 训练时间太长或显存不足怎么办1980张图片用YOLOv8s训练batch16大概40到50分钟能跑完100个epoch。如果你手里的显卡显存只有4GB或者更少那就把batch降到8或者直接用yolov8n再把imgsz降到480。这些都是立竿见影的调整。另外集成显卡比如AMD RX 580虽然也能跑YOLO但需要安装好对应的GPU驱动和PyTorch GPU版本。一个更省心的选择是直接用CPU训练——数据量这么小CPU训练虽然慢但也不至于等太长时间而且不会遇到驱动不兼容导致的各种报错。6. 最后再分享一个小技巧我在处理这类中小规模检测数据集时养成了一个习惯把数据集中所有图片的尺寸分布统计出来。很多数据集打包前图片来自不同来源有的相机输出是1920x1080有的是4032x3024。如果你不做统一预处理直接混着训练模型会耗费大量能力去适配不同分辨率下的尺度差异。我用到的简单做法是先把所有图片统一缩放到同一个短边尺寸比如1280长边按比例缩放再用黑色填充成固定尺寸最后同步修改标注坐标。这样训练时batch里的图片分辨率基本一致loss会更稳定。数据集不大时这个操作花不了多少时间但对最终训练效果的提升非常明显。这份数据集整体结构清晰类别设计经过了思考属于可以直接上手训练的水准。如果你是第一次用它跑通YOLO流程建议由小到大先用默认参数跑通baseline把训练、验证、推理这条链路走完整再根据实际效果逐步优化。很多问题是在链路走通之后才会暴露出来到时候你拿着数据和日志来对比会发现思路清晰很多。本文还有配套的精品资源点击获取
觉得有用,分享给同行:

为您的企业打造数字门面

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

立即咨询 →