ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

LabelImg使用教程:目标检测数据标注从入门到实践

LabelImg使用教程:目标检测数据标注从入门到实践 算法入门有个反直觉的地方真正卡住进度的常常不是模型代码而是训练数据的准备工作。我第一次跑目标检测项目时模型代码花半天就调通了数据却折腾了整个周末——因为模型需要大量“图片标签”的配对数据而这些标签不会自己长出来。于是我去装了LabelImg这个开源工具解决的就是一件事用鼠标在图片里把目标对象圈出来再给它打上一个类别的名字最终生成算法训练能读的标注文件。换句话说标题里的“剪切出能够描述目标的标签照片”放到工作流里就是画框、命名、保存三个动作。这篇文章写给三类人刚接触深度学习目标检测、正准备做自己第一个数据集的算法学习者需要用Windows电脑完成标注工作但不想在环境配置上浪费时间的工程师以及已经听过LabelImg但被安装问题劝退的初学者。我会从安装环境讲起把界面操作、格式转换、常见崩溃和标注质量对算法的影响全部过一遍最后附上我实际踩坑后总结的流程建议。1. 为什么目标检测算法离不开LabelImg这类标注工具1.1 算法训练需要的是“带答案的题”很多人学算法时把精力全放在理解卷积、注意力机制、损失函数上却忽略了一个前提监督学习需要“带答案的样本”。目标检测领域的“答案”是什么是每个目标对象在图片中的位置和类别。位置通常用一个矩形框表示也就是常说的bounding box类别则是这个框对应的名字比如“人”“车”“猫”。模型训练的过程可以类比成学生做题模型看到一张图输出它是“猫”以及“猫在哪里”这两个结果然后拿去和标准答案比对。标准答案就是人工标注出来的矩形框和类别名也就是我们常说的“标签”。如果标准答案是错的、乱的、不完整的模型学到的东西也会跟着偏后面做推理时自然准不了。这正是LabelImg这类标注工具存在的意义。它本质上是一个图形化的“标准答案编辑器”你把图片打开按住鼠标拖出一个框输入一个类别名再保存成模型能读的格式。整个过程没有太高技术含量但属于算法工程中不可跳过的一环。1.2 标题里的“剪切”和“标签”到底指什么“剪切能够描述目标的标签照片”这个说法听起来有点绕放到实际操作里其实很直白。你在一张照片里找到目标比如一只猫然后用鼠标画一个矩形把它圈起来这一步就是“剪切”——当然它不是真的把像素切掉而是用坐标记录下这块区域的位置和大小。紧接着你给它起个名字“cat”这就是“标签”。两者组合起来就形成了一条标准标注数据。LabelImg以这个逻辑为核心默认支持两种主流输出格式PascalVOC和YOLO。PascalVOC格式会把每张图片的标注信息写入同名XML文件里面记录图片尺寸、文件名、每个目标的类别和坐标YOLO格式则生成同名TXT文件内容是一行一个目标的类别ID和归一化坐标。这两种格式分别对应不同训练框架的习惯比如某些经典检测项目偏好VOC而YOLO系列训练脚本更常用TXT。LabelImg在界面上可以直接切换这是它比很多后来者好用的重要原因。2. Windows下安装LabelImg两条路线和我的选型思路2.1 为什么我建议你先装Anaconda虚拟环境安装LabelImg本身不难但很多人在Windows上装完启动就闪退根源不是LabelImg坏了而是系统Python环境里各种包互相冲突。我吃过这个亏当时电脑里有Python 3.8、3.10好几个版本还有一堆乱七八糟的全局依赖直接用pip装完LabelImg后一启动就报“Failed to load PyQt5”之类的错。后来我改用Anaconda创建独立虚拟环境问题一次性解决。虚拟环境的好处是给这个工具单独隔离一个Python运行空间你在里面装什么都不会影响系统其他项目。如果你不想装Anaconda全套也可以用Miniconda它体积小很多功能上足够创建和管理环境。创建环境的命令很简单打开Anaconda Prompt或Windows Terminal执行conda create -n labelimg python3.9 conda activate labelimgPython版本我推荐3.9主要原因是LabelImg依赖的PyQt5在3.9下兼容性很稳换更高的Python版本偶尔会遇到某些依赖库还没跟上。等技术熟了以后你当然可以随意折腾但入门阶段稳定优先。2.2 路线一pip直接安装最省事的方案创建好环境后安装过程基本就是一行命令的事pip install labelimg -i https://pypi.tuna.tsinghua.edu.cn/simple换清华源是为了在境内加速下载如果你网络环境本身很好不加源也可以。装完之后在当前虚拟环境里直接敲labelimg界面就能弹出来。这个方案的优点是快缺点是版本不一定是最新——PyPI上的LabelImg发行版可能落后于GitHub源码。但对大多数标注任务来说功能完全够用。如果你在Windows上执行时提示“labelimg不是内部或外部命令”多半是当前终端没有激活虚拟环境或者Python脚本目录没有加入PATH。确认第一步的conda activate labelimg执行成功即可。2.3 路线二源码安装适合想改工具的人想使用最新功能或者有二次开发需求就从GitHub拉源码装。打开终端执行git clone https://github.com/HumanSignal/labelImg.git cd labelImg conda activate labelimg pip install pyqt5 lxml如果还想重新编译资源文件可以再试pyrcc5 -o libs/resources.py resources.qrc但我要提醒一句在Windows上执行pyrcc5经常报“不是内部或外部命令”这是因为PyQt5的安装目录没有自动加入PATH。我后来发现的稳妥做法是不管这条命令因为新版源码的libs目录里通常已经带好了resources.py直接跳过也能正常运行。实在不行可以手动执行python -m PyQt5.pyrcc_main -o libs/resources.py resources.qrc然后回到labelImg目录启动python labelImg.py2.4 两条路线的对比与我的建议我把两种安装方式摆在一起对比一下方便你按自己的情况选安装方式耗时版本新鲜度适合人群pip直接安装约1分钟相对滞后只想快速标注不想折腾环境源码安装约10分钟与GitHub同步有二次开发需求或pip版启动异常我的实际建议是如果你第一次接触直接用pip装别在环境上消耗太多心智。环境问题永远不是算法学习的重点把精力省下来去体验完整的标注流程更重要。等你有经验了再按需换成源码版。3. 动手标注第一张图从打开目录到保存标注文件3.1 软件界面和目录准备启动LabelImg后你会看到左右两个区域左边是图片画布右边是标注信息列表和框的属性面板。顶部是菜单栏和几个按钮底部有当前图片路径、缩放比例等状态信息。开始正式标注前建议先建好两个目录一个放待标注图片一个放标注结果。图片目录最好只放图片文件标注目录留空即可。我习惯把项目结构组织成my_dataset/ ├── images/ # 原始图片 └── labels/ # 标注输出点击左侧工具栏的“打开目录”选择images文件夹再点击“更改保存目录”选择labels文件夹。这两个目录必须分开如果指向同一个地方XML文件会和图片混在一起管理起来容易乱。3.2 五步完成第一张图片标注第一步点击界面左侧菜单栏里类似“PascalVOC”格式的按钮确认当前格式。实际上界面上有个下拉入口在“PascalVOC”和“YOLO”之间切换。新版本通常在左侧工具栏或顶部菜单里可以直接看到也有的版本需要从菜单栏“View”里打开Auto Saving模式。建议先把自动保存打开避免标注过程中数据丢失。第二步点击“打开目录”后画布上会显示第一张图。按CtrlShiftR可以随机打乱图片顺序这在不希望连续标注同一场景时很实用。第三步按快捷键W进入创建框模式鼠标会变成十字形。在目标物体左上角按下左键拖到右下角松开一个矩形框就出来了。第四步弹出对话框让你输入类别名比如输入cat点击OK。如果这个类别之前输入过LabelImg会记住并出现在下拉列表里。第五步按CtrlS保存。如果当前格式是PascalVOC就会在labels目录下生成和图片同名的XML文件。然后按D切到下一张图重复上述画框、命名、保存的流程。只有成功切换到下一张图才说明上一张标注数据已正常保存。我初期经常标完忘保存切到下一张时悔不当初所以后来基本一直开着“自动保存”选项。3.3 必背快捷键和操作习惯常用的快捷键没有想象中多核心就这几个按键功能W创建矩形框A / D上一张 / 下一张图CtrlS保存当前标注Del删除选中的矩形框Ctrl鼠标滚轮缩放画布CtrlU打开图片目录CtrlShiftR随机打乱图片顺序Space锁定/解锁当前选择的框标注时我习惯先不急着画框先把整张图扫一遍看清有几个目标然后按W逐个画。画完一张图后统一按CtrlS保存。如果中途发现画错了点击选中框按Del删除重画。放大镜功能也很有用按住Ctrl滚动鼠标滚轮把局部放大后能精确检查边界是否贴合目标。3.4 保存后的XML长什么样打开标好的XML文件能看到完整的标注信息annotation folderimages/folder filenamecat_001.jpg/filename size width1280/width height720/height depth3/depth /size object namecat/name bndbox xmin142/xmin ymin95/ymin xmax674/xmax ymax568/ymax /bndbox /object /annotation其中的xmin、ymin、xmax、ymax分别表示目标框左上角和右下角的像素坐标。模型训练脚本会读取这些坐标和图像尺寸一起计算出目标的绝对位置。这也是我强调“标签就是坐标加类别”这句口诀的来源。3.5 切到YOLO格式时会发生什么如果你在界面上把保存格式切到YOLO再保存标注LabelImg就不再生成XML而是生成同名TXT文件同时生成一个classes.txt记录类别列表。TXT每一行格式为class_id x_center y_center width height其中坐标都是相对图片宽高的归一化数值范围在0到1之间。比如一张1280x720的图片里目标中心在(640, 360)宽400高300对应的行就是0 0.5 0.5 0.3125 0.4167这个格式在YOLOv5、YOLOv8等项目中很常用。类别ID从0开始顺序由classes.txt决定所以中途最好不要频繁增删类别否则要回头改大量TXT文件。4. 实测中常见的崩溃、乱码和异常我的排查过程4.1 启动闪退先看终端输出别急着重装我在不同电脑上装过LabelImgWindows平台最常见的问题就是启动闪退。具体表现是双击图标后界面一闪而过或者命令行启动后报错退出。很多人遇到这种情况第一反应是卸载重装但正确答案是看错误信息。步骤如下打开终端激活虚拟环境在命令行里输入labelimg观察报错。如果输出里出现ModuleNotFoundError: No module named PyQt5说明PyQt5没装好如果出现No module named cv2说明OpenCV相关依赖缺失如果报错信息很长涉及resources模块则多半是资源文件没编译成功。针对性的修复命令其实很简单pip install pyqt5 lxml opencv-python然后再启动。如果还是不行检查当前Python版本是不是3.10以上部分老版本LabelImg与新版Python的兼容性不好换到3.9环境通常能解决。4.2 图片加载不出来不一定是软件坏了有一次我在文件夹里放了一批PNG图片打开目录后里面只显示JPG格式文件PNG全看不到。后来发现是LabelImg默认的图片筛选后缀有限制对某些非标准扩展名和格式兼容性一般。解决办法有两种一是把图片批量转成JPG格式二是检查图片本身是否编码损坏。更常见的情况是图片路径或文件名里带中文比如C:\用户\图片\猫猫1.jpg。LabelImg在Windows上处理中文路径时有时会出现文件读取或保存失败我建议所有图片、标注文件、项目目录一律用英文命名这也是深度学习项目的通用习惯。遇到中文路径产生乱码时最简单的处理就是复制到纯英文路径目录下再标注。4.3 标注到一半闪退开启自动保存是保命符我遇到过标完30张图准备保存程序突然崩溃的事。因为当时手动保存习惯没养成丢了小半天的成果。后来我强制自己开启Auto Saving模式同时每标完一张图按CtrlS即使崩溃最多丢一张图的工作量。如果你已经开了自动保存但仍然闪退试着把图片目录里的图片量减少比如一次性只打开一个子文件夹里的100张图而不是直接打开包含几千张图的根目录。LabelImg在加载大量图片时内存占用会攀升低配置电脑容易出现无响应。4.4 标注了错误类别或框位置不准批量修正技巧在标注过程中类别名输错是很容易发生的事。比如某类物体命名成了catt标注到中途才发现。界面里可以选中对应框在右侧属性面板直接修改label字段。但如果已经标了上百张图一个个改就太慢了。我常用的办法是写个小脚本批量把XML里的name内容替换成正确类别名称或者用文本编辑器对XML做全局替换。替换前务必先备份一份标注文件避免替换错导致大批量数据损坏。这一步很多人会忽略但恰恰是保护劳动成果最重要的措施。5. 标注质量决定算法上限影响模型效果的关键细节5.1 标注框的贴合度是模型精度的基础画框看起来只是鼠标拖动但框的边界贴不贴目标对模型输出影响很大。检测算法在训练时会把预测框和标注框做对比计算回归损失。如果标注框普遍比目标大一圈模型学到的“大框倾向”就会被固化推理时输出的外框总带明显冗余如果框偏小又会切掉目标的一部分导致特征提取不完整。实操中我给自己定的标准是矩形框必须紧贴目标轮廓最高点、最低点、最左点、最右点与目标边缘之间尽量不超过1到2个像素。对于有复杂轮廓的目标比如人、动物不需要精确贴合每一处弯曲但至少不能把四肢或头顶切掉。模糊的图像就放大画布后仔细对边界。5.2 类别定义必须在一开始就明确标注前就要把类别列表定死并且写进一份说明文档里。比如做车辆检测你打算分为“car”“bus”“truck”还是统称“vehicle”这直接决定了模型能学到什么粒度的语义。类别之间有重叠时标注者的判断标准也会漂移比如今天把小型载货汽车标成car明天标成truck模型就会无所适从。我见过一个项目里类别“person”和“pedestrian”同时存在标注员区分不了两者边界结果模型对行人的置信度一直不稳定。正确做法是合并同类项只保留互斥的类别。每个类别在全部标注里也要分布均匀如果一类占了95%另一类只有5%模型在推理时会对少数类非常不敏感。5.3 错标和漏标比“没标够”更危险很多初学者以为少标一点没关系反正模型能“自己学会”。这个想法在目标检测场景里非常危险。一幅图中存在的目标如果没被标注训练时模型会把它当作背景处理相当于给模型喂了一个错误样本。尤其在密集场景里漏标一个目标可能让模型把附近区域预测成背景的概率拉高。反过来错误标注同样致命。我曾经标注一张路边停着卡车的图把远处的行人当成“person”画进去了但由于框没对准真正该标的人反而漏了。这种错误数据积累多了模型对“person”这个类的特征就会混乱。建议每标完一批图片至少肉眼抽查一遍框的贴合度和类别准确性尤其是模糊、遮挡、小目标三类图片。5.4 边缘目标和遮挡目标直接影响泛化能力检测模型的泛化能力很大程度取决于训练数据里是否包含足够多的“难例”。难例指的是目标在图片边缘被截断、被其他物体遮挡、目标很小、背景复杂等情况。如果你标注时只挑清晰正中间的大目标模型学到的是“目标都在画面中央”的隐含假设遇到真实场景中的边缘目标就容易漏检。我自己的经验是在标注时不要跳过那些被截断一半的汽车也不要忽略被树叶挡住一部分的行人只要人能通过肉眼识别出这是什么就值得标注。多标这类难例比单纯堆数量更能提升模型在复杂场景下的表现。6. 从LabelImg到算法训练VOC转YOLO、半自动标注与流程建议6.1 为什么不需要手工维护TXT文件如果你打算用YOLO系列训练脚本但之前已经用PascalVOC格式标了一批数据不用回到LabelImg里重新保存。LabelImg生成XML之后我们可以用脚本批量转换成YOLO需要的TXT格式。这类转换脚本网上很多我建议自己写一遍顺便理解两种格式之间的数学关系。核心逻辑是从XML里读出每个框的xmin、ymin、xmax、ymax再和图片宽高做归一化计算出x_center、y_center、width、height。一个简单可用的转换脚本如下import os import xml.etree.ElementTree as ET def convert_voc_to_yolo(xml_dir, txt_dir, class_names): os.makedirs(txt_dir, exist_okTrue) for xml_file in os.listdir(xml_dir): if not xml_file.endswith(.xml): continue tree ET.parse(os.path.join(xml_dir, xml_file)) root tree.getroot() img_w int(root.find(size/width).text) img_h int(root.find(size/height).text) lines [] for obj in root.iter(object): cls_name obj.find(name).text if cls_name not in class_names: continue cls_id class_names.index(cls_name) bndbox obj.find(bndbox) xmin float(bndbox.find(xmin).text) ymin float(bndbox.find(ymin).text) xmax float(bndbox.find(xmax).text) ymax float(bndbox.find(ymax).text) x_center (xmin xmax) / 2.0 / img_w y_center (ymin ymax) / 2.0 / img_h box_w (xmax - xmin) / img_w box_h (ymax - ymin) / img_h lines.append(f{cls_id} {x_center:.6f} {y_center:.6f} {box_w:.6f} {box_h:.6f}) txt_name xml_file.replace(.xml, .txt) with open(os.path.join(txt_dir, txt_name), w) as f: f.write(\n.join(lines))使用时把class_names定义成和LabelImg里顺序一致的类别列表。如果顺序不一致类别ID就会错位模型训练起来就是灾难。6.2 半自动标注先跑模型再人工修正标注效率是很多项目的痛点。标1000张图人工作业可能要花一个周末但如果你手里已经有一个预训练检测模型哪怕是通用模型都可以做半自动标注。思路很简单先用现有模型对未标注图片做推理把输出的预测框写到VOC XML或YOLO TXT文件里然后事后再用LabelImg打开这些结果人工确认和修正。修正的工作量比从零画框少很多尤其当预训练模型在目标场景上精度较高时效率能提升数倍。实现上可以直接写一段脚本把模型输出的坐标和置信度过滤掉低置信度框后拼成LabelImg能读的XML格式。LabelImg本身不限制你能不能先写XML再打开它能正常加载并让你逐个调整。我遇到过很多工程师因为嫌标注累而迟迟不动手做数据集半自动标注恰好是破解心理门槛的办法。6.3 我的个人标注流程从0到可以训练的数据集整理一下我经过几次项目沉淀后养成的标注流程给你做参考。第一步建立项目目录图片统一英文命名确认类别列表写README记录各类别定义和标注规则。第二步启动LabelImg打开图片和保存目录切换PascalVOC格式开启自动保存。第三步按批标注每标完50张图停下检查一遍XML数量和文件名对应关系。第四步写一个统计脚本统计每张图的目标数量、每个类别出现的频次看类别是否均衡。第五步随机抽取10%标注结果可视化检查框的边界和类别名。第六步确认无误后再批量导出成YOLO或COCO格式。这套流程我很推荐刚入门的人直接照搬。它避免了标到最后发现标注格式错了、类别顺序乱了、漏标严重的问题。数据标注看起来是体力活但任何环节疏忽都可能让训练出来的模型跟着崩盘。LabelImg不是最智能的标注工具但它简单、免费、跨平台、格式兼容性好尤其是在Windows环境下作为第一个标注工具非常合适。我到现在的一些小项目里依然会打开它快速处理数据省去切换其他重型标注平台的成本。先把这些基本功练熟你会发现后面接触更复杂的标注平台和自动标注方案时理解起来会顺畅得多。
返回列表