YOLOv11成人和小孩检测数据集:1738张图片与70.9%识别率实战
2026/9/24 23:15:09 网站建设 项目流程

简介:这份成人与小孩识别数据集面向计算机视觉初学者及目标检测开发者,用于训练和验证YOLO系列模型在人物类别区分上的效果。资源包含1738张原始图片,均已完成yolov11格式标注,可直接投入训练流程,省去自行标注的时间成本。压缩包共约2000个文件,以1738个txt标注文件、261张jpg图像和1个yaml配置文件为主,其中txt对应每张图片的边界框与类别信息,yaml用于定义数据集路径与类别名称,整体包大小约91.35MB,结构清晰便于快速接入。目前已有112人学习下载,适合作为小规模人物检测实验的起点。读者可借助该数据集完成成人、小孩两类目标的模型训练与验证,参考70.9%的识别率评估基线表现,并在此基础上调整网络结构、数据增强或超参数以提升精度,也可用于课堂演示、课程设计或算法对比实验。

1. 成人和小孩数据集:1738 张原始图片与 70.9% 识别率的真实边界

如果你正在做家庭场景、商场客流、儿童看护或者公共区域的人群分析,大概率绕不开一个基础问题:怎么把画面里的人分成“成人”和“小孩”两类。这份成人和小孩数据集给了一个很直接的起点——1738 张原始图片,全部按 yolov11 格式标注,官方给出的识别率是 70.9%。注意,这个 70.9% 不是随便说说的营销数字,它意味着你在拿到这份数据之后,如果直接套用标准 yolov11n 或 yolov11s 训练,验证集上的 mAP 大概就在这个区间浮动。它适合谁?适合想快速验证“成人/小孩”二分类检测可行性的人,适合需要一份已经切好、标好、能直接丢进 ultralytics 训练脚本的从业者,也适合拿它当基线,再决定要不要自己补数据的团队。但如果你指望它直接上生产、覆盖所有年龄段的细粒度识别,那 70.9% 这个数字本身就是第一个需要正视的边界。

2. 拆开这份 yolov11 数据集:目录结构、标注格式与类别定义

2.1 从文件名看数据来源与预处理痕迹

项目正文里列出的文件名很有代表性,比如000000000368_jpg.rf.a354cea163edd946205e4d13985aba16.jpgperson_406_bmp.rf.fe806abab8d8cc3c7a8d81b60be6bc73.jpg。带.rf.中间缀的文件名,常见于 Roboflow 导出流程,说明这批图大概率经历过在线标注、增强或格式转换。person_406_bmp这种命名暗示原始图可能来自某个行人数据集,19254_jpg16715_jpg则像视频抽帧或图片库编号。对训练来说,文件名本身不影响结果,但它透露了两个信息:一是图片尺寸和长宽比可能不统一,二是部分图可能已经过缩放或压缩。我一般会先跑一遍统计,确认没有 0 字节文件、没有损坏图,再开始转格式。

# 统计图片数量与尺寸分布,提前发现异常图 python - <<'PY' from pathlib import Path from PIL import Image import collections root = Path("images") sizes = collections.Counter() bad = [] for p in root.rglob("*.jpg"): try: with Image.open(p) as im: sizes[im.size] += 1 except Exception as e: bad.append((str(p), str(e))) print("总图片数:", sum(sizes.values())) print("常见尺寸:", sizes.most_common(5)) print("损坏图:", bad[:10]) PY

这段脚本做三件事:遍历images下所有 jpg,用 PIL 打开确认可读,统计尺寸分布,并记录打不开的文件。参数上,root换成你解压后的图片目录即可;sizes.most_common(5)帮你看清主流分辨率,如果 640×480 和 1920×1080 混在一起,后面训练时 letterbox 会统一处理,但小图放大后细节损失会拉低小孩这一类的小目标召回。

2.2 yolov11 标注格式与类别映射

yolov11 沿用 YOLO 系列的 txt 标注:每张图对应一个同名 txt,每行class_id x_center y_center width height,坐标全部归一化到 0~1。这份数据只有两个类,常见映射是0: adult1: child,但你必须自己确认,因为有些导出会把顺序反过来。确认方法很简单:随便找一张同时有成人和小孩的图,用标注可视化脚本画框,看颜色和类别是否对得上。

# 可视化一张图的标注,确认类别顺序 from pathlib import Path import cv2 img_path = Path("images/000000000368_jpg.rf.a354cea163edd946205e4d13985aba16.jpg") label_path = Path("labels/000000000368_jpg.rf.a354cea163edd946205e4d13985aba16.txt") names = {0: "adult", 1: "child"} # 先按假设写,不对再换 img = cv2.imread(str(img_path)) h, w = img.shape[:2] for line in label_path.read_text().strip().splitlines(): c, x, y, bw, bh = line.split() c = int(c) x, y, bw, bh = float(x)*w, float(y)*h, float(bw)*w, float(bh)*h x1, y1 = int(x-bw/2), int(y-bh/2) x2, y2 = int(x+bw/2), int(y+bh/2) cv2.rectangle(img, (x1, y1), (x2, y2), (0,255,0), 2) cv2.putText(img, names[c], (x1, max(0,y1-5)), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0,255,0), 2) cv2.imwrite("check.jpg", img) print("已保存 check.jpg,打开确认框和类别")

逻辑说明:读图后按归一化坐标还原像素框,names字典控制显示文字。如果发现“小孩”被标成 adult,就把names和后续data.yaml里的names顺序一起改。参数上,cv2.rectangle的线宽和字号按图大小调,大图可以加到 3 和 0.8。这一步花两分钟,能避免训练完才发现类别反了的血泪经验。

2.3 data.yaml 的写法与路径陷阱

ultralytics 训练依赖一个 yaml 描述文件,常见写法如下:

path: /home/user/adult_child_dataset train: images/train val: images/val test: images/test names: 0: adult 1: child

注意path用绝对路径最稳,train/val写相对path的子目录。很多人翻车在labels目录没跟images平行,ultralytics 默认把images替换成labels去找 txt,所以目录结构最好是:

adult_child_dataset/ ├── images/ │ ├── train/ │ ├── val/ │ └── test/ └── labels/ ├── train/ ├── val/ └── test/

如果原始压缩包没有划分 train/val,你需要自己按 8:1:1 或 7:2:1 切分。切分时注意同一段视频抽出的帧不要同时进 train 和 val,否则验证集精度会虚高,这是目标检测里最常见的泄漏坑。

3. 用 yolov11 训练成人小孩检测:环境、命令与参数调优

3.1 环境配置与最小可跑命令

ultralytics 现在把 yolov11 集成在同一个包里,安装命令很直接:

pip install ultralytics yolo checks

yolo checks会打印 Python、torch、CUDA 版本。如果你有 NVIDIA 显卡,确认 torch 带 cu 后缀;没有显卡就用 CPU,但 1738 张图训练会慢很多。最小训练命令:

yolo detect train \ data=/home/user/adult_child_dataset/data.yaml \ model=yolo11n.pt \ epochs=100 \ imgsz=640 \ batch=16 \ project=runs/adult_child \ name=baseline

参数说明:model=yolo11n.pt是最轻量版本,适合先跑通;imgsz=640是默认输入尺寸,如果原图里小孩占画面比例很小,可以提到 960 或 1280,但显存占用会明显上升;batch=16在 8G 显存上比较稳,爆显存就降到 8 或 4;epochs=100对 1738 张图通常够收敛,配合patience=20早停更省时间。训练日志里重点看mAP50mAP50-95,官方说的 70.9% 大概率对应mAP50量级,别拿mAP50-95去对,否则会觉得被坑了。

3.2 提升小孩召回:小目标与类别不平衡的处理

成人和小孩在画面里的尺度差异很大,小孩往往更小、更远、更容易被遮挡。1738 张图里如果小孩样本偏少,模型会偏向成人。常见做法有三条:一是提高输入分辨率,让小孩占更多像素;二是用copy_pastemosaic增强,但 mosaic 对小目标有时反而添乱;三是在损失里给小孩类更高权重,不过 ultralytics 默认不直接暴露类别权重,需要改cls损失或过采样。

# 提高分辨率 + 关闭部分增强的二次训练 yolo detect train \ data=/home/user/adult_child_dataset/data.yaml \ model=runs/adult_child/baseline/weights/best.pt \ epochs=80 \ imgsz=960 \ batch=8 \ mosaic=0.5 \ scale=0.3 \ project=runs/adult_child \ name=finetune_960

这里从best.pt继续训,imgsz=960提升小目标细节,mosaic=0.5降低拼接强度,scale=0.3控制随机缩放幅度。跑完对比两次的val结果,重点看小孩类的recall。如果 recall 还是低,就回到数据本身,检查标注有没有漏标远处小孩,漏标比模型问题更致命。

3.3 推理与保存结果:确认 70.9% 在你自己场景下的表现

训练完用yolo detect predict跑一批图,保存带框结果:

yolo detect predict \ model=runs/adult_child/finetune_960/weights/best.pt \ source=/home/user/test_images \ conf=0.25 \ iou=0.5 \ save=True \ save_txt=True \ project=runs/adult_child \ name=pred_test

conf=0.25是置信度阈值,调低会多出框但误报增加,调高会漏检;iou=0.5控制 NMS 合并程度,人群密集时可以试 0.6。save_txt=True会输出 yolov11 格式的预测 txt,方便你写脚本和真值对比,算自己场景下的实际识别率。官方 70.9% 是在它的验证集上,你的摄像头角度、光照、分辨率一变,数字就会动,这一步是必须自己复现的。

4. 避坑与排查:这份数据集最容易翻车的五个地方

4.1 现象:训练 loss 正常但 mAP 一直上不去

原因:data.yamlnames顺序和标注 txt 里的class_id对不上,模型学的是反的。解决:用 2.2 的可视化脚本抽查 10 张图,确认框和类别文字一致,再检查 yaml。

4.2 现象:验证集精度很高,实际测试一塌糊涂

原因:train/val 划分时同一段视频的帧被分到两边,造成数据泄漏。解决:按视频或按原始图片编号分组切分,同一来源只进一个集合。

4.3 现象:小孩漏检严重,成人框一堆

原因:小孩样本少且小,模型偏向多数类。解决:先统计两类框数量,差距超过 3:1 就过采样小孩图,或提高imgsz,再不行就补标小孩数据。

4.4 现象:训练报错No labels found

原因:labels目录没有和images平行,或 txt 文件名和图片名不完全一致(包括大小写、后缀)。解决:用脚本批量核对文件名,确保每张 jpg 都有同名 txt。

4.5 现象:显存爆了,batch 降到 1 还报 OOM

原因:imgsz设太大,或workers太多导致内存泄漏。解决:先把imgsz降到 640,workers=2,确认能跑再逐步加;也可以用yolo11n而不是sm

5. 把 70.9% 变成可用的基线:验证脚本与持续补数据习惯

拿到任何一份标注数据集,我都不会直接信它的识别率,而是先写一个最小验证脚本,用自己的测试图跑一遍,把预测结果和人工标注对比,算出成人、小孩各自的 precision 和 recall。下面这个脚本读取save_txt=True的输出,和真值目录做简单匹配,帮你快速看清哪一类拖后腿。

# 简化版:统计预测框与真值框的类别匹配情况 from pathlib import Path pred_dir = Path("runs/adult_child/pred_test/labels") gt_dir = Path("labels/test") names = {0: "adult", 1: "child"} stats = {0: {"tp":0, "fp":0, "fn":0}, 1: {"tp":0, "fp":0, "fn":0}} def load_boxes(p): boxes = [] if p.exists(): for line in p.read_text().strip().splitlines(): c, x, y, w, h = line.split() boxes.append((int(c), float(x), float(y), float(w), float(h))) return boxes for pred_file in pred_dir.glob("*.txt"): gt_file = gt_dir / pred_file.name preds = load_boxes(pred_file) gts = load_boxes(gt_file) # 这里只按类别数量粗匹配,精确匹配需算 IoU for c in [0, 1]: pc = sum(1 for b in preds if b[0] == c) gc = sum(1 for b in gts if b[0] == c) stats[c]["tp"] += min(pc, gc) stats[c]["fp"] += max(0, pc - gc) stats[c]["fn"] += max(0, gc - pc) for c, s in stats.items(): precision = s["tp"] / max(1, s["tp"] + s["fp"]) recall = s["tp"] / max(1, s["tp"] + s["fn"]) print(f"{names[c]}: precision={precision:.3f}, recall={recall:.3f}")

这段代码故意用数量粗匹配,目的是快速定位类别偏差,不是替代标准 mAP 计算。如果你要严格评估,还是用 ultralytics 的val模式,它会输出每类的 AP。参数上,pred_dirgt_dir换成你自己的路径,names和训练时保持一致。

跑完这个脚本,你大概率会发现小孩的 recall 明显低于成人,这就是 70.9% 背后的真实结构。我的习惯是:每补一批新场景的图,先标 50 张,跑一次这个脚本,看小孩 recall 有没有提升,再决定要不要继续标。数据集不是下载完就结束,而是一个持续迭代的起点。从那以后我每次拿到新数据集,都强制先跑一遍类别分布和可视化抽查,再开始训练,省下的返工时间远比这几分钟多。希望帮到你。

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

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

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

立即咨询