JHPixelProFaceDetect
Five landmarks, zero hand-pasting — feed your aligner automatically
- image
- landmarks_json
- bbox_json
- face_count
Every face pipeline needs landmarks, and hand-pasting JSON coordinates into a node is the kind of thing you do exactly once before you start looking for a detector. JHPixelProFaceDetect is the pack's MediaPipe-based detector: it finds faces on an image and returns the five landmarks - left eye, right eye, nose tip, left mouth, right mouth - as JSON that's built to plug straight into the pack's JHPixelProFacialAligner.
Under the hood it wraps MediaPipe's FaceLandmarker (tasks API) and uses the canonical indices (33, 263, 1, 61, 291) for those five points. That's the same point ordering the aligner expects, so in a single-face chain you take landmarks_json[0] and wire it directly into the aligner's landmarks input. No copy-paste, no coordinate surgery.
The controls
mode:single_largest(default) returns one face with the largest bbox area - that's ~90% of portrait use.multi_top_kreturns up tomax_faces, ranked by bbox area.max_faces(1–10): the cap inmulti_top_k. Bump to 5–10 for crowd scenes. Ignored insingle_largest.confidence_threshold(default 0.5): the MediaPipe detection gate. Here's the gotcha in the tooltip: values above ~0.85 start missing faces on typical portraits. Default 0.5 is balanced; only raise it for strict crowd-filtering scenarios.
Three outputs: landmarks_json (list of 5×2 pixel-absolute points per face), bbox_json (per-face {x, y, w, h, conf, batch_index}), and face_count. One honest warning about bbox_json: the conf field is not MediaPipe's per-face probability - the FaceLandmarker tasks API doesn't expose one, so conf just repeats the threshold you set. If you want to rank faces, use multi_top_k + bbox area, not conf.
The one thing to know up front
First call downloads the ~5 MB face_landmarker.task model into ComfyUI/models/mediapipe/. Subsequent runs reuse the cache, so it's a one-time cost - but if you're on an offline or restricted network, pre-place the file or the node will fail. It needs mediapipe installed; if pip can't install it (Python version mismatches are the usual culprit), the node raises a clear error with install instructions and points you at the fallback: paste 5-point JSON manually into the aligner.
Install
ComfyUI Manager → search ComfyUI-JH-PixelPro, or:
cd ComfyUI/custom_nodes
git clone https://github.com/jetthuangai/ComfyUI-JH-PixelPro.git
cd ComfyUI-JH-PixelPro
pip install -r requirements.txt
Restart ComfyUI; it's under ComfyUI-JH-PixelPro/face. The pack needs ComfyUI ≥ 0.43.x, Python ≥ 3.10, and installs kornia, mediapipe, opencv-python-headless, scipy - mediapipe ≥ 0.10.33 is the one this node actually leans on.
This node is the unglamorous plumbing that makes the pack's face pipeline run unattended. By itself it produces JSON strings you can't even preview, which makes it look useless until you wire it into the aligner and suddenly your batch of 200 portraits all get aligned to the same canonical frame without you touching anything. If you're building batch face work, that's the whole ballgame.
Inputs (4)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | — | |
| mode | COMBO | single_largest | single_largest (default, ~90% portrait use case) returns 1 face with the largest bbox area. multi_top_k returns up to max_faces ranked by bbox area. |
| max_faces | INT | 11–10 | Cap on detected faces. Ignored when mode = single_largest. Crowd scenes: bump to 5–10. |
| confidence_threshold | FLOAT | 0.500.1–0.95 | MediaPipe min_face_detection_confidence gate. Default 0.5 is balanced. WARNING: values > 0.85 may miss faces on typical portraits (sample_portrait ceiling tested ~0.85). Raise only for strict crowd-filtering scenarios. |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| landmarks_json | STRING | — |
| bbox_json | STRING | — |
| face_count | INT | — |