
    +jZ                        U d Z ddlZddlZddlmZmZmZ ddlm	Z	 ddl
mZ ddlZddlZddlZddlZddlmZmZ ddlmZ ddlmZ  ej        d	          Z ej        d
          ZdZdZ G d d          Zdej        dej        fdZ de!de"e#e#e#f         fdZ$de%de%fdZ&de%de%de'de%fdZ(de)e%         de)e%         de)e"e#e#f                  fdZ*de)e)e%                  de!ddfdZ+de,e"e#e#f                  de)e)e#                  fdZ- G d  d!ej.                  Z/d"Z0 G d# d$ej.                  Z1g ed%d&R Z2e"e!d'f         e3d(<   d)Z4e"e"e!e5f         d'f         e3d*<    G d+ d,ej.                  Z6	 d=d-ej        d.e)d/e"e#e#e#f         d0e#d1e#d2e)e)e#                  dz  dej        fd3Z7d4Z8e"e!d'f         e3d5<   d6Z9e"e"e!e5f         d'f         e3d7<    G d8 d9ej.                  Z: G d: d;e          Z;de;fd<Z<dS )>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                   2    e Zd ZdZdefdZdededefdZ	dS )	FaceLandmarkerModela  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           	      ~  	 t           j                                        | _        t           j                                        }t
          j        | _        i d D             D ]a}t          t          t                              |                                                              |t          d          d          <   b t                      j        fdt          D              d<   d         d         z  d         z  d<   | _        fdt"          D             | _        d	                                 D             }i | _        i | _        d
D ]}d| d	t-          |          }|                    	fd                                D                        t1          || j        d |                                          }|                    |d           || j        |<   t           j                            || j        |t           j                            |                    | j        |<   d S )Nc                 <    g | ]}|                     d           |S )	topology.
startswith).0ks     </home/wildlama/comfy/ComfyUI/comfy_extras/nodes_mediapipe.py
<listcomp>z0FaceLandmarkerModel.__init__.<locals>.<listcomp>4   s)    EEE1<<+D+DE!EEE    r   c              3   (   K   | ]}|         V  d S N )r   pbases     r!   	<genexpr>z/FaceLandmarkerModel.__init__.<locals>.<genexpr>6   s'      .O.O1tAw.O.O.O.O.O.Or#   contoursirisesnoseallc                 `    i | ]*}|                     |                                          +S r&   )popnumpy)r   r    r   s     r!   
<dictcomp>z0FaceLandmarkerModel.__init__.<locals>.<dictcomp>:   s4    5l5l5lWXa9J9J9P9P9R9R5l5l5lr#   c                 D    i | ]\  }}|                     d           ||S ))zmesh.zblendshapes.r   )r   r    vs      r!   r1   z0FaceLandmarkerModel.__init__.<locals>.<dictcomp><   s0    aaa41aF_9`9`a!Qaaar#   )shortfull	detector_.c                 v    i | ]5\  }}|                               d |t                    d          |6S )z	detector.N)r   len)r   r    r3   prefixs      r!   r1   z0FaceLandmarkerModel.__init__.<locals>.<dictcomp>C   sK    pppTQ[\[g[ghn[o[op5Ac&kkllO55qpppr#   )devicedtype
operationsdetector_variantF)strict)load_deviceoffload_devicesize)comfymodel_managementtext_encoder_devicer@   text_encoder_offload_devicetorchfloat32r<   	frozensetmaptupler/   tolistr9   union_CONTOUR_PARTSconnection_sets_CANONICAL_KEYScanonical_dataitemsmodelspatchersdictupdater
   evalload_state_dictmodel_patcherCoreModelPatchermodule_size)
selfr   rA   r    sharedvariantsubflr(   r:   s
    `      @@r!   __init__zFaceLandmarkerModel.__init__-   s@    1EEGG/KKMM]
 &(EEZEEE 	[ 	[A)23ujnnQ>O>O>V>V>X>X3Y3Y)Z)ZD3{##$$%&&,9;;,.O.O.O.O.O.O.OPZ:&h7$v,FU595l5l5l5l\k5l5l5laa:#3#3#5#5aaa13EG( 	 	G++++Fv,,CJJppppZEUEUEWEWpppqqq~TZTXkrsssxxzzBs5111#%DK %*%8%I%I 0+77;; &J & &DM'""	 	r#   	num_facesscore_threshr^   c                     t           j                            | j        |                    | j        |                             |||          S )N)rb   rc   )rC   rD   load_model_gpurT   rS   detect_batch)r\   imagesrb   rc   r^   s        r!   rf   z FaceLandmarkerModel.detect_batchM   sC    --dmG.DEEE{7#009[g0hhhr#   N)
__name__
__module____qualname____doc__rU   ra   intfloatstrrf   r&   r#   r!   r   r   %   sm         4    @ic i iQT i i i i i ir#   r   imagereturnc                    | dd df                              d                              d                              dd                              t          j                                                                                  S )N.        o@      ?r      )muladd_clamp_torG   uint8cpur0   )ro   s    r!   _image_to_uint8r|   R   sh    bqb>e$$))#..55a==@@MMQQSSYY[[[r#   colorc                 ^    	 t          j        |           d d         S # t          $ r Y dS w xY w)Nrr   )r   ru   r   )r   getrgb
ValueError)r}   s    r!   _parse_colorr   V   sC     ''++   {{s    
,,facec                     | d                                          t          | d                   | d                                          | d                                          | d         | d         d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   )copyrU   )r   s    r!   
_copy_facer   ]   sn     [)..00T-011^,1133^,1133Z(W  r#   abtc           	      2    dz
   d         z  d         z  z    fd d         D             dz
   d         z  d         z  z   dz
   d         z  d         z  z   dz
   d         z  d         z  z   dz
   d         z  d         z  z   d	S )
N   r   c                 ^    i | ])}|d z
  d         |         z  d         |         z  z   *S )r   r   r&   )r   r    r   r   r   s     r!   r1   z_lerp_face.<locals>.<dictcomp>l   sD    nnnXYQUa&6q&99A-@PQR@S<SSnnnr#   r   r   r   r   r   r   r&   )r   r   r   s   ```r!   
_lerp_facer   i   s    Q!K.0a!K.6HHnnnnnn]^_l]mnnnQ!N"33a!N:K6KKQ!N"33a!N:K6KKQ!J-/!a
m2CCQ!G*,!aj.@  r#   c                 D   | rsg S t          j        d | D                       }t          j        d D                       }t           j                            |dddf         |d         z
  d          g }t	                      }t	                      }t          fdt          t          |                     D                       }|D ]P\  }}	}
|	|v s|
|v r|                    |	|
f           |	                    |	           |	                    |
           Q|S )zGreedy nearest-neighbour pairing of faces between two frames by bbox
    centre distance. Unmatched (when counts differ) are dropped.c                     g | ]B}d |d         d         |d         d         z   z  d |d         d         |d         d         z   z  fCS rt   r   r      r   rr   r&   r   fs     r!   r"   z _match_faces.<locals>.<listcomp>y   o     V V VNO !K."3anQ6G"GH!K."3anQ6G"GHJ V V Vr#   c                     g | ]B}d |d         d         |d         d         z   z  d |d         d         |d         d         z   z  fCS r   r&   r   s     r!   r"   z _match_faces.<locals>.<listcomp>{   r   r#   N)axisc              3   p   K   | ]0}t          t                              D ]}||f         ||fV  1d S r%   )ranger9   )r   iaibr   distss      r!   r)   z_match_faces.<locals>.<genexpr>   sR      ``BRWX[\]X^X^R_R_``Br2vB/```````r#   )
nparraylinalgnormsetsortedr   r9   appendadd)r   r   	centers_a	centers_bpairsused_aused_b
candidates_r   r   r   s    `         @r!   _match_facesr   t   s[     A 	 V VSTV V V W WI V VSTV V V W WIINN9QQQW-	$?bNIIE#%EuuFuuF`````%A--`````J  	2r<<2<<b"X

2

2Lr#   framesmodec                 ^   	 |dk    rdS d t                     D             }|sdS |dk    r/g }t                     D ]\  }|r|}
|rd |D              <   dS t          t                               D ]          rt          fd|D             d          t	          fd|D             d          d	           D              <   ]d
           D              <   uz
  z
  z  	t                                        } 	fd|D              <   dS )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.emptyNc                     g | ]	\  }}||
S r&   r&   )r   ifrs      r!   r"   z(_fill_missing_frames.<locals>.<listcomp>   s!    44451b4Q444r#   previousc                 ,    g | ]}t          |          S r&   r   r   s     r!   r"   z(_fill_missing_frames.<locals>.<listcomp>   s    999qZ]]999r#   c              3   (   K   | ]}|k     |V  d S r%   r&   r   r3   r   s     r!   r)   z'_fill_missing_frames.<locals>.<genexpr>   '      00A!a%%a%%%%00r#   defaultc              3   (   K   | ]}|k    |V  d S r%   r&   r   s     r!   r)   z'_fill_missing_frames.<locals>.<genexpr>   r   r#   c                 ,    g | ]}t          |          S r&   r   r   s     r!   r"   z(_fill_missing_frames.<locals>.<listcomp>       ???1A???r#   c                 ,    g | ]}t          |          S r&   r   r   s     r!   r"   z(_fill_missing_frames.<locals>.<listcomp>   r   r#   c                 h    g | ].\  }}t                   |                  |                   /S r&   )r   )r   r   r   r   next_iprev_ir   s      r!   r"   z(_fill_missing_frames.<locals>.<listcomp>   s>    ___QUQRTUF6N1$5vf~a7H!LL___r#   )	enumerater   r9   maxminr   )
r   r   validlastr   r   r   r   r   r   s
   `     @@@@r!   _fill_missing_framesr      s    w44If--444E zv&& 	: 	:EAr : :99D999q	3v;; ` `!9 	0000000$???0000000$???>??v???F1II^??v???F1IIV0A @@E_______Y^___F1II` `r#   edgesc                 @  
 i }| D ]o\  }}|                     |t                                                    |           |                     |t                                                    |           pt                      }g }|D ]}||v r|g}|                    |           d|c
}	 t          
fd||         D             d          }	|	|	|k    rn0|                    |	           |                    |	           ||	c
}[|                    |           |S )zWalk an unordered edge set into one or more closed-loop vertex rings
    (handles multi-loop sets like FACEMESH_LIPS: outer + inner).r   Tc              3   (   K   | ]}|k    |V  d S r%   r&   )r   r3   prevs     r!   r)   z!_ordered_rings.<locals>.<genexpr>   s'      99aqDyyyyyy99r#   N)
setdefaultr   r   nextr   )r   adjr   r   visitedringsstartringcurnxtr   s             @r!   _ordered_ringsr      sH     "C ( (1q#%%  $$Q'''q#%%  $$Q''''GE  GwE	c	!99993s89994@@C{cUllKKKKSID#	! 	TLr#   c                   N    e Zd ZdZed             Zedej        fd            ZdS )LoadMediaPipeFaceLandmarkerzLoad MediaPipe Face Landmarker v2 weights. Contains both detector variants
    (short / full), shared mesh, blendshapes, and canonical geometry.c                     t          j        dg dddt           j                            dt	          j        d          d          gt                                          g	          S )
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_schemaz)LoadMediaPipeFaceLandmarker.define_schema   ss    y1www@$|\5ST_5`5`'U  W W '--//0

 

 

 
	
r#   rp   c                     t           j                            t          j        d|          d          }t          |          }t          j        |          S )Nr   T)	safe_load)rC   utilsload_torch_filer   get_full_path_or_raiser   r	   
NodeOutput)r   r   sdwrappers       r!   executez#LoadMediaPipeFaceLandmarker.execute   sH    [(()L[Zd)e)equ(vv%b))}W%%%r#   N	rh   ri   rj   rk   classmethodr   r	   r   r  r&   r#   r!   r   r      sd        I I 
 
 [
 &BM & & & [& & &r#   r   )r   r   interpolatec                   N    e Zd ZdZed             Zedej        fd            ZdS )MediaPipeFaceLandmarkeru   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                 ^   t          j        dg ddddt                              d          t           j                            d          t           j                            dg d	d
d          t           j                            dddddd          t           j                            ddddddd          t           j                            dt          t                    ddd          gt                              d           t           j                            d!          g"          S )#Nr  r   z!Detect Face Landmarks (MediaPipe)image/detectionz/Detects facial landmarks using MediaPipe model.face_detection_modelro   r>   )r4   r5   bothr4   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   rb   r   r      zDMaximum faces to return per frame. 0 = no cap (return all detected).r   r   r   stepr   min_confidencert   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   z%MediaPipeFaceLandmarker.define_schema   s>   y-www<&I!''(>??w''1;T;T;T^e(k  l l
 [!%k  m m/#3UYdh'h  j j7oAVAV`grv(|  } }& "((6F(GG%%h//1
 
 
 	
r#   rp   c                    j         }t          |          j        d d         \  }}	d|dk    }
|
rdz  nt          j                                      dt          dt          t          t                            ffd}|
r3 |d           |d	          fd
t                    D             }n ||          }t          ||           g }|D ]}g }|D ]c}t          ||	||          |d<   d |d         D             \  }}}}|                    ||||z
  ||z
  dt          |d                   d           d|                    |           t          j        |||	fj        d|          S )Nrr   r  r  r   r^   rp   c                    g }t          d|  d          5 }t          d          D ]}t          |z             }|                                        fdt          ||          D             t          
          t          	          |                                          t          j        ||z
  z                        |	                    ||z
             	 d d d            n# 1 swxY w Y   |S )NzMediaPipe Face Landmarker ())totaldescr   c                      g | ]
}|         S r&   r&   )r   biimg_nps     r!   r"   zAMediaPipeFaceLandmarker.execute.<locals>._run.<locals>.<listcomp>  s    <<<<<<r#   )rb   rc   r^   )
r   r   r   extendrf   rl   rm   update_absolutecurrentrV   )r^   restqr   endBchunkr  r$  r  rb   pbar
total_works        r!   _runz-MediaPipeFaceLandmarker.execute.<locals>._run  s]   $&CA$L'$L$L$LMMM 
'QSq!U++ 	' 	'Aa%i++CJJ3@@<<<<eAsmm<<<"%i..%*>%:%: '	  A        ((T\S1W-Ez)R)RSSSIIcAg&&&&	'
' 
' 
' 
' 
' 
' 
' 
' 
' 
' 
' 
' 
' 
' 
' Js   CC44C8;C8r4   r5   c                     g | ]>}t          |                   t          |                   k    r|         n|         ?S r&   )r9   )r   r#  full_res	short_ress     r!   r"   z3MediaPipeFaceLandmarker.execute.<locals>.<listcomp>'  sX     ( ( ( "%Yr]!3!3s8B<7H7H!H!H	"hWYl( ( (r#   transformation_matrixc              3   4   K   | ]}t          |          V  d S r%   rm   )r   r3   s     r!   r)   z2MediaPipeFaceLandmarker.execute.<locals>.<genexpr>3  s(      !C!Cq%((!C!C!C!C!C!Cr#   r   r   r   )xywidthheightlabelr   )r   
image_sizerO   )rQ   r|   shaperC   r   ProgressBarrn   r  rU   r   r   r   r   rm   r	   r   rO   )r   r  ro   r>   rb   r  r  	canonicalHWis_bothr/  r   r  	per_frameper_bbr   x1y1x2y2r+  r,  r1  r$  r-  r2  r.  s    `  ``               @@@@@@@r!   r  zMediaPipeFaceLandmarker.execute	  sO    )7	 '',rr"1a"f,%,QUU1
{&&z22	# 	$tDz"2 	 	 	 	 	 	 	 	 	 	 	 	 	  		,WItF||H( ( ( ( (((( ( (FF
 T*++FV%;<<< 	" 	"IF D D-QRSUVXY[d-e-e)*!C!CAkN!C!C!CBBBR"r'RRTW_epuvwx  wA  qB  qB  C  C  D  D  D  DMM&!!!!}q!f1E1UW WX^` ` 	`r#   Nr  r&   r#   r!   r  r     sj         
 
 
 [
> -`+-=-` -` -` [-` -` -`r#   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                   P    e Zd ZdZed             Zeddej        fd            ZdS )MediaPipeFaceMeshVisualizezuDraw a FACEMESH_* subset over an image. Topology travels with the
    FACE_LANDMARKS payload (set at detection time).c                    t          j        dg ddddt                              d          t           j                            ddd	
          t           j                            ddt           j                            dg           t           j                            dg           t           j                            dd t          D                       g          t           j                            dd          t           j	                            dddddd          t           j	                            dddddd          gt           j        
                                g          S ) NrM  )r   r   r   r   r   r   r   	visualizez$Visualize Face Landmarks (MediaPipe)r
  z-Draws face landmarks mesh on the input image.r  ro   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customc           	      `    g | ]+\  }}t           j                            ||d | d          ,S )z
Draw the 'z' connection set.r   r   r	   Booleanr   )r   featr   s      r!   r"   z<MediaPipeFaceMeshVisualize.define_schema.<locals>.<listcomp>^  sY     : : : !.g J,,T75Y$5Y5Y5Y - [ [: : :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OptionrK  Colorr  r   r   s    r!   r   z(MediaPipeFaceMeshVisualize.define_schemaM  si   y0 E  E  E?&G!''(899w?opp%%! a..ub99..vr::..x : : 2B: : :   &   w	::[!%^  ` `\1!!%_  a a', X__&&'9
 
 
 	
r#   Nrp   c           
         |d         d         }d }|dk    r$t          d                   }t                      }	nc|dk    r6fdt          D             }
 t                      j        fd|
D              }	n' t                      j        fdt          D              }	t          |          t          |          t          |          }}}|d	         }|=|d
         \  }}t          j        t          |          ||dft          j
                  }nt          |          }|j        d         }t          |          }t          j                            |          }t          j        |          }t#          |          D ]H}||k     r||         ng }t%          ||         ||	||||          ||<   |                    |dz              It)          j        t-          j        |                              t          j                                        t          j                                                                      d                    S )NrO   rQ  rR  r   rS  c                 F    g | ]\  }}                     |d           |S Fget)r   rX  r   rQ  s      r!   r"   z6MediaPipeFaceMeshVisualize.execute.<locals>.<listcomp>w  s1    ZZZgdA[__TSX=Y=YZTZZZr#   c              3   (   K   | ]}|         V  d S r%   r&   r   r'   setss     r!   r)   z5MediaPipeFaceMeshVisualize.execute.<locals>.<genexpr>x  s'      '?'?AQ'?'?'?'?'?'?r#   c              3   (   K   | ]}|         V  d S r%   r&   rf  s     r!   r)   z5MediaPipeFaceMeshVisualize.execute.<locals>.<genexpr>z  s'      'O'OAQ'O'O'O'O'O'Or#   r   r;  rr   r<   r   r   r;   r<   rs   )r   rI   rK  rM   rH  r   rl   r   zerosr9   rz   r|   r<  rC   r   r=  
empty_liker   
_draw_meshr&  r	   r   rG   
from_numpyry   rD   intermediate_deviceintermediate_dtypediv_)r   r  rQ  r}   rZ  r\  ro   sel
fill_ringsr   partsrgbthickpsizer   r?  r@  r$  r+  n_framesr-  outr#  facesrg  s     `                     @r!   r  z"MediaPipeFaceMeshVisualize.executen  s3   /0-(-1
&=='[(9::JKKEEH__ZZZZ)9ZZZE%IKK%'?'?'?'?'?'?'?@EE%IKK%'O'O'O'O9N'O'O'OPE(//YZEU)=!,/DAqXs6{{Aq!4BHEEEFF$U++FLOv;;{&&q))mF##(( 	) 	)B"$x--F2JJRE UE3ujYYCG  a((((}U-c2255)==??(;;== 6 
 
 $u++  	r#   r%   r  r&   r#   r!   rM  rM  I  sj        7 7 
 
 [
@  _a_l    [  r#   rM  	image_rgbrz  ru  rZ  r\  rs  c                 
   |dk    o|}|r
||s|dk    r|                                  S t          j        |           }t          j        |          }	|dz  }
|I|D ]2}|d         |D ]%}|	                    fd|D             |           &3t          j        |          S |D ]K}|d         j        d         }|r|D ]\  }}||k     rx||k     rr|		                    t          |df                   t          |df                   ft          |df                   t          |df                   fg||           |dk    r<|	                                                                                    |           |dk    rcD ]`\  }}|	                    t          |          |
z
  t          |          |
z
  t          |          |
z   t          |          |
z   f|           aMt          j        |          S )Nr   rt   r   c                 l    g | ]0}t          |d f                   t          |df                   f1S r   r   r5  r   r   lmkss     r!   r"   z_draw_mesh.<locals>.<listcomp>  s>    SSSuT!Q$Z00%QT
2C2CDSSSr#   rR  r   )rR  r8  )r   r   	fromarrayr   Drawpolygonr   asarrayr<  linerm   pointflattenrL   ellipse)r{  rz  r   ru  rZ  r\  rs  
draw_edgespildrawrr   r   nr   r   r6  r7  r  s                     @r!   rm  rm    sX    Q(5J  Z'
'zQ~~
/)
$
$C>#DSA 	_ 	_A^$D" _ _SSSSdSSSZ]^^^^_z# a a JqM 	c c c1q55QUUIId1a4j 1 15ad3D3DE %d1a4j 1 15ad3D3DEGMPXa  c c c??JJt||~~,,..SJ9999!^^ a a1eAhhlE!HHqL%((Q,aSTU\_````:c??r#   )r   r   r   r   r+   _MASK_REGIONS)rI  )r   F)r   F)r   F)r+   F_MASK_CUSTOM_FEATURESc                   N    e Zd ZdZed             Zedej        fd            ZdS )MediaPipeFaceMaskzBinary mask from face landmarks, filled polygon per face. One mask per
    frame in the batch; faces in the same frame composite (union).c                    t          j        dg ddddt                              d          t           j                            ddt           j                            d	g           t           j                            d
d t          D                       g          gt           j                                        g          S )Nr  )r   r   r   z	face maskr   r   rO  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-   rS  c           	      `    g | ]+\  }}t           j                            ||d | d          ,S )zInclude the 'z' region in the mask.rU  rV  )r   regr   s      r!   r"   z3MediaPipeFaceMask.define_schema.<locals>.<listcomp>  sY     : : : !-W J,,S'5_S5_5_5_ - a a: : :r#   rY  r  )	r	   r   r  r   r]  r^  r  Maskr   r   s    r!   r   zMediaPipeFaceMask.define_schema  s    y'sss5&;!''(899%% K..ub99..x : : 1F: : :   &   W^^%%&+
 
 
 	
r#   rp   c                    |d         d         }|dk    rfdt           D             }nt          t                    }fd|D             }|d         }|d         \  }}t          j        t          |          ||ft          j                  }	t          j        	                    t          |                    }
t          |          D ]\  }}|rxt          j        d	||fd
          }t          j        |          }|D ]2}|d         |D ]%}|                    fd|D             d           &3t          j        |          |	|<   |
                    |dz              t%          j        t)          j        |	                              t          j                                        t          j                                                                      d                    S )NrO   r  rS  c                 F    g | ]\  }}                     |d           |S rb  rc  )r   r  r   r  s      r!   r"   z-MediaPipeFaceMask.execute.<locals>.<listcomp>  s1    YYYfc1SRWAXAXYcYYYr#   c                 D    g | ]}t          |                   D ]}|S r&   )r   )r   r  r  rg  s      r!   r"   z-MediaPipeFaceMask.execute.<locals>.<listcomp>  s2    HHHsnT#Y.G.GHHHHHHr#   r   r;  ri  Lr   r   c                 l    g | ]0}t          |d f                   t          |df                   f1S r~  r5  r  s     r!   r"   z-MediaPipeFaceMask.execute.<locals>.<listcomp>  s?    %[%[%[QRuT!Q$Z'8'8%QT
:K:K&L%[%[%[r#   ru   r  r   rj  rs   )r  r  r  r   rk  r9   rz   rC   r   r=  r   r   newr   r  r  r  r&  r	   r   rG   rn  ry   rD   ro  rp  rq  )r   r  r  rr  pickedr   r   r?  r@  masksr-  r#  rB  r  r  r   r   r  rg  s     `              @@r!   r  zMediaPipeFaceMask.execute  s   /0i (??YYYY(=YYYFF-((FHHHHfHHH)l+1#f++q!,BH==={&&s6{{33&v.. 		) 		)MB	 ,iaVQ// ~c**" g gA^,D % g g%[%[%[%[VZ%[%[%[beffffgJsOOb	  a((((}U-e4477)==??(;;== 8 
 
 $u++  	r#   Nr  r&   r#   r!   r  r    sd        F F 
 
 [
2     [  r#   r  c                   L    e Zd Zedeeej                          fd            ZdS )MediaPipeFaceExtensionrp   c                 :   K   t           t          t          t          gS r%   )r   r  rM  r  )r\   s    r!   get_node_listz$MediaPipeFaceExtension.get_node_list  s      +-DF`bsttr#   N)	rh   ri   rj   r   r  typer	   	ComfyNoder  r&   r#   r!   r  r    sL        uT$r|*<%= u u u Xu u ur#   r  c                  "   K   t                      S r%   )r  r&   r#   r!   comfy_entrypointr    s      !###r#   r%   )=rk   r0   r   rG   PILr   r   r   	tqdm.autor   typing_extensionsr   comfy.model_managementrC   comfy.model_patchercomfy.utilsr   comfy_api.latestr   r	   &comfy_extras.mediapipe.face_landmarkerr
   $comfy_extras.mediapipe.face_geometryr   Customr   r  rP   rN   r   Tensorndarrayr|   rn   rK   rl   r   rU   r   rm   r   r  r   r   rI   r   r  r   r  r  rH  __annotations__rK  boolrM  rm  r  r  r  r  r  r&   r#   r!   <module>r     s  
 
 
      , , , , , , , , , ,       & & & & & &                 / / / / / / / / A A A A A A U U U U U U BI455 BI.// T`*i *i *i *i *i *i *i *iZ\5< \BJ \ \ \ \ 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` T` T` T` T`bl T` T` T`p *M>)L8)LV)L)L uS#X L L L
2 %c4i(#-. 
 
 
D D D D D D D DR FJ "* T #sC-(58,0cOd,BNPj   @ "ZuS#X Y Y Y7 uU39-s23   8 8 8 8 8 8 8 8vu u u u u^ u u u$ 6 $ $ $ $ $ $r#   