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
GelSight ยท DIGIT ยท PaXini ยท Daimon โ one tool, one format, all sensors
๐ Quick Start ยท ๐ค AI Pre-Annotation ยท ๐ Benchmark ยท ๐ Docs ยท ๐ค Contributing
๐ What's New
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)
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 |
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[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 toidle - ๐ค 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
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file tlabel-0.8.0.tar.gz.
File metadata
- Download URL: tlabel-0.8.0.tar.gz
- Upload date:
- Size: 205.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ed8f57149a342fc674f220000711e850e00ce09fabb8fb09e2bdfa0c925dba81
|
|
| MD5 |
44b833914b275eab197854a6c0473d08
|
|
| BLAKE2b-256 |
478a5bd52c3737771023899331181c9aaf62a7c8d808a6e0200afc253ff5dc54
|
File details
Details for the file tlabel-0.8.0-py3-none-any.whl.
File metadata
- Download URL: tlabel-0.8.0-py3-none-any.whl
- Upload date:
- Size: 213.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
04f212d4a35fb92eb87ecbe9de0f2e8d927433fd2aa40746f3bc0c9d27b53668
|
|
| MD5 |
bf89f4127959c42e50a8db3670efb666
|
|
| BLAKE2b-256 |
9174369371aca3261f0e61a1ebe8018515a8012a391fc857443a59b767f27521
|