
    +jZ                        % S r SSKrSSKrSSKJrJrJr  SSKJ	r	  SSK
Jr  SSKrSSKrSSKrSSKrSSKJrJr  SSKJr  SSKJr  \R0                  " S	5      r\R0                  " S
5      rSrSr " S S5      rS\R<                  S\R>                  4S jr S\!S\"\#\#\#4   4S jr$S\%S\%4S jr&S\%S\%S\'S\%4S jr(S\)\%   S\)\%   S\)\"\#\#4      4S jr*S\)\)\%      S\!SS4S jr+S\,\"\#\#4      S\)\)\#      4S jr- " S  S!\R\                  5      r/S"r0 " S# S$\R\                  5      r1/ \QS%PS&P7r2\"\!S'4   \3S('   S)r4\"\"\!\54   S'4   \3S*'    " S+ S,\R\                  5      r6 S=S-\R>                  S.\)S/\"\#\#\#4   S0\#S1\#S2\)\)\#      S-  S\R>                  4S3 jjr7S4r8\"\!S'4   \3S5'   S6r9\"\"\!\54   S'4   \3S7'    " S8 S9\R\                  5      r: " S: S;\5      r;S\;4S< jr<g)>u,  ComfyUI nodes for the pure-PyTorch MediaPipe Face Landmarker port.

Custom IO types:
  FACE_LANDMARKER  — FaceLandmarkerModel wrapper (ModelPatcher inside)
  FACE_LANDMARKS   — {"frames": List[List[face_dict]], "image_size": (H, W),
                      "connection_sets": dict[str, frozenset[(int, int)]]}
                     face_dict: bbox_xyxy, blendshapes, landmarks_xy,
                                landmarks_3d, presence, score, transformation_matrix

MediaPipeFaceLandmarker also emits the core BOUNDING_BOX type — pair with DrawBBoxes.
    N)Image
ImageColor	ImageDraw)tqdm)override)ComfyExtensionio)FaceLandmarker)$transformation_matrix_from_detectionFACE_DETECTION_MODELFACE_LANDMARKS)canonical_verticesprocrustes_indicesprocrustes_weights)	face_ovalleft_eye	right_eyeleft_eyebrowright_eyebrowlipsc                   <    \ rS rSrSrS\4S jrS\S\S\	4S jr
S	rg
)FaceLandmarkerModel%   a
  Loaded FaceLandmarker variants + ModelPatcher per variant.

Safetensors layout: `detector_short.*` / `detector_full.*` plus shared
`mesh.*`, `blendshapes.*`, `canonical_*`, and `topology.*`.
PReLU forces plain-nn / fp32 (manual_cast strands buffers across devices).

state_dictc                 r  ^
 [         R                  R                  5       U l        [         R                  R	                  5       n[
        R                  U l        0 m
U Vs/ s H  o3R                  S5      (       d  M  UPM     sn HH  n[        [        [        UR                  U5      R                  5       5      5      T
U[        S5      S  '   MJ     [        5       R                  " U
4S j[          5       6 T
S'   T
S   T
S   -  T
S   -  T
S'   T
U l        [$         Vs0 s H"  o3UR                  U5      R'                  5       _M$     snU l        UR+                  5        VVs0 s H  u  p4UR                  S5      (       d  M  X4_M!     nnn0 U l        0 U l        S GH  nS	U S
3n[1        U5      nUR3                  UR+                  5        VVs0 s H/  u  p4UR                  U5      (       d  M  SU[        U5      S   3U_M1     snn5        [5        X R                  S US9R7                  5       n	U	R9                  USS9  XR,                  U'   [         R:                  R=                  XR                  U[         R                  R?                  U	5      S9U R.                  U'   GM     g s  snf s  snf s  snnf s  snnf )Nz	topology.c              3   .   >#    U  H
  nTU   v   M     g 7fN ).0pbases     </home/wildlama/comfy/ComfyUI/comfy_extras/nodes_mediapipe.py	<genexpr>/FaceLandmarkerModel.__init__.<locals>.<genexpr>6   s     .O1tAw   contoursirisesnoseall)zmesh.zblendshapes.)shortfull	detector_.z	detector.)devicedtype
operationsdetector_variantF)strict)load_deviceoffload_devicesize) comfymodel_managementtext_encoder_devicer3   text_encoder_offload_devicetorchfloat32r/   
startswith	frozensetmaptuplepoptolistlenunion_CONTOUR_PARTSconnection_sets_CANONICAL_KEYSnumpycanonical_dataitemsmodelspatchersdictupdater
   evalload_state_dictmodel_patcherCoreModelPatchermodule_size)selfr   r4   kvsharedvariantprefixsubflr!   s             @r"   __init__FaceLandmarkerModel.__init__-   sR    11EEG//KKM]]
 &('EZ<<+D!ZEA)23ujnnQ>O>V>V>X3Y)ZD3{#$%& F$;,,.O.OPZ:&h7$v,FU59\k5l\kWX9J9P9P9R6R\k5l#-#3#3#5a#541F_9`$!$#5a13EG(G 	+Fv,CJJZEUEUEWpEWTQ[\[g[ghn[o8)Ac&klO#45q8EWpq~ZZTXkrsxxzBs51#%KK %*%8%8%I%I 0 0++77; &J &DMM'" ) F 6ma qs*   J#;J#)J(J-?J-J3+J3	num_facesscore_threshrW   c                     [         R                  R                  U R                  U   5        U R                  U   R                  XUS9$ )N)r]   r^   )r6   r7   load_model_gpurK   rJ   detect_batch)rS   imagesr]   r^   rW   s        r"   ra    FaceLandmarkerModel.detect_batchM   s?    --dmmG.DE{{7#00[g0hh    )rH   rE   r/   r3   rJ   rK   N)__name__
__module____qualname____firstlineno____doc__rL   r[   intfloatstrra   __static_attributes__r   rd   r"   r   r   %   s3    4 @ic i iQT ird   r   imagereturnc                     U SS S24   R                  S5      R                  S5      R                  SS5      R                  [        R
                  5      R                  5       R                  5       $ )N.        o@      ?r      )muladd_clamp_tor:   uint8cpurG   )rn   s    r"   _image_to_uint8r{   R   sX    bqb>e$))#.55a=@@MQQSYY[[rd   colorc                 V     [         R                  " U 5      S S $ ! [         a     gf = f)Nrq   )r   rt   r   )r   getrgb
ValueError)r|   s    r"   _parse_colorr   V   s1      '++ s    
((facec                     U S   R                  5       [        U S   5      U S   R                  5       U S   R                  5       U S   U S   S.$ )zKShallow copy of a face_dict with array-fields cloned so callers can mutate.	bbox_xyxyblendshapeslandmarks_xylandmarks_3dpresencescorer   r   r   r   r   r   )copyrL   )r   s    r"   
_copy_facer   ]   s]     [)..0T-01^,113^,113Z(W rd   abtc           	         SU-
  U S   -  X!S   -  -   U S    Vs0 s H  o3SU-
  U S   U   -  X!S   U   -  -   _M     snSU-
  U S   -  X!S   -  -   SU-
  U S   -  X!S   -  -   SU-
  U S   -  X!S   -  -   SU-
  U S   -  X!S   -  -   S.$ s  snf )	N   r   r   r   r   r   r   r   r   )r   r   r   rT   s       r"   
_lerp_facer   i   s    Q!K.0aK.6HH]^_l]mn]mXYQUa&6q&99A-@PQR@S<SSS]mnQ!N"33aN:K6KKQ!N"33aN:K6KKQ!J-/!
m2CCQ!G*,!j.@ ns   #B
c           
        ^^ U (       a  T(       d  / $ [         R                  " U  Vs/ s H+  nSUS   S   US   S   -   -  SUS   S   US   S   -   -  4PM-     sn5      n[         R                  " T Vs/ s H+  nSUS   S   US   S   -   -  SUS   S   US   S   -   -  4PM-     sn5      n[         R                  R                  USS2S4   US   -
  SS	9m/ n[	        5       n[	        5       n[        UU4S
 j[        [        U 5      5       5       5      nU HF  u  pnX;   d  X;   a  M  UR                  X45        UR                  U
5        UR                  U5        MH     U$ s  snf s  snf )zGreedy nearest-neighbour pairing of faces between two frames by bbox
centre distance. Unmatched (when counts differ) are dropped.rs   r   r      r   rq   N)axisc              3   l   >#    U  H)  n[        [        T5      5        H  nTX4   X4v   M     M+     g 7fr   )rangerB   )r   iaibr   distss      r"   r#   _match_faces.<locals>.<genexpr>   s3     `-BRWX[\]X^R_Brv/R_/-s   14)
nparraylinalgnormsetsortedr   rB   appendadd)r   r   f	centers_a	centers_bpairsused_aused_b
candidates_r   r   r   s    `          @r"   _match_facesr   t   s    A	STVSTa !K."3anQ6G"GH!K."3anQ6G"GHJSTV WISTVSTa !K."3anQ6G"GH!K."3anQ6G"GHJSTV WIIINN9QW-	$?bNIE#%EuFuF`%A-``J	r<2<bX

2

2   LVVs   2E$42E)framesmodec           
        ^ US:X  a  g[        U 5       VVs/ s H  u  p#U(       d  M  UPM     nnnU(       d  gUS:X  aK  / n[        U 5       H9  u  mnU(       a  UnM  U(       d  M  U Vs/ s H  n[        U5      PM     snU T'   M;     g[        [        U 5      5       H  mU T   (       a  M  [	        U4S jU 5       SS9n[        U4S jU 5       SS9nUc#  X    Vs/ s H  n[        U5      PM     snU T'   M]  Uc#  X    Vs/ s H  n[        U5      PM     snU T'   M  TU-
  X-
  -  n	[        X   X   5      n
U
 VVs/ s H  u  p[        X   U   X   U   U	5      PM     snnU T'   M     gs  snnf s  snf s  snf s  snf s  snnf )zIn-place fill empty frame slots from neighbouring detections. Multi-face
aware: pairs faces across bracketing frames by greedy bbox-centre NN.
When counts differ, unmatched faces are dropped from the synthesised frame.emptyNpreviousc              3   6   >#    U  H  oT:  d  M
  Uv   M     g 7fr   r   r   rU   is     r"   r#   '_fill_missing_frames.<locals>.<genexpr>        0Aa%aa   		defaultc              3   6   >#    U  H  oT:  d  M
  Uv   M     g 7fr   r   r   s     r"   r#   r      r   r   )	enumerater   r   rB   maxminr   r   )r   r   r   frvalidlastr   prev_inext_ir   r   r   r   s     `          r"   _fill_missing_framesr      sw    w%f-4-51Q-E4zv&EAr489DqZ]D9q		 '
 	3v;!900$?00$?>06?1A?F1I^06?1A?F1IV0A @EY^_Y^QUQRFN1$5v~a7H!LY^_F1I   5 : @? `s"   E/E/*E5E:E? #Fedgesc                   ^
 0 nU  HW  u  p#UR                  U[        5       5      R                  U5        UR                  U[        5       5      R                  U5        MY     [        5       n/ nU H~  nXd;   a  M
  U/nUR                  U5        SUsm
n [        U
4S jX    5       S5      n	U	b  X:X  a  O(UR	                  U	5        UR                  U	5        Xsm
nMI  UR	                  U5        M     U$ )zWalk an unordered edge set into one or more closed-loop vertex rings
(handles multi-loop sets like FACEMESH_LIPS: outer + inner).r   c              3   6   >#    U  H  oT:w  d  M
  Uv   M     g 7fr   r   )r   rU   prevs     r"   r#   !_ordered_rings.<locals>.<genexpr>   s     98aDy8r   N)
setdefaultr   r   nextr   )r   adjr   r   visitedringsstartringcurnxtr   s             @r"   _ordered_ringsr      s      "Cq#% $$Q'q#% $$Q'  GEwE	c93894@C{clKKKKID#  	T  Lrd   c                   T    \ rS rSrSr\S 5       r\S\R                  4S j5       r	Sr
g)LoadMediaPipeFaceLandmarker   zLoad MediaPipe Face Landmarker v2 weights. Contains both detector variants
(short / full), shared mesh, blendshapes, and canonical geometry.c                     [         R                  " S/ SQSS[         R                  R                  S[        R
                  " S5      SS9/[        R                  5       /S	9$ )
Nr   r   facial	mediapipeface landmark	face mesh	blazefaceface detectionz%Load Face Detection Model (MediaPipe)zmodel/loaders
model_name	detectionz,Face detection model from models/detection/.)optionstooltip)node_idsearch_aliasesdisplay_namecategoryinputsoutputs)r	   SchemaComboInputfolder_pathsget_filename_listFaceDetectionTypeOutputclss    r"   define_schema)LoadMediaPipeFaceLandmarker.define_schema   s^    yy1w@$|\5S5ST_5`'U  W '--/0

 
	
rd   ro   c                     [         R                  R                  [        R                  " SU5      SS9n[        U5      n[        R                  " U5      $ )Nr   T)	safe_load)r6   utilsload_torch_filer   get_full_path_or_raiser   r	   
NodeOutput)r   r   sdwrappers       r"   execute#LoadMediaPipeFaceLandmarker.execute   sC    [[(()L)L[Zd)equ(v%b)}}W%%rd   r   Nre   rf   rg   rh   ri   classmethodr   r	   r   r   rm   r   rd   r"   r   r      s;    I 
 
 &BMM & &rd   r   )r   r   interpolatec                   T    \ rS rSrSr\S 5       r\S\R                  4S j5       r	Sr
g)MediaPipeFaceLandmarker   u   BlazeFace → FaceMesh v2 → ARKit-52 blendshapes, batched across the
input. Also emits a BOUNDING_BOX list (landmark-extent bbox per face) —
pair with DrawBBoxes for detector-only viz or MediaPipeFaceMeshVisualize
for the mesh overlay.c                     [         R                  " S/ SQSSS[        R                  S5      [         R                  R                  S5      [         R
                  R                  S/ S	QS
SS9[         R                  R                  SSSSSSS9[         R                  R                  SSSSSSSS9[         R
                  R                  S[        [        5      SSSS9/[        R                  SS 9[         R                  R                  S!5      /S"9$ )#Nr  r   z!Detect Face Landmarks (MediaPipe)image/detectionz/Detects facial landmarks using MediaPipe model.face_detection_modelrn   r1   )r*   r+   bothr*   u   Face detector range. 'short' is tuned for close-up faces (within ~2 m of the camera); 'full' covers farther / smaller faces (up to ~5 m) but is slower. 'both' runs both detectors and keeps whichever found more faces per frame (~2× detection cost).)r   r   r   r]   r   r      zDMaximum faces to return per frame. 0 = no cap (return all detected).r   r   r   stepr   min_confidencers   g        g      ?g{Gz?Tz?BlazeFace score threshold. Lower to catch small/occluded faces.)r   r   r   r	  advancedr   missing_frame_fallbackr   a$  Per-frame behaviour when detection fails in a batch. 'empty' leaves the frame faceless. 'previous' copies the most recent successful detection. 'interpolate' lerps landmarks/bbox/blendshapes between bracketing successful frames. Multi-face: pairs faces across frames by greedy bbox-centre NN.)r   r   r  r   face_landmarks)r   bboxesr   r   r   r   descriptionr   r   )r	   r   r   r   r   r   IntFloatlist_FALLBACK_MODESFaceLandmarksTyper   BoundingBoxr   s    r"   r   %MediaPipeFaceLandmarker.define_schema   s   yy-w<&I!''(>?w'1;T^e(k  l
 [!%k  m/#3UYdh'h  j7oAV`grv(|  }& "((6F(G%%h/1
 	
rd   ro   c                 (  ^^^^^^^^ TR                   n[        U5      mTR                  S S u  mpSmUS:H  n
U
(       a  ST-  OTm[        R                  R                  T5      mS[        S[        [        [              4UUUUUUUU4S jjnU
(       aN  U" S5      nU" S	5      n[        T5       Vs/ s H'  n[        X   5      [        X   5      :  a  X   OX   PM)     nnOU" U5      n[        X5        / nU Hj  n/ nU HN  n[        UXU5      US
'   S US    5       u  nnnnUR                  UUUU-
  UU-
  S[        US   5      S.5        MP     UR                  U5        Ml     [        R                   " XU	4TR"                  S.U5      $ s  snf )Nrq   r  r  r   rW   ro   c                   > / n[        TSU  S3S9 n[        STT5       H  n[        UT-   T5      nUR                  TR	                  [        X45       Vs/ s H  nT	U   PM
     sn[        T5      [        T
5      U S95        TR                  [        TR                  XC-
  -   T5      5        UR                  XC-
  5        M     S S S 5        U$ s  snf ! , (       d  f       U$ = f)NzMediaPipe Face Landmarker ())totaldescr   )r]   r^   rW   )
r   r   r   extendra   rj   rk   update_absolutecurrentrM   )rW   restqr   endbiBchunkr  img_npr
  r]   pbar
total_works         r"   _run-MediaPipeFaceLandmarker.execute.<locals>._run  s    $&CA&A'!$LMQSq!U+Aa%i+CJJ3@@.3Am<mm<"%i.%*>%: '	  A    ((T\\SW-Ez)RSIIcg& , N J =	 NM Js   ACC$ACC
C!r*   r+   transformation_matrixc              3   8   #    U  H  n[        U5      v   M     g 7fr   )rk   )r   rU   s     r"   r#   2MediaPipeFaceLandmarker.execute.<locals>.<genexpr>3  s     !CNq%((Ns   r   r   r   )xywidthheightlabelr   )r   
image_sizerE   )rH   r{   shaper6   r   ProgressBarrl   r  rL   r   rB   r   r   r   rk   r	   r   rE   )r   r  rn   r1   r]   r
  r  	canonicalHWis_bothr)  	short_resfull_resr#  r   r  	per_frameper_bbr   x1y1x2y2r$  r%  r&  r'  r(  s    `  ``                  @@@@@r"   r   MediaPipeFaceLandmarker.execute	  s    )77	 ',,r"1"f,%QU1
{{&&z2	# 	$tDz"2 	 	 WIF|H  (("B "%Y]!3s8<7H!H	hlZ"  (F
 *+FV<IF-QRSUV[d-e)*!CAkN!CBBBR"r'RRTW_epuvwx  wA  qB  C  D  MM&!   }}!f1E1U1UWX^` 	`(s   3.Fr   Nr   r   rd   r"   r  r     s>    
 
 
> -`+-==-` -`rd   r  r'   r(   ._ALL_CONNECTION_PARTS)	r   T)r   T)r   T)r   T)r   T)r   T)r'   T)r(   T)tesselationF_CUSTOM_FEATURESc                   X    \ rS rSrSr\S 5       r\SS\R                  4S jj5       r	Sr
g)	MediaPipeFaceMeshVisualizeiI  zqDraw a FACEMESH_* subset over an image. Topology travels with the
FACE_LANDMARKS payload (set at detection time).c                 
   [         R                  " S/ SQSSS[        R                  S5      [         R                  R                  SSS	S
9[         R
                  R                  SS[         R
                  R                  S/ 5      [         R
                  R                  S/ 5      [         R
                  R                  S[         VVs/ s H'  u  p[         R                  R                  XSU S3S9PM)     snn5      /S9[         R                  R                  SSS9[         R                  R                  SSSSSSS9[         R                  R                  SSSSSS S9/[         R                  R                  5       /S!9$ s  snnf )"NrH  )r   r   r   r   r   r   r   	visualizez$Visualize Face Landmarks (MediaPipe)r  z-Draws face landmarks mesh on the input image.r  rn   Tz.If not connected, a black canvas will be used.)optionalr   connectionsz'all' = oval+eyes+brows+lips+irises+nose. 'fill' = solid face_oval polygon (silhouette mask). 'custom' = toggle each feature individually (including 'tesselation', the full 2547-edge wireframe).r)   fillcustomz
Draw the 'z' connection set.r   r   r   r   r|   z#00ff00r   	thicknessr   r      z7Edge line thickness in pixels. 0 disables edge drawing.r  
point_sizer   r  z8Landmark dot radius in pixels. 0 disables point drawing.r  )r	   r   r  r   r   DynamicComboOptionrF  BooleanColorr  r   )r   featr   s      r"   r   (MediaPipeFaceMeshVisualize.define_schemaM  sl   yy0 E?&G!''(89w?op%%! a..ub9..vr:..x 2B: 2B JJ,,T7A$GX5Y - [1A:  &  w	:[!%^  `\1!!%_  a', XX__&'9
 	
:s   .E?*Nro   c           
      j  ^ US   mUS   nS nUS:X  a  [        TS   5      n[        5       n	OUS:X  aU  [         V
Vs/ s H   u  pUR                  U
S5      (       d  M  U
PM"     nn
n[        5       R                  " U4S jU 5       6 n	O%[        5       R                  " U4S j[
         5       6 n	[        U5      [        U5      [        U5      pnUS	   nUc9  US
   u  nn[        R                  " [        U5      UUS4[        R                  S9nO[        U5      nUR                  S   n[        U5      n[        R                  R!                  U5      n[        R"                  " U5      n[%        U5       H9  nUU:  a  UU   O/ n['        UU   UXXU5      UU'   UR)                  US-   5        M;     [*        R,                  " [.        R0                  " U5      R3                  [        R4                  R7                  5       [        R4                  R9                  5       S9R;                  S5      5      $ s  snn
f )NrE   rL  rM  r   rN  Fc              3   .   >#    U  H
  nTU   v   M     g 7fr   r   r   r    setss     r"   r#   5MediaPipeFaceMeshVisualize.execute.<locals>.<genexpr>x  s     '?AQr%   c              3   .   >#    U  H
  nTU   v   M     g 7fr   r   r\  s     r"   r#   r^  z  s     'O9NAQ9Nr%   r   r3  rq   r/   r   r   r.   r/   rr   )r   r=   rF  getrC   rC  r   rj   r   zerosrB   ry   r{   r4  r6   r   r5  
empty_liker   
_draw_meshr  r	   r   r:   
from_numpyrx   r7   intermediate_deviceintermediate_dtypediv_)r   r  rL  r|   rQ  rS  rn   sel
fill_ringsr   rX  r   partsrgbthickpsizer   r7  r8  r&  r$  n_framesr'  outr#  facesr]  s                             @r"   r   "MediaPipeFaceMeshVisualize.executen  s   /0-(-1
&='[(9:JKEH_)9Z)9gd[__TSX=YT)9EZK%%'?'?@EK%%'O9N'OPE(/YZE)=!,/DAqXXs6{Aq!4BHHEF$U+FLLOv;{{&&q)mmF#(B"$x-F2JRE UEjYCG  a(  }}U--c255))==?((;;= 6 
 $u+ 	' [s   H/H/r   r   r   r   rd   r"   rH  rH  I  s>    7 
 
@ _a_l_l  rd   rH  	image_rgbrr  rm  rQ  rS  rk  c                    US:  =(       a    UnU(       a  Uc  U(       d  US::  a  U R                  5       $ [        R                  " U 5      n[        R                  " U5      n	US-  n
Ubj  U HN  nUS   nU H@  nU	R                  U Vs/ s H!  n[        XS4   5      [        XS4   5      4PM#     snUS9  MB     MP     [        R                  " U5      $ U GH  nUS   nUR                  S   nU(       aj  U Hd  u  nnUU:  d  M  UU:  d  M  U	R                  [        UUS4   5      [        UUS4   5      4[        UUS4   5      [        UUS4   5      4/X4S9  Mf     US:X  a.  U	R                  UR                  5       R                  5       US9  M  US:  d  M  U HJ  u  nnU	R                  [        U5      U
-
  [        U5      U
-
  [        U5      U
-   [        U5      U
-   4US9  ML     GM     [        R                  " U5      $ s  snf )Nr   rs   r   r   rM  )rM  r0  )r   r   	fromarrayr   Drawpolygonrk   r   asarrayr4  linepointflattenrA   ellipse)rt  rr  r   rm  rQ  rS  rk  
draw_edgespildrawrr   lmksr   r   nr   r   r.  r/  s                       r"   re  re    s    Q(5JZ'
zQ~~
//)
$C>>#DSAA^$D"dSduTQ$Z0%T
2CDdSZ]^ #  zz# JJqM1q5QUIId1a4j 15ad3DE %d1a4j 15ad3DEGMP  c  ?JJt||~,,.SJ9!^1eAhlE!HqL%(Q,aSTU\_`   ::c? Ts   (H)r   r   r   r   r'   _MASK_REGIONS)rD  )r   F)r   F)r   F)r'   F_MASK_CUSTOM_FEATURESc                   T    \ rS rSrSr\S 5       r\S\R                  4S j5       r	Sr
g)MediaPipeFaceMaski  zBinary mask from face landmarks, filled polygon per face. One mask per
frame in the batch; faces in the same frame composite (union).c                    [         R                  " S/ SQSSS[        R                  S5      [         R                  R                  SS[         R                  R                  S	/ 5      [         R                  R                  S
[         VVs/ s H'  u  p[         R                  R                  XSU S3S9PM)     snn5      /S9/[         R                  R                  5       /S9$ s  snnf )Nr  )r   r   r   z	face maskr   r   rJ  zDraw Face Mask (MediaPipe)r  z!Draws a mask from face landmarks.r  regionsz'all' = union of face_oval+lips+eyes+irises (which collapses to face_oval since it encloses the rest). 'custom' = toggle each region individually for combos like lips+eyes.r)   rN  zInclude the 'z' region in the mask.rO  rP  r  )
r	   r   r  r   rT  rU  r  rV  Maskr   )r   regr   s      r"   r   MediaPipeFaceMask.define_schema  s    yy's5&;!''(89%% K..ub9..x 1F: 1F JJ,,S7DSEI^5_ - a0E:  &  WW^^%&+
 	
:s   	.C#&ro   c                 v   US   nUS   nUS:X  a4  [          VVs/ s H   u  pVUR                  US5      (       d  M  UPM"     nnnO[        [        5      nU VVs/ s H  n[	        X5   5        H  oPM     M     n	nnUS   n
US   u  p[
        R                  " [        U
5      X4[
        R                  S9n[        R                  R                  [        U
5      5      n[        U
5       H  u  nnU(       a  [        R                  " SX4S	5      n[        R                   " U5      nU HP  nUS
   nU	 HB  nUR#                  U Vs/ s H#  n[%        UUS	4   5      [%        UUS4   5      4PM%     snSS9  MD     MR     [
        R&                  " U5      X'   UR)                  US-   5        M     [*        R,                  " [.        R0                  " U5      R3                  [        R4                  R7                  5       [        R4                  R9                  5       S9R;                  S5      5      $ s  snnf s  snnf s  snf )NrE   r  rN  Fr   r3  r`  Lr   r   r   rt   rv  ra  rr   )r  rb  r  r  r   r   rc  rB   ry   r6   r   r5  r   r   newr   rx  ry  rk   rz  r  r	   r   r:   rf  rx   r7   rg  rh  ri  )r   r  r  r]  rj  r  r   pickedr  r   r   r7  r8  masksr'  r#  r<  r  r  r   r  r   r   s                          r"   r   MediaPipeFaceMask.execute  s   /0i (?(=Y(=fcSRWAXc(=FYF-(F$HfsnTY.G.GfH)l+#f+q,BHH={{&&s6{3&v.MB	iiaVQ/ ~~c*"A^,D %VZ%[VZQRuT!Q$Z'8%QT
:K&LVZ%[bef !& # JJsO	  a( / }}U--e477))==?((;;= 8 
 $u+ 	% Z I &\s   H*H* H0*H6r   Nr   r   rd   r"   r  r    s;    F 
 
2   rd   r  c                   L    \ rS rSr\S\\\R                        4S j5       r	Sr
g)MediaPipeFaceExtensioni  ro   c                 6   #    [         [        [        [        /$ 7fr   )r   r  rH  r  )rS   s    r"   get_node_list$MediaPipeFaceExtension.get_node_list  s     +-DF`bstts   r   N)re   rf   rg   rh   r   r  typer	   	ComfyNoder  rm   r   rd   r"   r  r    s,    uT$r||*<%= u urd   r  c                     #    [        5       $ 7fr   )r  r   rd   r"   comfy_entrypointr    s     !##s   r   )=ri   rG   r   r:   PILr   r   r   	tqdm.autor   typing_extensionsr   comfy.model_managementr6   comfy.model_patchercomfy.utilsr   comfy_api.latestr   r	   &comfy_extras.mediapipe.face_landmarkerr
   $comfy_extras.mediapipe.face_geometryr   Customr   r  rF   rD   r   Tensorndarrayr{   rl   r?   rj   r   rL   r   rk   r   r  r   r   r=   r   r  r   r  r  rC  __annotations__rF  boolrH  re  r  r  r  r  r  r   rd   r"   <module>r     s  
   , ,  &     / A U II45 II./ T`*i *iZ\5<< \BJJ \ c3m 4 	T 	d 	$ 4 E d DJ 4: $uS#X2G .`d4j!1 ` ` `B)E#s(O4 d3i 4&",, &4 7T`bll T`p *M>)L8)LV)L uS#X L
2 %c4i(#-. 
D DR FJ"** T #sC-(58,0cOd,BNPjj@ "ZuS#X Y7 uU39-s23 8 8vu^ u$ 6 $rd   