ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

YOLOv5半自动标注实战:从权重到XML,省去从零画框的人力

YOLOv5半自动标注实战:从权重到XML,省去从零画框的人力 简介这份资源面向目标检测方向的学习者与工程实践者提供一套基于YOLO系列的半自动标注数据集代码用于缓解大规模图像标注耗时耗力的问题。其核心思路是先人工标注少量样本训练出初版模型再用模型对剩余图像做预标注最后人工复核修正误检从而显著降低标注成本。压缩包共5个文件约7KB包含2个Python脚本、1个yaml数据集配置文件、1个使用说明txt及1个系统隐藏文件脚本分别承担自动标注与单图检测功能配置文件用于指定数据集路径与类别信息。资源已获得523人学习关注说明其在数据标注场景中具有一定实用价值。读者可据此快速搭建预标注流程理解模型权重加载、图片路径与xml输出路径的配置方式并掌握从少量标注到批量预标注再到人工校验的完整工作流适合需要处理大批量图像标注任务的目标检测开发者参考使用。1. 半自动标注这套代码到底省的是哪一段人力手上接过一个身份证检测的项目两万张图客户催着两周出标注。纯手工拉框一个人一天撑死标八百张算下来得二十五天直接翻车。后来换了个思路先手标三百张训练一版 YOLOv5拿初版模型去预测剩下的图把预测框直接写成 XML再人工过一遍修正误检漏检。这套yolov5自动标注.zip干的就是中间这段——把模型预测结果批量转成标注文件省掉的是「从零画框」这一步留下的是「检查修正」这一步。它适合两类人一类是数据集量大、标注预算有限的目标检测从业者另一类是已经有一版能跑的 YOLOv5 权重、想快速扩充数据集的算法同学。包里东西不多auto_label.py是主脚本detect_image_only.py是纯推理的辅助脚本custom_data.yaml是数据集配置外加一份使用步骤说明.txt。核心逻辑就一句话读图、推理、把检测框按 VOC 的 XML 格式落盘。下面把它拆开讲清楚包括参数怎么改、坑在哪、怎么验证标出来的东西能不能用。2. 从权重到 XMLauto_label.py 的推理链路与参数落点2.1 为什么是「先训少量再预标注」而不是直接上大模型很多人第一反应是找个通用检测模型直接标比如 COCO 预训练的权重。问题是通用模型的类别和你自己的目标对不上——身份证、工牌、特定零件这类目标COCO 里根本没有对应类模型要么不框要么框成一堆无关的东西预标注的可用率极低人工修正的成本比从零标还高。半自动标注的前提是「领域内先验」。你手标的那三百张作用不是凑数是让模型学会你这个场景下目标长什么样、在什么位置、什么尺度。三百张听起来少但对于单一类别、背景相对固定的场景身份证、卡片、面板类YOLOv5 微调后 mAP 能到一个可用的水平预标注的召回率通常能到七八成剩下两三成靠人工补。这个比例下总工时能压到纯手工的三分之一左右。选 YOLOv5 而不是更新的版本是因为这套脚本的推理接口是按 YOLOv5 的DetectMultiBackend和non_max_suppression写的权重格式、输入尺寸、置信度阈值的处理都对齐了 v5 的约定。你换成 v8 或 v11 的权重加载那一步就可能报错除非自己改推理部分。所以这份代码的边界很清楚权重必须是 YOLOv5 训练出来的.pt。2.2 四个必须改对的路径参数脚本第 62 到 65 行是全部需要你动手的地方四个变量对应四个路径。原文给的是相对路径写法实际跑的时候建议全改成绝对路径避免工作目录不一致导致的找不到文件。# auto_label.py 第 62-65 行附近 path rauto_label/images # 待标注图片所在目录 xml_path rauto_label/images # 输出的 xml 标注文件保存目录 yolo_model_weight ./weight/IDCard_v6x_best.pt # 训练好的 YOLOv5 权重 data_conf ./data/custom_data.yaml # 数据集配置文件逐个说清楚path是输入目录脚本会遍历这个目录下的图片。注意它一般只扫一层如果你的图按子文件夹分好了要么改成递归遍历要么先把图拍平到一个目录里。我一般会先ls auto_label/images | wc -l确认图片数量跑完再对一遍 XML 数量数量对不上就是有图被跳过了。xml_path是输出目录。原文把它和输入目录写成同一个意味着 XML 会和原图混在一起。图少无所谓图多了目录会很乱而且下一轮如果拿这个目录当输入脚本可能把 XML 也当图片去读。稳妥做法是单独建一个auto_label/xml目录。yolo_model_weight指向你的.pt权重。这里有个容易忽略的点权重里保存的类别名和custom_data.yaml里的names必须一致否则写出来的 XML 里类别名会错位人工检查时看到的标签是错的后面训练直接污染数据集。data_conf是数据集配置文件YOLOv5 推理时用它来拿类别数和类别名。它的结构就是标准的 v5 格式# custom_data.yaml path: ../datasets/custom train: images/train val: images/val nc: 1 names: [idcard]nc是类别数names是类别名列表。推理阶段其实只用到nc和namestrain/val路径填不填不影响跑通但建议填对方便你后面直接拿这个 yaml 去训练。2.3 推理到 XML 的转换逻辑脚本内部做的事拆开就是三步加载模型、逐图推理、把框写成 XML。推理部分用的是 YOLOv5 的标准流程输入尺寸默认 640置信度阈值和 NMS 的 IoU 阈值在脚本里通常有默认值。转换部分是把归一化的xywh还原成像素坐标再按 VOC 的 XML 结构写出来。# 推理与坐标还原的核心逻辑示意实际以脚本为准 img cv2.imread(img_file) results model(img, size640) # 输入尺寸小目标可调大 pred non_max_suppression(results, conf_thres0.25, iou_thres0.45) for det in pred: if det is not None and len(det): # det 的 xywh 是相对原图的归一化坐标 det[:, :4] scale_coords(img.shape[2:], det[:, :4], img.shape).round() for *xyxy, conf, cls in det: # 写进 XML 的 bndbox ...conf_thres是置信度阈值默认 0.25。这个值直接决定预标注的松紧调低召回高但误检多人工要删一堆框调高误检少但漏检多人工要补一堆框。身份证这种目标清晰、背景简单的场景我一般会把它提到 0.4 到 0.5宁可漏一点也别让误检淹没人工。iou_thres是 NMS 的重叠阈值默认 0.45目标密集、容易框重叠的场景可以适当调低。scale_coords那一步是把模型输入尺寸下的坐标映射回原图尺寸。如果你的原图分辨率特别大比如 4000 像素宽而推理尺寸只有 640小目标在缩放后会糊掉检测效果打折。这种情况要么把推理尺寸提到 1280要么先把大图切块再标。2.4 跑通第一轮并核对结果改完参数直接跑python auto_label.py跑完先别急着人工检查做两件事核对。第一数 XML 文件个数和输入图片数对比ls auto_label/images/*.jpg | wc -l ls auto_label/xml/*.xml | wc -l两个数应该相等。少了说明有图读取失败或推理异常去看终端有没有报错。第二随便打开一个 XML 看结构对不对annotation folderimages/folder filename0001.jpg/filename size width1920/width height1080/height depth3/depth /size object nameidcard/name bndbox xmin412/xmin ymin233/ymin xmax1508/xmax ymax842/ymax /bndbox /object /annotation重点看name是不是你的类别名、bndbox的四个值有没有超出图片宽高。如果xmax大于width说明坐标还原那步有问题通常是scale_coords的输入尺寸传错了。这一步核对花两分钟能省掉后面返工几小时。3. 预标注结果怎么验、怎么修、怎么进训练集3.1 用 detect_image_only.py 做可视化抽检XML 是给训练用的肉眼看不直观。包里那个detect_image_only.py就是干这个的——它只做推理并把框画在图上不写 XML。用它抽检几十张能快速判断预标注的整体质量。python detect_image_only.py --weights ./weight/IDCard_v6x_best.pt \ --source auto_label/images --conf 0.4--source可以是单张图、目录或通配符。--conf和主脚本里的阈值保持一致这样看到的框和写进 XML 的框是同一批。抽检时重点看三类问题漏检该有的目标没框、误检背景被框了、框不准框偏大偏小。如果漏检集中在某个尺度或某种光照条件下说明训练样本没覆盖到得补标这类图再重训。3.2 人工修正的取舍哪些框值得改预标注不可能全对人工检查要有优先级不然两万张图逐张精修省下来的时间又还回去了。我的做法是分三档高置信度且框位置合理的直接过不动。这类通常占六七成是省下来的主要工时。置信度中等、框大致对但边界有偏差的微调四个坐标。这类占两三成改起来快。漏检和明显误检的手动补框或删框。这类占一成左右是最花时间的部分但量小。修正工具用 LabelImg 或 Labelme 都行它们能直接读 VOC 的 XML改完存回去格式不变。注意 LabelImg 默认可能存成 YOLO 的 txt 格式要在设置里切回 PascalVOC否则格式混了后面训练读不进去。3.3 修正后的数据集怎么组织进 YOLOv5 训练修完的 XML 要转成 YOLOv5 训练用的 txt 格式每行cls x_center y_center w h全部归一化。v5 官方仓库里有voc2yolo.py之类的转换脚本也可以自己写一个逻辑就是把 XML 的绝对坐标转成归一化中心点格式。# xml 转 yolo txt 的核心换算 w xmax - xmin h ymax - ymin x_center (xmin xmax) / 2 / img_w y_center (ymin ymax) / 2 / img_h w_norm w / img_w h_norm h / img_h转换完按images/train、labels/train、images/val、labels/val的目录结构放好custom_data.yaml里的路径指过去就能直接开训。第二轮训练出来的模型比第一版强可以再拿它去标剩下的图形成迭代。这就是半自动标注真正的价值——不是一次省力是每轮都在滚雪球。提示每轮迭代后把人工修正过的图单独留一份作为下一轮的验证集。这样你能量化地看到模型是不是真的在变好而不是凭感觉。4. 避坑这套脚本跑起来最容易翻车的五个地方4.1 权重类别和 yaml 对不上XML 里全是错标签现象跑完打开 XMLname字段是person、car这种但你明明只标身份证。原因custom_data.yaml里的names和权重训练时的类别顺序不一致。YOLOv5 的类别是按索引对应的权重里names[0]是idcard你 yaml 里names[0]写成了别的写出来的标签就错位。解决打开权重训练时用的那个 yaml把names原样抄过来。不确定的话用python -c import torch; ckpttorch.load(xxx.pt); print(ckpt[model].names)把权重里的类别名打出来以它为准。4.2 输入输出同目录第二轮把 XML 当图片读现象第一次跑正常第二次跑报错说读不了某张图或者 XML 数量翻倍。原因path和xml_path设成了同一个目录第一轮生成的 XML 混在图片里第二轮遍历时把 XML 也当输入了。解决输入和输出目录分开xml_path单独建一个目录。已经混了的用find . -name *.xml -delete清掉重跑。4.3 大分辨率图小目标漏检严重现象原图 4K目标只占几十个像素预标注几乎框不到。原因推理尺寸默认 640大图缩到 640 后小目标信息丢失。解决把推理尺寸提到 1280 甚至 1536代价是显存和耗时上升。显存不够就切块推理把大图裁成带重叠的小块分别标再合并。或者干脆在训练阶段就用切块后的图让模型适应小目标。4.4 置信度阈值照搬默认值误检淹没人工现象预标注框一大堆人工删框删到手酸比从零标还累。原因conf_thres用了默认的 0.25对简单场景太松。解决先拿几十张图试不同阈值看误检和漏检的平衡点。身份证这类场景从 0.4 起调逐步往上加直到误检明显减少而漏检还能接受。这个值没有标准答案取决于你的场景和人工成本。4.5 坐标超出图片边界训练时报越界现象训练时提示某个 label 的坐标大于 1 或小于 0。原因scale_coords还原时输入尺寸传错或者原图有 EXIF 旋转信息导致宽高读反。解决转换前统一用 PIL 读图并ImageOps.exif_transpose处理旋转确保宽高和实际像素一致。转换后加一道校验把x_center、y_center、w、h不在(0,1]区间的行打出来人工确认是丢弃还是修正。5. 把预标注接进迭代闭环一个可复用的阈值调优技巧这套代码跑通不难难的是让它每一轮都比上一轮省力。我踩过最大的坑是第一版模型标完人工修完直接拿去训练第二轮模型没变好多少因为修正的样本和原始训练集混在一起模型学到的还是老分布。后来改了个做法把「预标注—人工修正—重训」当成一个闭环来管效果才稳定下来。具体操作是维护三个集合。seed是最初手标的那三百张永远留在训练集里保证基础分布不漂。auto是每轮预标注后人工修正过的图按轮次打标签比如auto_r1、auto_r2。hard是每轮里漏检和误检最严重的那批图单独拎出来下一轮训练时给更高的采样权重。这样模型每轮都在补自己的短板而不是在已经会的样本上重复。阈值这块也有个可复用的调法。不要一次定死conf_thres而是每轮跑三个值——比如 0.3、0.4、0.5——各标一小批一两百张统计人工修正的耗时。哪个阈值下「预标注可用框数 / 总框数」最高、人工改动最少就用哪个。随着模型变强最优阈值会往上走因为模型的置信度越来越可信。我一般每两轮重调一次把当前最优值记在使用步骤说明.txt旁边免得下次忘了上轮用的多少。# 批量试三个阈值分别输出到不同目录对比 for c in 0.3 0.4 0.5; do python auto_label.py --conf $c --xml_path auto_label/xml_c$c done跑完对比三个目录里 XML 的框数量和抽检图选人工负担最小的那个。这个循环跑上三四轮预标注的可用率通常能从最初的六七成提到九成以上人工基本只剩微调。注意每轮重训前务必把验证集固定下来不要用当轮预标注的图当验证集否则指标虚高你会误以为模型已经很好。从那以后我每次接标注量大的项目都强制先跑一轮半自动标注的闭环哪怕只有几百张图也先走一遍流程确认阈值和目录结构没问题再放量。这套yolov5自动标注.zip里的脚本不复杂但把「先训少量、再预标注、人工修正、迭代重训」这条链路串起来了省下的是实打实的画框时间。希望帮到你。本文还有配套的精品资源点击获取
返回列表