4-2 图像标注实战(Label Studio)
学习目标
- 掌握 Label Studio 的安装、启动与界面使用
- 学会配置三种图像标注类型(分类、目标检测、语义分割)
- 独立完成边界框、多边形、关键点的标注
- 理解 VOC / YOLO / COCO 三种导出格式的区别
1. Label Studio 简介
1.1 一句话定义
Label Studio:一个开源的、多模态数据标注平台,支持图像、文本、语音、视频等几乎所有数据类型的标注与团队协作。
1.2 为什么选它
我们这门课统一用 Label Studio 的原因:
| 需求 | Label Studio 对应能力 |
|---|---|
| 多种数据类型 | 图像 / 文本 / 语音 / 视频 / 时序,一站式 |
| 不用写代码 | 通过 XML 标签可视化配置标注界面 |
| 团队协作 | 内置成员管理、角色权限、任务分配 |
| 格式灵活 | 内置 YOLO、COCO、VOC、JSON、CSV 导出 |
| 本地部署 | 数据不出学校,开源免费 |
传统方案(多工具切换):
图像 → LabelImg
文本 → Doccano
语音 → Audacity / ELAN
协作 → Excel 邮件
Label Studio 一站式:
图像 / 文本 / 语音 / 协作 → Label Studio
1.3 与其他工具的对比
| 工具 | 类型 | 适用场景 | 本课程 |
|---|---|---|---|
| Label Studio | 开源/多模态 | 课程学习 / 中小团队 / 综合项目 | 主选 |
| LabelImg | 开源/图像 | 极简目标检测 | 仅做对比 |
| CVAT | 开源/图像视频 | 大型分割、视频跟踪 | 了解 |
| Doccano | 开源/文本 | 简单文本分类 | 已弃用 |
| Scale AI | 商业 | 企业级标注 | 了解 |
2. Label Studio 安装与启动
2.1 环境要求
- Python 3.8 及以上
- 浏览器(Chrome / Edge / Firefox)
- 建议 8G 以上内存
2.2 pip 安装(推荐)
# 在命令行中执行
pip install label-studio
# 启动 Label Studio
label-studio
启动后命令行会显示:
[INFO] Label Studio is running at http://localhost:8080
[INFO] Open it in your browser to start labeling
2.3 第一次打开
- 浏览器访问
http://localhost:8080 - 第一次进入需要 Sign Up 注册管理员账号(用你的邮箱 + 密码)
- 注册后自动登录到主界面
┌────────────────────────────────────────────────────────┐
│ Label Studio │
│ Sign Up │
├────────────────────────────────────────────────────────┤
│ │
│ Email: [___________________________] │
│ Username: [___________________________] │
│ Password: [___________________________] │
│ │
│ [ Create Account ] │
│ │
└────────────────────────────────────────────────────────┘
2.4 安装常见问题
| 问题 | 解决 |
|---|---|
| 端口 8080 被占用 | label-studio --port 8001 |
| 启动报错找不到模块 | pip install --upgrade label-studio |
| 中文乱码 | 系统区域设置改为 UTF-8 |
| 浏览器无法打开 | 检查防火墙、放行端口 |
3. 主界面导览
登录后看到的主界面:
┌──────────────────────────────────────────────────────────────┐
│ [Label Studio] Projects Members Settings [用户头像] │
├──────────────────────────────────────────────────────────────┤
│ │
│ My Projects │
│ │
│ ┌────────────────────────────────────────────────┐ │
│ │ + Create Project │ │
│ └────────────────────────────────────────────────┘ │
│ │
│ 没有任何项目,点上面按钮开始 │
│ │
└──────────────────────────────────────────────────────────────┘
主要功能区:
- Projects:项目列表,每个项目对应一个标注任务
- Members:成员管理(管理员可见)
- Settings:个人设置
4. 创建第一个项目:图像分类
4.1 任务说明
任务:对 10 张动物图片进行分类,类别有:cat / dog / bird
4.2 创建项目
- 点击
+ Create Project - 填写:
- Project Name:
animal_classification - Description:动物图片三分类
- Project Name:
- 点击
Save
4.3 配置标注界面
进入项目后,先点 Settings → Labeling Interface → Code:
<View>
<Image name="image" value="$image"/>
<Choices name="label" toName="image" choice="single">
<Choice value="cat"/>
<Choice value="dog"/>
<Choice value="bird"/>
</Choices>
</View>
逐行解释:
<View> ← 整个标注界面的根标签
<Image ...> ← 显示图像($image 是任务数据里的字段名)
<Choices ...> ← 单选/多选控件
<Choice/> ← 一个选项
</View>
关键参数:
toName="image":告诉 Label Studio,这个控件是对上面Image控件的结果choice="single":单选(可选single-radio、multiple)
保存后点 Label All Tasks 就能看到标注界面。
4.4 导入数据
在项目页 → Settings → Data Import:
方式 A:上传本地文件
1. 准备文件夹
images/
├── cat_001.jpg
├── cat_002.jpg
├── dog_001.jpg
└── bird_001.jpg
2. 拖拽到上传区域
或点击 Upload Files 选中文件夹
方式 B:上传 CSV / JSONL(推荐,标签稳定)
tasks.csv:
image
images/cat_001.jpg
images/cat_002.jpg
images/dog_001.jpg
images/bird_001.jpg
方式 C:粘贴 URL
image
https://example.com/cat_001.jpg
https://example.com/dog_001.jpg
上传完后点 Save → 任务列表里就会看到每一张图对应一行任务。
4.5 开始标注
- 点击
Label All Tasks - 进入标注界面:
- 上面是图片
- 下面是三个单选按钮
- 选中正确类别
- 点击右下角
Submit进入下一张 - 全部完成后回到项目页,可以看到完成进度
┌──────────────────────────────────────────────────┐
│ Project: animal_classification │
├──────────────────────────────────────────────────┤
│ Tasks: 10 total / 7 done / 3 skipped │
│ Progress: ████████████░░░░░░ 70% │
└──────────────────────────────────────────────────┘
4.6 导出数据
项目页 → Export:
- 格式选
JSON - 下载得到
project-1-at-2024-05-20.json
导出内容示例:
[
{
"id": 1,
"data": {"image": "images/cat_001.jpg"},
"annotations": [{
"result": [{
"from_name": "label",
"to_name": "image",
"type": "choices",
"value": {"choices": ["cat"]}
}]
}]
}
]
5. 创建第二个项目:目标检测(边界框)
5.1 任务说明
任务:对 10 张街景图进行目标检测,标出每张图中的 person、car、bicycle
5.2 项目配置 XML
<View>
<Image name="image" value="$image"/>
<RectangleLabels name="label" toName="image" strokeWidth="3">
<Label value="person" background="#FF0000"/>
<Label value="car" background="#00FF00"/>
<Label value="bicycle" background="#0000FF"/>
</RectangleLabels>
</View>
新增标签:
<RectangleLabels>:矩形框 + 标签(Label Studio 专门用于目标检测)<Label value="..." background="...">:每个标签的颜色strokeWidth="3":边框线宽
5.3 标注操作
进入标注界面后:
┌──────────────────────────────────────────────────┐
│ [image] │
│ ┌────────┐ │
│ │ 人 │ ← 拖动鼠标画框 │
│ └────────┘ │
│ ┌─────────┐ │
│ │ 车 │ │
│ └─────────┘ │
├──────────────────────────────────────────────────┤
│ 标签栏: │
│ [ person ] [ car ] [ bicycle ] │
└──────────────────────────────────────────────────┘
操作步骤:
- 选中上方标签(点击 person/car/bicycle 之一)
- 在图片上 按住鼠标左键拖动,画矩形框
- 松开后,框会自动带上刚才选中的标签
- 继续选下一个标签,再画下一个框
- 同一张图可以有多个框
- 标完后点
Submit
5.4 快捷键速查
| 快捷键 | 功能 |
|---|---|
Ctrl + Enter |
提交当前任务 |
H |
切换显示已画框 |
Ctrl + Z |
撤销上一个框 |
Delete |
删除选中的框 |
数字 1-9 |
快速选择第 N 个标签 |
+ / - |
缩放图像 |
| 滚轮 | 上下滚动 |
5.5 边界框标注规范
基本规则:
正确(紧贴目标) 错误(框太大) 错误(截断)
┌──────────┐ ┌────────────────┐ ┌──────────
│ ▓▓▓▓▓▓▓ │ │ ▓▓▓▓▓▓▓▓▓▓▓▓▓ │ │ ▓▓▓▓▓▓▓ │
│ ▓ 人 ▓▓ │ │ ▓ 人 ▓▓▓▓▓▓ │ │ ▓ 人 ▓▓ │
│ ▓▓▓▓▓▓▓ │ │ ▓▓▓▓▓▓▓▓▓▓▓▓▓ │ │ ▓▓▓▓▓▓▓ │
└──────────┘ └────────────────┘ └──────────┘
多目标处理:
- 一张图有几个就标几个,每个独立画框
- 互相重叠的目标也要分别标
- 远处很小的目标可以标 "difficult" 标记
遮挡处理:
情况1:目标被部分遮挡
→ 标可见部分(标框框住能看到的人)
情况2:目标被严重遮挡(< 20% 可见)
→ 建议不标(标记为非标注目标)
情况3:多人重叠
→ 每个独立标,画框按可见边界
5.6 YOLO 格式导出
项目页 → Export → 选 YOLO:
下载得到压缩包,解压后结构:
project-1-at-2024-05-20-yolo/
├── images/
│ ├── street_001.jpg
│ └── street_002.jpg
├── labels/
│ ├── street_001.txt
│ └── street_002.txt
├── classes.txt
└── notes.json
classes.txt(类别映射):
0: person
1: car
2: bicycle
street_001.txt(一张图的标注):
# 格式: <class_id> <x_center> <y_center> <width> <height>
# 所有值都是相对图片尺寸的归一化值 (0-1)
0 0.35 0.45 0.18 0.55
1 0.75 0.50 0.30 0.20
逐字段解释:
0 → 类别 ID(0=person)
0.35 → 框中心点 x / 图片宽度
0.45 → 框中心点 y / 图片高度
0.18 → 框宽度 / 图片宽度
0.55 → 框高度 / 图片高度
5.7 Pascal VOC 格式导出
项目页 → Export → 选 PascalVOC:
street_001.xml:
<?xml version="1.0" encoding="UTF-8"?>
<annotation>
<filename>street_001.jpg</filename>
<size>
<width>1920</width>
<height>1080</height>
<depth>3</depth>
</size>
<object>
<name>person</name>
<bndbox>
<xmin>134</xmin>
<ymin>216</ymin>
<xmax>478</xmax>
<ymax>810</ymax>
</bndbox>
</object>
<object>
<name>car</name>
<bndbox>
<xmin>1100</xmin>
<ymin>450</ymin>
<xmax>1680</xmax>
</bndbox>
</object>
</annotation>
注意 VOC 用的是绝对像素坐标(xmin、ymin、xmax、ymax),而 YOLO 是归一化坐标(0-1)。
5.8 COCO 格式导出
项目页 → Export → 选 COCO:
result.json:
{
"images": [
{"id": 1, "file_name": "street_001.jpg", "width": 1920, "height": 1080},
{"id": 2, "file_name": "street_002.jpg", "width": 1920, "height": 1080}
],
"categories": [
{"id": 0, "name": "person"},
{"id": 1, "name": "car"},
{"id": 2, "name": "bicycle"}
],
"annotations": [
{
"id": 1, "image_id": 1, "category_id": 0,
"bbox": [134, 216, 344, 594],
"area": 204336,
"iscrowd": 0
}
]
}
注意 COCO 的 bbox 格式是 [x_min, y_min, width, height](前两个是左上角,后两个是宽高),和 VOC 略有区别。
5.9 三种格式对比
| 特性 | VOC | YOLO | COCO |
|---|---|---|---|
| 文件类型 | 每个图一个 XML | 每个图一个 TXT | 所有图一个 JSON |
| 坐标系 | 绝对像素 (xmin,ymin,xmax,ymax) | 归一化 0-1(中心点+宽高) | 绝对像素 (x,y,w,h) |
| 多目标 | 一个 object 一对 bndbox | 一行一个目标 | 一个 annotation 一个目标 |
| 适用框架 | Faster R-CNN, SSD | YOLO 系列 | Mask R-CNN, Detectron2 |
| 优缺点 | 直观但文件多 | 紧凑、YOLO 专用 | 强大、适合大项目 |
| 人类可读 | ⭐⭐⭐ | ⭐ | ⭐⭐ |
怎么选:
- 学 YOLO 模型 → 导 YOLO
- 用 MMDetection / Detectron2 → 导 COCO
- 通用、自己写训练脚本 → 导 VOC 或 JSON
6. 创建第三个项目:语义分割(多边形)
6.1 任务说明
任务:对 5 张街景图做像素级语义分割,类别:road、building、sky、vegetation
6.2 项目配置 XML
<View>
<Image name="image" value="$image"/>
<PolygonLabels name="label" toName="image" strokeWidth="2">
<Label value="road" background="#808080"/>
<Label value="building" background="#A52A2A"/>
<Label value="sky" background="#87CEEB"/>
<Label value="vegetation" background="#228B22"/>
</PolygonLabels>
</View>
<PolygonLabels>:多边形 + 标签,专门用于语义分割。
6.3 标注操作
- 选中标签(点击 road / building / sky / vegetation)
- 在图像上连续点击多个点画出多边形
- 双击或按回车结束当前多边形
- 一个类别画完,再选下一个类别继续
- 一张图可能有很多个多边形
标注过程示意:
点 1 ──→ 点 2
│
↓
点 4 ←── 点 3
(双击结束)
┌──────────────────┐
│ │
│ 1────────2 │
│ │ │ │
│ │ 区域 │ │
│ │ │ │
│ 4────────3 │
│ │
└──────────────────┘
6.4 分割标注注意事项
| 情况 | 处理 |
|---|---|
| 两个区域紧贴 | 各画一个多边形,不要合成一个 |
| 区域很小 | 至少 3 个点画出三角形 |
| 形状不规则 | 多点描边,越细越准 |
| 类别不确定 | 选最接近的,宁可错记也不要漏 |
6.5 导出多边形
项目页 → Export → 选 JSON:
{
"id": 1,
"data": {"image": "street_001.jpg"},
"annotations": [{
"result": [{
"from_name": "label",
"to_name": "image",
"type": "polygonlabels",
"value": {
"points": [[0.1, 0.8], [0.9, 0.8], [0.9, 1.0], [0.1, 1.0]],
"polygonlabels": ["road"]
}
}]
}]
}
points 数组里每个点都是 [x, y] 的归一化坐标(0-1),是按顺时针或逆时针排列的多边形顶点。
💡 想转成 mask(像素级 PNG 图)?需要用
label-studio-converter工具,详见 4-4 节。
7. 课堂演示:Python SDK
7.1 简介
Label Studio 提供 label-studio-sdk,可以用 Python 编程式管理项目、查询任务、写入预标注。
7.2 安装
pip install label-studio-sdk
7.3 常用代码
from label_studio_sdk import Client
# 连接本地服务
ls = Client(url='http://localhost:8080', api_key='YOUR_API_KEY')
# 获取 API Key:
# Label Studio → Settings → Account → Access Token
# 列出所有项目
projects = ls.list_projects()
for p in projects:
print(p.id, p.title)
# 获取某个项目的任务
project = ls.get_project(id=1)
tasks = project.get_tasks()
print(f"项目里有 {len(tasks)} 个任务")
# 导入新任务
project.import_tasks([
{"image": "images/new_001.jpg"},
{"image": "images/new_002.jpg"}
])
# 导出标注
project.export_tasks(export_type='JSON')
这一节以了解为主,详细用法 4-4 节会展开。
8. 实战练习
8.1 任务一:图像分类(必做)
任务:在 Label Studio 创建项目 fruit_classification
步骤:
- 准备 10 张水果图片(apple、banana、orange)
- 启动 Label Studio,创建项目
- 配置
<Choices>三分类界面 - 上传 10 张图
- 完成 10 张标注
- 导出 JSON 并截图
8.2 任务二:目标检测(必做)
任务:创建项目 vehicle_detection
步骤:
- 准备 10 张街景图
- 配置
<RectangleLabels>目标检测界面 - 类别:person / car / bicycle / traffic_light
- 标完所有目标
- 导出 YOLO 格式
- 检查导出的 .txt 文件坐标是否正确
8.3 任务三(选做):语义分割
任务:创建项目 scene_segmentation
步骤:
- 准备 3-5 张风景图
- 配置
<PolygonLabels>分割界面 - 类别:sky / vegetation / road / building
- 画多边形
- 导出 JSON
8.4 标注自检清单
图像分类:
□ 类别选择是否正确
□ 是否有漏标的任务
□ 导出 JSON 是否完整
目标检测:
□ 边界框是否紧贴目标
□ 是否每个目标都标了
□ 框内类别是否正确
□ 导出 YOLO 格式后坐标值是否在 0-1 之间
□ classes.txt 是否齐全
语义分割:
□ 多边形顶点是否足够(至少 3 个)
□ 类别判断是否准确
□ 不同区域之间是否有遗漏
9. 本节知识小结
┌────────────────────────────────────────────────────────────┐
│ 4-2 图像标注实战(Label Studio) │
├────────────────────────────────────────────────────────────┤
│ │
│ 📌 Label Studio 是多模态标注平台,一站式解决图像/文本/语音 │
│ │
│ 📌 安装: │
│ pip install label-studio │
│ label-studio │
│ 浏览器访问 http://localhost:8080 │
│ │
│ 📌 三种图像标注类型: │
│ 分类 → <Choices> │
│ 目标检测 → <RectangleLabels> │
│ 语义分割 → <PolygonLabels> │
│ │
│ 📌 三种导出格式: │
│ VOC → XML,像素绝对坐标 │
│ YOLO → TXT,归一化 0-1 坐标 │
│ COCO → JSON,[x,y,w,h] 像素坐标 │
│ │
│ 📌 标注规范:框要紧贴目标、不多不少 │
│ │
└────────────────────────────────────────────────────────────┘
课后任务
- 安装 Label Studio,截图证明能正常打开
- 完成"任务一"图像分类 10 张图
- 完成"任务二"目标检测 10 张图,导出 YOLO 格式
- (选做)完成"任务三"语义分割
下节预告
下一节我们将学习 4-3 文本标注与语音标注(Label Studio):
- 文本分类、NER 命名实体识别
- 意图识别与槽位标注
- 语音转写 ASR
- 说话人分离与音频分类