Skip to content

feat: MediaPipe face detection (CORE-235)#14009

Merged
comfyanonymous merged 6 commits into
Comfy-Org:masterfrom
kijai:mediapipe
May 20, 2026
Merged

feat: MediaPipe face detection (CORE-235)#14009
comfyanonymous merged 6 commits into
Comfy-Org:masterfrom
kijai:mediapipe

Conversation

@kijai

@kijai kijai commented May 20, 2026

Copy link
Copy Markdown
Collaborator

This PR adds dependency free re-write of Google's MediaPipe's Face detection and land marker.

image

mediapipe_example.json

Model has been extracted as a .safetensors:

https://huggingface.co/Comfy-Org/mediapipe/blob/main/mediapipe/mediapipe_face_fp32.safetensors

@kijai kijai changed the title feat: MediaPipe face detection May 20, 2026
@coderabbitai

coderabbitai Bot commented May 20, 2026

Copy link
Copy Markdown

Review Change Stack

Important

Review skipped

Review was skipped as selected files did not have any reviewable changes.

💤 Files selected but had no reviewable changes (1)
  • models/mediapipe/put_mediapipe_models_here
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 4a82254d-bb54-4bfa-bfb9-c93b23ff7973

📥 Commits

Reviewing files that changed from the base of the PR and between c0304a1 and 16db0dc.

📒 Files selected for processing (1)
  • models/mediapipe/put_mediapipe_models_here

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This PR adds a MediaPipe face-landmarker pipeline: a NumPy Procrustes-based 4×4 face transform solver; short- and full-range BlazeFace detectors with anchor decoding and weighted NMS; a FaceMesh model producing 478 canonical 3D landmarks; an MLP‑Mixer FaceBlendshapes regressor producing 52 coefficients; a FaceLandmarker orchestrator for batched detection, ROI warping, and inference; and ComfyUI nodes for model loading, detection with missing-frame fallbacks, mesh visualization, and mask generation.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 40.68% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat: MediaPipe face detection (CORE-235)' clearly and concisely summarizes the main change: adding MediaPipe face detection functionality to the codebase.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description check ✅ Passed The PR description clearly describes the addition of a dependency-free re-write of MediaPipe's face detection and landmarker, with supporting images showing the node pipeline and functionality.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
comfy_extras/mediapipe/face_landmarker.py (1)

566-571: ⚡ Quick win

Validate detector_variant with a clear error message.

If an invalid detector_variant is passed, det_cls will be None and line 571 will raise an unhelpful TypeError: 'NoneType' object is not callable. A validation check provides clearer feedback.

💡 Proposed improvement
     def __init__(self, device=None, dtype=None, operations=None, detector_variant: str = "short"):
         super().__init__()
-        det_cls = {"short": BlazeFace, "full": BlazeFaceFullRange}.get(detector_variant)
+        det_cls_map = {"short": BlazeFace, "full": BlazeFaceFullRange}
+        if detector_variant not in det_cls_map:
+            raise ValueError(f"detector_variant must be 'short' or 'full', got {detector_variant!r}")
+        det_cls = det_cls_map[detector_variant]

         self.detector_variant = detector_variant
         self.detector = det_cls(device=device, dtype=dtype, operations=operations)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@comfy_extras/mediapipe/face_landmarker.py` around lines 566 - 571, The
__init__ currently maps detector_variant to det_cls and directly instantiates
it, which yields a confusing TypeError if detector_variant is invalid; add an
explicit validation after det_cls assignment in face_landmarker.__init__ that
checks if det_cls is None and raises a ValueError with a clear message like
"Invalid detector_variant: {detector_variant}; expected 'short' or 'full'".
Reference the existing symbols det_cls, detector_variant, BlazeFace,
BlazeFaceFullRange and perform the check before calling det_cls(...) so
self.detector is only created when a valid class is selected.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@comfy_extras/nodes_mediapipe.py`:
- Around line 377-386: The code sets B from img_np.shape[0] when image is
provided but then indexes frames[bi], causing IndexError if the two batch sizes
differ; update the logic in the mesh-drawing block (the variables image,
face_landmarks, frames, B, img_np, _image_to_uint8, and _draw_mesh) to ensure
both arrays are the same length before looping: either validate and raise a
clear error when img_np.shape[0] != len(frames), or compute B =
min(img_np.shape[0], len(frames)) and iterate only up to B (ensuring out is
sized accordingly) so you never index past frames. Ensure the chosen fix adjusts
out shape and progress bar (comfy.utils.ProgressBar) consistently.

---

Nitpick comments:
In `@comfy_extras/mediapipe/face_landmarker.py`:
- Around line 566-571: The __init__ currently maps detector_variant to det_cls
and directly instantiates it, which yields a confusing TypeError if
detector_variant is invalid; add an explicit validation after det_cls assignment
in face_landmarker.__init__ that checks if det_cls is None and raises a
ValueError with a clear message like "Invalid detector_variant:
{detector_variant}; expected 'short' or 'full'". Reference the existing symbols
det_cls, detector_variant, BlazeFace, BlazeFaceFullRange and perform the check
before calling det_cls(...) so self.detector is only created when a valid class
is selected.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 968cf85a-d162-4cca-9715-248398a7b40a

📥 Commits

Reviewing files that changed from the base of the PR and between 78b5dec and 1c0334b.

📒 Files selected for processing (5)
  • comfy_extras/mediapipe/face_geometry.py
  • comfy_extras/mediapipe/face_landmarker.py
  • comfy_extras/nodes_mediapipe.py
  • folder_paths.py
  • nodes.py
Comment thread comfy_extras/nodes_mediapipe.py Outdated
@comfyanonymous comfyanonymous merged commit 4d6a058 into Comfy-Org:master May 20, 2026
14 checks passed
@shivdbz2010

Copy link
Copy Markdown

can MediaPipe face detection detect gender? or any other nodes that can do
its would be nice to have face filtering method, left to right,top to bottom, face size, index id, gender, age

@alexisrolland

alexisrolland commented May 22, 2026

Copy link
Copy Markdown
Member

can MediaPipe face detection detect gender? or any other nodes that can do its would be nice to have face filtering method, left to right,top to bottom, face size, index id, gender, age

You can probably use Gemma 4 to detect gender in an image. It is natively supported in ComfyUI. You could also combine it with SAM3 for segmenting / tracking / extracting faces.

simonri pushed a commit to simonri/ComfyUI-flash-attention-3 that referenced this pull request May 26, 2026
* Initial mediapipe face detection support

* Update face_geometry.py

* Account for diff sized batch input

* Model folder placeholder
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

4 participants