
    +j                     V   d dl Z d dlZd dlZd dlZd dlZd dlZd dlmZ d dl	m
Z
 d dlmZmZ d dlmZ d Zd Z G d d	          Z G d
 dej                  Z G d dej                  Zd Z G d dej                  Z G d dej                  Z G d de          ZdefdZdS )    N)tqdm)override)ComfyExtensionio)LotusConditioningc                 |   t          j        | t           j                  }t          j        |t           j                  }t          |          dk    r|d         |d         z   dz  }|d         dk    r(|d         dk    rt	          |d         |d                   nd}t          j        |d|d          }t          j        |d|          }t          j        g d	          }t          j        g d
          }|                                |                                }	}||         ||<   ||         |	|<   ||	}}||fS )a<  Insert neck keypoint and remap from MMPose to OpenPose ordering.

    Returns (kp, sc) where kp has shape (134, 2) and sc has shape (134,).
    Layout:
      0-17   body  (18 kp, OpenPose order)
      18-23  feet  (6 kp)
      24-91  face  (68 kp)
      92-112 right hand (21 kp)
      113-133 left hand (21 kp)
    dtype            333333?r   axis)r   r      
      	                  r            )r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   )nparrayfloat32lenmininsertcopy)
kp_rawsc_rawkpscneck
neck_score
mmpose_idxopenpose_idxtmp_kptmp_scs
             9/home/wildlama/comfy/ComfyUI/comfy_extras/nodes_sdpose.py_preprocess_keypointsr0      s'    
&
	+	+	+B	&
	+	+	+B
2ww"}}11"*,Q%#++"Q%#++SA1&&&1
Yr2t!,,,Yr2z**x W W WXX
x [ [ [\\BGGII!*~|!*~|Br6M    c                    d }g }t          t          |                     D ]0}g }t          | |         ||                   D ]\  }}	t          ||	          \  }
}t	          j        |
dd         |
ddg         gd          }t	          j        |dd         |ddg         gd          }|                     ||
dd         |dd                    ||
dd         |dd                    |||           ||
dd	         |dd	                    ||
d	d
         |d	d
                   d           |                    |||d           2|S )a  Convert raw keypoint lists to a list of OpenPose-style frame dicts.

    Each frame dict contains:
      canvas_width, canvas_height, people: list of person dicts with keys:
        pose_keypoints_2d       - 18 body kp  as flat [x,y,score,...] (absolute pixels)
        foot_keypoints_2d       -  6 foot kp  as flat [x,y,score,...] (absolute pixels)
        face_keypoints_2d       - 70 face kp  as flat [x,y,score,...] (absolute pixels)
                                   indices 0-67: 68 face landmarks
                                   index  68:    right eye (body[14])
                                   index  69:    left  eye (body[15])
        hand_right_keypoints_2d - 21 right-hand kp (absolute pixels)
        hand_left_keypoints_2d  - 21 left-hand  kp (absolute pixels)
    c                     t          j        | d d df         | d d df         |gd                                                                          S )Nr   r   r   )r   stackflattentolist)kp_slicesc_slices     r/   _flattenz%_to_openpose_frames.<locals>._flatten6   sN    x!!!Q$!!!Q$BKKKSSUU\\^^^r1      \   r   r   r   r      q      )pose_keypoints_2dfoot_keypoints_2dface_keypoints_2dhand_right_keypoints_2dhand_left_keypoints_2d)canvas_widthcanvas_heightpeople)ranger!   zipr0   r   concatenateappend)all_keypoints
all_scoresheightwidthr9   framesimg_idxrF   r%   r&   r'   r(   face_kpface_scs                 r/   _to_openpose_framesrS   (   s   _ _ _ F]++,, Z Z!-"8*W:MNN 	 	NFF*66::FBnbBiRH%>QGGGGnbBiRH%>QGGGGMM+38BqtH1R4+I+I+38Br"uI2b5	+J+J+38G+H+H+38Br#vJ2c6
+K+K+38Bs3wKCG+M+M      	uvQWXXYYYYMr1   c                       e Zd ZdZd Zed             Zedd            Zed             Zedd            Z		 	 ddZ
dS )KeypointDrawzP
    Pose keypoint drawing class that supports both numpy and cv2 backends.
    c                    	 dd l }|| _        n# t          $ r
 | | _        Y nw xY wddgddgddgddgddgddgddgdd	gdd
gd
dgddgddgddgddgddgddgddgddgddgddgg| _        ddgddgddgddgddgdd	gdd
gd
dgddgddgddgddgddgddgddgddgddgg| _        g dg dg dg dg dg dg dg dg dg dg d g d!g d"g d#g d$g d%g d&g d'g| _        d S )(Nr   r   r   r   r   r   r   r   r   r   r      r   r   r   r   r   r   r<         )   r   r   )rZ   U   r   )rZ      r   )rZ   rZ   r   )r\   rZ   r   )r[   rZ   r   )r   rZ   r   )r   rZ   r[   )r   rZ   r\   )r   rZ   rZ   )r   r\   rZ   )r   r[   rZ   r   r   rZ   )r[   r   rZ   )r\   r   rZ   )rZ   r   rZ   )rZ   r   r\   )rZ   r   r[   )cv2drawImportError
hand_edgesbody_limbSeqcolors)selfr^   s     r/   __init__zKeypointDraw.__init__P   s   	JJJDII 	 	 	DIII	
 FQFQFQFFQFQFQFFQGb"XBxGb"XBx"bGb"XBx"b
 FQFQFQFQFQFQFQGHq"gBx"bAq6Ar7RHGb"X
 KK}}}mmm]]]LL+++|||]]]MMMMM<<<lllMM===---	
s    ""c                    |\  }}| j         dd         \  }}t          t          j        |                    }	t	          d||	z
            t          |||	z   dz             }}
t	          d||	z
            t          |||	z   dz             }}||
k    s||k    rdS t          j        |
|||f         \  }}||z
  dz  ||z
  dz  z   |dz  k    }|| |
|||f         |<   dS )z7Draw a filled circle using NumPy vectorized operations.Nr   r   r   )shapeintr   ceilmaxr"   ogrid)	canvas_npcenterradiuscolorkwargscxcyhw
radius_inty_miny_maxx_minx_maxyxmasks                    r/   circlezKeypointDraw.circleo   s    Brr"1))
1b:o..ArJ7J0K0Ku1b:o..ArJ7J0K0KuE>>Ue^^FxeU5[011B{a"fq[(FAI549	%+uU{*+D111r1   r   c           	      0   g ||R \  }}}}	| j         dd         \  }
}t          ||z
            t          |	|z
            }}||k     rdnd||	k     rdnd}}||z
  ||g f\  }}}}	 |                    ||f           ||k    r||	k    rn'd|z  }|| k    r
||z
  ||z   }}||k     r
||z   ||z   }}K|dk    r|dz  dz   t          t	          j        |dz  dz                       }}|D ]\  }}t          d||z
            t          |
||z   dz             t          d||z
            t          |||z   dz             f\  }}}}||k    rH||k    rBt          j        ||||f         \  }}|| ||||f         ||z
  dz  ||z
  dz  z   |dz  k    <   dS t	          j	        |          }|dddf         dk    |dddf         |
k     z  |dddf         dk    z  |dddf         |k     z  }||         x} j
        r|| | dddf         | dddf         f<   dS dS )	z<Draw line using Bresenham's algorithm with NumPy operations.Nr   r   Tg       @      ?r   )rg   absrJ   rh   r   ri   rj   r"   rk   r   size)!rl   pt1pt2ro   	thicknessrp   x0y0x1y1rs   rt   dxdysxsyerrr{   rz   line_pointse2rn   ru   pxpyrv   rw   rx   ry   yyxxvalidvalid_pointss!                                    r/   linezKeypointDraw.line   s    $#BBrr"1R"Ws27||BBww!!BrBww!!BB!#b"b"!4Q;	*1v&&&Bww177SBRCxxr1r6QBwwr1r6Q	* q=="+c/S!8#bgySVZ]F]>^>^:_:_JF% j jB-0BO-D-Dc!RR\__`M`FaFacfghjloyjyczcz|  AB  DF  IS  DS  VW  DW  }X  }X  .X*ueU5==UU]]XeEk5;&>?FBdiIeEk5;67b1RRS|8SW]_`W`8`a	j j (;//K A&!+AAAqD0AA0EF+VWVWVWYZVZJ[_`J`aepqrqrqrtuquevyzez{E +E 228 JDI	,qqq!t,l111a4.@@AAAJ Jr1   c           	      P   t          |          dk     rdS t          j        |t          j                  }| j        dd         \  }}t          d|dddf                                                   t          ||dddf                                         dz             t          d|dddf                                                   t          ||dddf                                         dz             f\  }}}}	||k    s|	|k    rdS t          j        ||||	f         \  }
}t          j        ||z
  |	|z
  ft                    }t          t          |                    D ]}||         ||dz   t          |          z           }}|d         |d         }}||k    r<||k    r|||d         |d         f\  }}}}|
|k    |
|k     z  x}                                s{||||d         |
|z
  |d         |d         z
  z  ||z
  z  z   k    z  z  }|| ||||	f         |<   dS )z1Fill polygon using vectorized scanline algorithm.r   Nr	   r   r   r   )r!   r   r   int32rg   rj   r"   mgridzerosboolrG   any)rl   ptsro   rp   rs   rt   rv   rw   rx   ry   r   r   r|   ip1p2r   y2	edge_masks                      r/   fillConvexPolyzKeypointDraw.fillConvexPoly   s    s88a<<Fhs"(+++rr"1%(C1IMMOO%<%<c!SAY]]__WXEX>Y>Y[^_`befgfgfgijfjbkbobobqbq[r[rtwxy{~  @A  @A  @A  CD  @D  |E  |I  |I  |K  |K  NO  |O  uP  uP  &P"ueUE>>Ue^^F%+uU{23Bx6dCCCs3xx 		X 		XAVS!a%3s88!34BUBqEBRxxBww!#RA1!5BB"$(rBw!77I<<>> Ir!uRBqEBqEM/JbSUg/V'V!VWWDD49	%+uU{*+D111r1   c                    |d         dz   |d         dz   f}|dz  }||k    r||}}|dk     r|dz   |dz   }}|dk     |dk    r|dz
  |dz
  }}|dk    ||z
  dk    rd\  }}t          j        |          }t          j        |          t          j        |          }	}g }
t	          |||z   |          D ]}t          j        t          ||                    }|d         t          j        |          z  |d         t          j        |          z  }}|
                    t          t          | d         ||z  z   ||	z  z
                      t          t          | d         ||	z  z   ||z  z                       g           g t          d          t          d          f}}|
D ].}t          |          x}|k    r|                    |           |}/t          |          dk    r|n| d         | d         g| d         | d         ggS )z*Python implementation of cv2.ellipse2Poly.r   r   r   h  )r   r   inf)mathradianscossinrG   r"   rJ   rh   roundfloattupler!   )rm   axesangle	arc_startarc_enddeltarp   	angle_radalphabetar   r   	theta_radr{   rz   
unique_ptsprev_ptptpt_tuples                      r/   ellipse2PolyzKeypointDraw.ellipse2Poly   s>    Q#tAw}-w!()wI!mm!*S'C-wI !mmmm!(3	CYG mmY$$!'IwL''	hy))48I+>+>ty'E/599 	u 	uASG__55I7TXi000$q'DHY<O<O2OqAJJE&)a%i"7!d("BCCDDc%PVWXPY\]`d\dPdghkpgpPpJqJqFrFrstttt 5<<u">G
 	# 	#B!"II%'11!!"%%%" __q00zzq	6!97MPVWXPY[abc[dOe6ffr1   Nr   Tr   r   c                 X   |j         \  }}}|rt          |          dk    rt          | j                  D ]\  }}|d         dz
  |d         dz
  }}|dk    s|dk    r)|||         |k     s||         |k     rD||         d         ||         d         g}||         d         ||         d         g}|d         |d         z   dz  |d         |d         z   dz  }}t	          j        |d         |d         z
  dz  |d         |d         z
  dz  z             }|dk     rt	          j        t	          j        |d         |d         z
  |d         |d         z
                      }| j        	                    t          |          t          |          ft          |dz            |	ft          |          ddd          }| j                            ||| j        |t          | j                  z                      |rt          |          dk    rt          d          D ]}|||         |k     rt          ||         d                   t          ||         d                   }}d|cxk    r|k     rTn Wd|cxk    r|k     rDn g| j                            |||fd| j        |t          | j                  z           d	           |rt          |          d
k    rt          dd
          D ]}|||         |k     rt          ||         d                   t          ||         d                   }}d|cxk    r|k     rTn Wd|cxk    r|k     rDn g| j                            |||fd| j        |t          | j                  z           d	           |r`t          |          dk    rLd}t          | j                  D ]\  }}d|d         z   d|d         z   }}|||         |k     s||         |k     r7t          ||         d                   t          ||         d                   }}t          ||         d                   t          ||         d                   }!} ||k    r||k    r| |k    r|!|k    rd|cxk    r|k     rn d|cxk    r|k     rn d| cxk    r|k     rn d|!cxk    r|k     rn t!          j        |t%          t          | j                            z  dd          \  }"}#}$t          |"dz            t          |#dz            t          |$dz            f}%| j                            |||f| |!f|%d	           t          dd          D ]}|||         |k     rt          ||         d                   t          ||         d                   }}||k    rG||k    rAd|cxk    r|k     r4n cd|cxk    r|k     r$n s| j                            |||fddd	           |rst          |          dk    r_d}t          | j                  D ]\  }}d|d         z   d|d         z   }}|||         |k     s||         |k     r7t          ||         d                   t          ||         d                   }}t          ||         d                   t          ||         d                   }!} ||k    r||k    r| |k    r|!|k    rd|cxk    r|k     rn d|cxk    r|k     rn d| cxk    r|k     rn d|!cxk    r|k     rn t!          j        |t%          t          | j                            z  dd          \  }"}#}$t          |"dz            t          |#dz            t          |$dz            f}%| j                            |||f| |!f|%d	           t          dd          D ]}| |t          |          k     r||         |k     r$t          ||         d                   t          ||         d                   }}||k    rG||k    rAd|cxk    r|k     r4n vd|cxk    r|k     r$n | j                            |||fddd	           |rt          |          dk    rd}t          d
d          D ]}|||         |k     rt          ||         d                   t          ||         d                   }}||k    rG||k    rAd|cxk    r|k     r4n cd|cxk    r|k     r$n s| j                            |||f|
dd	           |S )a  
        Draw wholebody keypoints (134 keypoints after processing) in DWPose style.

        Expected keypoint format (after neck insertion and remapping):
        - Body: 0-17 (18 keypoints in OpenPose format, neck at index 1)
        - Foot: 18-23 (6 keypoints)
        - Face: 24-91 (68 landmarks)
        - Right hand: 92-112 (21 keypoints)
        - Left hand: 113-133 (21 keypoints)

        Args:
            canvas: The canvas to draw on (numpy array)
            keypoints: Array of keypoint coordinates
            scores: Optional confidence scores for each keypoint
            threshold: Minimum confidence threshold for drawing keypoints

        Returns:
            canvas: The canvas with keypoints drawn
        r<   r   r   Nr   r   r   r   )r   r:   r=   {Gz?r;         ?rZ   r]   r>   )rZ   rZ   rZ   )rg   r!   	enumeraterb   r   sqrtdegreesatan2r_   r   rh   r   rc   rG   r}   ra   colorsys
hsv_to_rgbr   r   )&rd   canvas	keypointsscores	threshold	draw_body	draw_feet	draw_face
draw_handsstick_widthface_point_sizeHWCr   limbidx1idx2YXmXmYlengthr   polygonr{   rz   epsieedger   r   x2r   rgbro   s&                                         r/   draw_wholebody_keypointsz%KeypointDraw.draw_wholebody_keypoints   s	   * ,1a  	]Y2--$T%677 ] ]4!!Wq[$q'A+d2::%d|i//6$<)3K3K t_Q'4);<t_Q'4);<A$1+*QqTAaD[A,=BAaD1Q4KA#51!8J#JKKA::TZ!qtQqTAaD[%I%IJJ)00#b''3r771Cc&ST*ooWbEcehineoeoqrtwyz{{	(($+a#dkJZJZFZ:[\\\\  	iY2--2YY i i%&)i*?*?9Q<?++S1a-A-A1::::A:::::!q****1*****I$$VaVQADKHXHXDX8Yeg$hhh  	iY2--2r]] i i%&)i*?*?9Q<?++S1a-A-A1::::A:::::!q****1*****I$$VaVQADKHXHXDX8Yeg$hhh  	S#i..C//C%do66 W WD$q'\2Q<d%d|i//6$<)3K3K Yt_Q/00#ioa6H2I2IBYt_Q/00#ioa6H2I2IB88SR#XX"s((B{{{{{{{{{qB{{{{{{{{{qB{{{{{{{{{qB{{{{QR{{{{{"*"5b5T_AUAU;V;V6VX[]`"a"a1a!$QWs1s7||SS\\ J	vBx"b5TUVVV 2s^^ S S%&)i*?*?9Q<?++S1a-A-A1s77q3ww1::::A:::::!q****1*****I$$VaVQr$RRR  	S#i..C//C%do66 W WD 47]C$q'Md%d|i//6$<)3K3K Yt_Q/00#ioa6H2I2IBYt_Q/00#ioa6H2I2IB88SR#XX"s((B{{{{{{{{{qB{{{{{{{{{qB{{{{{{{{{qB{{{{QR{{{{{"*"5b5T_AUAU;V;V6VX[]`"a"a1a!$QWs1s7||SS\\ J	vBx"b5TUVVV 3__ S S%!c&kk//fQi)>S>S9Q<?++S1a-A-A1s77q3ww1::::A:::::!q****1*****I$$VaVQr$RRR  	eY2--C2r]] e e%&)i*?*?9Q<?++S1a-A-A1s77q3ww1::::A:::::!q****1*****I$$VaV_oac$dddr1   )r   )Nr   TTTTr   r   )__name__
__module____qualname____doc__re   staticmethodr}   r   r   r   r    r1   r/   rU   rU   L   s         
 
 
> : : \:" J J J \J> : : \:2 g g g \g: RU BCD D D D D Dr1   rU   c                   J    e Zd Zed             Zedej        fd            ZdS )SDPoseDrawKeypointsc                    t          j        dddg dt          j        d                              d          t           j                            dd	          t           j                            d
d	          t           j                            dd	          t           j                            dd	          t           j                            ddddd          t           j                            ddddd          t           j                            ddddd          gt           j                                        g          S )Nr   zSDPose Draw Keypointsimage/detection)openposepose detectionpreprocessorr   posePOSE_KEYPOINTr   r   T)defaultr   r   r   Fr   r   r   r   r   r"   rj   stepr   r   score_thresholdr   g        r   r   node_iddisplay_namecategorysearch_aliasesinputsoutputs)	r   SchemaCustomInputBooleanIntFloatImageOutputclss    r/   define_schemaz!SDPoseDrawKeypoints.define_schema`  s   y)0&^^^	/**00==
  d ;;
  t <<
  d ;;
  e <<]A1"1MM.qbqQQ0#3CVZ[[	 !!
 
 
 	
r1   returnc	                    |s2t          j        t          j        dt          j                            S |d         d         }	|d         d         }
d }d }g }t                      }t          |d	          D ]4}t          j        |	|
d
ft          j                  }|d         D ]} ||d         d          \  }}|	                    d          }|r ||d          n
 |d          \  }} ||d         d          \  }}|d d         |d d         }} ||d         d          \  }} ||d         d          \  }}t          j
        |||||gd          }t          j
        |||||gd          }|                    ||||||||||
  
        }|                    |           6t          |          dk    rt          j        |          nt          j        |d         d          }t          j        |                              t$          j                                        t$          j                                                  dz  } t          j        |           S )N)r   @   r  r   r	   r   rE   rD   c                     t          j        | t           j                                      |d          }|d d d df         |d d df         fS )Nr	   r   r   )r   r   r    reshape)flatnarrs      r/   _parsez+SDPoseDrawKeypoints.execute.<locals>._parse}  sO    (4rz222::1a@@Cqqq"1"u:s111a4y((r1   c                     t          j        | dft           j                  t          j        | t           j                  fS )Nr   r	   )r   r   r    )r  s    r/   _zerosz+SDPoseDrawKeypoints.execute.<locals>._zeros  s3    8QF"*555rx7T7T7TTTr1   zDrawing keypoints on framesdescr   rF   r?   r<   r@   r   rA   F   D   rB      rC   r   )r   r   r   r   r   r   r   r   )devicer
   g     o@)r   
NodeOutputtorchr   r    rU   r   r   uint8getrI   r   rJ   r!   r4   expand_dims
from_numpytocomfymodel_managementintermediate_deviceintermediate_dtype)!r  r   r   r   r   r   r   r   r   rM   rN   r  r  pose_outputsdrawerframer   personbody_kpbody_scfoot_rawfoot_kpfoot_scrQ   rR   rhand_kprhand_sclhand_kplhand_scr'   r(   pose_outputs_npfinal_pose_outputs!                                    r/   executezSDPoseDrawKeypoints.executev  s    	S=^5=!Q!Q!QRRR1o.1n-	) 	) 	)	U 	U 	U )*GHHH 	( 	(EXvua0AAAF/  %+VF3F,Gr%R%R!'!::&9::<D%SVVHa%8%8%8&&QR))!'%+VF3F,Gr%R%R!'%,SbS\73B3<'%+VF3L,Mr%R%R"(%+VF3K,Lr%R%R"(^Wgw($SZ[\\\^Wgw($SZ[\\\88B-'9'J +_ 9   ''''474E4E4I4I"(<000r~^jkl^mopOqOq!,_==@@)==??(;;== A ? ?AFG }.///r1   Nr   r   r   classmethodr  r   r  r4  r   r1   r/   r   r   _  s`        
 
 [
* +0  @B  @M +0 +0 +0 [+0 +0 +0r1   r   c                   L    e Zd Zed             Zeddej        fd            ZdS )SDPoseKeypointExtractorc                    t          j        dddg ddt           j                            d          t           j                            d          t           j                            d          t           j                            d	d
ddd          t           j                            dddd          gt          j        d          	                    dd          g          S )Nr8  zSDPose Keypoint Extractorr   )r   r   r   r   sdposezxExtract pose keypoints from images using the SDPose model: https://huggingface.co/Comfy-Org/SDPose/tree/main/checkpointsmodelvaeimage
batch_sizer   r   i'  r   bboxesTzZOptional bounding boxes for more accurate detections. Required for multi-person detection.)optionalforce_inputtooltipr   r   zHKeypoints in OpenPose frame format (canvas_width, canvas_height, people)rB  r   r   r   r   descriptionr   r   )
r   r   Modelr   Vaer  r  BoundingBoxr   r  r  s    r/   r  z%SDPoseKeypointExtractor.define_schema  s    y-4&``` Sw''U##w''\21%aPP$$X$  Yu$  v  v 	/**11+  HR1  S  S
 
 
 	
r1   Nr	  c           
      R	  )*+,-. |j         d         |j         d         }}t                                                      j        d         *)fd}|                                ,dd|gii,j        d<   t          |j        j        d          st          d	          |j        j        j
        +|j         d         }	d )t          +j        d                   d
z  .t          +j        d                   d
z  --.fd}
dd})*+,fd}g }g }t          j                            |	          }|t!          |t"                    s|gg}nt%          |          dk    rd g|	z  }t'          t)          |	          d          D ]1}|||dz            }|r&|t+          |t%          |          dz
                     nd }g }g }|r>|D ]9}t-          dt          |d                             }t-          dt          |d                             }t+          |t          |d         |d         z                       }t+          |t          |d         |d         z                       }||k    s||k    r|d d ||||d d f         } |
|          \  }}}|                    |          } ||          \  }}  ||d         ||||          }!|                    |!           |                    | d                    ;ns |
|          \  }"}}|                    |"          }# ||#          \  }} |                     ||d         ||                     |                    | d                    |                    |           |                    |           |                    d           3nt'          t)          d|	|          d          D ]}$ |
||$|$|z                      \  }%}}|                    |%          }& ||&          \  }} t5          ||           D ]<\  }!}'|                     ||!||          g           |                    |'g           =|                    t%          |                     t7          ||||          }(t9          j        |(          S )Nr   c                 V    | j         d         dk    r|                                 | |fS )Nr   i  )rg   clone)rs   hsptransformer_optionscaptured_feats      r/   output_patchz5SDPoseKeypointExtractor.execute.<locals>.output_patch  s*    wqzS   !		c6Mr1   patchesoutput_block_patchrO  heatmap_headzThe provided model does not have a heatmap_head. Please use SDPose model from here https://huggingface.co/Comfy-Org/SDPose/tree/main/checkpoints.r   r   c                 6   | j         d         | j         d         }}|k    r|k    rdnd}|                     dddd                                          }t          j                            ||d	
          }|                    dddd          |z  |z  fS )zPStretch BHWC images to (model_h, model_w), model expects no aspect preservation.rJ  rK  areabilinearr   r   r   r   disabledupscale_methodcrop)rg   permuter   r!  utilscommon_upscale)imgsrs   rt   methodchwscaledmodel_hmodel_ws         r/   _resize_to_modelz9SDPoseKeypointExtractor.execute.<locals>._resize_to_model  s    :b>4:b>qA '1AVVJF,,q!Q**0022C[//WgV\cm/nnF>>!Q1--w{GaKGGr1   c                    t          | t          j                  r|                                 nt          j        | t          j                  } | d         dk     }| d         |z  |z   | d<   | d         |z  |z   | d<   d| |<   | S )z>Remap keypoints from model space back to original image space.r	   ).r   r   ).r   r   )
isinstancer   ndarrayr$   r   r    )r'   scale_xscale_yoffset_xoffset_yinvalids         r/   _remap_keypointsz9SDPoseKeypointExtractor.execute.<locals>._remap_keypoints  s    (RZ88\bhrQSQ[>\>\>\Bj1nGFg-8BvJFg-8BvJBwKIr1   c                     dt           j                            t          j        |           dddd| dd          }           S )zLRun one forward pass and return (keypoints_list, scores_list) for the batch.Nr   r   eulersimpleT)
noisestepscfgsampler_name	schedulerpositivenegativelatent_imagedisable_noisedisable_pbar)r!  sampler  
zeros_like)latent_batch_rP  contextheadmodel_clones     r/   _run_on_latentz7SDPoseKeypointExtractor.execute.<locals>._run_on_latent  s_     !M##&|44S$ 7)D $  A 4&&&r1   zExtracting keypoints from cropsr  r{   rz   rN   rM   zExtracting keypoints)r   r   )rg   r   r4  resultrM  model_optionshasattrr;  diffusion_model
ValueErrorrT  rh   heatmap_sizer!  r]  ProgressBarrg  listr!   r   rG   r"   rj   encoderJ   updaterH   rS   r   r  )/r  r;  r<  r=  r>  r?  rM   rN   rQ  total_imagesre  rn  r  rK   rL   pbarrP   img
img_bboxesimg_keypoints
img_scoresbboxr   r   r   r   r[  crop_resizedr   r   latent_cropkp_batchsc_batchr'   img_resized
latent_imgbatch_startbatch_resizedr~  r(   openpose_framesrP  r  r  r  rc  rd  s/                                            @@@@@@r/   r4  zSDPoseKeypointExtractor.execute  sX    BR#%%--//6q9	 	 	 	 	 kkmm<EH\_k^lGm;n!"78u{2NCC 	r  q  r  r  r{*7{1~d'*++a/d'*++a/	H 	H 	H 	H 	H 	H	 	 	 		' 	' 	' 	' 	' 	' 	' 	'" 
{&&|44fd++ /!(V!!,.l 3 3:[\\\ # #GGaK/0FLVVCVq$A$ABBRV
 "
 3 * 7 7 CS	NN33 CS	NN33 T#Yg-F)G)GHH T#Yh-G)H)HII88rRxx$"111beRUAAA#56/?/?/E/E,b"&)jj&>&>-;^K-H-H*(--hqk2r2rJJ%,,R000"))(1+6666!7$ +;*:3*?*?'KR!$K!8!8J)7
)C)C&Hh!(()9)9(1+r2)N)NOOO%%hqk222$$]333!!*---AG#L  $E!\:$F$FMcddd 	+ 	+(8(8{;YcKc?c9d(e(e%r2"zz-88%3^L%A%A"(!(H55 , ,FB!((*:*:2r2*F*F)GHHH%%rd++++CMM****-mZQVWW}_---r1   Nr5  r   r1   r/   r8  r8    sc        
 
 [
& w. w.BM w. w. w. [w. w. w.r1   r8  c                    |\  }}|                                  dd          ||fz  }t          j        |d          \  }}t          j        |d          \  }}	||z
  }
|	|z
  }|
dk    s|dk    rg dS |
|z  }||z  }t          j        ||
|z  z            }t          j        |||
z  z            }||
z
  dz  }||z
  dz  }t          ||z
  d          }t          ||z   |          }t          |d|z  z
  d          }t          |	|z   |          }t          |          t          |          t          |          t          |          gS )Nr   r   r   )r   r   r   r   r   r   r   )r$   r   r"   rj   r   rh   )kp2dsscaleimage_shapers   rt   
kp2ds_facemin_xmin_ymax_xmax_yinitial_widthinitial_heightinitial_areaexpanded_area	new_width
new_heightdelta_widthdelta_heightexpanded_min_xexpanded_max_xexpanded_min_yexpanded_max_ys                         r/   get_face_bboxesr  4  ss   DAqabb!QF*J6*1---LE56*1---LE5EMMU]N^q00|| >1L 5(M)GHIII.=*HIJJJ},1K/14L,a00N,a00N\!11155N-q11N^!4!4c.6I6I3~K^K^__r1   c                   J    e Zd Zed             Zedej        fd            ZdS )SDPoseFaceBBoxesc                 P   t          j        dddg dt          j        d                              d          t           j                            ddd	d
dd          t           j                            ddd          gt           j                            dd          g          S )Nr  zSDPose Face Bounding Boxesr   )z	face bboxzface bounding boxr   r   r   r   r  g      ?r   g      $@皙?z?Multiplier for the bounding box area around each detected face.r   r"   rj   r   rB  force_squareTzAExpand the shorter bbox axis so the crop region is always square.)r   rB  r?  zTFace bounding boxes per frame, compatible with SDPoseKeypointExtractor bboxes input.rC  r   )r   r   r   r   r  r  rH  r  r  s    r/   r  zSDPoseFaceBBoxes.define_schemaT  s    y&5&RRR	/**00==w$S  [\  ]  ]
    HK   L  L %%h  9O%  P  P
 
 
 	
r1   r	  c           	         g }|D ]}|d         }|d         }g }|d         D ]}	|	                     dg           }
|
st          j        |
t          j                                      dd          }|d d d df         }|t          j        ||gt          j                  z  }t          j        t          j        d	t          j                  |g          }t          ||||f          \  }}}}||k    r||k    r|r||z
  ||z
  }}||k    rt          ||          }||z   dz  ||z   dz  }}|dz  }t          d
||z
            }t          d
||z
            }t          |||z             }t          |||z             }t          d
||z
            }t          d
||z
            }|
                    ||||z
  ||z
  d           |
                    |           t          j        |          S )NrE   rD   rF   rA   r	   r   r   r   )r   r   r   )r{   rz   rN   rM   )r  r   r   r    r  vstackr   r  rj   r"   rJ   r   r  )r  r   r  r  
all_bboxesr'  rs   rt   frame_bboxesr(  	face_flatface_arrface_xykp_norm	kp_paddedr   r   r   r   bwbhsiderq   rr   halfs                            r/   r4  zSDPoseFaceBBoxes.executee  s&   
  	,  	,Eo&An%AL/ a a"JJ':B??	  8IRZ@@@HHQOO#AAArrE?!BHaV2:$F$F$FFIrxbj'I'I'I7&STT	!0EAq6!J!JBB77rBww# 3!#b"r'B88#&r2;;D&(2g!^b2g!^B#'19D!$QT	!2!2B!$QT	!2!2B!$QT	!2!2B!$QT	!2!2B!$QT	!2!2B!$QT	!2!2B ''brBGWY\^W^(_(_```l++++}Z(((r1   Nr5  r   r1   r/   r  r  R  sV        
 
 [
  $) $) $) $) [$) $) $)r1   r  c                   L    e Zd Zed             Zeddej        fd            ZdS )CropByBBoxesc                    t          j        dddg ddt           j                            d          t           j                            dd	          t           j                            d
ddddd          t           j                            dddddd          t           j                            dddddd          t           j                            dddgdd          gt           j                            d          g          S ) Nr  zCrop By Bounding Boxeszimage/transform)r[  z	face cropz	bbox cropr   zbounding boxzTCrop and resize regions from the input image batch based on provided bounding boxes.r=  r?  T)rA  output_widthi   r  i   r   zWidth each crop is resized to.r  output_heightzHeight each crop is resized to.paddingr   i   r   zGExtra padding in pixels added on each side of the bbox before cropping.keep_aspectstretchpadzfWhether to stretch the crop to fit the output size, or pad with black pixels to preserve aspect ratio.)optionsr   rB  z,All crops stacked into a single image batch.rC  rD  )r   r   r  r   rH  r  Combor  r  s    r/   r  zCropByBBoxes.define_schema  s	   y"1&UUUnw''$$X4$@@^crtRS]}~~_crtRS]~Yqd  U^  _  _}y%6HR[  fN  O  O (VWW
 
 
 	
r1   r  r	  c                 T   |j         d         }|j         d         }|j         d         }	|j         d         }
t          |t                    s|gg}n't          |          dk    rt	          j        |          S g }t          |          D ]K}|t          |t          |          dz
                     }|s,||                             ddd          	                    d          }t          d |D                       }t          d |D                       }t          d |D                       }t          d |D                       }|dk    rLt          d||z
            }t          d||z
            }t          |	||z             }t          |||z             }t          d|          t          |	|          }}t          d|          t          ||          }}||k    s||k    rt          t          ||	          d	z            }t          d|	|z
  dz            }t          dt          |d
z                      }t          |	||z             }t          |||z             }||k    s||k    r9|                    t          j        d|
|||j        |j                             ||||f\  }}}}|d d d d ||||f         }|dk    r||z
  ||z
  }}t          ||z  ||z            }t          t#          ||z                      }t          t#          ||z                      }t$          j                            |||dd          }||z
  dz  }||z
  dz  } t          j        d|
|||j        |j                  }!||!d d d d | | |z   |||z   f<   n$t$          j                            |||dd          }!|                    |!           M|st	          j        |          S t          j        |d                              dddd          }"t	          j        |"          S )Nr   r   r   r   c              3   @   K   | ]}t          |d                    V  dS )r{   Nrh   .0r   s     r/   	<genexpr>z'CropByBBoxes.execute.<locals>.<genexpr>  ,      77QS3[[777777r1   c              3   @   K   | ]}t          |d                    V  dS )rz   Nr  r  s     r/   r  z'CropByBBoxes.execute.<locals>.<genexpr>  r  r1   c              3   R   K   | ]"}t          |d          |d         z             V  #dS )r{   rN   Nr  r  s     r/   r  z'CropByBBoxes.execute.<locals>.<genexpr>  s7      EE1S3!G*,--EEEEEEr1   c              3   R   K   | ]"}t          |d          |d         z             V  #dS )rz   rM   Nr  r  s     r/   r  z'CropByBBoxes.execute.<locals>.<genexpr>  s7      EE1S3!H+-..EEEEEEr1   r   r  )r
   r  r  rV  rX  rY  )dim)rg   rg  r  r!   r   r  rG   r"   r\  	unsqueezerj   rh   rJ   r  r   r
   r  r   r!  r]  r^  cat)#r  r=  r?  r  r  r  r  total_framesimg_himg_wnum_chcrops	frame_idxr  	frame_chwr   r   r   r   fallback_sizefb_x1fb_y1fb_x2fb_y2crop_chwcrop_hcrop_wr  scaled_wscaled_hrb  pad_leftpad_topresized
out_imagess#                                      r/   r4  zCropByBBoxes.execute  sk   {1~AAQ&$'' 	(hZFF[[A='''|,, 0	" 0	"I!#iVq"A"ABL i(00Aq99CCAFFI 77,77777B77,77777BEEEEEEEBEEEEEEEB{{BL))BL))W--W--BZZUBBBZZUBB Rxx288 #Cu$5$5$; < <A 5!;<<As53;//00E5=#899E5=#899E>>Ue^^LLQ|[`[foto{!|!|!|}}}!&ue!;BB AAAr"ube!34He##!#b"r'L61=63IJJuVe^4455uVe^445533Hhagnx3yy(H4:)H4:+aTYT_hmhtuuuZ`111gg&88(8hCV:VVWW+44X|]kq  yC4  D  DLL!!!! 	(='''Yu!,,,44Q1a@@
}Z(((r1   N)r  r5  r   r1   r/   r  r    se        
 
 [
( C) C)dfdq C) C) C) [C) C) C)r1   r  c                   L    e Zd Zedeeej                          fd            ZdS )SDPoseExtensionr	  c                 :   K   t           t          t          t          gS r  )r8  r   r  r  )rd   s    r/   get_node_listzSDPoseExtension.get_node_list  s       $	
 	
r1   N)	r   r   r   r   r  typer   	ComfyNoder  r   r1   r/   r  r    sE        
T$r|*<%= 
 
 
 X
 
 
r1   r  r	  c                  "   K   t                      S r  )r  r   r1   r/   comfy_entrypointr    s      r1   )r  comfy.utilsr!  comfy.model_managementnumpyr   r   r   r   typing_extensionsr   comfy_api.latestr   r   comfy_extras.nodes_lotusr   r0   rS   rU   r  r   r8  r  r  r  r  r  r   r1   r/   <module>r     s                        & & & & & & / / / / / / / / 6 6 6 6 6 6  6! ! !HQ Q Q Q Q Q Q QfC0 C0 C0 C0 C0", C0 C0 C0JM. M. M. M. M.bl M. M. M.`` ` `<8) 8) 8) 8) 8)r| 8) 8) 8)vZ) Z) Z) Z) Z)2< Z) Z) Z)z
 
 
 
 
n 
 
 
      r1   