多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

Label Studio数据标注工具实战:从安装到导出YOLO格式

Label Studio数据标注工具实战:从安装到导出YOLO格式 1. 为什么数据标注是绕不开的一步而Label Studio恰好能帮你省事做过目标检测、图像分类这类深度学习项目的朋友应该都有体会模型结构再花哨、训练代码再熟练如果训练数据没有准备好一切都白搭。我最早开始做目标检测的时候自己闷头用Python脚本画框、存坐标写了一个简陋的标注工具结果用了没几天就发现根本撑不住——图片一多标注文件对不上、标签名字写错、坐标算错光是清洗数据就耗掉了大半个周末。后来换用数据标注工具才真正明白这类工具存在的意义。数据标注工具要解决的核心问题其实很朴素把“人在图片上框出目标”这件事变得足够简单并且把结果输出成训练框架能直接消费的格式。而在众多开源工具里Label Studio是我用了很久、也最愿意推荐给别人的一个。先说说它的定位。Label Studio是一个开源的数据标注平台支持图像、文本、音频、视频等多种数据类型。对做视觉方向的人来说常用的功能无非就是图像分类、矩形框目标检测、多边形分割、关键点标注这几种它全都覆盖了。更重要的是它内置了多种导出格式包括JSON、CSV、COCO、VOC甚至可以直接导出YOLO格式这意味着你标注完的数据能直接喂给YOLO系列模型训练不用再写一堆蹩脚的转换脚本。这篇文章适合谁如果你是刚入门深度学习、需要自己做数据集的在校学生或者是在小团队里需要快速搭建一套标注流程的工程师又或者只是单纯想找一个比Windows画图好用一万倍的标注工具那这篇内容基本就是为你准备的。下面我会用一套完整的流程从安装、创建项目、实际操作到导出数据帮你把Label Studio的基础使用方法一次讲透。数据标注这件事技术上不复杂但很多人在工具选型和使用细节上会走弯路。我踩过的坑希望你看完之后能直接绕开。2. 本地跑起来安装方式、启动命令与界面布局2.1 安装前的环境准备Label Studio对运行环境的要求不算高它本质上是一个Python服务通过浏览器访问页面操作。你可以把它理解成一个跑在本地的小型Web应用——类似你在本地启动过的Jupyter Notebook那样只不过它专门用来做数据标注。环境上你只需要满足这几点操作系统Windows、macOS、Linux都可以我分别在Windows 10和Ubuntu 20.04上跑过都没问题Python版本建议3.8以上官方文档说3.8-3.11都能用浏览器Chrome或者Edge最好Firefox也能用但某些交互在Chrome下更顺手内存标注工具本身不挑内存但如果你要一次性导入几百张高清大图并做缩略图预览8GB或以上会更舒服需要注意如果你电脑上装了多个Python版本建议用虚拟环境来安装Label Studio避免包依赖冲突。这个工具依赖了Django、DRF等一堆Python库和某些老旧项目的依赖撞车的概率不低。2.2 安装并启动Label Studio安装方式有两种pip安装和Docker运行。Docker适合多人协作的服务器部署场景省去了环境折腾的麻烦。但对于绝大多数个人使用场景我建议直接用pip简单直接。先用虚环境隔离一下依赖# 创建并激活虚拟环境Windows和Linux/macOS略有区别 python -m venv label-studio-env # Windows下激活 label-studio-env\Scripts\activate # Linux/macOS下激活 source label-studio-env/bin/activate # 安装label-studio pip install label-studio安装完成后在命令行输入label-studio start服务启动后终端会输出一段日志并提示你在浏览器中访问http://localhost:8080。我第一次启动的时候还担心端口被占用其实它默认用8080如果被占用可以用label-studio start --port 8081指定其他端口。首次访问时页面会让你创建一个管理员账号也就是设置用户名、邮箱和密码。这个账号就是整个系统里权限最高的账号后续的成员管理、标注任务分配都要用它来做。有人会问能不能跳过这一步答案是不能——Label Studio的数据都存储在服务端必须有一个账号体系来管理项目和权限。创建完账号进入主界面你会看到一个项目列表页目前是空的。先别急着新建项目我建议你先花两分钟把界面上的几个入口认清楚。2.3 界面布局和服务运行的底层逻辑Label Studio的主界面很简洁左侧有Projects项目列表、Import导入数据、Export导出数据这类入口但这些入口大多是在进入具体项目之后才生效的。实际上它的核心操作逻辑是项目是一等公民所有操作都围绕项目展开。有一个很多人忽略的细节Label Studio的数据存储方式。所有标注数据、项目配置都保存在本地的文件系统中。如果你用的是pip安装默认的数据目录会在你的用户目录下比如~/label-studio这个文件夹。里面包含media上传的图片等媒体文件、files项目配置和导出文件的缓存等子目录。这点很重要尤其是当你标注了大量数据后想备份或迁移直接复制这个目录就相当于备份了整个Label Studio。我个人习惯是在启动之前就用环境变量指定数据目录比如LABEL_STUDIO_BASE_DATA_DIR/your/path/label-studio-data label-studio start这样所有的数据都会存放到你指定的目录下不会因为系统盘空间不足或者用户目录被清理而丢数据。这个习惯帮我避免过一次大麻烦后面会详细说。3. 创建图片标注项目模板选择、标签设置与数据导入3.1 新建项目的两种路径在主界面点击Create Project按钮会看到两种创建方式从模板创建From Template和从空白项目创建Blank Project。我强烈建议新手先使用模板因为模板已经帮你配置好了标注界面和导出结构你只需要改标签名就行。等用熟了再自己用Labeling Config编辑器去写标签配置。点击From Template之后你会看到一个模板列表。这个列表涵盖了图像、文本、音频、视频各类任务。对做目标检测的朋友来说最常用的是这几个Object Detection with Bounding Boxes矩形框目标检测最常用Image Classification图像分类给整张图打标签Semantic Segmentation with Polygon多边形分割像素级标注KeyPoint Labeling关键点标注适合姿态估计选择Object Detection with Bounding Boxes模板进入项目配置页面。3.2 配置标签名与标签颜色项目配置页面有两个地方要填Project Name和Labeling Setup。Project Name随意最好起一个能一眼看出用途的名字比如“cat-dog-detection-dataset”。Labeling Setup是这个页面里最核心的部分。模板会自动生成一段XML格式的标签配置像这样View Image nameimage value$image/ RectangleLabels namelabel toNameimage Label valueCat background#FF0000/ Label valueDog background#00FF00/ /RectangleLabels /View你可以直接在这段配置中修改Label标签把value改成你自己的类别名。比如我做过一个口罩佩戴检测的数据集就把标签改成了WithMask和WithoutMask。颜色也可以自定义建议不同类别用对比度高的颜色标注的时候一眼就能区分。有一个细节值得注意标签名最好用英文和下划线尽量避免使用中文或带空格的类名。虽然Label Studio界面支持中文标签名但导出的YOLO格式中类别名称最终会映射到data.yaml的names列表中文类名在后处理时会带来不必要的麻烦。我见过有人用了中文类名后面解析标签映射文件时编码出错回头又要重新导一遍浪费时间。3.3 导入图片数据项目创建完成后会自动进入项目详情页。点击右上角Import按钮就能导入图片数据了。Label Studio支持几种导入方式从本地上传文件或文件夹拖拽即可通过URL批量导入从云存储如AWS S3、Google Cloud Storage导入本地导入最简单直接把图片文件拖进上传区域就行。一次拖入几百张图片也没问题它会自动创建任务队列每张图片就是一个待标注的Task。这里有一个我刚开始没注意到的细节Label Studio导入的其实不只是图片本身它会把每个文件封装成一个“Task”任务并且给每个Task分配一个唯一的ID。后续你标注的结果、导出的JSON文件都会关联到这个Task ID。理解这一点有助于你排查“为什么我的标注结果对不上某张图片”这类问题。另一个实际经验是如果你要导入的图片是几千万像素的高清大图建议先压缩到合理的分辨率再导入。原因有两个一是Label Studio在浏览器中渲染大图时缩放和拖拽会明显卡顿标注效率极低二是缩略图生成也会变慢。我通常会先用Python脚本把图片统一处理成1920像素以内的尺寸既不影响标注精度又让界面操作流畅很多。4. 动手标一张图工具箱、快捷键与完整标注流程4.1 标注界面的功能分区进入项目后点击任意一条任务就进入了标注界面。整个界面分为三个核心区域中间是图片画布可以缩放、拖拽左侧是工具条包含矩形框、画笔、缩放、撤销等工具右侧是标签面板和属性面板用于选择当前要标注的类别画布下方还有任务导航栏可以切换到上一张、下一张图片。右上角有Submit按钮代表完成了当前任务的标注并提交。第一次进入的时候可能会觉得工具栏图标太多其实常用的就那几个。做矩形框标注的话核心是Rectangle工具旁边的智能工具Smart是一个辅助工具后面我会单独说。4.2 标注一张图的完整流程以目标检测为例标准的标注流程是这样的在右侧标签面板选择一个类别比如Cat在画布上按住鼠标左键从目标物体的左上角拖到右下角松手后就能画出一个矩形框如果框的位置不准确可以选中这个框拖动边框上的控制点微调继续画下一个目标或者按快捷键切换到下一张图片所有目标都标完之后点击Submit提交听起来很简单但实际操作中有一个特别影响效率的点标签切换。如果你把鼠标移回右侧面板去点标签再回来画框一张图画几个目标就要来回移动好几次非常累。Label Studio的快捷键能解决这个问题。在键盘上按下对应数字键就能直接切换标签。默认情况下每个标签对应一个数字编号按1、2、3就能切换不同类别。这样你只需要把鼠标一直放在画布上标注速度能提升一倍不止。还有几个快捷键很常用滚轮缩放画布按住空格加拖拽平移画布CtrlZ撤销上一步操作CtrlC / CtrlV复制粘贴矩形框适用于重复场景这个技能尤其适合那种一张图里有几十个小目标的场景比如标注一群鸟或者一堆螺丝用快捷键配合复制粘贴效率提升很明显。4.3 属性面板与动态标签在标签配置中除了简单的RectangleLabelsLabel Studio还支持给标签添加属性Attributes比如一个框除了类别之外还能标记“是否模糊”“遮挡程度”等。这在真实项目中非常有用。举个例子我做过一个交通标志检测的数据集只需要找到标志矩形框但有些标志被树叶遮挡了一半。如果不标记遮挡属性模型训练时会被这类样本误导。我给标签增加了Occluded这个属性字段标注时勾选一下就行了。属性配置也是在Labeling Setup里加代码比如RectangleLabels namelabel toNameimage Label valueStopSign background#FFA500/ Label valueSpeedLimit background#0000FF/ /RectangleLabels Choices nameoccluded toNameimage showInLabeltrue Choice valueOccluded/ Choice valueNotOccluded/ /Choices把showInLabel设置为true之后右侧面板上就会针对每个已标注的框显示一个下拉选项非常直观。4.4 智能标注工具Smart的使用边界工具条上的Smart工具很多人第一次点开会觉得好奇使用后发现它是调用机器学习模型对矩形框附近的像素做进一步分割。它的原理是在矩形框区域内用预训练分割模型提取目标轮廓生成更精细的多边形掩膜。但这里我要泼一盆冷水如果你是做常规的矩形框目标检测Smart工具其实帮不上太大的忙因为矩形框检测要的是“外接矩形”而不是“精准轮廓”。Smart更适合分割标注场景比如你要给一张图里的人抠出精细轮廓先拉个大框包住人再让Smart去自动分割会比手动一个点一个点描边快得多。所以我的建议是如果主要做目标检测忽略Smart工具就好别在这上面纠结。4.5 Review机制与任务状态管理每标完一张图点击Submit后任务状态会变成Submitted。但在多人协作的场景下你可能还希望有一个“审核”环节。Label Studio默认的工作流是Created → Labeled你可以通过配置增加Review步骤让经验丰富的人去检查新手标注的框有问题就退回重标。这个机制小团队可能用不上人少的时候自己标完自己审核一遍就完事了。但如果团队里有几个人同时标注Review流程能拦截不少低级错误比如框画错位置、漏标目标这些。配置方式是在Settings → Review页签里开启Review Enabled被分配Review权限的账号就能在标注界面看到Review模式。5. 让数据变成YOLO能吃的格式导出与格式转换5.1 导出面板与原生格式当一批图片都标注完成之后回到项目详情页点击右上角的Export按钮会弹出一个导出面板。这里面列出了Label Studio支持的所有导出格式包括JSON、CSV、COCO、VOC、YOLO等。大部分刚接触Label Studio的人会在这里卡一下明明数据标好了为什么导出的文件里找不到一个能直接用来训练YOLO的txt文件答案很简单因为YOLO训练需要的数据格式不是单一文件而是需要图片文件夹、标注文件夹和类别配置文件三者配套存在。Label Studio的YOLO导出功能其实已经内置了。在导出面板选择YOLO格式会下载一个压缩包解压后里面包含images图片、labels标签txt和一个classes.txt或data.yaml文件。很多时候你会发现它导出的目录结构跟你预期的略有差异这是因为Label Studio本身支持多种YOLO变体darknet、ultralytics不同版本的目录结构稍有不同。5.2 导出的YOLO文件到底是什么结构如果你选择的是darknet风格导出解压后你会看到类似这样的结构yolo_export/ ├── obj_train_data/ │ ├── image001.jpg │ ├── image001.txt │ ├── image002.jpg │ ├── image002.txt │ └── ... ├── obj.names ├── train.txt └── ...其中obj.names文件内容就是每个类别的名称按顺序排列比如Cat Dog每一行对应一个类别ID从0开始。而每个image001.txt文件里每一行代表一个目标框格式是class_id x_center y_center width height注意这里的所有坐标都是归一化的即像素坐标除以图片的宽高后得到的0到1之间的浮点数。比如一张1000x800的图片框的左上角在(100, 100)右下角在(300, 250)那么宽度 300 - 100 200高度 250 - 100 150x_center (100 200/2) / 1000 0.2y_center (100 150/2) / 800 0.21875width 200 / 1000 0.2height 150 / 800 0.1875所以txt中记录的一行就是0 0.2 0.21875 0.2 0.1875。搞清楚这个结构你才真正理解YOLO格式以后不管是手动检查标注还是写脚本做数据增强心里都有底。5.3 如果导出的格式不对如何手动转COCO为YOLO虽然Label Studio内置了YOLO导出但有时候你会在Project设置里发现导出面板并没有YOLO选项。这通常是因为创建项目时选择的标注模板不被YOLO导出器识别或者Label Studio版本较老。这时候不用慌我们可以走一条通用路径先导出COCO格式的JSON文件再写个小脚本转成YOLO格式。COCO格式的JSON是这样一个结构它把所有信息集中在一个JSON文件里包含images数组每张图的id、宽高、文件名、annotations数组每个框所属的image_id、类别id、bbox坐标、categories数组所有类别名与id的映射。转成YOLO格式的核心逻辑就是用Python遍历这些数组把COCO的bbox坐标左上角x、左上角y、宽度、高度转换为YOLO的归一化中心点坐标然后按图片分组写到txt文件里。下面这个脚本我一直在用非常稳定你可以直接抄走import json import os # 原COCO标注文件路径 coco_file coco.json # 输出目录 output_dir yolo_dataset os.makedirs(os.path.join(output_dir, labels), exist_okTrue) with open(coco_file, r, encodingutf-8) as f: coco_data json.load(f) # 构建类名列表和id到索引的映射 categories {cat[id]: idx for idx, cat in enumerate(coco_data[categories])} class_names [cat[name] for cat in coco_data[categories]] with open(os.path.join(output_dir, data.yaml), w, encodingutf-8) as f: f.write(names:\n) for name in class_names: f.write(f - {name}\n) # 构建图片信息字典image_id - (file_name, width, height) image_info {} for img in coco_data[images]: image_info[img[id]] (img[file_name], img[width], img[height]) # 对每张图片聚合所有标注框并写入txt annotations_by_image {} for ann in coco_data[annotations]: annotations_by_image.setdefault(ann[image_id], []).append(ann) for img_id, anns in annotations_by_image.items(): file_name, img_w, img_h image_info[img_id] txt_path os.path.join(output_dir, labels, os.path.splitext(os.path.basename(file_name))[0] .txt) with open(txt_path, w, encodingutf-8) as f: for ann in anns: cls_idx categories[ann[category_id]] bbox ann[bbox] # [x, y, w, h] x_center (bbox[0] bbox[2] / 2) / img_w y_center (bbox[1] bbox[3] / 2) / img_h width bbox[2] / img_w height bbox[3] / img_h # 过滤掉越界的异常框 if x_center 0 or y_center 0 or width 0 or height 0: continue f.write(f{cls_idx} {x_center:.6f} {y_center:.6f} {width:.6f} {height:.6f}\n) print(转换完成文件已输出到:, output_dir)关于这个脚本有两个地方要提醒你注意。一是COCO的bbox是用左上角坐标加宽高来表示的不是中心点二是如果标注过程中出现过坐标越界、宽高为负的情况脚本里我加了一个过滤条件避免生成无效的训练数据。如果你用的Label Studio版本正常一般不会出现负值但写脚本时防一手总是稳妥的。5.4 导出前的数据检查训练之前最重要的5分钟不管用内置导出还是脚本转换导出完成后都别急着去训练。花五分钟检查一下结果能帮你省下后面好几个小时的排查时间。检查的内容主要有几个方面一是每个标签类别对应的txt文件是否存在文件数量是否和图片数量一致二是txt文件里的坐标值是否都在0到1之间三是打开一张有标注的图片对比一下能显示出来的框和原来标注的形状是否吻合。Label Studio还提供了一个很实用的功能在数据导入前先检查一下源文件与标注文件的关联。具体做法是在项目面板找到Download Backup按钮这个按钮会导出整个项目的元数据。有时候你发现标注结果对不上图片多半就是任务和图片文件之间的对应关系出了问题这时候可以回去用备份数据核对。6. 半路最常翻车的位置与提升效率的小建议6.1 坑一自动保存并不等于万无一失Label Studio有自动保存功能标注操作的实时更新会被写入后端数据库。很多人因此就有一种“标了就会自动存好”的错觉。但实际使用中我遇到过这样一个情况项目组新来的实习生标注了200张图第二天打开项目发现只显示了100张原因是他标注完成后没有点Submit按钮属于草稿状态的任务在特定情况下不会进入已完成列表。所以我的习惯是每标注完一张图顺手按一下快捷键或点击Submit从机制上确保任务状态确实是Labeled。如果你是一个标了很多张图又不想挨个点Submit的人可以在项目Settings里开启Auto Submit功能。开启后切换下一张图片时当前图片会自动提交但小心如果你还在犹豫要不要修改某个框误触了切换那就不好找回来了。6.2 坑二大图片导致浏览器崩溃或卡顿图片分辨率过高时Label Studio在前端渲染会非常吃力尤其是同时加载多个缩略图的时候。有些监控视频抽帧出来的图片是1920x1080其实还好。但如果你做遥感图像或者显微图像原始分辨率动辄上亿像素这时候硬标肯定卡成幻灯片。针对这种场景比较务实的方案是先在本地用脚本对图片做切片把大图切成若干个小图块Tile每个Tile单独标注最后再把标注框的坐标映射回原图。整个过程说起来复杂但就算不做切片至少要把图片降采样到2400px以内再导入否则浏览器页面会响应极慢每一帧操作都有延迟非常崩溃。6.3 坑三多人协作时标签命名混乱如果你的项目不是一个人标而是三个人分工最容易出现的问题就是标签命名不统一。一个人把类别写成Cat另一个人写成了cat还有人写成Kitty导出的YOLO类别数量直接翻倍。这个问题的根源通常出在项目启动阶段没有统一规范。我从第二次做项目开始都会在开工前写一个简单的标签规范说明里面列出每个类别的标准名称、缩写、颜色并把它贴在项目简介里。同时给不同成员分配不同的Task区间避免同一个人重复标注同一批图片。Label Studio本身就支持在Project里管理团队成员和角色你可以给成员设置Reviewer、Annotator之类的角色让标注质量和进度都更可控。6.4 提升标注效率的几个实操技巧排完坑再分享几个我实际用下来提升效率的小技巧。一是善用快捷键。前文提过数字键切换标签这里再说一个画矩形框时如果你觉得画出来的框要反复微调可以适当放大画布再画放大的情况下鼠标控制精度更高。缩小画布画大框再放大微调其实效率更高。二是合理利用复制粘贴。对于一张图中有多个相同大小的目标先画好一个框调整到合适大小和比例然后CtrlC、CtrlV复制几个再拖到对应位置能省下大量重复画框的时间。三是随时关注数据分布。Label Studio首页的项目面板会显示每个项目的任务数量、已完成数量、标注进度百分比。我会给自己定个小目标每标完100张图就导出一次备份顺便看一下各类别数量有没有失衡。我做过的一个项目里第一轮标注完发现某个类别的出现频率只有另一个的十分之一于是及时补充采集了一批对应场景的数据最后模型训练效果好很多。如果等全部标完才发现数据失衡返工成本就大了。6.5 最后再分享一点个人习惯从最早用脚本手工标注到后来使用Label Studio完成了几个完整的数据集项目我最大的感受是工具只是手段它不能替你把数据质量提高但能把你从机械劳动里解放出来让你把精力花在真正重要的地方——检查类别定义是否清晰、框有没有包围住完整目标、边界案例有没有覆盖到。数据集的标注质量决定了一个模型能走到什么程度。很多模型效果不好问题不在于网络结构而在于训练数据本身就有大量错标、漏标和边界不清的样本。我自己见过不少人用Label Studio标完数据导出YOLO格式后跑出的mAP指标很低排查来排查去才发现是某个类别的框普遍画小了把目标的一部分框出去了。所以我的建议是哪怕工具用熟了、流程跑顺了也一定要定期抽查标注结果尤其是项目中后期、疲劳状态下标注的图片。找一个没参与标注的人随机抽几十张图检查一遍往往能发现你自己根本意识不到的规律性错误。这一点看起来笨拙却是保证标注质量最有效的办法。
返回列表