简介:本资源为labelImg目标检测标注工具的图文操作教程文档,面向计算机视觉与机器学习方向的初学者、数据标注人员及算法工程师,帮助其快速掌握图像标注流程与标注文件格式转换方法。压缩包内共1个doc文档,约2.96MB,内容涵盖软件安装与Auto Save设置、图片文件夹打开与保存目录配置、画框标注与快捷键切换、predefined_classes.txt预定义类别修改,以及VOC与YOLO两种标注格式的生成与转换说明。教程结合电塔标注等实际案例,展示了XML文件中图片大小、通道数、标签名称与选框位置等参数含义,并说明如何借助xml_to_csv与tfrecord工具完成后续格式转换,同时给出YOLO格式中类别id与归一化中心点坐标、宽高的组织方式。目前已有731人学习,适合需要系统入门标注工具、对照实操与查漏补缺的读者参考。
1. 标注工具选型:为什么 labelImg 仍是目标检测入门的第一站
如果你刚拿到一批图片,准备做目标检测,第一件让人头疼的事往往不是选模型,而是怎么把几百上千张图里的目标框出来。labelImg 就是干这个的:一个用 Python 写的轻量级图像标注工具,支持 Pascal VOC 的 XML 和 YOLO 的 txt 两种主流格式,装完就能用,不需要 GPU,也不需要联网。它解决的是「从原始图片到可训练标注文件」这一段最枯燥、也最容易出错的环节。适合谁?适合刚入门目标检测的开发者、需要快速验证数据集可行性的算法同学,以及带学生做课程设计的一线工程师。我见过太多人模型调得飞起,结果标注格式错位,训练时 loss 不降,回头查半天才发现是坐标归一化的问题——这种血泪经验,后面会细讲。
2. 装好 labelImg 并跑通第一张图的标注
2.1 三种安装方式的选择与取舍
labelImg 的安装方式主要有三种:pip 直接装、源码运行、以及打包好的可执行文件。选哪种,取决于你的系统环境和是否需要改源码。
pip 安装最省事,适合 Windows 和 Linux 桌面环境:
# 建议在虚拟环境里装,避免和系统 Python 包冲突 python -m venv labelenv source labelenv/bin/activate # Windows 用 labelenv\Scripts\activate pip install labelImg装完后直接在终端敲labelImg就能启动。注意,pip 包名里那个大写 I 是官方约定,写成全小写labelimg在部分镜像源上会找不到包。
源码运行适合需要改快捷键、改默认保存路径的人:
git clone https://github.com/HumanSignal/labelImg.git cd labelImg pip install -r requirements/requirements-linux-python3.txt python labelImg.py可执行文件方式适合完全不想碰命令行的 Windows 用户,下载后双击运行,但版本更新慢,遇到高分辨率屏幕可能缩放异常。
我一般推荐 pip 装,因为升级和卸载都干净。如果公司网络对 pip 源有限制,换成国内镜像即可,这里不展开。
2.2 界面里每个按钮对应的实际操作
启动后界面分三块:左侧文件列表、中间画布、右侧标签列表和文件列表。核心操作就几个快捷键,记住能省一半时间:
W:画矩形框A:上一张D:下一张Ctrl+S:保存当前标注Ctrl+Shift+S:另存为Del:删除选中的框
画框时按住鼠标左键拖拽,松手后会弹出标签输入框。如果标签已经存在,直接从右侧列表点选,避免手打出错别字——标签名不一致是训练时类别对不上的头号原因。
2.3 切换 VOC 与 YOLO 格式的关键设置
labelImg 默认保存为 Pascal VOC 的 XML 格式。要切到 YOLO 的 txt 格式,点左侧工具栏的「PascalVOC」按钮,它会循环切换成「YOLO」。切换后保存的 txt 文件里,每行是类别索引 中心x 中心y 宽 高,且坐标都是归一化到 0~1 的浮点数。
这里有个容易翻车的点:YOLO 格式依赖一个classes.txt文件来定义类别顺序。这个文件必须和图片放在同一目录,或者你在 labelImg 里通过「Open Dir」打开图片目录时,它会自动读取同目录下的classes.txt。如果这个文件缺失或类别顺序和训练时不一致,模型学到的类别就是错位的。
# 一个典型的 classes.txt 内容,每行一个类别,顺序即索引 person car dog提示:切换格式后,之前用另一种格式标好的文件不会自动转换,需要重新标注或写脚本转换。建议项目开始前就定好格式。
3. 把标注结果整理成能直接喂给训练脚本的数据集
3.1 目录结构该怎么摆
标注完成后,你得到的是一堆散落的图片和同名标注文件。训练框架通常要求固定的目录结构。以 VOC 格式为例,常见做法是:
dataset/ ├── JPEGImages/ # 所有图片 ├── Annotations/ # 所有 XML ├── ImageSets/ │ └── Main/ # 存放 train.txt / val.txt └── classes.txtYOLO 格式则更简单,图片和 txt 放一起,再配一个classes.txt和训练用的train.txt、val.txt列表文件。
3.2 用脚本自动划分训练集和验证集
手动分文件容易漏、容易重。我一般写个小脚本按 8:2 随机划分,并生成列表文件:
import os import random # 图片目录,按实际路径改 img_dir = "dataset/JPEGImages" # 输出列表的目录 out_dir = "dataset/ImageSets/Main" os.makedirs(out_dir, exist_ok=True) # 只取图片文件,排除隐藏文件 names = [f[:-4] for f in os.listdir(img_dir) if f.lower().endswith((".jpg", ".png"))] random.seed(42) # 固定随机种子,保证每次划分一致 random.shuffle(names) split = int(len(names) * 0.8) train, val = names[:split], names[split:] with open(os.path.join(out_dir, "train.txt"), "w") as f: f.write("\n".join(train)) with open(os.path.join(out_dir, "val.txt"), "w") as f: f.write("\n".join(val)) print(f"训练集 {len(train)} 张,验证集 {len(val)} 张")这段脚本的关键参数是random.seed(42),固定种子后每次运行划分结果一致,方便复现实验。split控制比例,数据量少时可以调到 0.9。注意文件名去掉了扩展名,因为大多数训练脚本读列表时只认文件名主干。
3.3 校验标注文件是否和图片一一对应
标注过程中难免出现图片删了但 XML 还在,或者 XML 内容为空的情况。训练前跑一遍校验能省很多事:
import os import xml.etree.ElementTree as ET img_dir = "dataset/JPEGImages" ann_dir = "dataset/Annotations" imgs = {f[:-4] for f in os.listdir(img_dir) if f.lower().endswith((".jpg", ".png"))} anns = {f[:-4] for f in os.listdir(ann_dir) if f.endswith(".xml")} # 有图无标注、有标注无图,都要报出来 print("缺标注的图片:", imgs - anns) print("缺图片的标注:", anns - imgs) # 检查空标注文件 for a in anns: tree = ET.parse(os.path.join(ann_dir, a + ".xml")) objs = tree.findall("object") if len(objs) == 0: print("空标注:", a)imgs - anns是集合差集,直接列出不匹配的文件名。空标注文件在训练时会被当成负样本,如果本意是正样本,就会拖低召回。这个检查我每次建完数据集都会跑一遍。
4. 标注环节最容易踩的五个坑
4.1 框贴边导致坐标越界
现象:训练时提示坐标超出图像范围,或者可视化时框跑到图外。原因:画框时鼠标拖到了图像边缘外,labelImg 记录的坐标可能略大于图像宽高。解决:画框时留一两个像素边距,或者写脚本把坐标裁剪到[0, width-1]和[0, height-1]范围内。
4.2 标签名大小写不一致
现象:训练日志里类别数比预期多,比如person和Person被当成两类。原因:不同人标注时手输标签,大小写没统一。解决:提前建好classes.txt,标注时只从右侧列表点选,禁止手动输入。已经标完的用脚本统一转小写。
4.3 YOLO 格式的类别索引错位
现象:模型把车识别成人,或者类别完全乱套。原因:classes.txt的顺序和训练配置里的类别顺序不一致。解决:把classes.txt作为唯一类别来源,训练脚本直接读它生成类别列表,不要在两处分别维护。
4.4 中文路径导致保存失败
现象:点保存没反应,或者报编码错误。原因:labelImg 在某些系统上对中文路径支持不好。解决:图片目录和标注目录都用纯英文路径,这是最省事的办法。
4.5 忘记保存就切图
现象:标了十几张,回头发现文件没生成。原因:labelImg 不会自动保存,切图前必须按Ctrl+S。解决:养成「画完框就按 Ctrl+S」的习惯,或者在设置里勾选自动保存选项(部分版本支持)。
注意:标注是个体力活,但格式错误会让后面所有训练工作白费。宁可标慢一点,也要保证每张图保存后抽查一下。
5. 用 Python 批量转换与校验标注格式的进阶技巧
5.1 VOC 转 YOLO 的完整脚本
项目中途换格式是常事。与其重标,不如写个转换脚本。下面这个把 VOC 的 XML 转成 YOLO 的 txt:
import os import xml.etree.ElementTree as ET # 类别列表,顺序即索引,必须和训练时一致 classes = ["person", "car", "dog"] ann_dir = "dataset/Annotations" out_dir = "dataset/labels" os.makedirs(out_dir, exist_ok=True) for xml_file in os.listdir(ann_dir): if not xml_file.endswith(".xml"): continue tree = ET.parse(os.path.join(ann_dir, xml_file)) root = tree.getroot() size = root.find("size") w = int(size.find("width").text) h = int(size.find("height").text) 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) # 归一化并转为中心点+宽高 cx = (x1 + x2) / 2.0 / w cy = (y1 + y2) / 2.0 / h bw = (x2 - x1) / w bh = (y2 - y1) / h lines.append(f"{cls_id} {cx:.6f} {cy:.6f} {bw:.6f} {bh:.6f}") out_name = xml_file.replace(".xml", ".txt") with open(os.path.join(out_dir, out_name), "w") as f: f.write("\n".join(lines))关键点:classes列表的顺序决定了 txt 里的类别索引,必须和训练配置完全一致。if name not in classes这行是后悔药,防止 XML 里出现没定义的类别导致索引报错。坐标保留 6 位小数足够,再多没必要。
5.2 转换后怎么验证没转错
转完不能直接开训,抽几张图把 YOLO 的 txt 画回图上看看:
import cv2 img = cv2.imread("dataset/JPEGImages/000001.jpg") h, w = img.shape[:2] with open("dataset/labels/000001.txt") as f: for line in f: cls_id, cx, cy, bw, bh = map(float, line.split()) # 反归一化回像素坐标 x1 = int((cx - bw / 2) * w) y1 = int((cy - bh / 2) * h) x2 = int((cx + bw / 2) * w) y2 = int((cy + bh / 2) * h) cv2.rectangle(img, (x1, y1), (x2, y2), (0, 255, 0), 2) cv2.imwrite("check.jpg", img)打开check.jpg,如果框的位置和原图目标吻合,说明转换正确。这个方法比看数字直观得多,我每次转换后至少抽三张不同场景的图验证。
5.3 一个提高标注效率的小习惯
标注前先把图片按场景分组,相似的图放一起标,标签可以连续点选,不用反复切换。另外,labelImg 支持「复制上一张的标注」功能(快捷键Ctrl+D),对于连续帧或相似场景,能省大量重复劳动。但复制后一定要逐张检查,目标位置变了就得手动调,别偷懒。
希望帮到你。
本文还有配套的精品资源,点击获取