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

资讯详情

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

车内视角行人识别数据集:采集、标注与YOLO训练全链路指南

车内视角行人识别数据集:采集、标注与YOLO训练全链路指南 简介这是一份面向自动驾驶与计算机视觉方向学习者的车内视角行人识别数据集取自BDD100K并仅保留行人类别适合YOLO系列、Faster R-CNN、SSD等目标检测模型的训练与验证可用于车载场景下的行人检测算法研究、课程实验与项目复现。资源包共2000个文件以1999个txt标注文件和1个yaml类别配置文件为主txt对应YOLO格式的边界框标签yaml用于指定类别信息同时提供VOC格式xml标签图片与标签已按训练集、验证集、测试集划分完毕压缩包约421.52MB解压后可直接投入YOLOv5至YOLOv10等版本训练。目前已有207人学习下载。数据集共6470张图片覆盖真实道路车内视角标注规范、目录清晰能帮助读者省去数据采集与格式转换环节快速搭建行人检测基线并对比不同模型效果。1. 车内视角行人识别数据集从采集到可训练样本的完整链路车内视角行人识别数据集指的是把摄像头装在挡风玻璃后方或仪表台位置以驾驶员/乘客的视线角度持续拍摄车外行人再对每一帧里的行人做标注最终形成能直接喂给检测模型训练的数据集。它和常见的固定监控视角、无人机俯拍视角有本质区别车内视角存在挡风玻璃反光、雨刷遮挡、仪表台倒影、曝光剧烈跳变行人尺度从远到近连续变化近处行人经常被A柱或后视镜切掉一半。这些特性决定了它不能直接拿COCO、CrowdHuman这类通用数据集替代必须自己采、自己标、自己校验。适合做这件事的人有三类做ADAS前装或后装算法的工程师、做车内DMS/OMS联动行人预警的团队、以及需要特定视角数据做域适应的研究者。下面按采集、标注、格式转换、训练验证、避坑的顺序把整条链路拆开讲清楚。2. 采集方案与硬件选型决定数据集上限的三个参数2.1 摄像头安装位置与视场角怎么定车内视角的核心变量是安装位置。常见做法有三种后视镜下方居中、仪表台正中央、副驾侧A柱附近。后视镜下方视野最接近人眼但容易被后视镜本体和雨刷遮挡仪表台中央视野稳定但引擎盖会占据画面下沿约15%到25%副驾侧A柱附近能拍到更多右侧行人但左侧盲区大。我一般推荐仪表台中央偏驾驶员一侧水平视场角选100°到120°。低于90°会漏掉横向穿出的行人高于140°边缘畸变严重标注时边界框会被拉伸得很难看。分辨率建议1080p起步最好2K。行人识别在车内视角下远处行人可能只有30到50像素高1080p勉强够用2K能显著提升小目标召回。帧率25fps或30fps即可再高对训练增益有限反而让标注成本翻倍。曝光策略上优先开宽动态WDR因为进出隧道、树荫交替时普通曝光会让行人瞬间变成剪影。注意不要用手机支架临时凑合。手机自动对焦和自动曝光在行车过程中会频繁呼吸导致同一行人连续帧的尺度不一致标注时框会跳。2.2 采集路线与场景配比数据集的价值不在数量在场景覆盖。我一般按以下配比规划采集路线总时长控制在8到12小时能产出约3到5万帧有效画面场景类型占比采集要点城市主干道白天30%行人密集、遮挡多、广告牌干扰居民区/学校周边20%儿童突然横穿、路边停车遮挡夜间有路灯20%车灯眩光、行人穿深色衣服黄昏/黎明10%逆光、曝光剧烈变化雨天/雨后10%挡风玻璃水珠、雨刷运动地下车库/隧道10%低照度、人工光源频闪每条路线至少跑两遍一遍顺行一遍逆行保证同一场景有不同光照方向。采集时记录GPS、时间戳、天气后续做场景均衡采样时用得上。2.3 抽帧策略与去重原始视频不能直接标必须抽帧。抽帧不是固定间隔就完事我一般用两段式先按1fps粗抽再用感知哈希做去重。连续帧之间如果画面差异小于阈值只保留一帧。这样能把冗余帧压掉60%以上标注成本直接降一半。import cv2 import imagehash from PIL import Image import os def extract_frames(video_path, out_dir, fps1, hash_threshold5): cap cv2.VideoCapture(video_path) src_fps cap.get(cv2.CAP_PROP_FPS) interval int(src_fps / fps) saved, last_hash 0, None os.makedirs(out_dir, exist_okTrue) idx 0 while True: ret, frame cap.read() if not ret: break if idx % interval 0: img Image.fromarray(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)) h imagehash.phash(img) # 与上一张保留帧比较差异过小则丢弃 if last_hash is None or (h - last_hash) hash_threshold: cv2.imwrite(f{out_dir}/frame_{idx:06d}.jpg, frame) last_hash h saved 1 idx 1 cap.release() print(fsaved {saved} frames)这段代码里fps1控制粗抽频率hash_threshold5是感知哈希差异阈值。阈值调大保留帧更少但可能漏掉快速运动片段调小则保留更多相似帧。我一般先用5跑一遍人工翻看抽出的帧如果发现连续多帧几乎一样就降到3再跑。phash对亮度变化不敏感适合行车场景但对剧烈运动中的行人可能误判所以抽完后还要按场景分段人工过一遍。3. 标注规范与质量控制让框和标签真正可用3.1 标注类别与属性设计车内视角行人识别类别不要只设一个“person”。我一般分四类pedestrian站立或行走、cyclist骑车人、child身高明显低于成人单独标、occluded_pedestrian被遮挡超过50%但可见部分仍可辨认。前两类是检测主目标后两类是提升召回的关键。属性上至少记录遮挡比例0/1/2三档、是否在斑马线上、是否面向车辆、是否夜间。这些属性在训练时可以做加权采样也能在误检分析时快速定位问题。标注框规则框必须包住行人可见部分被遮挡时不要脑补完整人体。如果行人被A柱切成两半只标可见的那一半并在属性里记遮挡。框边缘留2到3像素余量不要贴死。小于20像素高的行人如果肉眼能辨认标如果只是模糊色块不标否则会引入大量噪声。3.2 用LabelImg做标注的实操流程LabelImg是常见选择但直接开干容易乱。我一般按以下步骤走把抽好的帧按场景分文件夹每个文件夹不超过500张避免标注时翻找困难。在LabelImg里预设类别列表用predefined_classes.txt内容一行一个类别名。开启Auto Save mode每标完一张自动存XML防止崩溃丢进度。标注顺序固定先标大目标再标小目标最后标遮挡目标。这样能保持注意力集中减少漏标。每标完一个文件夹用脚本统计各类别框数量数量异常比如某类为0立刻回查。# 启动LabelImg并加载预定义类别 labelImg ./frames_city_day ./predefined_classes.txt ./annotations \ --autosave --nosort--autosave开启自动保存--nosort禁止按文件名排序避免标注顺序被打乱。标注文件默认存PASCAL VOC格式XML后续转YOLO或COCO都方便。3.3 交叉校验与一致性检查一个人标完的数据集一致性通常只有85%左右。我一般做两轮校验第一轮随机抽10%的帧让另一个人重标计算IoU和类别一致率。如果某类一致率低于90%说明标注规范有歧义回去改规范。第二轮用已训练好的粗模型跑一遍全部标注帧把模型预测和人工标注差异大的帧挑出来人工复核。这一步能抓出漏标和错标尤其是小目标和遮挡目标。import xml.etree.ElementTree as ET import os def count_boxes(anno_dir): stats {} for f in os.listdir(anno_dir): if not f.endswith(.xml): continue tree ET.parse(os.path.join(anno_dir, f)) for obj in tree.findall(object): name obj.find(name).text stats[name] stats.get(name, 0) 1 return stats print(count_boxes(./annotations))这个统计脚本跑完如果child或occluded_pedestrian数量不到总数的5%说明采集或标注时忽略了这些场景需要补采或补标。类别不均衡在车内视角数据集里非常常见不要等到训练时才发现。4. 格式转换与训练集划分从XML到YOLO可读4.1 VOC转YOLO格式的脚本与四个边界坑YOLO格式要求每张图对应一个txt每行class_id cx cy w h全部归一化到0到1。转换本身不难但边界情况容易翻车。import xml.etree.ElementTree as ET import os classes [pedestrian, cyclist, child, occluded_pedestrian] def voc_to_yolo(xml_path, out_txt, img_w, img_h): tree ET.parse(xml_path) root tree.getroot() lines [] for obj in root.findall(object): name obj.find(name).text if name not in classes: continue cls_id classes.index(name) bbox obj.find(bndbox) x1 float(bbox.find(xmin).text) y1 float(bbox.find(ymin).text) x2 float(bbox.find(xmax).text) y2 float(bbox.find(ymax).text) # 边界裁剪防止标注越界导致归一化后为负 x1, y1 max(0, x1), max(0, y1) x2, y2 min(img_w, x2), min(img_h, y2) if x2 x1 or y2 y1: continue cx (x1 x2) / 2.0 / img_w cy (y1 y2) / 2.0 / img_h w (x2 - x1) / img_w h (y2 - y1) / img_h lines.append(f{cls_id} {cx:.6f} {cy:.6f} {w:.6f} {h:.6f}) with open(out_txt, w) as f: f.write(\n.join(lines))四个边界坑第一标注框可能超出图像边界不裁剪会导致归一化后出现负数或大于1的值训练时直接报错。第二x2 x1的退化框要跳过否则宽高为负。第三类别名大小写和空格必须和classes列表完全一致差一个字符就丢框。第四图像实际尺寸要用cv2.imread重新读不要信XML里的size字段有些标注工具会写错。4.2 训练集/验证集/测试集划分策略车内视角数据集不能随机划分。随机划分会让同一段视频的相邻帧同时出现在训练集和验证集导致验证指标虚高。正确做法是按视频片段划分先把所有帧按来源视频分组再按组分配。训练集占70%验证集15%测试集15%。测试集里必须包含至少一个完整夜间片段和一个完整雨天片段否则无法评估模型在恶劣条件下的真实表现。import os import random from collections import defaultdict def split_by_video(frame_dir, ratios(0.7, 0.15, 0.15)): video_groups defaultdict(list) for f in os.listdir(frame_dir): # 假设文件名格式为 videoId_frameId.jpg vid f.split(_)[0] video_groups[vid].append(f) vids list(video_groups.keys()) random.shuffle(vids) n len(vids) train_vids vids[:int(n * ratios[0])] val_vids vids[int(n * ratios[0]):int(n * (ratios[0] ratios[1]))] test_vids vids[int(n * (ratios[0] ratios[1])):] return train_vids, val_vids, test_vids划分完检查一下三个集合的类别分布如果child在测试集里一个都没有手动从训练集里调几个含child的视频片段过去。类别均衡比数量均衡更重要。4.3 用YOLOv8跑通第一版训练格式转好后用YOLOv8做基线训练。数据配置文件data.yaml这样写path: ./dataset train: images/train val: images/val test: images/test nc: 4 names: [pedestrian, cyclist, child, occluded_pedestrian]训练命令yolo detect train datadata.yaml modelyolov8s.pt epochs100 imgsz640 batch16 \ patience20 lr00.01 lrf0.01 mosaic1.0 close_mosaic10imgsz640是起点如果小目标召回低提到960或1280再试。mosaic1.0开启马赛克增强对车内视角的遮挡场景很有帮助但最后10个epoch要close_mosaic10关掉让模型适应真实分布。patience20防止过拟合。训练完看混淆矩阵如果pedestrian和occluded_pedestrian互相误判多说明遮挡属性标注不一致回去查标注。5. 避坑与排查车内视角数据集最容易翻车的五件事5.1 挡风玻璃反光被标成了行人现象模型在白天晴天场景下频繁把仪表台倒影或玻璃反光检成行人。原因采集时没装遮光罩反光在画面里形成类人轮廓标注时也没注意区分。解决采集阶段在镜头周围加黑色遮光泡棉标注阶段把明显是反光的区域标为ignore区域训练时用mask掉。如果已经标完了用训练好的模型跑一遍把反光误检帧挑出来重新标。5.2 雨刷运动导致连续帧框跳变现象同一行人在连续帧里框的位置和大小剧烈跳动训练时loss震荡。原因雨刷扫过画面时遮挡行人标注员在遮挡帧和可见帧之间框法不一致。解决标注规范里明确雨刷遮挡超过30%的帧行人标为occluded_pedestrian框只包可见部分遮挡低于30%的帧按完整行人标。同时抽帧时避开雨刷密集时段或者把雨刷运动片段单独拿出来做增强。5.3 夜间红外补光造成行人过曝现象夜间用主动红外补光的摄像头近处行人面部过曝成白块模型学不到有效特征。原因补光功率固定距离越近越亮。解决换用自动功率调节的补光方案或者采集时手动降低近处补光强度。标注时过曝到无法辨认的行人不标避免引入噪声。如果已经采了用直方图均衡做预处理但效果有限最好重采。5.4 类别不均衡导致小类召回为零现象训练完发现child和cyclist的AP接近零。原因这两类在数据集里占比不到3%模型被pedestrian主导。解决训练时用类别加权YOLOv8可以在data.yaml里加class_weights或者用过采样把含小类的帧复制多份。更根本的办法是补采专门去学校周边和自行车道采集。5.5 测试集泄漏导致指标虚高现象验证集mAP 0.85实际路测漏检严重。原因划分时按帧随机分同一段视频的相邻帧同时进了训练集和验证集模型只是记住了场景。解决严格按视频片段划分测试集用完全没参与训练的视频。划分完用文件名的视频ID检查一遍确保没有交叉。6. 进阶技巧用半自动标注把效率翻三倍手工标3万帧一个人至少两周。我后来改成半自动流程先用COCO预训练的YOLOv8跑一遍所有抽帧把置信度高于0.5的预测导出为预标注XML再导入LabelImg人工修正。修正比从头标快得多尤其是行人密集场景模型已经把大部分框画好了人只需要删误检、补漏检、改类别。实测效率提升2到3倍。具体操作分三步。第一步用预训练模型推理yolo detect predict modelyolov8s.pt source./frames save_txtTrue \ save_confTrue conf0.5 iou0.5save_txtTrue会输出YOLO格式的预测结果conf0.5过滤低置信度框。第二步把预测结果转回VOC XML类别名统一映射到你的类别体系。注意COCO的person要映射到pedestrian骑车人COCO里可能检成person和bicycle两个框需要合并。第三步导入LabelImg人工修正。修正时重点看三类置信度在0.5到0.7之间的框、小目标框、遮挡目标框。这三类模型最容易出错。还有一个技巧是用跟踪做帧间传播。对连续帧先用ByteTrack把行人轨迹连起来只在轨迹起始帧和消失帧做人工标注中间帧用跟踪结果自动生成框。这样能把标注量再压一半。但跟踪传播的框在遮挡和交叉时会漂移所以每隔10帧要抽一帧人工校验。我自己的习惯是每做完一个版本的数据集先不急着训大模型用YOLOv8n跑10个epoch看loss曲线和混淆矩阵。如果occluded_pedestrian和pedestrian混淆严重说明遮挡标注边界没定好回去改规范比调模型参数有用得多。数据集的质量上限在标注阶段就定死了后面再怎么调参也突破不了。希望帮到你。本文还有配套的精品资源点击获取
返回列表