MobileGaze-MobileOne-S0-MLX-fp32

MLX port of the MobileOne-S0 gaze estimator from yakhyo/gaze-estimation (MIT). Predicts gaze yaw and pitch in degrees from a 448×448 face crop. Weights are the upstream reparameterized checkpoint converted verbatim; no retraining, no quantization.

At a glance

Source yakhyo/gaze-estimation @ 27efe989fc45, release weights/mobileone_s0.pt
Source sha256 f50c99087f85f9a4fc8d75bd394262b6fcbc4ae21112928f67fabbf840664c95
Format MLX, single model.safetensors (1,238,004 params, float32) + config.json
Training data Gaze360 (upstream)
Upstream accuracy 12.58° mean angular error on Gaze360 (upstream README)
Decode 90 bins × 4° − 180° (expected bin index after softmax)

Parity gate

PASS — MLX graph vs. the fused torch oracle on 4 seeded image-like inputs on 2026-10-04 (arm64 Darwin 27.0.0, mlx 0.32.2). Worst decoded-angle difference 1.07e-04° (tolerance 0.001°); worst relative logit difference 8.88e-07 (tolerance 0.0001).

sample torch yaw mlx yaw torch pitch mlx pitch max Δ°
0 36.454 36.454 17.295 17.295 4.58e-05
1 35.854 35.854 22.446 22.446 1.07e-04
2 33.624 33.624 20.521 20.521 6.10e-05
3 38.254 38.254 20.445 20.445 6.10e-05

Evidence: .sisyphus/evidence/mobilegaze-mlx/fp32/parity.json in ajentik/majek.

Usage

import mlx.core as mx
from PIL import Image
from pipelines.mobilegaze_mlx import from_pretrained, preprocess

model = from_pretrained("majentik/MobileGaze-MobileOne-S0-MLX-fp32")
face = Image.open("face_crop.jpg").convert("RGB").resize((448, 448))
x = preprocess(mx.array(__import__("numpy").asarray(face)))
yaw_deg, pitch_deg = model.predict_degrees(x)
print(float(yaw_deg[0]), float(pitch_deg[0]))

Input: tight face crop (upstream uses the RetinaFace box without expansion), RGB, resized so the shorter side is 448, ImageNet mean/std. The model expects NHWC in MLX. config.json carries the bins, bin width, angle offset, input size and normalisation.

Compatibility notes

  • Inference-mode graph only (reparam_conv + ReLU per block); the training-time multi-branch MobileOne blocks are not represented.
  • Gaze360 angles are camera-relative; apps that need screen coordinates must add their own head-pose/viewing-distance calibration.
  • Wellness/research use. Not validated as a medical or safety device.

Reproduce

uv run python -m pipelines.mobilegaze_mlx_release --tiers fp32 --dry-run
uv run python -m pipelines.mobilegaze_mlx_release --tiers fp32

License

MIT, inherited from yakhyo/gaze-estimation. Converted weights are redistributed under the same terms with attribution to the upstream author.

Downloads last month
34
Safetensors
Model size
1.24M params
Tensor type
F32
·
MLX
Hardware compatibility
Log In to add your hardware

Quantized

Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support