简介这份YOLO汽车头部尾部检测数据集面向目标检测初学者与算法工程师围绕5000张真实场景图片构建涵盖不同光照、角度与道路环境可用于车辆前后部位识别、车流量统计等应用。数据经LabelImg标注提供VOC(xml)、COCO(json)、YOLO(txt)三种格式标签分目录存放可直接接入YOLOv5、YOLOv8等训练流程。下载包共2000个文件以xml标签文件为主另含Python划分脚本、txt列表文件以及HTML环境搭建与训练教程整体约569MB。除标注数据外附赠Linux和Windows双平台的YOLO环境搭建教程、训练案例教程以及三个数据集划分脚本可自行生成训练集、验证集、测试集并复现完整训练流程脚本支持按数量或比例划分也能生成ImageSets下的txt文件便于YOLO读取。目前已有311人学习下载适合需要现成车辆检测数据与配套教程的开发者快速上手。1. 汽车头尾检测为什么值得单独建数据集停车场道闸与 ETC 场景先想清楚这 5000 张图的价值拿到一份“YOLO汽车头部尾部检测数据集”压缩包多数人的第一反应是解压、看目录、直接开训。但做过车流方向项目的工程师会先停一步车头、车尾这两个类恰好是停车场道闸、高速 ETC、加油站入口这类场景里最容易把检测模型逼到翻车的地方。通用目标检测只给一个 car 标签车头车尾混在一起检测框收敛慢、误报高把同一个目标拆成 head 和 tail 两个类别模型才能学到格栅、大灯和尾灯、牌照位置这些区分性特征。这份资源把 5000 张图连同 VOC、COCO、YOLO 三种格式标签、划分脚本和训练教程打包在一起适合正在做停车管理、车流统计、路口感知或车辆朝向判断的工程师直接拿来做原型验证。2. 拆开 .rar 看门道5000 张图的构成与 voc、coco、yolo 三种标签的真实差异2.1 为什么是 5000 张这个量级能做什么不能做什么车辆朝向检测不是通用检测那种上千类的大任务类别就两个head 和 tail。5000 张图按常规标注分布平均到每个类大约 2500 个实例这个量级对 YOLO 来说属于“中等偏小但够跑通”的范围。它能做到的事很明确训练出一个在白天、正常光照、常见车型下能稳定区分头尾的检测模型用于 demo、原型验证、算法预研。它不能做到的事同样明确直接扔到某个具体停车场做生产级识别大概率会在夜间、逆光、远距离小目标、特殊车型这些分布外样本上掉点。我一般把这类数据集当作“底模数据”先训出一个通用头尾检测器再用目标场景的少量数据做微调。5000 张还有一个隐含价值标注噪声的容忍度比 500 张高得多。配合划分脚本按 7:1:2 切分后训练集约 3500 张足以让 YOLOv8n 这类轻量模型收敛到可用的 mAP。如果压缩包里附带的是带场景差异的采集数据划分时还得留意别把同一辆车同时切进训练集和验证集这个问题后面单开一章讲。2.2 voc、coco、yolo 三种格式的坐标体系差异同一辆车三种写法三种格式对应三条不同的工具链VOC 是早期检测竞赛的 XML 格式COCO 是 JSON 格式YOLO 是训练框架直接读取的 txt 格式。很多人以为三者只是“文件后缀不同”实际坐标定义完全不同转换时错一个公式模型训练出来就是乱的。VOC 的标注文件是 XML每个目标一个object节点核心坐标存在bndbox里annotation filename00001.jpg/filename size width1920/width height1080/height /size object namehead/name bndbox xmin120/xmin ymin80/ymin xmax340/xmax ymax300/ymax /bndbox /object /annotation这段 XML 里 xmin、ymin、xmax、ymax 是像素坐标单位是整数左上角为原点。注意 xmax、ymax 不是宽高而是右下角坐标算目标宽度要用xmax - xmin。很多人在这一步把 xmax、ymax 直接当 width、height 用转出来的框全部偏大一圈。COCO 格式则是把整批数据汇总到一个 JSON 文件里images数组存图片信息annotations数组存标注。每个标注对象里的bbox字段是[x, y, width, height]x、y 是左上角坐标width、height 是宽高单位同样是像素但已经是浮点数。COCO 的area字段和iscrowd字段是另外两个容易忽略的坑转换时area可以用width * height重算iscrowd统一写 0。YOLO 格式最直接每张图对应一个同名 txt每行一个目标五个字段用空格分隔0 0.3245 0.4821 0.2648 0.2013第一个数字是类别 id后四个是归一化后的中心点 x、中心点 y、宽度、高度取值范围 0 到 1。归一化的意思是cx 等于目标中心点的像素 x 坐标除以图片宽度w 等于目标像素宽度除以图片宽度y 方向同理。这套定义和 VOC、COCO 都不同中心点和宽高的组合意味着同一目标转成 YOLO 格式后无法直接读出“左上角在哪”。格式文件组织坐标定义单位与范围VOC每图一个 XMLxmin, ymin, xmax, ymax像素整数COCO全量一个 JSONx, y, width, height像素浮点YOLO每图一个 txtcx, cy, width, height归一化 0~12.3 从 voc 到 yolo 的换算关系与三个常见误用VOC 转 YOLO 的换算公式是固定的先把 xmin、ymin、xmax、ymax 换算成中心点和宽高再除以图片尺寸。假设图片宽 W、高 Hcx ((xmin xmax) / 2) / W cy ((ymin ymax) / 2) / H w (xmax - xmin) / W h (ymax - ymin) / HCOCO 转 YOLO 更简单因为 COCO 的 bbox 已经是左上角加宽高只需要把x width / 2再除以 W。三个常见误用每一个我都看人踩过。第一个是把 xmax、ymax 当宽高转换后目标宽度被放大一倍。第二个是忘了归一化直接把像素坐标写进 YOLO txt训练时损失函数直接爆掉。第三个是归一化时用了训练时的 resize 尺寸而不是原图尺寸比如训练时 imgsz 设为 640就用 640 做分母但标注时框是在原图上画的分母必须用原图宽高否则框的位置全部错位。这里顺带提一句如果你后续要碰遥感旋转框检测比如 DOTA 这类数据集坐标体系又完全不一样单目标要用四点角点坐标表示MMRotate 处理的是那种带角度的格式和汽车头尾检测这种水平框正交坐标系不是一个套路别把转换脚本混用。3. 划分脚本怎么落地用 Python 把单目录数据集切成 train / val / test 并校验三格式标签3.1 最小可用的 7:2:1 随机划分脚本标题里提到“划分脚本”这是整个资源包里使用频率最高的工具。常见的数据集组织方式是 images 目录放图片labels 目录放 YOLO 格式 txtvoc 目录放 XMLcoco_annotations.json 汇总 COCO 标注。划分的目标是把这个单目录结构切成 train、val、test 三个子集并且三种格式的标签同步迁移。下面这个脚本以图片文件名为主键做划分对 5000 张图这个规模完全够用固定随机种子后两次运行结果一致 divide_dataset.py 把单目录 images / yolo_labels / voc_labels 按 7:1:2 切成 train/val/test 同步迁移 YOLO txt 与 VOC xml并根据迁移结果重建 COCO json。 import json import random import shutil from pathlib import Path IMG_SUFFIX {.jpg, .jpeg, .png} RANDOM_SEED 42 RATIO (0.7, 0.1, 0.2) # train:val:test def main(images_dir, labels_dir, voc_dir, coco_annotation, out_dir): images_dir Path(images_dir) labels_dir Path(labels_dir) voc_dir Path(voc_dir) out_dir Path(out_dir) out_dir.mkdir(parentsTrue, exist_okTrue) random.seed(RANDOM_SEED) # 固定种子保证划分结果可复现 image_files [p for p in images_dir.iterdir() if p.suffix.lower() in IMG_SUFFIX] image_files.sort() random.shuffle(image_files) n len(image_files) n_train int(n * RATIO[0]) n_val int(n * RATIO[1]) # 文件名不含后缀作为主键避免列表顺序和标签顺序不一致 splits {} for i, img in enumerate(image_files): if i n_train: splits.setdefault(train, []).append(img) elif i n_train n_val: splits.setdefault(val, []).append(img) else: splits.setdefault(test, []).append(img) for split, files in splits.items(): im_dst out_dir / split / images lb_dst out_dir / split / labels voc_dst out_dir / split / voc im_dst.mkdir(parentsTrue, exist_okTrue) lb_dst.mkdir(parentsTrue, exist_okTrue) voc_dst.mkdir(parentsTrue, exist_okTrue) for img in files: stem img.stem shutil.move(str(img), str(im_dst / img.name)) for label_path in (labels_dir / f{stem}.txt, voc_dir / f{stem}.xml): if label_path.exists(): dst lb_dst if label_path.suffix .txt else voc_dst shutil.move(str(label_path), str(dst / label_path.name)) # COCO 的 annotation 是一个整体 json按子集重写 images 与 annotations with open(coco_annotation, r, encodingutf-8) as f: coco json.load(f) img_id_to_name {img_info[id]: img_info[file_name] for img_info in coco[images]} for split, files in splits.items(): keep_ids set() for img in files: for img_id, fname in img_id_to_name.items(): if Path(fname).stem img.stem: keep_ids.add(img_id) break sub_images [img_info for img_info in coco[images] if img_info[id] in keep_ids] sub_anns [ann for ann in coco[annotations] if ann[image_id] in keep_ids] split_json { info: coco.get(info, {}), licenses: coco.get(licenses, []), categories: coco[categories], images: sub_images, annotations: sub_anns, } with open(out_dir / split / coco_annotations.json, w, encodingutf-8) as f: json.dump(split_json, f, ensure_asciiFalse, indent2) for split, files in splits.items(): print(f{split}: {len(files)} images) if __name__ __main__: main( images_dirdatasets/images, labels_dirdatasets/yolo_labels, voc_dirdatasets/voc_labels, coco_annotationdatasets/coco_annotations.json, out_dirdatasets/split, )脚本里有两个关键设计。第一随机打乱前先sort()保证在不同机器上运行得到相同顺序配合固定随机种子让划分结果可复现。第二迁移标签时用img.stem拼标签文件名而不是遍历目录列表后按索引对齐这样即使 images 目录和 labels 目录的文件顺序不一致也不会错位。COCO 那部分需要单独说明COCO 是一个汇总的 JSON不能像 txt 那样直接移动文件必须按划分后的 image_id 集合重建子集 JSON。上面代码的做法是先建立 image_id 到文件名的映射再根据图片主键反向找到该图在 COCO 里的 id最后过滤 images 和 annotations 两个数组。5000 张图规模下线性扫描没问题数据量到 5 万张时建议先把 file_name 到 id 的映射建成字典再查。3.2 用校验脚本把“图像-标签”错位一次查清划分迁移完并不代表数据一定正确我见过太多案例是训练跑了一半才发现 labels 目录里有孤儿标签或者某张图在 VOC 里有标注、在 YOLO 里却是空文件。下面这个校验脚本以图片为基准检查 YOLO txt 是否存在、字段是否完整、坐标是否在合法范围内同时检查同名 VOC xml 是否存在 check_labels.py 以图片文件名为基准检查 yolo / voc 标签是否齐全且坐标合法。 import json from pathlib import Path from PIL import Image IMG_SUFFIX {.jpg, .jpeg, .png} def check_yolo(txt_path, img_w, img_h): problems [] for line in txt_path.read_text(encodingutf-8).strip().splitlines(): parts line.split() if len(parts) ! 5: problems.append(f字段数不是 5: {line}) continue try: cls_id int(parts[0]) cx, cy, w, h (float(v) for v in parts[1:]) except ValueError: problems.append(f含无法解析的数字: {line}) continue if cls_id not in (0, 1): problems.append(f类别 id 越界: {line}) if not (0 cx 1 and 0 cy 1): problems.append(f中心点坐标超出归一化范围: {line}) if not (0 w 1 and 0 h 1): problems.append(f宽高超出归一化范围: {line}) # 换算回像素确认目标没有完全超出图像边界 x (cx - w / 2) * img_w y (cy - h / 2) * img_h if x 0 or y 0 or x w * img_w img_w or y h * img_h img_h: problems.append(f目标超出图像边界: {line}) return problems def main(images_dir, labels_dir, voc_dir): errors 0 for img_path in Path(images_dir).iterdir(): if img_path.suffix.lower() not in IMG_SUFFIX: continue stem img_path.stem txt_path Path(labels_dir) / f{stem}.txt if not txt_path.exists(): print(f[缺失] {img_path.name} 没有对应的 yolo txt) errors 1 continue with Image.open(img_path) as img: img_w, img_h img.size for problem in check_yolo(txt_path, img_w, img_h): print(f[坐标异常] {img_path.name}: {problem}) errors 1 voc_path Path(voc_dir) / f{stem}.xml if not voc_path.exists(): print(f[缺失] {img_path.name} 没有对应的 voc xml) errors 1 print(f检查完成共发现 {errors} 个问题) if __name__ __main__: main( images_dirdatasets/split/train/images, labels_dirdatasets/split/train/labels, voc_dirdatasets/split/train/voc, )这个脚本用 PIL 读图片宽高用它作为坐标合法性的判断基准。很多人只检查 YOLO txt 的数值范围在 0 到 1 之间但归一化坐标在 0 到 1 之间只能说明格式合法不能说明目标在图像内比如一张 1920×1080 的图上写了一个0.9 0.9 0.4 0.4的框换算回去大部分区域已经超出画面这类标签会造成训练时 loss 异常波动。加一道“换算回像素再判断边界”的检查能直接过滤这种脏数据。校验脚本建议在划分后、训练前各跑一次。划分后跑能发现迁移丢文件的问题训练前跑能发现坐标异常的问题。5000 张图的校验时间通常在一两分钟内这个成本值得付。3.3 划分后的目录组织训练命令、数据配置与推理路径划分脚本跑完输出目录结构应该是这样的无论你后续用 YOLOv5、YOLOv8 还是其他框架这个结构都能直接对接datasets/split/ ├── train/ │ ├── images/ │ ├── labels/ │ ├── voc/ │ └── coco_annotations.json ├── val/ │ ├── images/ │ ├── labels/ │ ├── voc/ │ └── coco_annotations.json └── test/ ├── images/ ├── labels/ ├── voc/ └── coco_annotations.jsontrain 和 val 子集用于训练曲线和模型选型test 子集只在最终评估时用一次用来模拟真实发布效果。我习惯在划分脚本里额外输出一份 class_ids.txt记录类别顺序比如第一行 head、第二行 tail这份文件在后面配置 YOLO 的 data yaml 时是唯一的类别顺序依据能避免目录结构变了、类别顺序也跟着乱的问题。4. 用 YOLOv8 训练汽车头尾模型环境配置、数据 yaml 与三个必调参数4.1 环境配置用最小命令装好 ultralytics 并确认 GPU 可用yolov8 训练自己的数据集第一步不是改代码而是确认环境干净。按最小可用原则只需要一个 Python 3.9 以上的虚拟环境加两个安装步骤pip install ultralytics python -c import torch; print(torch.__version__, torch.cuda.is_available())第二条命令输出True说明 CUDA 版 PyTorch 可用如果输出False训练会掉到 CPU5000 张图、100 个 epoch 在 CPU 上要跑十几个小时基本不可接受。yolo 环境配置最常见的问题是先装 ultralytics 再装 torch导致 ultralytics 自动装了一个 CPU 版 torch后面怎么调都用不上 GPU。顺序应该是先确认 torch 和 CUDA 匹配再装 ultralytics。第一次训练时框架会自动下载 yolov8n.pt 或 yolov8s.pt 预训练权重这是 YOLO 系列迁移学习的常规做法用 COCO 上训好的权重做初始化能显著缩短收敛时间。yolov5 到 yolov8 在这条数据链路上一脉相承标签格式和训练命令差别不大区别主要在模型结构不影响你处理这份数据集的方式。4.2 数据 yaml 与 class 顺序一致的配置方法YOLOv8 用 data yaml 描述数据集路径和类别名这是最容易配错的文件。在 datasets/split 目录下新建 data.yaml# data.yaml path: datasets/split train: train/images val: val/images test: test/images nc: 2 names: 0: head 1: tailpath是相对于你运行训练命令的工作目录的根路径train、val、test都写相对 path 的子目录。这里最关键的约束是names列表的顺序必须和 YOLO txt 里每行第一个数字的语义一致如果划分脚本输出 class_ids.txt 第一行是 head那 names 的索引 0 必须对应 head索引 1 对应 tail。这个顺序问题隐蔽在“看起来没问题”里。VOC 的 XML 里目标名是字符串COCO 的 categories 里有 name 字段但 YOLO 的 txt 只存数字数字的含义全靠 data.yaml 里的顺序定义。如果划分脚本转换时把类别列表按文件扫描顺序排成了 head、tail而 data.yaml 里写成 tail、head训练全程不会报错但预测结果里所有 head 都被标记成 tail。4.3 三个必调参数imgsz、epochs、batch 的取值逻辑训练命令本身不长参数才是决定模型好坏的核心yolo detect train \ datadatasets/split/data.yaml \ modelyolov8s.pt \ epochs100 \ imgsz640 \ batch16 \ patience20参数常用值直接影响imgsz640 或 960远处车头尾灯占比小imgsz 越大小目标特征越完整epochs100 起步配合早停防止欠拟合和过拟合同时出现batch16~64影响 BatchNorm 稳定性和单 epoch 耗时imgsz 是这三个参数里最值得花时间调的。汽车头尾检测的难点在远距离小目标一张 1920×1080 的图里距离 50 米的车头可能只有 60×40 像素缩到 640 边长后只剩 20×13 像素左右几乎等于一个点。我一般先按 imgsz640 跑通流程确认数据没问题后再用 960 复训一次对比两个模型的 mAP 变化。960 的训练时间大约是 640 的 2.2 倍但小目标召回率通常有明显提升。epochs 放到 100 是因为预训练权重会把大部分特征复用过来一般 50 到 80 个 epoch 已经收敛100 只是给足余量。patience 设为 20val loss 连续 20 个 epoch 不下降就早停避免无效训练时间。batch 的取值受显存限制yolov8s 在 16GB 显存上 batch16 比较稳V100 这类 32GB 大显存可以直接放宽到 64。batch 太小会让 yolo 损失函数曲线抖动明显BatchNorm 的统计量也不稳定所以宁可降低 imgsz 也要保证 batch 不低于 8。4.4 训练完成后怎么判断收敛混淆矩阵、PR 曲线与 mAP训练结束后runs/detect/train 目录下会生成 confusion_matrix.png、PR_curve.png、results.csv 等文件。判断模型是否真的学会区分车头车尾按这个顺序看第一看 results.csv 里的 train/val loss 曲线正常情况是两条曲线同步下降并趋于平缓val loss 在后期小幅波动是正常的持续不降或反向上升才是问题。第二看 PR_curve.pnghead 和 tail 两条曲线越靠近右上角越好注意 tail 的曲线通常会比 head 差一点因为车尾外观在不同车型间差异更大。第三看 confusion_matrix.png重点看 head 被预测成 tail 以及 tail 被预测成 head 的比例。如果这三项都正常再记下命令行输出的 mAP50 和 mAP50-95 两个数字。mAP50 是 IoU 阈值 0.5 下的均值平均精度对车辆检测任务来说超过 0.85 算可用的原型模型mAP50-95 更严格通常在 0.6 到 0.7 之间这个数字决定了后续做模型选型时是保留 yolov8s 还是换回 yolov8n。如果这套流程需要跑很多组对比也可以把 data.yaml 和训练命令接到 Ultralytics HUB 这类开源训练平台上托管但判断模型好坏还是得回到这几个指标上。5. 汽车头尾检测的 5 个避坑记录标签错位、BN 崩溃和混淆矩阵之谜5.1 换格式后标签错位一张图三个文件不在同一子集现象训练集能正常加载但 val 的 mAP 极低随机抽图检查发现 YOLO txt 对应的框和图片内容完全对不上。原因资源包在生成三种格式时如果 VOC 的 XML 列表和 YOLO 的 txt 列表分别用不同的遍历顺序导出比如一个按文件名排序、另一个按标注时间排序后续划分脚本再按目录列表索引做 zip 配对就会把 A 图的标签贴到 B 图上。解决划分前先做一次基于文件名主键的对齐检查确认每张图的三个格式标签都指向同一个 stem。用第 3.2 节的校验脚本检查时再额外打印 size 为 0 的 txt 文件和 XML 里 filename 与图片名不一致的记录这两种情况都是错位的前兆。5.2 随机划分把同一辆车同时塞进 train 和 val现象mAP 很高但在 test 集或真实场景里明显掉点典型的“验证集虚胖”。原因车辆数据集通常来自连续视频帧或连续连拍同一辆车在几帧内外观几乎不变。随机划分按单张图打散同一辆车的前后帧可能一张进 train、一张进 val模型等于提前“见过”验证集内容指标虚高换到新场景就露馅。解决按场景或时间段做组划分而不是按单帧随机划分。如果图片文件名里有场景前缀或时间戳比如camera_03_000012.jpg就把camera_03作为分组键同一组的所有帧必须进同一个子集。如果文件名没有结构化信息退一步的做法是划分前先聚类相似图片或者至少保证同一文件序号段内连续 30 帧不分家。5.3 yolov8 训练中 BN 崩溃导致 loss 变 NaN现象训练跑到第几个 epochloss 突然变成 nan曲线直接断掉后续所有 epoch 的 loss 都是 nan。原因两个来源。一是 batch 太小加上学习率太大BatchNorm 的统计量在少量样本上剧烈波动数值不稳定二是标签里有 nan 或 inf 坐标比如 YOLO txt 某一行写了0 nan 0.5 0.2 0.3前向传播时 loss 算到这一项直接爆掉。解决先用第 3.2 节的校验脚本查标签坐标重点看有没有 nan、inf 字段。标签没问题再调训练参数把 batch 提到至少 16学习率从默认值往下调一个数量级。我习惯在训练命令里显式加lr00.001对 5000 张图的中等规模数据集这个值比默认的 0.01 更稳代价是收敛略慢但不会翻车。5.4 confusion matrix 总和对不上样本数现象验证集总共就几百个目标但画出来的混淆矩阵里head 行和 tail 行的数字加到一块远大于目标总数甚至每行数字看起来都像单独归一化过的。原因Ultralytics 默认保存的 confusion matrix 是 normalize 过的每行按该类别实际样本数归一化到 0 到 1行内比例相加才等于 1整行数字跨行直接相加没有意义。这是 yolo 混淆矩阵总合不唯一的常见原因不是模型出了问题。解决看绝对计数时读 runs/detect/train/confusion_matrix.json 或者用plotFalse参数重新生成原始计数矩阵不要在 PNG 图上人工相加对比。如果要对比两个模型的混淆矩阵统一都用归一化版本只看对角线数值的差异和 head、tail 两个非对角元素的相对大小。5.5 类别名大小写不一致带来的隐蔽灾难现象VOC 标签里目标名大小写不统一比如一部分写 head、一部分写 HeadCOCO categories 里写成 HEAD。转换到 YOLO 后同一个语义目标被分成了多个类别 id。原因VOC 转 YOLO 时通常用一个类别名字典做映射字典里没有覆盖到的写法会被当成新类别追加到列表末尾。如果原始标注就是多人协作完成的大小写不统一几乎必然出现类别数从 2 悄悄变成 3 或 4训练时模型学得一团糟但 val loss 看起来又很正常。解决在训练前统计整个标签目录里出现过的所有类别字符串做一次归一化映射全部转成小写再合并。校验脚本里加一道断言类别 id 必须严格等于 0 或 1任何 2 以上的 id 直接判失败。这道断言能把这个坑挡在训练前。6. 用预测可视化与分错统计验证模型真的学会分车头6.1 用类别过滤与分错统计验证头尾模型“学对了”训练完的 best.pt 到底靠不靠谱我很少只看 mAP 数字而是直接对 val 集做一次批量预测然后按类别做分错统计。第一步用 YOLO 自带的预测命令yolo detect predict \ modelruns/detect/train/weights/best.pt \ sourcedatasets/split/val/images \ save_txtTrue \ save_confTrue预测结果里每张图对应一个同名 txt里面每行是class_id cx cy w h conf和训练标签格式一致可以直接和 ground truth 做比对。第二步写一个小脚本按真实类别和预测类别统计混淆重点看 tail 被预测成 head 的比例from pathlib import Path gt_dir Path(datasets/split/val/labels) pred_dir Path(runs/detect/predict/labels) confusion {head-head: 0, head-tail: 0, tail-tail: 0, tail-head: 0} for gt_file in gt_dir.glob(*.txt): pred_file pred_dir / gt_file.name if not pred_file.exists(): continue gt_cls {int(line.split()[0]) for line in gt_file.read_text().splitlines()} pred_cls {int(line.split()[0]) for line in pred_file.read_text().splitlines()} for g in gt_cls: for p in pred_cls: key f{head if g 0 else tail}-{head if p 0 else tail} confusion[key] 1 total sum(confusion.values()) for k, v in sorted(confusion.items()): print(f{k}: {v} ({v / total:.1%}))统计结果里如果 tail-head 的比例超过 15%说明车尾特征里有相当一部分和车头重合典型是远处车辆的尾部轮廓和头部轮廓几乎一样。这时候不要急着加数据先看预测可视化图把 head 预测画成红色框、tail 画成蓝色框逐张翻图确认误检是不是集中在远距离小目标上。如果是优先用第 4.3 节的方法把 imgsz 提到 960 复训一轮通常比盲目加数据更有效。我现在的习惯是拿到任何车辆朝向数据集先随机抽 20 张图把三种格式的画框结果叠在原图上扫一遍头尾标签不对齐的图超过 2 张就退回上一环节别急着开训。这个习惯帮我挡掉过至少三次返工——标注问题在数据准备阶段暴露的成本远低于训练跑完再回头排查的成本。希望帮到你。本文还有配套的精品资源点击获取
企业数字化 ERP 产品动态
相关推荐
libcef.dll 缺失报错全解析:从排查到修复的完整指南 1. 从报错弹窗说起:M9OLUM4P.exe 和 libcef.dll 到底是什么关系如果你在 Windows 上运行某个程序时突然弹出"系统找不到 libcef.dll 文件"或者"由于找不到 libcef.dll,无法继续执行代码",先别急着把锅甩给系统或者杀毒软… · 2026/9/26 18:20:40
ETestDEV5通信协议管理:从界面布局到报文配置实战 说实话,很多第一次打开ETestDEV5通信协议管理界面的朋友,都会有那么几秒钟的懵。左边一棵树,中间一堆表格,右边一个属性栏,看上去和常见的组态软件有点像,但真要动手把自己的报文配出来,又不知道… · 2026/9/26 18:20:40
AgentScope实战:多智能体协作、RAG服务化与Java落地指南 两年前我第一次看到一个能让几个大语言模型像同事一样互相传话、分工干活的开源项目时,我的第一反应是:这玩意儿是给实验室玩儿的吧。直到自己上手把AgentScope系统跑起来,在一台普通的开发机上把三个模型串成一个“虚拟小组”,我… · 2026/9/26 18:20:40
金融服务项目实战:账户、支付、风控与合规全链路拆解 做金融科技的朋友大概都有同感:见过太多“financial-services”项目挂着一个笼统的名字,实际落地时却不知道从哪里下刀。我一直觉得,这类项目的难点不在于写代码,而在于你心里有没有一套完整的金融服务认知框架。这篇内容想围绕我… · 2026/9/26 20:24:18
本地部署AI Agent自动剪辑:OpenMontage全流程实测 坦白说,我最初对这个项目完全不看好。一条视频从选题、文案、找素材、配音到粗剪精剪,中间隔着的不是某个单点工具能搞定的,而是整条流水线。而我要测的东西恰恰是最容易被质疑的一环:AI Agent 能不能把这活儿全包了,而… · 2026/9/26 20:24:12
Flutter鸿蒙适配实战:纯Dart统计库stats的踩坑与治理 最开始接手这个活儿的时候,我其实没太当回事。从 Android/iOS 把 Flutter 应用迁到鸿蒙的过程里,真正让人头疼的是那些带着原生壳的三方插件,而 stats 这种老牌统计库怎么看都不该有麻烦——它是纯 Dart 写的,不走 Platform Chann… · 2026/9/26 20:24:00
OpenClaw+阿里云轻量服务器:个人AI助理部署全教程 最近一直在折腾个人AI助理,试了不少开源项目,最后留在OpenClaw上没换。这东西本质上是一个可以常驻在你服务器上的AI Agent,能接到飞书、Teams、Telegram这些聊天工具里,让它替你查资料、跑自动化、管理消息流。配合阿里云轻量服务… · 2026/9/26 20:24:00
可信数据空间×区块链:2026数据基础设施底座技术拆解 1. 为什么2026年要谈“可信数据空间 区块链”2026年还没到,但圈子里的讨论已经明显从“要不要上区块链”变成了“怎么让区块链真正长在数据流通的管线上”。我今年参与的几个数据空间项目,几乎都在同一个交叉点上打转:可信数据空间 区块链&… · 2026/9/26 20:24:00
可信数据空间与区块链:构建跨域数据流通的信任底座 这几年做数据要素相关项目,我最大的感受是:数据流通的瓶颈早就不是存储、计算这类硬技术了,而是信任。数据在自家系统里怎么跑都行,一旦要跨组织、跨行业、跨地域去共享,谁都不敢轻易把核心数据交出去。2026年被反复提… · 2026/9/26 20:24:00
数据库课后习题答案别硬背:当测试用例集刷,效率翻倍 简介:万常选版《数据库原理与设计》课后习题答案资源,覆盖第2至6章及第9章,适合正在学习关系模型、数据库建模、关系数据理论与模式求精的本科生、自学者作为复习与自测材料。压缩包共7个文件,含3个doc参考答案、2个sql示例脚本、… · 2026/9/26 0:00:21
OpenClaw 替代品?Hermes Agent 踩坑实录:macOS 飞书接入 TaoToken 配置 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 0:00:40
向下兼容与向上兼容:接口设计中的兼容性策略与工程实践 一次版本升级事故,是很多团队绕不过去的坎。线上环境里,服务端明明已经上线了新版接口,老的移动端还在照着旧文档传参数。请求一到网关,校验直接拒绝,用户操作失败,客服群炸了锅,开发群里开始互… · 2026/9/26 0:00:46