Instructions to use a-ml/FaceDepth with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- DepthAnythingV2
How to use a-ml/FaceDepth with DepthAnythingV2:
# Install from https://github.com/DepthAnything/Depth-Anything-V2 # Load the model and infer depth from an image import cv2 import torch from depth_anything_v2.dpt import DepthAnythingV2 # instantiate the model model = DepthAnythingV2(encoder="<ENCODER>", features=<NUMBER_OF_FEATURES>, out_channels=<OUT_CHANNELS>) # load the weights filepath = hf_hub_download(repo_id="a-ml/FaceDepth", filename="depth_anything_v2_<ENCODER>.pth", repo_type="model") state_dict = torch.load(filepath, map_location="cpu") model.load_state_dict(state_dict).eval() raw_img = cv2.imread("your/image/path") depth = model.infer_image(raw_img) # HxW raw depth map in numpy - Notebooks
- Google Colab
- Kaggle
Update card: demo video, second comparison, video script, Instagram
Browse files
README.md
CHANGED
|
@@ -8,11 +8,8 @@ tags:
|
|
| 8 |
- face
|
| 9 |
- coreml
|
| 10 |
- apple-silicon
|
| 11 |
-
- knowledge-distillation
|
| 12 |
- depth-anything-v2
|
| 13 |
base_model: depth-anything/Depth-Anything-V2-Large
|
| 14 |
-
datasets:
|
| 15 |
-
- CelebAMask-HQ
|
| 16 |
language:
|
| 17 |
- en
|
| 18 |
---
|
|
@@ -21,39 +18,54 @@ language:
|
|
| 21 |
|
| 22 |
Face-specialized monocular depth estimation. One photo in, sharp facial relief out, with no depth sensor.
|
| 23 |
|
| 24 |
-
General depth models train on
|
| 25 |
|
| 26 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 27 |
|
| 28 |
## Results
|
| 29 |
|
| 30 |
-
Measured on 500 held-out
|
| 31 |
|
| 32 |
-
| metric |
|
| 33 |
|---|---|---|---|
|
| 34 |
| face-region SSI-MAE | 0.02764 | **0.00906** | **-67%** |
|
| 35 |
-
| depth-edge F1 vs
|
| 36 |
-
| edge recall vs
|
| 37 |
-
| edge precision vs
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 38 |
|
| 39 |
-
|
|
|
|
|
|
|
| 40 |
|
| 41 |
## Files
|
| 42 |
|
| 43 |
| file | format | size | notes |
|
| 44 |
|---|---|---|---|
|
| 45 |
-
| `FaceDepth_step15792.pt` | PyTorch | 2.5 GB |
|
| 46 |
| `coreml/FaceDepth_fp32.mlpackage` | Core ML | 1.2 GB | unquantized reference, 5.4 fps |
|
| 47 |
-
| `coreml/FaceDepth_fp16.mlpackage` | Core ML | 668 MB | **realtime, 40.5 fps,
|
| 48 |
-
| `coreml/FaceDepth_int8.mlpackage` | Core ML | 335 MB | 39.4 fps, smallest,
|
|
|
|
| 49 |
|
| 50 |
-
|
| 51 |
|
| 52 |
-
On this hardware int8 buys a 2x size reduction rather than speed
|
| 53 |
|
| 54 |
-
##
|
| 55 |
|
| 56 |
-
### Core ML
|
| 57 |
|
| 58 |
```python
|
| 59 |
import numpy as np, coremltools as ct
|
|
@@ -63,10 +75,10 @@ model = ct.models.MLModel("coreml/FaceDepth_fp16.mlpackage",
|
|
| 63 |
compute_units=ct.ComputeUnit.ALL)
|
| 64 |
img = Image.open("face.jpg").convert("RGB").resize((392, 518))
|
| 65 |
disp = np.asarray(model.predict({"image": img})["depth"]).reshape(518, 392)
|
| 66 |
-
#
|
| 67 |
```
|
| 68 |
|
| 69 |
-
Input is a 392x518 portrait RGB image. ImageNet normalization is folded into the graph, so pass raw pixels.
|
| 70 |
|
| 71 |
### PyTorch
|
| 72 |
|
|
@@ -82,58 +94,52 @@ m.load_state_dict(ck["ema_model"])
|
|
| 82 |
m = m.to("mps").eval()
|
| 83 |
```
|
| 84 |
|
| 85 |
-
The checkpoint also
|
| 86 |
|
| 87 |
### Normalizing the output for display
|
| 88 |
|
| 89 |
-
The model returns relative inverse depth with an arbitrary scale. Normalize
|
| 90 |
|
| 91 |
```python
|
| 92 |
lo, hi = np.percentile(disp, 2), np.percentile(disp, 98)
|
| 93 |
norm = np.clip((disp - lo) / (hi - lo), 0, 1) # 1 = nearest
|
| 94 |
```
|
| 95 |
|
| 96 |
-
##
|
| 97 |
-
|
| 98 |
-
**Teacher.** Depth Pro at native 1024 px labels 30,000 CelebA-HQ faces, stored as inverse depth. The teacher sets the ceiling on the student's sharpness, and this choice is the dominant lever in the whole recipe.
|
| 99 |
-
|
| 100 |
-
**Masks.** The 19 CelebAMask-HQ classes collapse into a head foreground mask, a per-pixel feature weight (eyes and brows highest, nose and lips medium, skin and hair base), and a boundary map of feature edges.
|
| 101 |
|
| 102 |
-
|
| 103 |
|
| 104 |
-
|
| 105 |
-
|
| 106 |
-
|
| 107 |
-
|
|
|
|
| 108 |
|
| 109 |
-
|
| 110 |
|
| 111 |
## Limitations
|
| 112 |
|
| 113 |
-
This model optimizes single-image sharpness
|
| 114 |
-
|
| 115 |
-
Distillation caps detail at the teacher. The claim here is sharp feature relief and boundaries, not sub-millimeter texture, and per-eyelash depth is beyond what any current monocular teacher resolves.
|
| 116 |
|
| 117 |
-
|
| 118 |
|
| 119 |
-
|
| 120 |
|
| 121 |
## License and provenance
|
| 122 |
|
| 123 |
Released under **CC-BY-NC-4.0**, non-commercial research use.
|
| 124 |
|
| 125 |
-
|
| 126 |
|
| 127 |
## Citation
|
| 128 |
|
| 129 |
```bibtex
|
| 130 |
@software{facedepth2026,
|
| 131 |
-
title = {FaceDepth: Face-Specialized Monocular Depth
|
| 132 |
-
Boundary-Accurate Teacher under Segmentation-Guided Losses},
|
| 133 |
author = {Lintzeris, Aristides},
|
| 134 |
year = {2026},
|
| 135 |
url = {https://huggingface.co/a-ml/FaceDepth}
|
| 136 |
}
|
| 137 |
```
|
| 138 |
|
| 139 |
-
Please also cite the
|
|
|
|
| 8 |
- face
|
| 9 |
- coreml
|
| 10 |
- apple-silicon
|
|
|
|
| 11 |
- depth-anything-v2
|
| 12 |
base_model: depth-anything/Depth-Anything-V2-Large
|
|
|
|
|
|
|
| 13 |
language:
|
| 14 |
- en
|
| 15 |
---
|
|
|
|
| 18 |
|
| 19 |
Face-specialized monocular depth estimation. One photo in, sharp facial relief out, with no depth sensor.
|
| 20 |
|
| 21 |
+
General depth models train on streets, rooms, and furniture, so they flatten a face into a smooth blob. A face holds its information in millimeters of relief, the bridge of the nose against the cheek, the small step from lid to eyeball, and that signal sits far below what a scene-trained model represents. Face relighting, avatar capture, and AR effects need the part those models throw away.
|
| 22 |
|
| 23 |
+
FaceDepth is a Depth Anything V2-Large variant tuned to keep that detail. It resolves the eyelid crease, the nostril rim, the lip contour, and the hairline.
|
| 24 |
+
|
| 25 |
+
Code and paper: [github.com/AristidesAI/FaceDepth](https://github.com/AristidesAI/FaceDepth) · Instagram: [@aristides.lab](https://instagram.com/aristides.lab)
|
| 26 |
+
|
| 27 |
+
<video controls autoplay loop muted playsinline src="https://huggingface.co/a-ml/FaceDepth/resolve/main/figures/facedepth_video_demo.mp4"></video>
|
| 28 |
+
|
| 29 |
+
*Source on the left, FaceDepth on the right.*
|
| 30 |
|
| 31 |
## Results
|
| 32 |
|
| 33 |
+
Measured on 500 held-out faces.
|
| 34 |
|
| 35 |
+
| metric | baseline DA2-Large | FaceDepth | change |
|
| 36 |
|---|---|---|---|
|
| 37 |
| face-region SSI-MAE | 0.02764 | **0.00906** | **-67%** |
|
| 38 |
+
| depth-edge F1 vs reference | 0.717 | **0.882** | **+23%** |
|
| 39 |
+
| edge recall vs reference | 0.745 | **0.873** | +17% |
|
| 40 |
+
| edge precision vs reference | 0.694 | **0.893** | +29% |
|
| 41 |
+
|
| 42 |
+
Edge metrics are density-matched at 5% of in-face gradient pixels with a 2-pixel tolerance, so a blurry model cannot win by spreading weak gradients across the whole face. Recall and precision both rise, so the model finds real depth edges and stops inventing ones that are not there.
|
| 43 |
+
|
| 44 |
+

|
| 45 |
+
|
| 46 |
+
*Left to right: input, reference depth, baseline DA2-Large, FaceDepth, and the difference between the last two. Depth is normalized inside the face mask so relief stays visible. Compare columns three and four against column two.*
|
| 47 |
|
| 48 |
+

|
| 49 |
+
|
| 50 |
+
*Six more held-out faces, same layout. The difference column concentrates on the face interior and hairline.*
|
| 51 |
|
| 52 |
## Files
|
| 53 |
|
| 54 |
| file | format | size | notes |
|
| 55 |
|---|---|---|---|
|
| 56 |
+
| `FaceDepth_step15792.pt` | PyTorch | 2.5 GB | full checkpoint. Use the `ema_model` key. |
|
| 57 |
| `coreml/FaceDepth_fp32.mlpackage` | Core ML | 1.2 GB | unquantized reference, 5.4 fps |
|
| 58 |
+
| `coreml/FaceDepth_fp16.mlpackage` | Core ML | 668 MB | **realtime, 40.5 fps, Neural Engine** |
|
| 59 |
+
| `coreml/FaceDepth_int8.mlpackage` | Core ML | 335 MB | 39.4 fps, smallest, GPU |
|
| 60 |
+
| `video_depth.py` | script | | convert any video into a depth-map video |
|
| 61 |
|
| 62 |
+
Every Core ML export correlates at 1.00000 against the PyTorch reference. Benchmarks use 392x518 input on an Apple-silicon laptop with `ComputeUnit.ALL`, averaged over 20 runs after warmup.
|
| 63 |
|
| 64 |
+
On this hardware int8 buys a 2x size reduction rather than speed, so its advantage is the app bundle. The ranking may differ on iPhone, where the Neural Engine is relatively stronger, and that has not been measured.
|
| 65 |
|
| 66 |
+
## Quick start
|
| 67 |
|
| 68 |
+
### Core ML, realtime
|
| 69 |
|
| 70 |
```python
|
| 71 |
import numpy as np, coremltools as ct
|
|
|
|
| 75 |
compute_units=ct.ComputeUnit.ALL)
|
| 76 |
img = Image.open("face.jpg").convert("RGB").resize((392, 518))
|
| 77 |
disp = np.asarray(model.predict({"image": img})["depth"]).reshape(518, 392)
|
| 78 |
+
# inverse depth: larger = nearer
|
| 79 |
```
|
| 80 |
|
| 81 |
+
Input is a 392x518 portrait RGB image. ImageNet normalization is folded into the graph, so pass raw pixels.
|
| 82 |
|
| 83 |
### PyTorch
|
| 84 |
|
|
|
|
| 94 |
m = m.to("mps").eval()
|
| 95 |
```
|
| 96 |
|
| 97 |
+
The checkpoint also carries a `conf_head`. Inference does not need it and the Core ML exports drop it.
|
| 98 |
|
| 99 |
### Normalizing the output for display
|
| 100 |
|
| 101 |
+
The model returns relative inverse depth with an arbitrary scale. **Normalize inside the face, not across the frame.** A whole-frame min-max collapses the face's range the moment a distant background enters the shot, which reads as a black or washed-out face. This one detail causes most of the "the model looks broken" reports.
|
| 102 |
|
| 103 |
```python
|
| 104 |
lo, hi = np.percentile(disp, 2), np.percentile(disp, 98)
|
| 105 |
norm = np.clip((disp - lo) / (hi - lo), 0, 1) # 1 = nearest
|
| 106 |
```
|
| 107 |
|
| 108 |
+
## Video
|
|
|
|
|
|
|
|
|
|
|
|
|
| 109 |
|
| 110 |
+
`video_depth.py` converts any video ffmpeg can read, up to 4K, into a depth-map video. Frames stream through an ffmpeg pipe, so a long clip never lands on disk as a frame dump and memory stays flat.
|
| 111 |
|
| 112 |
+
```bash
|
| 113 |
+
python video_depth.py --input clip.mov --output depth.mp4 --ckpt FaceDepth_step15792.pt
|
| 114 |
+
python video_depth.py --input clip.mov --output sbs.mp4 --side-by-side --colormap magma
|
| 115 |
+
python video_depth.py --input clip.mp4 --output out.mp4 --smooth-depth 0.3 --bf16
|
| 116 |
+
```
|
| 117 |
|
| 118 |
+
Colormaps: inferno, magma, turbo, viridis, plasma, bone, gray. `--range-ema` smooths the near/far range across frames and is on by default with no ghosting. `--smooth-depth` smooths depth itself, which cuts residual jitter but ghosts behind fast motion. Needs ffmpeg on PATH and [Depth-Anything-V2](https://github.com/DepthAnything/Depth-Anything-V2) cloned into `third_party/DepthAnythingV2`.
|
| 119 |
|
| 120 |
## Limitations
|
| 121 |
|
| 122 |
+
This model optimizes single-image sharpness, so live video flickers more than a temporally stabilized model would. For offline video, `video_depth.py` damps that with `--range-ema` and `--smooth-depth`.
|
|
|
|
|
|
|
| 123 |
|
| 124 |
+
Detail is capped by the reference the model learned from. The claim is sharp feature relief and boundaries, not sub-millimeter texture. Per-eyelash depth is beyond what any current monocular model resolves.
|
| 125 |
|
| 126 |
+
Training data is centered, well-lit, and limited in pose, occlusion, and demographic diversity relative to in-the-wild use. Performance by demographic group has not been measured. Evaluate before deploying on populations or capture conditions that differ from the training distribution.
|
| 127 |
|
| 128 |
## License and provenance
|
| 129 |
|
| 130 |
Released under **CC-BY-NC-4.0**, non-commercial research use.
|
| 131 |
|
| 132 |
+
FaceDepth derives from [Depth Anything V2-Large](https://huggingface.co/depth-anything/Depth-Anything-V2-Large), which is CC-BY-NC-4.0. It builds on [Apple Depth Pro](https://github.com/apple/ml-depth-pro) and [CelebAMask-HQ](https://github.com/switchablenorms/CelebAMask-HQ), whose terms restrict use to non-commercial research and education. Honor the upstream terms of all three.
|
| 133 |
|
| 134 |
## Citation
|
| 135 |
|
| 136 |
```bibtex
|
| 137 |
@software{facedepth2026,
|
| 138 |
+
title = {FaceDepth: Face-Specialized Monocular Depth Estimation},
|
|
|
|
| 139 |
author = {Lintzeris, Aristides},
|
| 140 |
year = {2026},
|
| 141 |
url = {https://huggingface.co/a-ml/FaceDepth}
|
| 142 |
}
|
| 143 |
```
|
| 144 |
|
| 145 |
+
Please also cite the work this builds on: Depth Anything V2 (arXiv:2406.09414), Depth Pro (arXiv:2410.02073), MiDaS (arXiv:1907.01341), DPT (arXiv:2103.13413), DINOv2 (arXiv:2304.07193), and CelebAMask-HQ (arXiv:1907.11922).
|