一个具身智能实验室研究员的触觉数据标注全流程实操记录。


背景:触觉数据标注,到底有多痛?
我在一个具身智能实验室做触觉操作相关的工作。最近接了个任务:用GelSight Mini传感器采集一批"抓取不同物体并放置"的触觉数据,标注好之后喂给模仿学习模型训练。
听起来很简单对吧?实际操作下来简直是一场噩梦:
原始 .pkl 文件里是一堆看不懂的数值,帧数上万,逐帧看?不现实
之前写的标注脚本换个物体就得改一遍,传感器一换就彻底废了
标注完还要转成LeRobot格式、FTP-1格式……每种训练框架要一种格式,光写转换器就写了一周
后来同事推荐我试试 TLabel(TouchLabel AI),说是一个"传感器无关的触觉数据标注工具包"。我用了一周,把整个流程从头到尾跑通了,感觉确实值得分享一下。

环境准备
安装非常简单:

pip install tlabel[all]

💡 如果用清华/阿里镜像源遇到版本过旧的问题,建议指定官方源:

pip install tlabel[all] -i https://pypi.org/simple/

装完之后,我打开Jupyter Notebook,开始正式的流程。

Step 1:导入数据——一行代码搞定适配器
我的实验用了GelSight Mini传感器,采集了30个episode的抓取放置数据,每个episode大约200帧。原始数据是 .pkl 文件。
TLabel 的 tlabel.load() 会自动识别传感器格式,不用手动指定适配器:

import tlabel

# 自动识别为GelSight格式,加载并提取22维标准特征
data = tlabel.load("raw_data/episode_001.pkl")

print(f"帧数: {data.num_frames}")      # 218
print(f"时长: {data.duration_s:.1f}s")  # 10.9s
print(f"传感器: {data.sensor_type}")     # gelsight
print(f"维度: {len(data.dimension_keys)}") # 22

支持哪些传感器? 目前TLabel内置了7种适配器:
传感器 格式 一行加载
GelSight / DIGIT .pkl tlabel.load("xx.pkl")
帕西尼 PaXini .h5 tlabel.load("xx.h5")
戴盟 Daimon .parquet/目录 tlabel.load("xx/")
TLabel Format .json tlabel.load("xx.json")
ToucHD-Force 目录 tlabel.load("xx/", format="touchd")
UniVTAC .hdf5 tlabel.load("xx.hdf5")
TacQuad (AnyTouch) 目录 tlabel.load("xx/", format="tacquad")
不管什么传感器,加载之后全部统一成22维标准特征空间——接触力、滑移熵、光流、摩擦锥比……全是一样的字段名和含义。
同时,TLabel会自动生成 sensor_profile 元数据层,记录传感器型号、采样率、标定参数等信息——这些数据后续导出时会一起打包,方便追溯。

💡 Tips:如果自动识别失败,可以用 format= 参数强制指定适配器。


Step 2:看看数据长啥样——Jupyter可视化面板
数据加载完,第一件事是看看数据质量怎么样。TLabel提供了一个嵌在Jupyter里的交互面板:

data.review()  # 中文界面
# data.review(lang="en")  # 也可以切英文

面板直接嵌在Notebook里,我能看到:
🎬 触觉图像序列:Canvas渲染的图像回放,支持播放/暂停/拖动/变速,还能开暗色模式
🎨 彩色时间轴:绿色=接触、红色=滑移、灰色=空闲,一目了然
🕸 22维雷达图:每帧自动更新,哪些维度突出一眼就看出来
✏️ 帧编辑器:点击任何维度直接修改数值
我一边拖时间轴一边看雷达图,很快就对这批数据有了整体感觉——大部分episode的抓取过程都很清晰,接触→稳定抓取→抬起→放置的节奏一目了然。

💡 Tips:面板右上角可以一键切换中英文,还有暗色模式,长时间标注不伤眼。


Step 3:数据质量过关吗?——质量评估 + 多模态同步检测
在正式标注之前,我习惯先做一轮数据质量检查。有些episode可能因为传感器松动或者采集异常,数据质量不行,得提前筛掉。
3.1 质量评估仪表盘
TLabel从4个维度对数据进行打分:

# 在面板中点击"质量"Tab即可查看
# 也可以通过代码获取
quality = data.quality_score()
print(quality)
# {
#   "physical_consistency": 0.92,  # 物理一致性:力和形变是否匹配
#   "temporal_smoothness": 0.88,   # 时序平滑度:相邻帧变化是否合理
#   "completeness": 0.95,          # 完整性:22维是否有大量缺失
#   "coverage": 0.85,              # 覆盖度:是否覆盖了完整操作过程
#   "overall": 0.90,               # 综合评分
#   "grade": "A"                   # 等级
# }

物理一致性检查的是"力和形变是否匹配"这种基本物理常识——如果力很大但形变为零,那多半数据有问题。时序平滑度检查帧间变化是否合理,突然跳变的帧会被标记出来。
3.2 多模态同步检测
我同时录了触觉和RGB相机的数据,需要确认时间戳是对齐的:

from tlabel.sync import SyncChecker

checker = SyncChecker()
report = checker.check(data, rgb_timestamps="raw_data/rgb_timestamps.npy")

print(report)
# ⏱ 时间戳偏差: max=12ms, mean=3.2ms ✅
# 📊 频率完整性: 触觉30Hz ✅, RGB 30Hz ✅
# 🔗 同步状态: 通过(偏差<50ms阈值)

这一步帮我揪出了2个episode的时间戳偏差超过50ms,直接剔除。

💡 Tips:质量评估建议做在所有episode上,不合格的提前筛掉,别标了半天发现数据本身就有问题。


Step 4:让AI先帮我标一遍——Primitive预标注
30个episode,每个200帧,一共6000帧。逐帧标?我会疯掉的。
TLabel的AI预标注功能救了我。它包含两层能力:
4.1 基础特征预标注(contact/slip/phase)

from tlabel.predict import PredictEngine

engine = PredictEngine()

# 先用一部分手动标注的数据做热启动(可选,但推荐)
# 我只手动标了前2个episode,约400帧
engine.fit(data)

# 对所有帧进行预标注
results = engine.predict(data)

# 只应用置信度 >= 0.7 的预测
applied = engine.apply(data, results, min_confidence=0.7)
print(f"自动填充了 {applied} 个字段")

引擎做了什么:
contact检测:融合力+形变+接触面积多信号判断
slip检测:剪切力+力变化率+滑移熵综合判断
manipulation_phase:HMM + Viterbi解码,自动识别 idle → initial_contact → stable_contact → slip → release 各阶段
4.2 Primitive预标注(v0.14.0新功能)
这个功能更厉害——直接从触觉图像推断出操作动作类型:

# 自动从视触觉图像推断力分布→检测事件→标注primitive
data.predict_primitives()

TLabel内置了一套Taxonomy系统,默认包含7种物理含义明确的primitive(来自T-Rex论文的22种中选出的):
Primitive 含义 力特征
reach 接近 无接触
grasp 抓取 力上升
press 按压 法向力增大
squeeze 挤压 力下降但仍接触
wrap 包覆 稳定接触+运动
wipe 擦拭 剪切力为主
lift 抬起 力变化+上移
如果我的任务有特殊动作(比如 twist 旋转),可以注册自定义primitive:

tlabel.register_custom_primitive('twist',
    force_range=(0.2, 1.0),
    deformation_max=0.2,
    contact_required=True,
    confidence=0.5
)

不需要力传感器也行——对于GelSight/DIGIT这类视触觉传感器,引擎会从图像中自动估算力分布,然后再映射到primitive。预测结果会带来源标签(ai_predicted_estimated)和置信度分数,完全透明。

💡 Tips:预标注的设计原则是"辅助标注,不做主"。低置信度的段落会自动留空,让你手动补。


Step 5:人工Review和调整——Episode标注
AI标完之后,我打开面板review。大部分标注都很准,但有些边界帧需要调整。
5.1 帧级修正
在面板里点击时间轴跳转到可疑帧,直接修改数值。TLabel有个很贴心的联动规则——当我把 contact 设为 0 时,force_magnitudeslip_event 等7个关联字段会自动归零,manipulation_phase 自动变成 idle

# 代码方式修正也行
frame = data[42]
frame.patch("contact", 0)  # cascade=True,联动7个字段

5.2 批量修正
发现某个区间全部标错了?批量修正:

data.batch_patch(100, 150, "contact", 1)  # 第100-150帧全部设为接触

5.3 Episode级语义标注
除了帧级的22维特征,我还需要给整个episode打语义标签——成功还是失败?操作类型是什么?难度多大?

from tlabel.episode import EpisodeLabel

label = EpisodeLabel(
    outcome="success",          # 操作结果:success/failure/abort/partial
    manipulation_type="grasp",  # 操作类型:grasp/push/pull/tap...
    difficulty="medium",        # 难度等级
    object_name="rubber_ball",  # 物体名称
    notes="轻微滑移后恢复"       # 备注
)
data.set_episode_label(label)

这个信息会跟着数据一起导出,后续做数据分析时非常方便——比如可以快速筛出所有"失败"的episode来分析失败模式。

💡 Tips:联动规则能省很多时间。改一个contact就能自动清理7个相关字段,不会出现"contact=0但force_magnitude=3.5"这种逻辑矛盾。


Step 6:数据不够?增强一下
30个episode不够训练?TLabel内置了5种数据增强方法,全部纯numpy实现,不需要额外依赖:

# 方式1:一行增强(默认time_warp + noise_inject)
augmented = tlabel.augment(data)

# 方式2:自由组合5种方法
augmented = tlabel.augment(data,
    methods=["time_warp", "noise_inject", "random_crop", "force_scale", "frame_dropout"],
    seed=42
)

# 方式3:通过TLabelData方法
augmented = data.augment(methods=["force_scale", "frame_dropout"], seed=42)

5种增强方法的含义:
方法 做了什么
time_warp 时间轴拉伸/压缩,模拟不同速度
noise_inject 注入高斯噪声,模拟传感器噪声
random_crop 随机裁剪时间窗口
force_scale 力值缩放,模拟不同力度
frame_dropout 随机丢帧,模拟数据缺失
我给每个episode做了2倍增强,数据集从30个变成90个,训练效果明显提升。

💡 Tipsseed 参数保证可复现。做实验时一定要记录seed,不然结果没法复现。


Step 7:批量处理——BatchProcessor
30个episode一个个处理太慢。TLabel的 BatchProcessor 可以对整个目录批量执行相同流程:

from tlabel.batch import BatchProcessor

processor = BatchProcessor(
    input_dir="raw_data/",
    output_dir="processed/",
)

# 批量执行:加载 → 预标注 → 质量评估 → 导出
processor.run(
    predict=True,           # 自动预标注
    quality_check=True,     # 质量评估
    min_quality=0.6,        # 低于0.6的episode自动跳过
    export_format="json",   # 导出格式
)

# 结果统计
print(processor.summary())
# ✅ 成功: 28/30
# ⚠️ 质量不达标: 2/30 (episode_017, episode_023)

这样我只需要review那2个质量不达标的episode就行了,其他28个全自动处理完。

💡 Tips:BatchProcessor特别适合跑完一批实验后统一处理数据,配合质量阈值过滤,省掉大量重复劳动。


Step 8:导出给训练框架用——多格式导出
最后一步,把标注好的数据导出成训练框架需要的格式。TLabel支持多种导出格式:

# 1. TLabel标准JSON(完整22维 + 元数据 + primitive标注)
data.export("annotated/episode_001.json")

# 2. CSV(pandas友好)
data.export("annotated/episode_001.csv")

# 3. HDF5(适合大规模数据集)
data.export("annotated/episode_001.hdf5")

# 4. FTP-1/MTTS Zarr(触觉基础模型微调)
data.export_ftp1("dataset/episode_001.zarr",
    sensor_name="GelSightMini",
    functional_areas=[0, 1]  # 拇指尖 + 食指尖
)

# 5. LeRobot Parquet(LeRobot框架)
data.export_lerobot("dataset/episode_001.parquet")

另外,还能把触觉图像序列导出为视频文件,方便做汇报展示:

# 导出触觉图像序列为视频
data.export_video("videos/episode_001.mp4", fps=30)

TLabel内部有一个 Exporter Plugin Registry,目前已经注册了7种导出格式(JSON、CSV、HDF5、FTP-1、MTTS Zarr、LeRobot、RLDS),而且支持注册自定义导出插件。
我这次主要用了两种格式:
JSON:给自己存档,保留完整信息
LeRobot Parquet:给模仿学习模型训练用

# 批量导出多个episode到FTP-1格式
from tlabel.converters import batch_to_ftp1

batch_to_ftp1(
    ["annotated/ep_001.json", "annotated/ep_002.json", ...],
    "dataset/full_dataset.zarr",
    sensor_name="GelSightMini",
    functional_areas=[0, 1]
)

导出的CSV里还会自动包含 primitive_labelprimitive_sourceprimitive_confidence 三列,完整保留AI预标注的元数据。

💡 Tipsexport_ftp1() 会自动把图像缩放到224×224并做归一化,直接就能喂给FTP-1基础模型。


全流程回顾
把整个流程串起来,其实就是一条清晰的管线:

原始传感器数据 (.pkl/.h5/.parquet)
    │
    ├─ Step 1: tlabel.load() ──→ 统一22维特征
    │
    ├─ Step 2: data.review() ──→ 可视化检查
    │
    ├─ Step 3: quality_score() + SyncChecker ──→ 质量筛选
    │
    ├─ Step 4: PredictEngine + predict_primitives() ──→ AI预标注
    │
    ├─ Step 5: 面板修正 + EpisodeLabel ──→ 人工精标
    │
    ├─ Step 6: tlabel.augment() ──→ 数据增强
    │
    ├─ Step 7: BatchProcessor ──→ 批量处理
    │
    └─ Step 8: data.export() ──→ 多格式导出
          │
          ├─ JSON / CSV / HDF5
          ├─ FTP-1 MTTS Zarr
          ├─ LeRobot Parquet
          └─ 视频导出

从拿到原始 .pkl 文件到最终导出LeRobot可用的Parquet数据集,我大概花了半天时间(包括review)。如果纯手动标注同样的数据量,估计至少需要3-4天。

总结
TLabel解决的核心问题:触觉数据从采集到训练,中间那个"标注"环节太碎了。不同传感器格式不统一、没有好用的可视化、手动标注效率极低、导出格式千变万化——TLabel把这些全打通了。
我的使用感受:
✅ 适配器确实好用,tlabel.load() 一行加载,格式自动识别
✅ 可视化面板是刚需,没有这个面板我根本没法高效review
✅ AI预标注大概能帮我完成70%的标注量,我只需要修正边界情况
✅ 多格式导出省了写转换器的时间,特别是FTP-1和LeRobot格式
⚠️ 目前还比较新,有些edge case可能遇到bug,但Issues响应挺快的
适合谁用:
做触觉操作研究的实验室,特别是需要大量标注数据的
需要跨传感器对比实验的(统一格式太重要了)
用LeRobot/FTP-1等框架训练触觉策略的
如果你也在做触觉数据相关的工作,推荐试试看。

📦 PyPI: https://pypi.org/project/tlabel/
💻 GitHub: https://github.com/liesliy/tlabel (欢迎 Star ⭐)
📄 中文文档: README_CN.md
📜 开源协议: MIT

如果这篇文章帮你省了时间,欢迎点个 Star,也欢迎评论区交流使用心得。

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐