BD MP Face Export
A passthrough node that quietly saves your face landmarks to JSON — the Blender handoff
- image
- image
- landmark_count
- json_path
BD MP Face Export looks like a do-nothing node, and that's the trick: it passes your image through unchanged while quietly doing important work on the side. It runs MediaPipe face landmarking on the input, writes two files to disk - the 478-point landmark JSON and a reference RGBA zone-mask PNG - and hands your image right back to the graph as if nothing happened. You insert it into the pipeline before the greyscale/albedo/channel-pack steps, it saves the data those steps would destroy, and your image never knows it was there.
Why does this matter? The output of this pack's face pipeline is a set of masks computed from the original full-color image. Once you've converted that image to greyscale or packed it into channels, MediaPipe can't detect a face on it anymore. So you export the landmark data before the destructive steps, at the moment the face is still detectable, and hand it to the next stage - the calibrate_faceplate_uv.py script in the Blender face-plate UV pipeline. The JSON becomes the source of truth for placing the face plate on a 3D model.
How it works
Only image[0] (the first frame of a batch) is processed; every frame passes through unchanged. The angle input (default front) is stored in the JSON and becomes the filename suffix - _mp_front, so front/side/three-quarter views don't clobber each other. On the saving side you have two paths:
context_id- if aBD Save Contextis registered, the output directory and filename stem resolve from its template, withangleas the suffix. This is the intended path in a real workflow.output_dir+filename_stem- the fallback when no context exists. Path is<stem>_mp_front.json.
The detection_confidence default of 0.3 is deliberately low - the tooltip notes it works for stylized renders, where faces are less photoreal and stricter detectors refuse. There's also a quiet min_face_span guard (0.35): MediaPipe occasionally returns a degenerate tiny detection on a frame-filling head, and below this span the node retries with a fresh landmarker and padded copies before accepting. Set it to 0 to disable.
Outputs
image (the untouched pass-through), landmark_count (478 if a face was found, 0 if not), and json_path (absolute path of the written JSON). The _model_path_deprecated input exists purely so old workflows don't break - it's ignored.
A note on MediaPipe itself
MediaPipe is the license-clean choice this community reaches for when face detection has to survive commercial use: Apache 2.0, no AGPL, no non-commercial model weights. It loses to InsightFace on extreme angles but wins on speed and installability, and it's only ever a detection/landmarking step - it doesn't produce identity embeddings. For this pack's purposes (zone masks and UV calibration), that's exactly what's needed. The face_landmarker.task model auto-downloads on first use, so there's no manual model fetch.
Installing
Standard BrainDead pack install - ComfyUI Manager search "BrainDead" or clone + pip install -r requirements.txt, restart. It needs the mediapipe Python package (the node lazy-imports it and tells you if it's missing) and a current ComfyUI for the V3 API.
The one thing to remember: insert it before you flatten or greyscale. Put it after and you'll get a landmark_count of 0 and wonder why your JSON is empty.
Inputs (8)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | Full-color full-resolution image. Only image[0] is processed; all batch items pass through unchanged. | |
| angle | COMBO | front | Camera angle. Stored in JSON and used as path suffix in context mode (e.g. _mp_front → <stem>_mp_front.json). |
| context_idopt | STRING | BD_SaveContext context_id. When set, output_dir and filename_stem are resolved from the context template. angle becomes the suffix. | |
| output_diropt | STRING | Fallback absolute path when no context is registered. Ignored when context_id resolves. | |
| filename_stemopt | STRING | Fallback filename stem (no extension) when no context is registered. angle is appended automatically: <stem>_mp_front.json | |
| _model_path_deprecatedopt | STRING | /tmp/ComfyUI/models/mediapipe/face_landmarker.task | Deprecated — model path is now fixed internally. This input is kept for workflow backward-compatibility only and is ignored. |
| detection_confidenceopt | FLOAT | 0.300.1–1 | Minimum face detection confidence. 0.3 works for stylized renders. |
| min_face_spanopt | FLOAT | 0.350–1 | Sanity guard: minimum plausible face span (fraction of frame, larger of x/y). MediaPipe occasionally returns a degenerate tiny detection on a frame-filling head; below this the node retries with a fresh landmarker and padded copies before accepting. Set 0 to disable the guard. |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| image | IMAGE | Passthrough — identical to input image. |
| landmark_count | INT | 478 if face detected, 0 if not. |
| json_path | STRING | Absolute path of the written JSON file. |