Nodes/lip_mask_from_pose/Lip Mask from Sapiens2 Pose
ComfyUI Node

Lip Mask from Sapiens2 Pose

Sapiens2's 32 lip keypoints turned into a mask — only worth it if you already run Sapiens2

By Jalen-Brunson·Created 5 months ago·Updated 21 days ago· 2
Lip Mask from Sapiens2 Pose
  • pose_keypoint
  • mask
  • centroid_x_list
  • centroid_y_list
  • fallback_active_list
region_1full_inner_lip
region_2none
region_3none
region_4none
blur_radius5
grow_pixels0
point_radius6
person_index0
confidence_threshold0.30
auto_fallbacktrue
fallback_area_threshold0.15
fallback_pad_h1.20
fallback_pad_v1.30

Sapiens2 is Meta's April 2026 family of high-resolution transformers pretrained on a billion human images - pose, body-part segmentation, surface normals, pointmaps. The pose head outputs a monster 308-keypoint set (the "Goliath-308" layout), and the mouth gets special treatment: a 16-point outer lip ring plus a 16-point inner ring, 32 lip keypoints where DWPose only has 20. More points, more faithful contours. That's the entire pitch of LipMaskFromSapiens2: it reads that richer lip ring and turns it into a mask.

Straight up, though: this is a niche-of-a-niche node. You only want it if you're already running a Sapiens2 pose preprocessor - this pack is a consumer of that POSE_KEYPOINT payload, not a producer. If your pipeline is DWPose, the sibling LipMaskFromPose node gives you the same idea with less setup. If you're doing the Sapiens2 thing for the segmentation head anyway, the finer lip contours are a real upgrade for lip-focused inpainting.

How it works

The 308-keypoint layout puts the outer lip ring at indices 188–203 (vermilion border) and the inner ring at 204–219 (the wet line / mouth opening). The node reads each person's keypoints_2d array from the POSE_KEYPOINT payload, needs at least ~220 points to trust the mouth ring, and refuses otherwise.

Where DWPose's node gives you one mask_mode, this gives you four region dropdowns (region_1 through region_4), each selectable from 14 named regions - full_outer_lip, full_inner_lip, full_mouth, lips_only, outer_top_lip, outer_bottom_lip, inner_top_lip, inner_bottom_lip, top_lip_full, bottom_lip_full, plus point-based ones (mouth_corners, cupid_bow, inner_centers) that draw small disks whose size is set by point_radius (default 6). Selected regions are unioned into one mask. So "upper lip flesh plus the cupid's bow, but not the mouth interior" is a few dropdown clicks instead of a geometry problem.

Everything else is the pack's shared defensive machinery: auto_fallback swaps in an anchor-based ellipse when the inner ring collapses (puckers, kisses, occlusion), gated by fallback_area_threshold (inner/outer area ratio, default 0.15) and padded by fallback_pad_h/fallback_pad_v; confidence_threshold (default 0.3) skips people/frames with weak lip-keypoint scores; person_index picks who to mask, -1 unions everyone.

Outputs mirror the DWPose node: mask, centroid_x_list/centroid_y_list (for SAM-2 point prompting), and fallback_active_list telling you which frames ran on the fallback ellipse.

One honest limitation

Sapiens2 pose has no teeth and no tongue keypoints - the teeth were stripped from the original 344-keypoint set, and tongue never existed in the taxonomy. The node says so plainly in its own description. If you need per-pixel teeth or tongue, that's the segmentation head's job, and the same pack's MouthMaskFromSapiens2Seg node is the piece that reads it.

Installing it

Manager (search "lip_mask_from_pose") or git clone https://github.com/Jalen-Brunson/lip_mask_from_pose into custom_nodes/, then restart. This node adds zero dependencies - numpy/cv2/torch only. What you actually need is a Sapiens2 pose preprocessor that emits the 308-keypoint POSE_KEYPOINT (lassiiter's comfyui-sapiens2 or Kijai's are the ones people run). Without one of those, this node has nothing to eat.

Troubleshooting

  • Mask never appears: you're feeding it a DWPose POSE_KEYPOINT, which doesn't carry the 308-keypoint keypoints_2d field. Check the source preprocessor, not the node.
  • Everything silently falls back to ellipses: low-quality face crops mean weak keypoints; raise the source resolution or loosen confidence_threshold.
Categorymask/pose

Inputs (14)

NameTypeDefaultDescription
pose_keypointPOSE_KEYPOINT
region_1COMBOfull_inner_lip14 options: full_outer_lip, full_inner_lip, full_mouth, lips_only, outer_top_lip, outer_bottom_lip, +8
region_2COMBOnone14 options: full_outer_lip, full_inner_lip, full_mouth, lips_only, outer_top_lip, outer_bottom_lip, +8
region_3COMBOnone14 options: full_outer_lip, full_inner_lip, full_mouth, lips_only, outer_top_lip, outer_bottom_lip, +8
region_4COMBOnone14 options: full_outer_lip, full_inner_lip, full_mouth, lips_only, outer_top_lip, outer_bottom_lip, +8
blur_radiusINT50–100Gaussian blur radius for feathered edges. 0 = hard edge.
grow_pixelsINT00–200Dilate the unioned mask outward by this many pixels.
point_radiusINT61–100Disk radius used when a selected region is point-based (mouth_corners, cupid_bow, inner_centers).
person_indexINT0-1–99Which detected person to use (0 = first). -1 = union all people.
confidence_thresholdFLOAT0.300–1Skip a person/frame when avg lip-keypoint score is below this.
auto_fallbackBOOLEANtrueFall back to an anchor-based ellipse when the inner ring collapses (puckered/occluded lips).
fallback_area_thresholdFLOAT0.150.01–1Inner-ring area / outer-ring area below which the ring is considered collapsed.
fallback_pad_hFLOAT1.200.5–3Horizontal scale for the fallback ellipse.
fallback_pad_vFLOAT1.300.5–3Vertical scale for the fallback ellipse.

Outputs (4)

NameTypeDescription
maskMASK
centroid_x_listFLOAT
centroid_y_listFLOAT
fallback_active_listBOOLEAN