Skip to main content

TouchLabel AI - Tactile Data Annotation Toolkit

Project description

๐Ÿฆž TouchLabel AI

The World's First Sensor-Agnostic Tactile Data Annotation Toolkit

Load any tactile sensor โ†’ Annotate visually โ†’ Export a unified schema

PyPI Python License Downloads GitHub Stars Last Commit ไธญๆ–‡ๆ–‡ๆกฃ

TLabel Panel Demo

GelSight ยท DIGIT ยท PaXini ยท Daimon โ€” one tool, one format, all sensors

๐Ÿš€ Quick Start ยท ๐Ÿค– AI Pre-Annotation ยท ๐Ÿ“Š Benchmark ยท ๐Ÿ“– Docs ยท ๐Ÿค Contributing


๐Ÿ†• What's New

v0.10.2 โ€” UniVTAC Adapter

Cross-dataset tactile interoperability โ€” UniVTAC benchmark support.

  • ๐Ÿ†• UniVTAC Adapter: Load UniVTAC HDF5 datasets with auto-detection (dual GelSight Mini, 22 dims)
  • ๐Ÿ” Smart HDF5 Detection: Auto-distinguishes PaXini vs UniVTAC by internal structure
  • ๐Ÿ“ฆ pip install tlabel[univtac]

v0.8.0 โ€” FTP-1 / MTTS Export

Export labeled data directly to FTP-1's MTTS Zarr format for foundation model fine-tuning.

  • ๐Ÿš€ FTP-1 Converter: tlabel_to_ftp1() / batch_to_ftp1() โ€” one-click export to Zarr
  • ๐Ÿ– 21 Functional Areas: MTTS morphology-aware tactile token space (15 hand zones + 6 wrist torque channels)
  • ๐Ÿ“ก 7 Sensor Registry: GelSight, GelSightMini, FreeTacMan, ViTaMIn, 3DViTac, Contactile, BinaryContact
  • ๐ŸŽจ New Export Tab in Panel: sensor selection, functional area picker with presets, export preview
  • ๐Ÿ“ฆ Zarr backend: append mode for multi-episode datasets, auto image resize to 224ร—224 + normalization
from tlabel import demo
data = demo('gelsight')
data.export_ftp1("output.zarr",
    sensor_name="GelSightMini",
    functional_areas=[0, 1])  # thumb tip + index fingertip

v0.5.0 โ€” AI-Assisted Pre-Annotation

Let the engine suggest labels, then you review and correct โ€” human-in-the-loop, not black-box.

  • ๐Ÿค– PredictEngine: predict contact, slip, and manipulation phase automatically
  • ๐Ÿ“ˆ Warm start with fit(): learn from your partially labeled data โ€” even 10% labels significantly boost accuracy
  • ๐ŸŽฏ Confidence threshold: only apply predictions above your threshold, you stay in control
  • ๐Ÿ”ฌ HMM Phase Detection: Hidden Markov Model for manipulation phase inference with Viterbi decoding
  • ๐Ÿงน Removed black-box pkl models: no opaque pretrained weights โ€” every prediction is interpretable
Previous releases
  • v0.4.2 โ€” Full i18n: bilingual Panel UI (ไธญๆ–‡/English), localized error messages, docs in both languages
  • v0.4.1 โ€” Panel UI integration: Tab navigation, batch correction tool, export buttons directly in panel
  • v0.4.0 โ€” Interactive Panel: color-coded timeline, 22-dim radar chart, frame detail editor
  • v0.2.0b1 โ€” LeRobot integration, HDF5 export, enhanced metadata, comprehensive tutorials

๐ŸŽฏ Why TLabel?

Every tactile sensor spits out a different format. There's no universal annotation tool โ€” until now.

The Problem TLabel's Answer
4 different sensors โ†’ 4 different pipelines One tlabel.load() call, auto-detected
Raw tactile data = unreadable numbers Visual Panel: timeline + radar chart + frame editor
Fixing labels frame-by-frame is soul-crushing AI pre-annotation + batch patch + cascade rules
"We use DIGIT, they use PaXini" โ€” data doesn't mix Sensor-agnostic 22-dim schema, one format for all
No standardized tactile labels exist TLabel Format v2 โ€” the first unified specification
Annotation tools assume vision, not touch Built for tactile from day one

TLabel is the only tool that:

  • โœ… Supports 4+ tactile sensor families out of the box
  • โœ… Provides a unified 22-dimension annotation schema
  • โœ… Offers AI-assisted pre-annotation with human-in-the-loop
  • โœ… Ships an interactive visual Panel for Jupyter
  • โœ… Includes a cross-sensor benchmark (TLabel-Bench)

๐Ÿš€ Quick Start

Install

pip install tlabel

That's it. Core installs in seconds with just numpy as a dependency.

Try the Demo (30 seconds)

import tlabel

data = tlabel.demo()     # Built-in GelSight demo โ€” no files needed
data.review()            # Interactive Panel pops up in Jupyter

What you'll see: a color-coded timeline (๐ŸŸข contact / ๐Ÿ”ด slip / โฌœ idle), 22-dim radar chart, frame detail editor, and batch patching โ€” all in one panel.

Other sensors:

tlabel.demo('digit').review()    # DIGIT sensor
tlabel.demo('paxini').review()   # PaXini force sensor
tlabel.demo('daimon').review()   # Daimon DM-TacClaw

๐Ÿ‘‰ Try it live in your browser โ€” no install needed.

Load Your Own Data

import tlabel

# Auto-detect sensor format โ€” no config needed
data = tlabel.load("gelsight_force.pkl")     # GelSight / DIGIT
data = tlabel.load("paxini_episode.h5")      # PaXini
data = tlabel.load("daimon_data/")           # Daimon (directory or .parquet)
data = tlabel.load("univtac_episode.hdf5")   # UniVTAC (dual GelSight Mini)

Annotate & Export

# Interactive Jupyter panel (bilingual: ไธญๆ–‡ / English)
data.review()           # Chinese UI
data.review(lang="en")  # English UI

# Export โ€” unified TLabel Format v2
data.export("output.json")   # Full schema JSON
data.export("output.csv")    # Flat CSV for pandas/Excel

Full loop: load โ†’ review โ†’ correct โ†’ export ๐Ÿ”

Export to FTP-1 (Foundation Model Ready)

pip install tlabel[ftp1]   # installs zarr
# Export labeled data โ†’ FTP-1 Zarr format
data.export_ftp1("output.zarr",
    sensor_name="GelSightMini",
    functional_areas=[0, 1])

# Batch export multiple episodes
from tlabel.converters import batch_to_ftp1
batch_to_ftp1(["ep1.json", "ep2.json"], "dataset.zarr",
    sensor_name="GelSightMini",
    functional_areas=[0, 1])

# Preset configurations
from tlabel.converters import DEFAULT_AREA_MAPPINGS
# "parallel_gripper": [0, 1]
# "three_finger": [0, 1, 2]
# "five_finger": [0, 1, 2, 3, 4]
# "dexterous_hand": list(range(15))

The exported Zarr files are directly compatible with FTP-1 for fine-tuning the world's first general-purpose tactile foundation model.


๐Ÿค– AI Pre-Annotation

New in v0.5.0 โ€” Let the engine suggest labels, then you review and correct.

from tlabel.predict import PredictEngine

engine = PredictEngine()

# Option 1: Cold start โ€” no prior labels needed
results = engine.predict(data)

# Option 2: Warm start โ€” learn from your partial annotations first
engine.fit(data)          # Extract statistics from labeled frames
results = engine.predict(data)

# Apply only high-confidence predictions (โ‰ฅ 0.7)
applied = engine.apply(data, results, min_confidence=0.7)
print(f"Auto-filled {applied} fields")

# Review in Panel โ€” correct any mistakes
data.review()

What it predicts:

Dimension Method Confidence Range
contact Rule-based (force + deformation + area) 0.4 โ€“ 0.9
slip_event Rule-based (shear + delta + entropy) 0.55 โ€“ 0.8
manipulation_phase HMM + Viterbi decoding 0.55 โ€“ 0.65
Missing dims (with fit()) Statistical (mean from labeled frames) ~0.4

๐Ÿ’ก Tip: Use fit() on partially labeled data first โ€” even 10โ€“20% labeled frames significantly improve predictions. Predictions below your confidence threshold are simply skipped.


๐Ÿ“ก Supported Sensors

Sensor Type Format Dims Optical Flow Status
GelSight Mini Vision-based .pkl 22 โœ… โœ… Stable
DIGIT Vision-based .pkl 22 โœ… โœ… Stable
Daimon DM-TacClaw Multimodal .parquet / dir 22 (video) / 20 (no video) โœ… / โ€” โœ… Stable
PaXini PXCap Force array .h5 / .hdf5 20 โ€” โœ… Stable
UniVTAC Vision-based (Dual GelSight Mini) .hdf5 / .h5 22 โœ… โœ… New

Force-type sensors (PaXini) lack optical images โ†’ 20 dims. Image-type โ†’ full 22. Daimon gracefully degrades when no video is present. No errors, no surprises.

FTP-1 Compatible Sensors

All sensors below can export directly to FTP-1 MTTS Zarr format via export_ftp1():

Sensor Type Default Shape
GelSight / GelSightMini image (224, 224, 3)
FreeTacMan image (224, 224, 3)
ViTaMIn image (224, 224, 3)
3DViTac matrix (12, 32)
Contactile matrix (12, 32)
BinaryContact binary (1,)

Per-Sensor Installation

pip install tlabel[gelsight]   # GelSight / DIGIT โ†’ opencv-python
pip install tlabel[paxini]     # PaXini โ†’ h5py
pip install tlabel[daimon]     # Daimon โ†’ pyarrow + opencv-python
pip install tlabel[univtac]    # UniVTAC โ†’ h5py
pip install tlabel[ftp1]       # FTP-1/MTTS export โ†’ zarr
pip install tlabel[all]        # Everything

Sensor Tutorials


๐ŸŽจ Panel Features

  • ๐ŸŽจ Color-coded timeline: green = contact ยท red = slip ยท gray = idle โ€” patterns jump out instantly
  • ๐Ÿ•ธ 22-dim radar chart: see the full feature vector at a glance, bilingual labels
  • โœ๏ธ Frame & batch patching: fix one frame or a range, your call
  • ๐Ÿ”— Cascade rules: set contact=0 โ†’ 7 related fields auto-zero + phase resets to idle
  • ๐Ÿค– Pre-annotation integration: apply AI predictions, then review in the same panel
  • ๐ŸŒ Bilingual toggle: ไธญๆ–‡ / English, one click top-right
  • ๐Ÿ“ค In-panel export: JSON / CSV / FTP-1 Zarr with one click

๐Ÿ“ TLabel Format v2 โ€” 22 Dimensions

The first unified tactile annotation schema. Every frame, every sensor, same 22 dimensions.

Static Features (18-dim)

# Key Description
1 contact Binary contact flag
2 deformation_magnitude Surface deformation intensity
3 force_magnitude Normal force magnitude
4 force_peak Peak force in episode window
5 force_direction Force vector angle (ยฐ)
6 slip_entropy Uncertainty of slip detection
7 slip_event Binary slip event flag
8 texture_energy Surface texture frequency energy
9 edge_density Contact edge pixel ratio
10 contact_area Contact region area ratio
11 centroid_x Contact centroid x-position
12 normal_field_magnitude Normal pressure field magnitude
13 normal_field_variance Normal field spatial variance
14 shear_field_magnitude Shear stress magnitude
15 shear_field_direction Shear direction angle (ยฐ)
16 delta_force_normal Frame-to-frame ฮ”F_normal
17 delta_force_shear Frame-to-frame ฮ”F_shear
18 friction_cone_ratio Tangential/normal force ratio

Temporal Features (4-dim)

# Key Image-type Force-type Description
19 optical_flow_magnitude โœ… โ€” Inter-frame motion magnitude (Farneback)
20 optical_flow_direction โœ… โ€” Optical flow angle (ยฐ)
21 temporal_deformation_rate โœ… โœ… Rate of deformation change
22 contact_transition โœ… โœ… Contact state transition probability

๐Ÿ“– Full specification: annotation-spec.md | tlabel-format.md


๐Ÿ“– API Quick Reference

import tlabel

# โ”€โ”€ Loading โ”€โ”€
data = tlabel.load(path)                     # Auto-detect sensor format
data = tlabel.load(path, format="gelsight")  # Force specific adapter

# โ”€โ”€ Demo โ”€โ”€
data = tlabel.demo()                         # Built-in demo data
tlabel.list_demos()                          # See available sensors

# โ”€โ”€ Properties โ”€โ”€
data.num_frames        # int โ€” total frame count
data.duration_s        # float โ€” episode duration
data.sensor_type       # str โ€” sensor identifier
data.dimension_keys    # list โ€” all dimension keys
data.modified_count    # int โ€” frames with manual patches

# โ”€โ”€ Frame Access โ”€โ”€
frame = data[0]                          # Index access
frame = data.get_frame(42)               # By frame_idx
frame.contact                            # Contact value
frame.slip_event                         # Slip event value
frame.is_modified                        # Has patches?

# โ”€โ”€ Patching โ”€โ”€
frame.patch("contact", 0)                         # Single frame (cascade=True)
frame.patch("contact", 0, cascade=False)           # No cascade
data.batch_patch(10, 50, "contact", 0)             # Range patch

# โ”€โ”€ Pre-Annotation โ”€โ”€
from tlabel.predict import PredictEngine
engine = PredictEngine()
engine.fit(data)                                   # Warm start from partial labels
results = engine.predict(data)                     # Predict contact, slip, phase
engine.apply(data, results, min_confidence=0.7)    # Apply high-confidence only

# โ”€โ”€ Review & Export โ”€โ”€
data.review()                    # Jupyter panel (Chinese)
data.review(lang="en")           # English
data.export("output.json")       # JSON (TLabel Format v2)
data.export("output.csv")        # CSV
data.export_ftp1("out.zarr")     # FTP-1 Zarr format

Cascade Rules (contact โ†’ 0)

When contact is set to 0, these fields are automatically zeroed:

Auto-zeroed Field Condition
force_magnitude always
force_peak always
slip_event always
delta_force_normal always
delta_force_shear always
contact_area always
contact_transition only if value > 0.5
manipulation_phase โ†’ "idle" (if not already)

๐Ÿ† Benchmark

TLabel-Bench โ€” The first cross-sensor unified tactile annotation benchmark.

Same objects, different sensors, one format. TLabel-Bench provides cross-sensor annotations (material labels, episode segmentation, quality scores) for objects annotated with GelSight Mini, DIGIT, DMA, and more โ€” all in the unified TLabel format.

git clone https://github.com/liesliy/tlabel-bench.git
cd tlabel-bench
bash scripts/download_data.sh
python evaluation/material_classification.py

If you're using TLabel in research, citing the benchmark helps demonstrate sensor-agnostic value ๐Ÿ‘‡


๐Ÿ—‚ Project Structure

tlabel/
โ”œโ”€โ”€ core/
โ”‚   โ”œโ”€โ”€ types.py          # TLabelFrame / TLabelData containers
โ”‚   โ”œโ”€โ”€ loader.py         # Auto-detect & dispatch loading
โ”‚   โ””โ”€โ”€ registry.py       # Adapter registry
โ”œโ”€โ”€ adapters/
โ”‚   โ”œโ”€โ”€ base.py           # BaseAdapter interface
โ”‚   โ”œโ”€โ”€ gelsight.py       # GelSight Mini / DIGIT
โ”‚   โ”œโ”€โ”€ paxini.py         # PaXini PXCap
โ”‚   โ””โ”€โ”€ daimon.py         # Daimon DM-TacClaw (+ video decoding)
โ”œโ”€โ”€ converters/
โ”‚   โ”œโ”€โ”€ lerobot.py        # LeRobot format converter
โ”‚   โ””โ”€โ”€ ftp1.py           # FTP-1/MTTS Zarr format converter
โ”œโ”€โ”€ viewer/
โ”‚   โ”œโ”€โ”€ panel.py          # Jupyter _repr_html_ renderer
โ”‚   โ””โ”€โ”€ templates.py      # HTML + JS + CSS template engine
โ”œโ”€โ”€ predict/
โ”‚   โ””โ”€โ”€ engine.py         # AI-assisted pre-annotation engine
โ”œโ”€โ”€ demo.py               # Built-in demo data loader
โ””โ”€โ”€ export/
    โ””โ”€โ”€ writer.py         # JSON / CSV export + NumpyEncoder

๐Ÿ“ Citing TLabel

If you use TLabel in your research, please cite:

@software{tlabel2026,
  title = {TLabel: A Sensor-Agnostic Tactile Data Annotation Toolkit},
  author = {NiuZhu Tech},
  year = {2026},
  url = {https://github.com/liesliy/tlabel}
}

๐Ÿค Contributing

We welcome contributions! See CONTRIBUTING.md for guidelines.

Good first issues:

  • ๐Ÿ”Œ Add a new sensor adapter (SynTouch? XELA? Your call.)
  • ๐Ÿ“Š Improve radar chart UI (dark mode, interactive hover)
  • ๐ŸŒ Add more language support (ๆ—ฅๆœฌ่ชž, ํ•œ๊ตญ์–ด)
  • ๐Ÿงช Add integration tests for edge cases
  • ๐Ÿค– Improve pre-annotation models (replace rules with lightweight ML?)

๐Ÿ’ฌ Feedback

  • ๐Ÿ› Bug report โ†’ Open an Issue
  • ๐Ÿ’ก Feature request โ†’ GitHub Discussions
  • ๐ŸŒŸ Using TLabel in your research? โ†’ We'd love to hear about it! Drop us a star โญ

๐Ÿ“„ License

MIT ยฉ NiuZhu Tech


If this saved you from manually labeling tactile data, a โญ would make our day!

โญ Star on GitHub ยท ๐Ÿ“ฆ Install from PyPI ยท ๐Ÿ† Try the Benchmark

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

tlabel-0.11.0.tar.gz (201.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

tlabel-0.11.0-py3-none-any.whl (207.1 kB view details)

Uploaded Python 3

File details

Details for the file tlabel-0.11.0.tar.gz.

File metadata

  • Download URL: tlabel-0.11.0.tar.gz
  • Upload date:
  • Size: 201.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.12

File hashes

Hashes for tlabel-0.11.0.tar.gz
Algorithm Hash digest
SHA256 a4fe045844fbbcf7079ad0298bcc129abbf15f97b176430510d76f79ffe2fc60
MD5 cd38fc81aec0370ec7c4f58bb0552dc1
BLAKE2b-256 f82f65db765da5d02684597696826e52e394a0613fbf2c0cf3e7d079671227b3

See more details on using hashes here.

File details

Details for the file tlabel-0.11.0-py3-none-any.whl.

File metadata

  • Download URL: tlabel-0.11.0-py3-none-any.whl
  • Upload date:
  • Size: 207.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.12

File hashes

Hashes for tlabel-0.11.0-py3-none-any.whl
Algorithm Hash digest
SHA256 4f954f0618ea558dd07977d3db77b70053181d5a347019a2a08f98a1bb4ed4c7
MD5 589d62e67bcecef0e3924f2431a62ace
BLAKE2b-256 2c218cdb9331bcc949adaa33bb1158faa39ac0d1ffc89c01f9ea710111978ba4

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page