
简介这套全自动标注工具基于YOLOv5实现批量图片自动标注面向已训练好模型、需要快速产出XML标注文件的计算机视觉开发者能大幅降低手工框选成本。压缩包共135个文件大小约13.94MB核心包括Python脚本如detect_auto.py图形界面入口、YAML/yml配置、PyTorch权重、Shell辅助脚本、Markdown说明及少量样例XML/图片覆盖运行环境配置与标注输出两大环节。使用流程清晰把.pt权重和对应.yaml配置放入data文件夹在detector_classes.txt中指定类别将待标注图片放入images目录运行detect_auto.py即可在Annotation文件夹生成可用LabelImg查看的结果模块划分便于按需替换。已有3190人学习下载适合需要解放双手、快速扩充目标检测数据集的开发者包内文档和示例可帮助快速迁移到自身项目。1. 全自动标注工具遇上 YOLOv5先搞懂它在替你省哪段力标注一直是 YOLOv5 训练里最劝退的环节一个安全帽检测项目要标两万张图框到手抽筋。出现「全自动标注工具支持 YOLOv5」之后很多人第一反应是输入图片就吐标签、直接可以 train但实际用起来根本不是这么回事——它做的是「用模型给未标注图生成伪标签pseudo label」再转成 YOLOv5 能吃的 txt 格式人工只负责抽检和修正。这个方向能解决的是「标注人力不够、时间紧、类别相对固定」的项目适合已经跑通过一版 YOLOv5、手里有几百张干净人工标签的团队和个人开发者。新手也能跟这套流程走下来但前提是先搞懂它省的是哪段力、哪些环节还得靠你。2. 先分清三种「自动标注」流派别把选型做成玄学2.1 三种流派的核心区别候选框从哪来市面上叫「全自动标注」的工具内部机制差别很大选错流派后面全盘翻车。按候选框来源我习惯拆成三类模型预标注流用一个训练好的检测模型YOLOv5 权重、YOLOv8 权重、甚至自家上次训练的模型对未标注图像做推理把检测框置信度大于阈值的对象转成标注文件。这类是最接近 YOLOv5 工作流的输出天生就是 cx, cy, w, h 归一化格式转换成本最低适合「已有模型 新一批同类图片」的增量标注场景。交互分割流基于 SAM 这类分割模型的工具用户点几下生成掩膜再转成外接矩形框。它的精框能力很强适合轮廓复杂的实例但每张图都需要点击交互属于「半自动」而非「全自动」大批量场景下并没有真的解放双手。纯传统 CV 流用颜色空间、背景建模、边缘检测去自动提候选框。对背景干净、目标与背景颜色差异大的图像有效但一到夜间、反光、遮挡场景就崩迁移性差我基本只在采集设备固定、场景单一的生产线上用它。如果标题里说的「全自动标注工具」没有绑定具体算法默认优先按「模型预标注流」来做因为它的中间产物检测框和 YOLOv5 的标签格式是同构的落地成本最小。2.2 我的选型决策顺序先看有没有「能用的模型」能不能让「自动标注」这个词成立前提是你手里已经有一个能出框的模型。决策顺序我一般是这样如果目标类别和已有模型类别重叠直接用那个模型跑伪标签这是最快路径如果没有现成模型但能找到同类公开权重比如 YOLOv5 官方在 COCO 上的预训练权重先用它对目标类别做一次粗标、人工清理后训练第一版小模型再用这版小模型去做第二批自动标注迭代起来只有上面两条路都不通才考虑交互分割或传统 CV 方案。「完全从零开始自动标注」是不存在的。你至少要准备 50200 张人工标注的种子数据训练一个初始模型后面所谓的「全自动」才有基座。 把种子数据集单独放一个目录别跟自动生成的伪标签混在一起后面做模型效果对比时能省很多事。2.3 YOLOv5 标注格式回顾自动标注的产物最终要落到这四行数YOLOv5 数据集的标签文件是 txt跟图片同名放在labels/目录映射位置每行一个目标class_id x_center y_center width height这四个值都是相对于图片宽高的归一化值0~1不是像素坐标。自动标注工具无论内部跑的是什么模型最终都要把检测结果换算成这个格式。常见误区是拿目标检测输出的x1, y1, x2, y2像素坐标直接写入 txt也不归一化YOLOv5 跑训练就报「all bounding boxes are zero」或者 loss 为 nan。所以在选型时优先考虑「输出能直接映射到 yolo 格式」的工具其次才是考虑它标注的框精不精。人工标注软件导出的 XML/JSON 还要再走一步转换脚本多一个中转就是多一层出错风险。3. 用已有 YOLOv5 模型做全自动标注一套能落地的流程3.1 准备工作目录结构、环境检查、权重和置信度参数整个自动标注流程我习惯把它做成一个独立的 workspace 目录不跟训练目录混在一起tree -L 2 workspace workspace ├── images_unlabeled # 待标注原始图jpg/png ├── images_labeled # 种子数据集人工标注过用于训练初始模型 ├── labels_labeled # 种子数据集的 yolo 标注 txt ├── runs # 自动标注推理输出 ├── pseudo_labels # 生成的伪标签目录 └── weights # 初始模型权重放这里执行自动标注前要先把环境和权重准备好常见做法是把推理脚本放到项目根目录下统一管理# 在 conda 环境里安装好依赖后先跑通一遍官方推理做验证 conda activate yolov5-env cd yolov5 python detect.py --weights ../workspace/weights/best.pt --source ../workspace/images_unlabeled --conf-thres 0.35 --save-txt以上的--save-txt参数表示把检测结果以 txt 形式输出YOLOv5 会在runs/detect/exp*/labels/下生成与图片同名的标签文件。这里输出的标签像素坐标单位是像素下一步要自己转成归一化格式。如果 detect 能正常出框说明权重和环境都没问题可以进入批量处理阶段。如果一张框都没出来先别急着调--conf-thres下限优先去确认images_unlabeled里的图像尺寸、通道数和你训练时是否一致。3.2 批量推理并转出 YOLOv5 伪标签具体转换脚本官方 detect.py 每次输出会新建 exp 目录不方便直接当批处理工具用。我一般会写一个独立的转换脚本只加载模型权重、跑推理、解析结果、按 YOLO 格式写出 txt。这样每一步的错误都好定位不用去读 detect.py 那一大坨可视化代码。import os import cv2 import torch import numpy as np # 加载模型 model torch.hub.load(ultralytics/yolov5, custom, pathweights/best.pt, force_reloadFalse) model.conf 0.35 # 置信度阈值种子模型好用时可调到 0.5 model.iou 0.5 # NMS 的 IoU 阈值目标密集时建议下调到 0.4 src_img_dir images_unlabeled dst_label_dir pseudo_labels os.makedirs(dst_label_dir, exist_okTrue) for img_name in os.listdir(src_img_dir): if not img_name.lower().endswith((.jpg, .jpeg, .png)): continue img_path os.path.join(src_img_dir, img_name) img cv2.imread(img_path) if img is None: print(f跳过无法读取的图像: {img_path}) continue h, w img.shape[:2] results model(img[:, :, ::-1]) # BGR 转 RGB与训练时预处理保持一致 boxes results.xyxy[0].cpu().numpy() # 每一行: x1, y1, x2, y2, conf, class_id base_name os.path.splitext(img_name)[0] lines [] for x1, y1, x2, y2, conf, cls_id in boxes: int_cls_id int(cls_id) # 像素坐标转归一化中心点 宽高 cx ((x1 x2) / 2) / w cy ((y1 y2) / 2) / h bw (x2 - x1) / w bh (y2 - y1) / h # 越界保护避免出现负数或大于 1 的归一化值 cx max(0.0, min(cx, 1.0)) cy max(0.0, min(cy, 1.0)) bw max(0.0, min(bw, 1.0)) bh max(0.0, min(bh, 1.0)) lines.append(f{int_cls_id} {cx:.6f} {cy:.6f} {bw:.6f} {bh:.6f}) if lines: with open(os.path.join(dst_label_dir, base_name .txt), w) as f: f.write(\n.join(lines) \n) else: # 没有检测到目标的图也留一个空 txt保证训练时不报缺标签错 open(os.path.join(dst_label_dir, base_name .txt), w).close() print(f伪标签生成完成共处理 {len(os.listdir(src_img_dir))} 张图片标签保存至 {dst_label_dir})这个脚本里的关键参数有三个model.conf是置信度阈值设置太高漏检多、设置太低会引入大量背景误检0.35 是起步值model.iou是 NMS 的 IoU 阈值图中目标密集交叠时往下调到 0.4目标稀疏可以保持 0.5img[:, :, ::-1]是 BGR 转 RGB是因为模型训练时用的 OpenCV 读图是 BGR而 PyTorch Hub 加载的模型预期输入是三通道 RGB通道顺序不一致会让检测结果明显变差这是一个非常隐蔽的坑。3.3 把伪标签接回 YOLOv5 训练数据组织与初次验证生成的伪标签需要放到数据集的 labels 目录里才能训练。注意 YOLOv5 的数据配置 yaml 里train和val路径指向的是 images 目录但每个 labels 目录必须和 images 目录同级且目录名必须是labels。也就是说你的完整结构应该是dataset/ ├── images/ │ ├── train/ # 含种子人工标注图 自动标注图 │ └── val/ # 建议只放种子数据集里抽出来的人工标签图 └── labels/ ├── train/ └── val/训练前用一个快速脚本检查伪标签和图片是否一一对应这一步能省掉后续大量「标签错位」的报错排查# 检查两张图片的标签是否数量匹配调试用 python - EOF import os img_dir dataset/images/train label_dir dataset/labels/train img_names set(os.listdir(img_dir)) label_names set(os.listdir(label_dir)) missing [n for n in img_names if os.path.splitext(n)[0] .txt not in label_names] print(f缺失标签的图像数: {len(missing)}) for m in missing[:10]: print(m) EOF跑完检查之后先只用「种子人工标注 这个脚本生成的伪标签」混合训练 50 轮观察val集的 mAP 变化。这一步如果 mAP 没有明显下降说明伪标签质量可以接受再考虑放大量的全自动标注数据进去。4. 伪标签翻车案例与参数修正踩过的 5 个坑4.1 图像通道顺序搞反框全部偏到边缘现象单张测试图片检测结果全乱框不在目标上整体偏到图的一角或边缘。原因cv2.imread读进来是 BGR 数组直接塞给 PyTorch Hub 模型时如果模型内部用了 RGB 预处理输入分布完全错位。解决在推理前统一img[:, :, ::-1]转成 RGB或者干脆全程只用 PIL 读图并转成 RGB。核心是保证「训练时图片进模型的顺序」和「推理时图片进模型的顺序」一致推荐在脚本开头打一行日志打印输入的 shape 和通道均值翻车时方便定位。4.2 置信度阈值过低伪标签污染训练集现象自动标注结果里有大量背景误检框比如把栏杆、阴影、远处的路人全框进去了用了这些标签训练后模型的精确率明显下降误检变多。原因置信度阈值model.conf设太低比如 0.1模型把低置信度预测也当成可信标注输出。低置信度预测在检测任务里本来是用来提示「这里有疑似目标」但自动标注场景里它不区分 TP 和 FP。解决先把阈值调到 0.5 跑一批人工抽查 50 张图的标注质量如果框偏保守漏检多但框出的都准再每次降 0.05 往下试探直到找到「漏检和误检平衡」的点。降阈值的过程必须配人工抽检不能直接交给训练脚本。4.3 归一化坐标越界训练 loss 异常现象训练到一半 loss 突然变成 nan或者日志里有 warning 提示某张图的框宽高为负。原因模型在图像边缘预测的框坐标可能会超出图像边界例如 x2 大于图像宽度转换脚本里没有做边界截断归一化后宽高出现负值或大于 1 的值。解决转换公式里写max(0.0, min(value, 1.0))做截断但要注意这只是「止血」。根治要靠 NMS 后过滤掉极端坐标if x2 - x1 1 or y2 - y1 1: continue这种框大概率是误检或边缘噪声不该进入训练集。4.4 空标签文件不等于无目标类别遗漏让模型失忆现象自动标注完的类别比真实类别少很多尤其是小目标类别几乎全丢了模型训练后对小目标检测能力明显退化。原因目标太小、置信度太低被阈值过滤掉了脚本只输出有检测结果的文件没检测到就留空相当于告诉模型「这张图里没有这个类」。解决把空标签情况单独记录到一个skipped_images.txt里批量结束后抽查这些图如果某类目标频繁漏检就考虑把这个类别单独做一次「小目标增强」的模型微调或者对这批图人工补标。全自动标注的便宜不能把稀缺类别丢掉这是血泪经验。4.5 训练集和自动标注集分布不一致越标越偏现象在训练集上 mAP 很高但到新场景测试时泛化很差框不出来了。原因自动标注大量使用后新图片的分布逐渐偏移换了摄像头角度、光照条件变化模型在自我标注的循环里不断强化旧分布越标越偏离真实场景。解决每次自动标注后从images_unlabeled里随机抽 10% 图片强制人工标注混进训练集。相当于给自动标注管线注入「新场景锚点」。我做自动标注时有一个硬性习惯每批次至少保留 50 张人工标注的新场景图作为下次迭代的种子集。效果比单纯加大自动标注量更稳。5. 验证自动标注质量三类指标和一次漏检翻车修复伪标签到底能不能用不能靠感觉要靠「抽检 指标 人工修正」三重验证。我每批自动标注完成后会做三个动作第一抽检 50 张图叠加画框。把生成的 txt 转回像素框画在图上肉眼扫一遍把所有「明显误检」和「明显漏检」的张数记录下来误检率超过 10% 就直接调高置信度阈值重跑。这一步是最终的人工防线不需要每张都看但一定要保证覆盖不同光线、不同角度。第二用人工标签子集算伪标签的召回。从种子数据集里分出 200 张图先不参与自动标注等伪标签生成后统计这 200 张图里伪标签命中了多少个人工标注目标。命中公式按 IoU 0.5 计一个 TP最后算出伪标签相对人工标签的召回率。低于 0.7 说明漏检严重需要降低model.conf下限或换更强的初始模型。# 伪标签质量统计以人工标签为准统计召回率 import os import numpy as np def load_yolo_txt(path): boxes [] if not os.path.exists(path): return boxes with open(path) as f: for line in f: parts line.strip().split() if len(parts) ! 5: continue cls, cx, cy, w, h float(parts[0]), float(parts[1]), float(parts[2]), float(parts[3]), float(parts[4]) x1, y1, x2, y2 cx - w / 2, cy - h / 2, cx w / 2, cy h / 2 boxes.append((cls, x1, y1, x2, y2)) return boxes tp 0 total_gt 0 for txt_name in os.listdir(labels_ground_truth): gt_boxes load_yolo_txt(os.path.join(labels_ground_truth, txt_name)) pred_boxes load_yolo_txt(os.path.join(pseudo_labels, txt_name)) total_gt len(gt_boxes) for g in gt_boxes: for p in pred_boxes: # 计算 IoU0.5 计为命中 inter_x1 max(g[1], p[1]); inter_y1 max(g[2], p[2]) inter_x2 min(g[3], p[3]); inter_y2 min(g[4], p[4]) inter_area max(0, inter_x2 - inter_x1) * max(0, inter_y2 - inter_y1) union_area (g[3] - g[1]) * (g[4] - g[2]) (p[3] - p[1]) * (p[4] - p[2]) - inter_area iou inter_area / union_area if union_area 0 else 0 if iou 0.5: tp 1 break print(f人工目标总数: {total_gt}, 伪标签命中数: {tp}, 召回率: {tp / max(total_gt, 1):.2f})用脚本算出的召回率加上人工抽检的误检数就能定量决定「这批伪标签要不要直接进训练」。如果召回率达到 0.8、误检率低于 5%我才会把伪标签全量混入训练集。低于这个标准就回去调model.conf或换初始模型不应该硬着头皮往下走。第三修一批漏检把修正过的标签补回自动标注管线里。比如上面提到的安全帽场景伪标签对远距离小目标全漏我没有直接调参而是把漏检图单独拉出来用人工标签补了 200 张之后把这批「修正样本」混进种子集重新训练初始模型下一轮自动标注的召回率直接提了 20 多个点。全自动标注这套逻辑关键是用少量人工干预去修正模型的黑匣子偏移而不是指望全链路真的无人值守。我自己的一个习惯是每次自动标注的置信度阈值、抽检误检率、召回率都记在一个固定 markdown 表格里作为下一轮的调参依据。时间长了你就知道自己这套标注管线的稳定性到底怎么样。希望帮到你。本文还有配套的精品资源点击获取