Downloads · 30 days
18
31% of all-time downloads
luksamuk/LFM2.5-VL-450M-Hand-Tracking
LFM2.5-VL-450M-Hand-Tracking is a image-text-to-text model from luksamuk. Use it for the image-text-to-text task on the model card, and read the license before you ship it in a product. It is set up for transformers. The card lists the license as other.
Fine-tuned LFM2.5-VL-450M-Extract for hand bounding box detection in webcam images. Produces [{"label": "hand", "bbox": [x1, y1, x2, y2]}] in 0-1 normalized coordinates.
Downloads · 30 days
18
31% of all-time downloads
All-time downloads
59
Public
Parameters
449M
898 MB on disk
Likes
0
Public
Click a slice to open those files.
.safetensors897 MB · 99%
From the Hugging Face model README
Fine-tuned LFM2.5-VL-450M-Extract for hand bounding box detection in webcam images. Produces [{"label": "hand", "bbox": [x1, y1, x2, y2]}] in 0-1 normalized coordinates.
Disclaimer: This is a personal learning project — my first VLM fine-tune. It went through ~10 iterations of trial and error, documented honestly below (including what didn't work). It is not a research paper, not a production system, and not affiliated with Liquid AI.
The evaluation data is not scientifically rigorous. Val set results (100% accuracy) reflect controlled conditions on curated images. Empirical webcam testing shows more discrepant results, documented transparently below. This model was built for a specific use case (real-time hand tracking via webcam on consumer hardware) and optimized for that scenario, not for general-purpose hand detection.
Use it as a starting point for your own experiments, not as a drop-in solution.
| Parameter | Value |
|---|---|
| LoRA rank | 16 |
| LoRA alpha | 16 |
| LoRA dropout | 0 |
| Epochs | 2 |
| Learning rate | 2e-4 |
| LR scheduler | linear |
| Warmup steps | 5 |
| Batch size (train) | 2 |
| Batch size (eval) | 1 |
| Gradient accumulation | 4 |
| Effective batch size | 8 |
| Optimizer | adamw_8bit |
| Weight decay | 0.001 |
| Precision | BF16 |
| Max sequence length | 4096 |
| Max response length | 2048 |
| Seed | 3407 |
| Metric | Value |
|---|---|
| Total steps | 3,540 |
| Training time | ~118 min |
| Final train loss | ~0.55 |
| Final eval loss | ~0.42 |
| Seed | 3407 (CDA), 42 (split) |
| Category | Count | Source |
|---|---|---|
| Positive (1 hand) | 8,578 | HaGRID (palm + fist) |
| Positive (2 hands, oversampled x2) | 2,844 | HaGRID, duplicated for balance |
| Negative (HaGRID patches) | 2,000 | Cropped regions without hands |
| Negative (COCO val2017, no person) | 2,307 | Images without any person annotation |
| Negative (COCO val2017, person no wrists) | 594 | Images with person but wrists not visible |
| Total | 16,323 | 30% negatives |
HaGRID (HAnd Gesture Recognition Image Dataset)
COCO val2017 (negative samples)
Dataset iteration The negative sampling went through four iterations, each addressing a failure mode observed in testing:
Content order augmentation (positional bias)
During testing, I discovered that the Q8_0 quantization was sensitive to
the order of items in the user content. With image before text, the
model correctly returned [] when no hands were visible. With text
before image, the same model produced false positive hand detections.
This is a form of positional bias. To mitigate this, I applied Counterfactual Data Augmentation (CDA): each training example has a 50% chance of having the image/text order swapped. This teaches the model that content order should not affect the response.
References:
Seed: 3407 (reproducible augmentation)
HaGRID patches (negative samples)
{
"conversations": [
{
"role": "user",
"content": [
{"type": "image", "image": "path/to/image.jpg"},
{"type": "text", "text": "Detect all hands in the image."}
]
},
{
"role": "assistant",
"content": [
{"type": "text", "text": "[{\"label\":\"hand\",\"bbox\":[0.23,0.45,0.67,0.89]}]"}
]
}
]
}
Negative examples use "[]" as the assistant response.
luksamuk/LFM2.5-VL-450M-Hand-Tracking| File | Description |
|---|---|
adapter_config.json | LoRA adapter config |
adapter_model.safetensors | LoRA weights (5M params, 24MB) |
tokenizer.json + config | Tokenizer files |
README.md | This model card |
luksamuk/LFM2.5-VL-450M-Hand-Tracking-GGUF| File | Size | Description |
|---|---|---|
LFM2.5-VL-450M-Hand-Tracking-BF16.gguf | ~900MB | Full precision (for re-quantization) |
LFM2.5-VL-450M-Hand-Tracking-Q8_0.gguf | 379MB | Recommended (best quality) |
LFM2.5-VL-450M-Hand-Tracking-Q4_K_M.gguf | 229MB | Edge / lightweight |
mmproj-LFM2.5-VL-450M-Hand-Tracking-F16.gguf | 190MB | Vision encoder (required) |
The BF16 file is the merged model (LoRA + base) in full precision. It allows others to create custom quantizations or use the model without quantization. Q8_0 is recommended for PC/laptop. Q4_K_M is recommended for edge devices (Raspberry Pi).
llama-server \
--model LFM2.5-VL-450M-Hand-Tracking-Q8_0.gguf \
--mmproj mmproj-LFM2.5-VL-450M-Hand-Tracking-F16.gguf \
--port 8001 \
--temp 0.1 \
--jinja
from unsloth import FastVisionModel
import torch
model, tokenizer = FastVisionModel.from_pretrained(
model_name="luksamuk/LFM2.5-VL-450M-Hand-Tracking",
max_seq_length=4096,
load_in_4bit=False,
)
A demo harness (VLM Webcam Vision) is available at github.com/luksamuk/vlm-webcam-vision. It provides real-time webcam hand tracking with LERP smoothing, label sanitization, and camera controls. Supports any OpenAI-compatible endpoint (llama-swap, Ollama, llama-server) via environment variables.
The llama.cpp server also supports multi-model orchestration natively via model and mmproj flags, enabling hand tracking alongside other models without a proxy.
[{"label": "hand", "bbox": [0.23, 0.45, 0.67, 0.89]}]
Coordinates are normalized 0-1. Empty array [] when no hands are visible.
![]()
![]()
| Category | Q8_0 | Q4_K_M |
|---|---|---|
| 1 hand (recall) | 100% | 100% |
| 2 hands (recall) | 100% | 100% |
| Negative HaGRID (specificity) | 100% | 100% |
| Negative COCO no-person | 100% | 100% |
| Negative COCO person-no-wrists | 100% | 100% |
| Overall accuracy | 100% | 100% |
250 samples (50 per category). Zero false positives, zero false negatives.
Important: Val set accuracy reflects controlled conditions (curated dataset, ideal images). Empirical webcam testing shows more discrepant results — see below.
Structured protocol: ~10s setup + 5s phases (no hands / 1 hand / 2 hands / alternating) + 3s final.
| Model | Frames | [] (empty) | 1 hand | 2 hands | Latency | Flicker |
|---|---|---|---|---|---|---|
| 450M Q8_0 | 356 | 244 (69%) | 100 (28%) | 12 (3%) | 130ms | 20 |
| 450M Q4_K_M | 305 | 126 (41%) | 123 (40%) | 56 (18%) | 154ms | 29 |
| 1.6B Q8_0 | 90 | 42 (47%) | 48 (53%) | 0 (0%) | 462ms | 2 |
| 1.6B Q4_K_M | 113 | 53 (47%) | 60 (53%) | 0 (0%) | 405ms | 4 |
Key findings:
A 1.6B Extract variant was trained with the same dataset using QLoRA (4-bit base, r=16). Val set showed 100% accuracy, identical to 450M. However, empirical webcam testing revealed zero 2-hand detection and 3x higher latency (400-460ms vs 130-154ms).
The 1.6B is excluded from publication because:
The domain gap (HaGRID studio images vs webcam real-world) appears to be the primary bottleneck for 2-hand detection, not model size. This affects both 450M and 1.6B equally.