bed-posture-depth-nano

A 46,899-parameter CNN that reads lying posture -- supine or one of the two lateral positions -- from a 64x64 depth frame, and is unaffected by bedding. ONNX, ~190 KB. Built for pressure-injury prevention auditing: repositioning schedules run on "which way is the patient facing, and when did that last change".

Domain measured / deployment domain tested: measured on the SLP dataset (102 adult volunteers in a laboratory bed, overhead depth camera, three bedding conditions), split by subject. Deployment domain: no hospital bed, no clinical population, no real ward camera has been tested. SLP subjects are healthy adults who assumed poses on command; patients are not.

The finding: a blanket costs depth nothing

condition n test balanced accuracy best transferred scalar lift
depth, uncover 1125 0.962 0.643 +0.319
depth, cover1 1125 0.981 0.588 +0.393
depth, cover2 1125 0.974 0.603 +0.372
pressure 1125 0.983 0.512 +0.471

Three-way task, chance 0.333, split by subject so no volunteer appears on both sides.

A thick blanket costs this model -0.012 balanced accuracy -- that is, nothing measurable. A pressure-sensing mattress beats covered depth by +0.009, also nothing. For in-bed posture, a depth camera performs like an instrumented mattress at a fraction of the installation cost.

Why, in numbers. The blanket raises the depth surface over the body by a median of 13-14 mm. The body's own height above the mattress is 123 mm uncovered and 144 mm covered. The feature that decides the label is about ten times larger than the disturbance, so the silhouette survives. The same reasoning predicts where this breaks: any bedding thick enough to approach the body's relief, or any posture distinction finer than 10 mm, is outside what this measures.

This is the counterpart to a negative result in the same family: an RGB model on room photographs could not separate a covered person from a rumpled empty bed at all. A blanket replaces appearance, which is everything RGB measures, while preserving shape, which is what depth measures.

Baseline + margin. Best single cheap statistic (frame mean, entropy or Laplacian variance), thresholds fitted on training subjects and applied unchanged to held-out subjects: 0.51-0.64. The model beats it by +0.32 to +0.47 in every condition.

Named failures.

  • The two lateral classes are lateral_A and lateral_B, not left and right. The joint annotations that would fix the sign live in SLP's password-protected archive. The three-way distinction is measured; the anatomical naming is not. Assign the sides yourself from one known frame in your own installation.
  • Trained only on an overhead view at SLP's camera height. Oblique or wall-mounted depth views are untested and the silhouette argument does not automatically survive a change of viewpoint.
  • Healthy adults holding deliberate poses. Contracture, traction, bed rails, multiple people, and a patient half out of bed are all unmodelled.

Refusal. This model always returns one of three classes. It has no "empty bed" and no "not a person" class -- SLP contains no empty-bed frames. Gate it with an occupancy check before calling it, or it will confidently report a posture for an empty mattress.

Scope. Operations, not diagnosis. It reports body orientation for repositioning audits. It is not a medical device, infers nothing about skin, tissue or ulcer risk, and must never sit where a missed detection causes harm.

Provenance. SLP (Liu, Huang, Ostadabbas et al., "Simultaneously-Collected Multimodal Lying Pose Dataset", arXiv 2008.08735), via the open Harvard Dataverse release doi:10.7910/DVN/ZS7TQS. Labels derive from SLP's capture protocol (45 poses per cover in three blocks of 15), verified against mean pressure maps before use, so they are independent of the depth frames classified. Non-commercial research licence from the source dataset. Scripts slp_depth_cover.py and slp_ship.py in the loglens repo. Trained 2026-09-04 on a Jetson AGX Orin.

Usage

import numpy as np, onnxruntime as ort, json, cv2
cfg = json.load(open("preproc.json"))
d = depth_frame.astype(np.float32)                     # millimetres, overhead view of the bed
lo, hi = np.percentile(d, 1), np.percentile(d, 99)
d = np.clip((d - lo) / (hi - lo + 1e-6), 0, 1)
x = cv2.resize(d, (64, 64), interpolation=cv2.INTER_AREA)[None, None].astype(np.float32)
logits = ort.InferenceSession("model.onnx").run(None, {"depth": x})[0][0]
print(cfg["classes"][int(logits.argmax())])            # gate on occupancy first

Part of the loglens nano family; the four-gate verdict behind this card is in resoajoe/nanolab.

Downloads last month

-

Downloads are not tracked for this model. How to track
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support

Space using resoajoe/bed-posture-depth-nano 1

Collection including resoajoe/bed-posture-depth-nano

Article mentioning resoajoe/bed-posture-depth-nano