
    
3j&                    r   S SK r S SKJs  Jr  S SKJr  S SKJrJ	r	J
r
Jr  S SKrS SKrS SKJr  S SKrS SKJr  S SKrS SKJr  S SKJr  S SKJr  S S	KJr  S SKrS
SKJrJr  \R@                  RC                  \R@                  RC                  \R@                  RE                  \#5      5      5      r$\RJ                  " 5       r&\RN                  " 5       r( " S S5      r) " S S5      r* " S S5      r+ " S S5      r, " S S5      r- " S S5      r. " S S5      r/ " S S5      r0 " S S5      r1 " S S5      r2 " S  S!5      r3 " S" S#5      r4 " S$ S%5      r5 " S& S'5      r6 " S( S)5      r7 " S* S+5      r8 " S, S-5      r9 " S. S/5      r: " S0 S15      r;S2 r< " S3 S45      r= " S5 S65      r> " S7 S85      r? " S9 S:5      r@g);    N)
functional)Image	ImageDrawImageFilter	ImageFont)nullcontext)tqdm)model_management)ProgressBar)common_upscaleMAX_RESOLUTION   )
tensor2pil
pil2tensorc                   H    \ rS rSrS r\S 5       rSrSrSr	Sr
SrSS
 jrSrg	)BatchCLIPSeg   c                     g N selfs    M/home/wildlama/comfy/ComfyUI/custom_nodes/ComfyUI-KJNodes/nodes/mask_nodes.py__init__BatchCLIPSeg.__init__           c           
          SSSS04SSSSS	S
.4SSS04SSS04SSS04S.SSSSSS
.4SSSS 04SSSSSS
.4SSS04S.S.$ )NIMAGESTRING	multilineFFLOAT      ?              $@MbP?defaultminmaxstepBOOLEANr*   T)imagestext	thresholdbinary_maskcombine_maskuse_cuda      Y@皙?CLIPSEGMODELMASK      ?{Gz?)
blur_sigma	opt_model	prev_maskimage_bg_levelinvertrequiredoptionalr   ss    r   INPUT_TYPESBatchCLIPSeg.INPUT_TYPES   s    
 #-!)K+? @&-3cRV`e/f%g(1It3D'E)2Y4F(G%.D0A$B (/CTYcf0g&h%7&,y$.?%@+2CX[ei4j*k#,y%.@"A 	r   KJNodes/masking)r9   r!   )Maskr   segment_imagez5
Segments an image or batch of images using CLIPSeg.
Nc                 P   SSK JnJn  SS KJn  [
        R                  " 5       n[
        R                  " 5       nU(       d  [        R                  " S5      n[
        R                  " 5       nUc  [        R                  R                  [        R                  SS5      n[!        U S5      (       dI   [        R                  R#                  U5      (       d  SSKJn  U" SUS	S
9  UR)                  U5      U l        UR)                  U5      nOUS   U l        US   nU R*                  R/                  U5      R/                  U5        UR0                  u  nnnnUR/                  U5      nU[        R2                  :g  =(       a    [
        R4                  " U5      (       + nU(       a)  [        R6                  " [
        R8                  " U5      US9O	[;        5          U Vs/ s Hy  n[<        R>                  " [@        RB                  " SURE                  5       RG                  5       RI                  5       -  SS5      RK                  [@        RL                  5      5      PM{     nnU/[O        U5      -  nU" UUSS9nU H  nUU   R/                  U5      UU'   M     U R*                  " S0 UD6nS S S 5        [        RP                  " WRR                  5      n U U RU                  5       -
  U RW                  5       U RU                  5       -
  -  n [        RX                  " U U:  U [        RZ                  " S[        R\                  S95      n [O        U R0                  5      S:X  a  U R_                  S5      n [`        Rb                  " U R_                  S5      UU4SS9n U RI                  S5      n U R*                  R/                  U5        U(       a  U S:  R]                  5       n US:  a5  [e        S[e        U5      -  S-   5      n!URg                  U!U!4Xw4S9n"U"" U 5      n U(       aC  [        RV                  " U SS9S   n U R_                  S5      Ri                  [O        U5      SS5      n A[
        Rj                  " 5         U	bk  U	R0                  U R0                  :w  a'  [`        Rb                  " U	R_                  S5      UU4SS9n	U U	R/                  U5      -   n [        Rl                  " U SSS9  U
(       a  SU -
  n UU R_                  S5      -  SU R_                  S5      -
  U-  -   n#[        Rl                  " U#SSS9RE                  5       R]                  5       n#U RE                  5       R]                  5       n U U#4$ ! [,         a    SnUR)                  U5      U l         GNf = fs  snf ! , (       d  f       GN= f)Nr   CLIPSegProcessorCLIPSegForImageSegmentationcpuclip_segzclipseg-rd64-refined-fp16modelsnapshot_downloadKijai/clipseg-rd64-refined-fp16Frepo_id	local_dirlocal_dir_use_symlinksCIDAS/clipseg-rd64-refined	processordtype     o@   pt)r0   r/   return_tensorsr      nearestsizemode   )kernel_sizesigmadimr&   r:   r+   r,   r   )7transformersrM   rN   torchvision.transforms
transformsr
   unet_offload_deviceget_torch_devicetorchdevice
unet_dtypeospathjoinfolder_paths
models_dirhasattrexistshuggingface_hubrS   from_pretrainedrQ   	Exceptiontoshapefloat32is_device_mpsautocastget_autocast_devicer   r   	fromarraynpcliprO   numpysqueezeastypeuint8lensigmoidlogitsr+   r,   wheretensorfloat	unsqueezeFinterpolateintGaussianBlurrepeatsoft_empty_cacheclamp)$r   r/   r0   r1   r2   r3   r4   r<   r=   r>   r@   r?   rM   rN   ro   offload_devicers   r\   checkpoint_pathrS   rZ   BHWCautocast_conditionimage
PIL_imagesprompt	input_prckeyoutputsmask_tensorrg   blurimage_tensors$                                       r   rJ   BatchCLIPSeg.segment_image<   s   N3)==?!224\\%(F ++- ggll<+B+B:OjkO4))^77>>/::E)2S_n  HM  N!<!L!L_!]DJ )88II #7+DJ!+.I

e'\\
1a6"#u}}4d>N>\>\]c>d:dZlU^^,@@HPUVr}r @F  H  @Fv{%//"''$9J9J9L9T9T9V2VXY[^*_*f*fgigogo*pq  @FJ  HVc&k)F!vjQUVI !*3!2!26!:	# !jj-9-G @ mmGNN3"[__%66;??;L{O`;`akk+";[%,,WX`e`k`kJlm{  !Q&%//2KmmK$9$9!$<Aq6PYZ!))!,

n%&?113K>a#j/1A56K**[7QZdYq*rD{+K))KQ7:K%//299#f+aJK))+ +"3"33MM)*=*=a*@1vT]^	%	V(<<KKK#6k/K 5 5b 99QAVAVWYAZ=Z^l<ll{{<ScBFFHNNP!oo'--/L))A ! ^&BO!<!L!L_!]DJ^" H @s3   /AU( VB VAV("VVV
V%rQ   )r&   NNFr%   __name__
__module____qualname____firstlineno__r   classmethodrF   CATEGORYRETURN_TYPESRETURN_NAMESFUNCTIONDESCRIPTIONrJ   __static_attributes__r   r   r   r   r      s>      * !H&L&LHKQ*r   r   c                   D    \ rS rSrS r\S 5       rSrSrSr	Sr
SrS	 rS
rg)DownloadAndLoadCLIPSeg   c                     g r   r   r   s    r   r   DownloadAndLoadCLIPSeg.__init__   r   r   c                     SSSS/400$ )NrB   rQ   rT   rY   r   rD   s    r   rF   "DownloadAndLoadCLIPSeg.INPUT_TYPES   s)     94 	r   rH   r7   )clipseg_modelrJ   zV
Downloads and loads CLIPSeg model with huggingface_hub,  
to ComfyUI/models/clip_seg
c                    SSK JnJn  [        R                  R                  [        R                  S[        R                  R                  U5      5      n[        U S5      (       dG  [        R                  R                  U5      (       d  SSKJn  U" XSS9  UR                  U5      U l        UR                  U5      n0 nU R                  US'   XgS'   U4$ )	Nr   rL   rP   rQ   rR   FrU   rZ   )rm   rM   rN   ru   rv   rw   rx   ry   basenamerz   r{   r|   rS   r}   rQ   )r   rQ   rM   rN   r   rS   rZ   r   s           r   rJ   $DownloadAndLoadCLIPSeg.segment_image   s    N'',,|'>'>z277K[K[\aKbctW%%77>>/22=!%chi4DD_UDJ$44_E	!%g%.k"~r   r   Nr   r   r   r   r   r      s=     
 
 !H$L%LHK
r   r   c                   :    \ rS rSrSrSrSrSr\S 5       r	S r
Srg	)
CreateTextMask   r!   r9   createtextmaskzKJNodes/textz
Creates a text image and mask.  
Looks for fonts from this folder:  
ComfyUI/custom_nodes/ComfyUI-KJNodes/fonts
  
If start_rotation and/or end_rotation are different values,  
creates animation between them.
c                     SSSS04SSSSSS.4SS	S	SSS.4SS	S	SSS.4SS
SSSS.4SSS04SSSS.4[         R                  " S5      4SSSSSS.4SSSSSS.4SS	S	SSS.4SS	SSSS.4S.0$ )NrB   r.   r*   FINTra      r)   r          r"   whitezHELLO!Tr*   r#   kjnodes_fonts      ig  i)r@   framestext_xtext_y	font_size
font_colorr0   fontwidthheightstart_rotationend_rotation)rx   get_filename_listrD   s    r   rF   CreateTextMask.INPUT_TYPES   s     %	5'9:!q$PQ#RS!q$PQ#RS!q$PQ#RS$"AdTU&VW (9g*>?"t$LM&88IL cDRS"TU!s"TST#UV$)q#WX+Y#Z"'Qd3XY)Z![
 	r   c           
      *   Un/ n/ nUnX:w  a
  X-
  US-
  -  n[         R                  " SU
5      n[        U5       GH,  n[        R                  " SX#4S5      n[
        R                  " U5      n[        R                  " UU5      n
UR                  S5      n/ nU H  nUR                  5       S:X  a  UR                  S5        M*  UR                  5       n/ nU Hy  nU(       a  SR                  UU/-   5      nOUn U
R                  U5      S   nUUSU-  -
  ::  a  UR                  U5        MV  UR                  SR                  U5      5        U/nM{     U(       d  M  UR                  SR                  U5      5        M     UnU HA  nU
R!                  U5      n Un!UU S-  -   n"UU!S-  -   n# UR#                  UU4UXS
/S9  UU!-  nMC     X:w  a  UR%                  UW"W#4S9nUW-  n[&        R(                  " U5      R+                  [&        R,                  5      S-  n[.        R0                  " U5      S   nUS S 2S S 2S S 2S	4   n$UR                  U$5        UR                  U5        GM/     U(       a0  S[.        R2                  " US	S9-
  S[.        R2                  " US	S9-
  4$ [.        R2                  " US	S9[.        R2                  " US	S94$ ! [         a    U
R                  U5      S	   n GNf = f! [         a    UR#                  UU4UXS9   GNPf = f)Nra   r   RGBblack
  r   r   z-liga)r   fillfeatures)r   r   )centerr]   r   r:   ri   )rx   get_full_pathranger   newr   Drawr   truetypesplitstripappendrw   getbboxr~   getsize	getlengthr0   rotater   arrayr   r   rr   
from_numpycat)%r   r   r   r   r@   r   r   r0   r   r   r   r   r   
batch_sizeoutmasksrotationrotation_increment	font_pathir   draw
text_lineslines	text_linewordscurrent_lineword	test_linetest_line_widthy_offsetline
text_widthtext_heighttext_center_xtext_center_ymasks%                                        r   r   CreateTextMask.createtextmask   s   
!)"."?JQRN!S ..E	z"AIIee_g>E>>%(D%%i;D D)JE'	??$*LL$!)!!D#$'HH\TF-B$C	$(	E*.,,y*A!*D '%!f**<<$++D1SXXl%;<(,v "  <LL,!78- (2 H!^^D1
' &a 7 (;? :TIIvx0$T^e]fIg K'  -X}m6TU..HHUO**2::6>E$$U+E2EAq!$DLLJJuk #n %))CQ//uyyA7N1NPP		#1%eii1&=??G % E*.,,y*A!*DE& ! TIIvx0$TISTs$   :K,K1K.	-K.	1LLr   N)r   r   r   r   r   r   r   r   r   rF   r   r   r   r   r   r   r      s3    %LHHK  $D@r   r   c                   :    \ rS rSrSrSrSrSr\S 5       r	S r
Srg	)
ColorToMaski"  r9   r   rH   z
Converts chosen RGB value to a mask.  
With batch inputs, the **per_batch**  
controls the number of images processed at once.
c                 h    SSSSS04SSSSS	S
.4SSSSS	S
.4SSSSS	S
.4SSSSS	S
.4SSS	SS	S
.4S.0$ )NrB   r    r.   r*   Fr   r   r^   ra   r)   
   r   r   )r/   r@   redgreenbluer1   	per_batchr   rD   s    r   rF   ColorToMask.INPUT_TYPES-  s}     %%	5'9:AQsA NO aqa"PQQaQ!OP$"AcST&UV$"QtUV&WX

 
	r   c                    [         R                  " X#U/[         R                  S9n[         R                  " / SQ[         R                  S9n	[         R                  " / SQ[         R                  S9n
U(       a  XpUR                  S   n[	        U5      n/ n[        SUR                  S   U5       H  n[         R                  " XX-    S-  U-
  SS9nX:*  n[         R                  " UR                  S5      X5      R                  5       nUR                  SS9nUR                  UR                  5       5        UR                  S   nUR                  U5        M     [         R                  " USS9n[         R                  " USS	S
9nU4$ )Nr[   )r   r   r   )r^   r^   r^   r   r^   rl   ri   r&   r:   rk   )rr   r   r   r   r   r   normr   r   r   meanr   rO   updater   r   )r   r/   r  r  r  r1   r@   r  colorr   r   stepspbartensors_out	start_idxcolor_distancesr  mask_outbatch_counts                      r   r   ColorToMask.clip;  sA   c$/u{{CYekk:_EKK@ 5Q5!q&,,q/9=I $jj):M)NQT)TW\)\bdeO #/D {{4>>"#5uDJJLH}}},Hx||~."..+KKK$ >  ii3kk+3C@|r   r   N)r   r   r   r   r   r   r   r   r   rF   r   r   r   r   r   r  r  "  s1    LH HK  r   r  c                   6    \ rS rSrSrSrSr\S 5       rS r	Sr
g)	CreateFluidMaski\  r   createfluidmaskKJNodes/masking/generatec                     SSSS04SSSSSS.4SS	S
SSS.4SS	S
SSS.4SSSSSS.4SSSSSS.4SSSSSS.4SSSSSS.4SSSSSS.4S.	0$ )NrB   r.   r*   Fr   ra   r   r)      r      r   r^   r   2   <   )	r@   r   r   r   inflow_countinflow_velocityinflow_radiusinflow_paddinginflow_durationr   rD   s    r   rF   CreateFluidMask.INPUT_TYPESb  s     %	5'9:!q$PQ#RS cDRS"TU!s"TST#UV"'QaUV)W!X%*3XY,Z$[#(aqVW*X"Y$)r3XY+Z#[%*!CYZ,[$\

 	r   c
                   ^ ^! SSK Jn
   SSKJn  / n/ nX#4nUnUnU	nUnUnUn[        R                  " S5        U
" US5      n[        R                  " US5      m [        R                  " T 5      U-
  m![        R                  " [        R                  * [        R                  USS9n[        S	 U 5       5      n[        S
 U 5       5      n[        U U!4S jU 5       5      n[        R                  " UR                  5      n[        R                   " UR"                  5      n[%        UU5       H\  u  nn[        R&                  R)                  UR*                  US S 2S S 4   -
  SS9U:*  nUS S 2U4==   US S 2S 4   U-  -  ss'   SUU'   M^     [-        U5       GHc  n[        R                  " SUS-    SU S35        UU::  a*  U=R                  U-  sl        U=R.                  U-  sl        UR1                  5       S   nU" US-  5      S-   S-  n[        R2                  " U[        R4                  " UR"                  5      UR.                  45      n[        R6                  " USS5      S-  R9                  S5      n[        R:                  " U5      R9                  [        R<                  5      S-  n[>        R@                  " U5      S   nUS S 2S S 2S S 2S4   nURC                  U5        URC                  U5        GMf     U(       a0  S[>        RD                  " USS9-
  S[>        RD                  " USS9-
  4$ [>        RD                  " USS9[>        RD                  " USS94$ ! [         a
    SSKJn   GNcf = f)Nr   )Fluidr   )erfz1Generating fluid solver, this may take some time.dyeF)endpointc              3      #    U  HE  n[         R                  " [         R                  " U5      [         R                  " U5      45      v   MG     g 7fr   )r   r   cossin.0ps     r   	<genexpr>2CreateFluidMask.createfluidmask.<locals>.<genexpr>  s1     HArxxBFF1I 677s   AAc              3   &   #    U  H  o* v   M	     g 7fr   r   r<  s     r   r?  r@    s     +FqFs   c              3   4   >#    U  H  nTU-  T-   v   M     g 7fr   r   )r=  r>  r   rs     r   r?  r@    s     6v!q1uv~vs   axisra   zComputing frame z of .   r^   r   r]   r   r:   ri   )#utility.fluidr5  scipy.specialr6  ImportErrorscipy.spatiallogginginfor   floor_divider+   linspacepituple
zeros_likevelocityzerosr   ziplinalgr  indicesr   r7  r-   dstackonesr   r   r   r   rr   r   r   r   )"r   r   r   r   r@   r.  r/  r0  r1  r2  r5  r6  r   r   
RESOLUTIONDURATIONINFLOW_PADDINGINFLOW_DURATIONINFLOW_RADIUSINFLOW_VELOCITYINFLOW_COUNTfluidpointsnormals
inflow_dyer>  nr  fcurlr  r   r   rC  s"                                   @@r   r'  CreateFluidMask.createfluidmaskr  s   )	*) ]
')%)#HIj%(Q/FF6N^+beeVRUUL5IHHH+F++6v66--7XXekk*
(DAq99>>%--!AtTM2B"B>K}\DAtG$!T'
_(DD$ Jt ) xALL+AE7$xjBCO#/1		Z'	::<?D qMA%*DIItRWWU[[%9599EFEWWUAq)C/77@EHHUO**2::6>E$$U+E2EAq!$DLLJJu# !& %))CQ//eii16M0MOO		#1%eii1&=??k  	*))	*s   M   M43M4r   N)r   r   r   r   r   r   r   r   rF   r'  r   r   r   r   r&  r&  \  s)    $L H)H 9@r   r&  c                   6    \ rS rSrSrSrSr\S 5       rS r	Sr
g)	CreateAudioMaski  r    createaudiomaskKJNodes/deprecatedc                 `    SSSS04SSSSSS	.4S
SSSSS	.4SSS04SSSSSS	.4SSSSSS	.4S.0$ )NrB   r.   r*   Fr   r   ra   r^   r)   r$   r%   r&   g       @r;   r"   	audio.wavr*  r   )r@   r   scale
audio_pathr   r   r   rD   s    r   rF   CreateAudioMask.INPUT_TYPES  sx     %	5'9:!r3PQ#RS"3sTX$YZ (9k*BC cDRS"TU!s"TST#UV
	 		r   c                     SS K nUn	/ n
/ nUS:X  a$  [        R                  R	                  [
        U5      nUR                  U5      u  p[        R                  " UR                  U5      5      n[        U	5       GH  n[        R                  " SX#4S5      n[        R                  " U5      nUS S 2U4   n[        U[        R                   " U5      -  5      nUU-  nUS-  US-  4nUR#                  US   U-
  US   U-
  4US   U-   US   U-   4/SS	9  [        R$                  " U5      R'                  [        R(                  5      S
-  n[*        R,                  " U5      S   nUS S 2S S 2S S 2S4   nUR/                  U5        U
R/                  U5        GM     U(       a  S[*        R0                  " U
SS9-
  4$ [*        R0                  " U
SS9[*        R0                  " USS94$ ! [         a  n[        S5      UeS nAff = f)Nr   z=Can not import librosa. Install it with 'pip install librosa'rn  r   r   r   ra   r   r   r]   r   r:   ri   )librosarJ  ru   rv   rw   script_directoryloadr   absstftr   r   r   r   r   r   r  ellipser   r   r   rr   r   r   r   )r   r   r   r   r@   rp  ro  rt  er   r   r   audiosrspectrogramr   r   r   framecircle_radiuscircle_centerr  s                         r   rk  CreateAudioMask.createaudiomask  s   	f 
$&6
CJLL,	ffW\\%01z"A99UUOW=5..'4q!t$5v67=E!=!QJ!4=<<-*]:M!<L}<\]$Q'-7q9IM9YZ\"  $ 88E?))"**5=5##E*5151a
#4<<::e! #$ %))CQ//11		#1%eii1&=??=  	f]^dee	fs   G# #
G>-G99G>r   N)r   r   r   r   r   r   r   r   rF   rk  r   r   r   r   rj  rj    s)    L H#H
 
!@r   rj  c                   6    \ rS rSrSrSrSr\S 5       rS r	Sr
g)	CreateGradientMaski  r  
createmaskr(  c           
      F    SSSS04SSSSSS	.4SS
SSSS	.4SS
SSSS	.4S.0$ )NrB   r.   r*   Fr   r   r^   ra   r)   r*  r   r   )r@   r   r   r   r   rD   s    r   rF   CreateGradientMask.INPUT_TYPES  sX     %	5'9:!q#q#QR cDRS"TU!s"TST#UV	
 	r   c                    Un/ n[         R                  " XSU4[         R                  S9n[        U5       HD  n[         R                  " SSU[         R                  S9n	X-  n
X-
  nUR                  SS5      Xx'   MF     [        R                  " U5      nUnUR                  U5        U(       a  S[        R                  " USS9-
  4$ [        R                  " USS94$ )Nr[   r:   r&   ra   rl   r   ri   )
r   rT  r   r   rO  reshaperr   r   r   r   )r   r   r   r   r@   r   r   image_batchr   gradienttimeoffset_gradientoutputr  s                 r   r  CreateGradientMask.createmask  s    
hh
E:"**Mz"A{{3U"**EH:D&oO,44Q;KN	 #
 !!+.

4%))CQ//11		#1%''r   r   N)r   r   r   r   r   r   r   r   rF   r  r   r   r   r   r  r    s(    LH)H (r   r  c                   6    \ rS rSrSrSrSr\S 5       rS r	Sr
g)	CreateFadeMaski  r  createfademaskrl  c                     SSSS04SSSSSS	.4SS
SSSS	.4SS
SSSS	.4/ SQ4SSSSSS	.4SSSSSS	.4SSSSSS	.4SSSSSS	.4S.	0$ )NrB   r.   r*   Fr   r   '  ra   r)   r*  r   r   )linearease_inease_outease_in_outr$   r:   r&   r;   r%   r   )	r@   r   r   r   interpolationstart_levelmidpoint_level	end_levelmidpoint_framer   rD   s    r   rF   CreateFadeMask.INPUT_TYPES  s     %	5'9:!q%QR#ST cDRS"TU!s"TST#UV#S"U!(cSZ^*_ `$+CPS]a-b#c&Cs3X\(]^$)q$XY+Z#[

 	r   c
                    S n
S nS nUn/ n[         R                  " XU4[         R                  S9nU	S:X  a  US-  n	[        U5       H  nUU	::  a<  UU	-  nUS:X  a	  U
" U5      nOUS:X  a	  U" U5      nOUS	:X  a  U" U5      nUUXg-
  -  -
  nO@UU	-
  X-
  -  nUS:X  a	  U
" U5      nOUS:X  a	  U" U5      nOUS	:X  a  U" U5      nUUXx-
  -  -
  n[         R                  " USS
5      n[         R
                  " X24U[         R                  S9nUUU'   M     [        R                  " U5      nUnUR                  U5        U(       a  S[        R                  " USS9-
  4$ [        R                  " USS94$ )Nc                 
    X -  $ r   r   ts    r   r  .CreateFadeMask.createfademask.<locals>.ease_in  	    5Lr   c                     SSU -
  SU -
  -  -
  $ Nra   r   r  s    r   r  /CreateFadeMask.createfademask.<locals>.ease_out       A!a%(((r   c                 *    SU -  U -  SU -  U -  U -  -
  $ Nr+  r   r   r  s    r   r  2CreateFadeMask.createfademask.<locals>.ease_in_out#  !    q519q1uqy1},,r   r[   r   r   r  r  r  r^   r:   ri   )
r   rT  r   r   r   fullrr   r   r   r   )r   r   r   r   r@   r  r  r  r  r  r  r  r  r   r   r  r   r  r  r   r  r  s                         r   r  CreateFadeMask.createfademask  s   		)	- 
hh
E:"**MQ'1_Nz"AN"& I-
A"j0 A"m3#AA#a;+G&HH'J,GH I-
A"j0 A"m3#AA&n.H)IIGGE1c*EGGVOU"**EE"KN- #0 !!+.

4%))CQ//11		#1%''r   r   N)r   r   r   r   r   r   r   r   rF   r  r   r   r   r   r  r    s(    LH#H /(r   r  c                   :    \ rS rSrSrSrSrSr\S 5       r	S r
Srg	)
CreateFadeMaskAdvancediM  r  r  r(  a  
Create a batch of masks interpolated between given frames and values. 
Uses same syntax as Fizz' BatchValueSchedule.
First value is the frame index (not that this starts from 0, not 1) 
and the second value inside the brackets is the float value of the mask in range 0.0 - 1.0  

For example the default values:  
0:(0.0)  
7:(1.0)  
15:(0.0)  
  
Would create a mask batch fo 16 frames, starting from black, 
interpolating with the chosen curve to fully white at the 8th frame, 
and interpolating from that to fully black at the 16th frame.
c                 Z    SSSSS.4SSS04S	S
SSSS.4S	SSSSS.4S	SSSSS.4/ SQ4S.0$ )NrB   r"   z0:(0.0),
7:(1.0),
15:(0.0)
Tr   r.   r*   Fr   r   r   r  ra   r)   r   r   )r  r  r  r  nonedefault_to_black)points_stringr@   r   r   r   r  r   rD   s    r   rF   "CreateFadeMaskAdvanced.INPUT_TYPESb  sn     #+9Yhl-m"n%	5'9:!r5RS#TU c4QR"ST!s!DRS#TU#o"q
	 		r   c                    S nS nS n	/ n
UR                  S5      nUR                  S5       H]  nUR                  S5      u  p[        UR                  5       5      n[	        UR                  5       SS 5      nU
R                  X45        M_     US	:w  aC  [        U
5      S
:X  d  U
S   S
   US-
  :w  a%  U
R                  US-
  U
(       a  U
S   S   OS
45        U
R                  S S9  Un/ n[        R                  " UX24[        R                  S9nSn[        U5       GHV  nU[        U
5      :  a.  UU
U   S
   :  a"  US-  nU[        U
5      :  a  UU
U   S
   :  a  M"  US-
  nUS:X  a-  SnU
 H  nUS
   U:X  d  M  US   nSn  O   U(       d  U
U   S   nOUS	:X  a'  SnU
 H  nUS
   U:X  d  M  US   nSn  O   U(       d  S
nOnUU
U   S
   -
  U
U   S
   U
U   S
   -
  -  nUS:X  a	  U" U5      nO%US:X  a	  U" U5      nOUS:X  a	  U	" U5      nOUS:X  a   U
U   S   UU
U   S   U
U   S   -
  -  -
  n[        R                  " WS
S5      n[        R                  " X24U[        R                  S9nUUU'   GMY     [        R                  " U5      nUnUR                  U5        U(       a  S[        R                   " US
S9-
  4$ [        R                   " US
S94$ )Nc                 
    X -  $ r   r   r  s    r   r  6CreateFadeMaskAdvanced.createfademask.<locals>.ease_inp  r  r   c                     SSU -
  SU -
  -  -
  $ r  r   r  s    r   r  7CreateFadeMaskAdvanced.createfademask.<locals>.ease_outs  r  r   c                 *    SU -  U -  SU -  U -  U -  -
  $ r  r   r  s    r   r  :CreateFadeMaskAdvanced.createfademask.<locals>.ease_in_outv  r  r   z,
,:ra   rl   r  r   c                     U S   $ Nr   r   xs    r   <lambda>7CreateFadeMaskAdvanced.createfademask.<locals>.<lambda>  s    !A$r   r   r[   r  FTr  r  r  r  r^   r:   ri   )rstripr   r   r   r   r   r   sortr   rT  r   r   r   r  rr   r   r   )r   r   r   r   r@   r  r  r  r  r  rb  	point_str	frame_str	color_strr~  r  r   r   r  
next_pointr   
prev_pointexact_matchr>  r  r   r  r  s                               r   r  %CreateFadeMaskAdvanced.createfademasko  s"   		)	- %,,U3&,,S1I#,??3#7 I	)*E)//+Ab12EMM5.)	 2 //c&kQ6F&QS*UV-[ade[eJeMM6A:vbz!}AFG 	'
hh
F:"**M 
z"As6{*q6*3Ea3H/Ha
 s6{*q6*3Ea3H/H $aJ&#Atqy !!&*	  
 #":.q1E"44#Atqy !!&*	  
 #E
+A..6*3Ea3H6R\K]^_K`3`a I-
A"j0 A"m3#AA"h.z*1-VJ5G5JVT^M_`aMb5b0ccGGE1c*EGGVOU"**EE"KNS #V !!+.

4%))CQ//11		#1%''r   r   N)r   r   r   r   r   r   r   r   r   rF   r  r   r   r   r   r  r  M  s2    LH)HK  
 
S(r   r  c                   :    \ rS rSrSrSrSrSr\S 5       r	S r
Srg	)
CreateMagicMaski  r9   r9   r  mask_invertedcreatemagicmaskr(  c                 |    SSSSSSS.4SSSS	SS.4S
SSSSS.4SSSSSS.4SSSSSS.4SSSSSS.4SSSSSS.4S.0$ )NrB   r   r   r   r   ra   r)      i  r$   g      ?r&   r5   r;   {   r   i   r   )r   depth
distortionseedtransitionsframe_widthframe_heightr   rD   s    r   rF   CreateMagicMask.INPUT_TYPES  s     !r4QR#ST b#q"QR 'SE[_)`aS(TU!VW!&AQrST(U V!&Cr$XY(Z ["'S4YZ)[!\

 
	r   c           	         SSK JnJn	Jn
  SS KJn  [        R                  R                  U5      n/ nU" Xg45      nX-  nU	" X5      UUS.n[        U5       GH  nUR                  5       nUR                  5       nU	" X5      US'   U	" X5      US'   [        U5       GH  nUU-  nUR                  5       nSU-
  US   -  UUS   -  -   US'   U
" S0 UD6nUS-  nUR                  SUS	9nUR                  S
5      nUR                  SSSSS9  UR                  5       R                  / 5        UR!                  5       R                  / 5        UR#                  USS9  UR$                  R'                  5         [        R(                  " UR$                  R*                  R,                  5      nUR/                  U5        [0        R2                  " U5      R5                  S5      n[6        R8                  " [        R(                  " U5      5      S-  nUR;                  U5        GM     GM     [6        R<                  " USS9S[6        R<                  " USS9-
  4$ )Nr   )coordinate_gridrandom_transformmagicr   )coordsr  r  r  ra   r  )r  r  )figsizedpio   leftrightbottomtopauto)aspectLr]   ri   r:   r   )utility.magictexr  r  r  matplotlib.pyplotpyplotr   randomdefault_rngr   copyfigureadd_subplotsubplots_adjust	get_yaxis	set_ticks	get_xaxisimshowcanvasr   r   renderer	_renderercloser   r   convertrr   r   r   stack)r   r   r  r  r  r  r  r  r  r  r  pltrngr   r  frames_per_transitionbase_paramsr  params1params2r   alphaparamstexr  figaximgpil_imgr  s                                 r   r  CreateMagicMask.createmagicmask  s   OO'ii##D) +!<= !' 5 'v3$

 {#A!&&(G!&&(G 0 =GH 0 =GH0111 !$%I1B#BUWU]M^E^#^x ofo!B&jjsj;__S)##!A1#E((,((,		#f	-

!hhszz22<<=		#//#.66s;||BHHW$56>

4 9 2 $L CQ'u{{3A/F)FHHr   r   N)r   r   r   r   r   r   r   r   r   rF   r  r   r   r   r   r  r    s.    $L-L H)H 6Ir   r  c                   >    \ rS rSrSrSrSrSrSr\	S 5       r
S rS	rg
)CreateShapeMaski  r  r  createshapemaskr(  z
Creates a mask or batch of masks with the specified shape.  
Locations are center locations.  
Grow value is the amount to grow the shape on each frame, creating animated masks.
c                     S/ SQSS04SSSSSS.4SS	S
SSS.4SS	S
SSS.4SS
SSSS.4SSSSSS.4SSSSSS.4SSSSSS.4SSSSSS.4S.	0$ )NrB   )circlesquaretriangler*   r  r   ra   r   r)   r*  r   i r   r      r   )	r   r   
location_x
location_ygrowr  r  shape_widthshape_heightr   rD   s    r   rF   CreateShapeMask.INPUT_TYPES  s     
 x !aqq"QR$#QtUV&WX$#QtUV&WXAd3PQ RS %3bWX'YZ!&Cr$XY(Z [ %3aVW'XY!&CqWX(Y Z!
 	r   c
                    Un
/ nSn[        U
5       GH   n[        R                  " SX#4S5      n[        R                  " U5      n[        SXmU-  -   5      n[        SX}U-  -   5      nU	S:X  d  U	S:X  aR  UUS-  -
  UUS-  -
  4nUUS-  -   UUS-  -   4nUU/nU	S:X  a  UR                  UUS9  OYU	S:X  a  UR                  UUS9  OBU	S	:X  a<  UUS-  -
  UUS-  -   4nUUS-  -   UUS-  -   4nXEUS-  -
  4nUR                  UUU/US9  [        U5      nUS S 2S S 2S S 2S4   nUR                  U5        GM#     [        R                  " USS
9nUSU-
  4$ )Nr   r   r   r   r  r  r   rs  r  ri   r:   )r   r   r   r   r   r,   ry  	rectanglepolygonr   r   rr   r   )r   r   r  r  r  r  r  r  r  r   r   r   r  r   r   r   current_widthcurrent_heightleft_up_pointright_down_point
two_points	top_pointr  outstacks                           r   r  CreateShapeMask.createshapemask4  s   
z"AIIek%@'JE>>%(D  ;4#78M LT6$9:N EX$5!+mq.@!@*~abObBb c$.!1C$CZR`deReEe#f +-=>
H$LL%L8h&NN:EN:*$!+mq.@!@*~abObBb c$.!1C$CZR`deReEe#f 'n6I)IJ	i8HIPUVu%EAq!$DJJt9 #: 99Sa(#.**r   r   N)r   r   r   r   r   r   r   r   r   r   rF   r  r   r   r   r   r  r    s6    $L-L H)HK  ,#+r   r  c                   :    \ rS rSrSrSrSrSr\S 5       r	S r
Srg	)
CreateVoronoiMaskiY  r  r  createvoronoir(  c                 l    SSSSSSS.4SSSSSS.4SS	SSSS.4S
SSSSS.4SSSSSS.4SSSSSS.4S.0$ )NrB   r   r   r   r   ra   r)      rG  r$   r%   r&   r:   r;   r   )r   
num_points
line_widthspeedr  r  r   rD   s    r   rF   CreateVoronoiMask.INPUT_TYPES`  s     !r4QR#ST %2QtUV'WX %1AdTU'VW"3sTX$YZ!&Cr$XY(Z ["'S4YZ)[!\
	 		r   c           	         SSK Jn  SSKJn  Un	/ n
XV-  n[        R
                  R                  US5      nUS S 2S4==   U-  ss'   [        R
                  R                  US5      nUS S 2S4==   U-  ss'   [        U	5       GH$  nX-  U	S-
  -  n[        R                  " USS5      nSU-
  U-  X-  -   nUS S 2S4==   U-  ss'   U" U5      nUR                  5       u  nnUR                  SSSSS9  UR                  SU/5        UR                  SS/5        UR                  S5        UR                  SS5        UR                  X-  S-  US-  5        UR!                  SS/SS/S	S
9  UR"                   Hi  n[        R$                  " U5      n[        R&                  " US:  5      (       d  M9  UR)                  UR*                  US4   UR*                  US4   SUS9  Mk     UR,                  R/                  5         [        R0                  " UR,                  R2                  R4                  5      nUR7                  U5        [8        R:                  " U5      R=                  S5      n[>        R@                  " [        R0                  " U5      5      S-  nU
RC                  U5        GM'     [>        RD                  " U
SS9S[>        RD                  " U
SS9-
  4$ )Nr   )Voronoi)r  r   ra   r  offd   r   )r  zk-)	linewidthr  r]   ri   r:   )#rK  r3  
matplotlibr  r   r  randr   r   subplotsr  set_xlimset_ylimrE  marginsset_size_inchesfill_betweenridge_verticesasarrayallplotverticesr  r   r   r  r  r  r   r   r   rr   r   r   r  )r   r   r.  r/  r0  r  r  r3  r  r   r   aspect_ratiostart_points
end_pointsr   r  rb  vorr  r  simplexr  r  r  s                           r   r+  CreateVoronoiMask.createvoronoim  sp   ),
 #1 yy~~j!4QTl*YY^^J2
1a4L(z"AzA~.A1a A!e|+an<F 1a4LL(L&/C llnGCQaqAKKL)*BKKA,?GGENJJq! ;C ?cAQROOQFQF'O: --**W-66'Q,''HHS\\'1*5s||GQJ7OQUakHl .
 JJOO((3::..889CIIcNooc*2237G<< 12U:DJJtE #H CQ'u{{3A/F)FHHr   r   N)r   r   r   r   r   r   r   r   r   rF   r+  r   r   r   r   r*  r*  Y  s.    $L-LH)H
 
5Ir   r*  c                   >    \ rS rSr\S 5       rSrSrSrSr	Sr
S rS	rg
)GetMaskSizeAndCounti  c                     SSS00$ NrB   r  r  r   rD   s    r   rF   GetMaskSizeAndCount.INPUT_TYPES      I
  	r   )r9   r   r   r   )r  r   r   countr   rH   z]
Returns the width, height and batch size of the mask,  
and passes it through unchanged.  

c                     UR                   S   nUR                   S   nUR                   S   nSU SU SU 3/0XX44S.$ )Nr   ra   r   r0   r  )uiresult)r   )r   r  r   r   rP  s        r   r   GetMaskSizeAndCount.getsize  sY    

1A

1wawax013F2
 	
r   r   N)r   r   r   r   r   rF   r   r   r   r   r   r   r   r   r   r   rK  rK    s6     
 1L8LH HK
r   rK  c                   B    \ rS rSr\S 5       rSrSrSrSr	Sr
SS jrS	rg
)GrowMaskWithBluri  c                     SSS[         * [         SS.4SSSSS	S.4S
SS04S
SS04SSSSS	S.4SSSSSS.4SSSSSS.4S.SS
SS040S.$ )Nr  r   r   ra   r)   r$   r&   r5   r6   r.   r*   TFr5  r:   r;   )r  expandincremental_expandratetapered_corners
flip_inputblur_radius
lerp_alphadecay_factor
fill_holesrA   r   clss    r   rF   GrowMaskWithBlur.INPUT_TYPES  s     " aP^hi"jk+2CX]gj4k*l$-	4/@#A(9e*<= '"	*    'CCY](^_!(c#c[_*` a  y9e*<=!
 	
r   rH   r  r  expand_maska  
# GrowMaskWithBlur
- mask: Input mask or mask batch
- expand: Expand or contract mask or mask batch by a given amount
- incremental_expandrate: increase expand rate by a given amount per frame
- tapered_corners: use tapered corners
- flip_input: flip input mask
- blur_radius: value higher than 0 will blur the mask
- lerp_alpha: alpha value for interpolation between frames
- decay_factor: decay value for interpolation between frames
- fill_holes: fill holes in the mask (slow)c
                    SS K Jn
  UnUnU(       a  SU-
  nUR                  SUR                  S   UR                  S   45      n/ nS nUn[	        USS9 GH\  nUR                  S5      R                  S5      R                  [        5      n[        [        U5      5      S:  a  UR                  5       S:  a  U(       a8  [        R                  " / SQ/ SQ/ SQ/[        R                  UR                  S	9nO7[        R                  " / SQ/ SQ/ SQ/[        R                  UR                  S	9n[        [        [        U5      5      5       H/  nUS:  a  U
R!                  UU5      nM  U
R#                  UU5      nM1     UR%                  S5      R%                  S5      nUS:  a  U[        U5      -  nOU[        U5      -  nU	(       a  US:  nUR'                  5       R)                  5       n[*        R,                  R/                  U5      n[        R0                  " UR3                  [4        R                  5      5      R                  UR                  5      nUS:  a  Ub  UU-  S
U-
  U-  -   nUS:  a  Ub  UX-  -  nUUR                  5       -  nUnUR7                  UR'                  5       5        GM_     US:w  a  [9        U5       Hc  u  nn[;        UR'                  5       R=                  5       5      S   nUR?                  [@        RB                  " U5      5      n[E        U5      UU'   Me     [        RF                  " USS9nUSU-
  4$ [        RH                  " USS9S[        RH                  " USS9-
  4$ )Nr   r:   rl   zExpanding/Contracting Maskdesc)r   ra   r   )ra   ra   ra   r\   rs   ra   ri   )%kornia.morphology
morphologyr  r   r	   r   r   main_devicerw  roundr,   rr   r   r   rs   r   erosiondilationr   rO   r   scipyndimagebinary_fill_holesr   r   r   r   	enumerater   detachfilterr   r   r   r   r  )r   r  rX  rZ  r[  r\  rY  r]  r^  r_  morphr  decaygrowmaskr   previous_outputcurrent_expandmr  kernel_r2   	output_npfilledidxr   	pil_imageblurreds                               r   rc  GrowMaskWithBlur.expand_mask  s   ):D<<TZZ^TZZ^ DEh%ABA[[^--a033K@F5()A-&**,2B""\\9(1(1+3:?--PVP]P]_F #\\9(1(1+3:?--PVP]P]_F s5#89:A%)!&vv!>!&!?	 ; ^^A&..q1F!#&<"==#&<"==$qj'OO-335	88C))&--

*CDGGVs{:1u9*GGs{:%11&**,.$OJJvzz|$M CP !(~V&vzz|':':'<=a@	%,,[-E-Ek-RS	%i0C  . ii+GS7]++KK+S5;;s3J-JLLr   r   N)F)r   r   r   r   r   rF   r   r   r   r   r   rc  r   r   r   r   rV  rV    s7    
 
, !H$L-LH
/K?Mr   rV  c                   >    \ rS rSr\S 5       rSrSrSrSr	Sr
S rS	rg
)MaskBatchMultii'  c                      SSSSSSS.4SSS.0$ )	NrB   r   r     ra   r)   r  )
inputcountmask_1mask_2r   rD   s    r   rF   MaskBatchMulti.INPUT_TYPES(  s.     $!AdTU&VW$$ 	r   r  )r   combinerH   z
Creates an image batch from multiple masks.  
You can set how many inputs the node has,  
with the **inputcount** and clicking update.
c                 Z   US   n[        SU5       H  nUSUS-    3   nUR                  SS  UR                  SS  :w  aP  [        R                  " UR	                  S5      UR                  S   UR                  S   4SS9R                  S5      n[        R                  " X54SS9nM     U4$ )	Nr  ra   mask_r   bicubicrc   r   ri   )r   r   r   r   r   r   rr   r   )r   r  kwargsr  cnew_masks         r   r  MaskBatchMulti.combine<  s    hq*%Aa!eWo.Hzz!"~!33==););A)>djjQRmUYU_U_`aUbEcjst||}~99d-15D	 &
 wr   r   N)r   r   r   r   r   rF   r   r   r   r   r   r  r   r   r   r   r  r  '  s6      LLH HKr   r  c                   B    \ rS rSr\S 5       rSrSrSrSr	Sr
SS jrS	rg
)
OffsetMaskiE  c                     SSSSS[         SSS.4SSS[         SSS.4SSS	S
SSS.4SSSSSSS.4SSS04SSS04/ SQSS04S.0$ )NrB   r  r   r   i ra   numberr*   r+   r,   r-   displayiih  r  r.   r*   F)emptyborder
reflectionr  )r  r  yangleduplication_factorrollincrementalpadding_moder   rD   s    r   rF   OffsetMask.INPUT_TYPESF  s     !!E.Z[hprs!E.Z[hprsaSRS`h!jk',1Qt]^ks.u&v"i$89 )Y+?@ '!
 	
r   r  r  offsetrH   a3  
Offsets the mask by the specified amount.  
 - mask: Input mask or mask batch
 - x: Horizontal offset
 - y: Vertical offset
 - angle: Angle in degrees
 - roll: roll edge wrapping
 - duplication_factor: Number of times to duplicate the mask to form a batch
 - border padding_mode: Padding mode for the mask
c	           	         UR                  USS5      R                  5       nUR                  u  pnUS:w  aZ  U(       aS  [        U	5       HC  nXLS-   -  n[        R
                  " X   R                  S5      U5      R                  S5      X'   ME     OQUS:  aK  [        U	5       H<  n[        R
                  " X   R                  S5      U5      R                  S5      X'   M>     U(       a  U(       a  [        U	5       Hm  n[        X,S-   -  US-
  5      n[        X<S-   -  U
S-
  5      nUS:w  a  [        R                  " X   USS9X'   US:w  d  MS  [        R                  " X   USS9X'   Mo     U4$ [        X+S-
  5      n[        X:S-
  5      nUS:w  a  [        R                  " XSS9nUS:w  a  [        R                  " XSS9nU4$ [        U	5       GH!  nU(       a)  [        X,S-   -  US-
  5      n[        X<S-   -  U
S-
  5      nO[        X+S-
  5      n[        X:S-
  5      nUS:  ak  US:X  a:  [        R                  " [        R                  " U
U45      XS S 2S U* 24   /SS9X'   OUS;   a$  [        R                  " XS S 2S U* 24   SU4US9X'   OpUS:  aj  US:X  a:  [        R                  " XS S 2S U24   [        R                  " U
U* 45      /SS9X'   O*US;   a$  [        R                  " XS S 2U* S 24   US4US9X'   US:  ar  US:X  a<  [        R                  " [        R                  " UU45      XS U* 2S S 24   /SS9X'   GMy  US;   a'  [        R                  " XS U* 2S S 24   SU4US9X'   GM  GM  US:  d  GM  US:X  a<  [        R                  " XS U2S S 24   [        R                  " U* U45      /SS9X'   GM  US;   d  GM  [        R                  " XU* S 2S S 24   US4US9X'   GM$     U4$ )	Nra   r   )shiftsdimsr   r  ri   )	replicatereflect)re   )r   cloner   r   TFr   r   r   r+   rr   r  r   rT  r   pad)r   r  r  r  r  r  r  r  r  r   r   r   r   rotation_angleshift_xshift_ytemp_xtemp_ys                     r   r  OffsetMask.offsetl  s   {{-q!4::<$(JJ!
EA:+:&!&A#))DG$5$5a$8.IQQRST ' QY:&))DG$5$5a$8%@HHK ' z*A!!qS'573G!!qS'6!84G!|"'**TWW1"M!|"'**TWW1"M +Z uK aq/a*a< ::dCDa< ::dCD@ u; :& cE!G4F cF1H5F !G_F 1H-FA:#w."'))U[[&&9I-JDTUW_Y_X_W_Q_L`,agh"i%)AA"#%%8VG8^(<q&kP\"]aZ#w."'))TQ--@%++vX^W^N_B`,agh"i%)AA"#%%F78^(<vqkP\"]A:#w."'))U[[&%-I4S[U[T[S[]^P^K_,`fg"h%)AA"#%%&!^(<q&kP\"] BaZ#w."'))TWfWa--@%++PVwX]N^B_,`fg"h%)AA"#%%!^(<vqkP\"]7 ': ur   r   N)FFra   r  )r   r   r   r   r   rF   r   r   r   r   r   r  r   r   r   r   r  r  E  s6    
 
, LLH H	K=r   r  c                   :    \ rS rSr\S 5       rSrSrSrSr	S r
Srg	)
	RoundMaski  c                     SSS00$ rM  r   rD   s    r   rF   RoundMask.INPUT_TYPES  rO  r   r  rl  rH   z
Rounds the mask or batch of masks to a binary mask.  
<img src="https://github.com/kijai/ComfyUI-KJNodes/assets/40791699/52c85202-f74e-4b96-9dac-c8bda5ddcc40" width="300" height="250" alt="RoundMask example">

c                 (    UR                  5       nU4$ r   )rl  )r   r  s     r   rl  RoundMask.round  s    zz|wr   r   N)r   r   r   r   r   rF   r   r   r   r   rl  r   r   r   r   r  r    s1     
 LH HKr   r  c                   F    \ rS rSr/ SQr\S 5       rSrSrSr	Sr
SrS	 rS
rg)
ResizeMaski  )nearest-exactbilineararear  lanczosc           
      l    SSSSS[         SSS.4SSS[         SSS.4S	S
S04U R                  4SS/4S.0$ )NrB   r  r   r   r   ra   r  r  r.   r*   Fdisabledr   )r  r   r   keep_proportionsupscale_methodcrop)r   upscale_methodsrD   s    r   rF   ResizeMask.INPUT_TYPES  sg     !c!N\]jr!tu s1^]^ks"uv%.)U0D$E#$#4#4"6$X.0	
 		
r   )r9   r   r   )r  r   r   resizerH   zG
Resizes the mask or batch of masks to the specified width and height.
c                    U(       aM  UR                   u  pxn	US:X  a  U	OUnUS:X  a  UOUn[        X)-  X8-  5      n
[        X-  5      n[        X-  5      nUS:X  aJ  [        UR	                  S5      R                  SSSS5      X#XVS9R                  SS5      S S 2S S 2S S 2S4   nO)[        UR	                  S5      X#XVS9R                  S5      nXR                   S   UR                   S   4$ )Nr   r  ra   r+  )r  rl   r   )r   r+   rl  r   r   r   movedimr   )r   r  r   r   r  r  r  r|  ohowratioout_masks               r   r  ResizeMask.resize  s   

IA21*B%E!Q;RFF
FK0E"(OE28_FY&%dnnQ&7&>&>q!Q&JE[iu}}~  AC  D  EF  HI  KL  NO  EO  PH%dnnQ&7bjjklmH*HNN1,=??r   r   N)r   r   r   r   r  r   rF   r   r   r   r   r   r  r   r   r   r   r  r    s<    QO

 

 +L/LH HK@r   r  c                   >    \ rS rSr\S 5       rSrSrSrSr	Sr
S rS	rg
)RemapMaskRangei  c           	      .    SSSSSSSS.4SSSS	SS.4S
.0$ )NrB   r  r$   r&   g      $r:   r;   r)   r'   )r  r+   r,   r   rD   s    r   rF   RemapMaskRange.INPUT_TYPES  s=     !ScSW!XYSDRV!WX
 	
r   r  r  remaprH   z+
Sets new min and max values for the mask.
c                     [         R                  " U5      nUS:  a  UOSnX-  X2-
  -  U-   n[         R                  " USSS9nU4$ )Nr   ra   r&   r:   rk   )rr   r,   r   )r   r  r+   r,   mask_maxscaled_masks         r   r  RemapMaskRange.remap  sQ     99T?  (!|8 395; kk+3C@r   r   N)r   r   r   r   r   rF   r   r   r   r   r   r  r   r   r   r   r  r    s6    
 
 LLH HKr   r  c                     SS K n UR                  XR                  UR                  5      u  p4U(       d  g [	        X2R
                  S9nSUR                  US5      -  nUR                  XVS5      nUR                  5       $ )Nr   r  g{Gz?T)	cv2findContoursRETR_EXTERNALCHAIN_APPROX_SIMPLEr,   contourArea	arcLengthapproxPolyDPr   )r   mask_npr  contoursr|  largest_contourepsilonr   s           r   get_mask_polygonr    st    9""7,=,=s?V?VWKH (8O S]]?D99G>G??r   c            
       z    \ rS rSr\S 5       rSrSrSrSr	Sr
SrS	 rS
 rS\R                  S\S\S\S\4
S jrSrg)SeparateMasksi  c                 F    SSSSSSSS.4SSSSSS.4/ S	Q4SS
SSSS.4S.0$ )NrB   r  r   r*  r&   r   ra   r)   )convex_polygonsr  boxr   r+  r   )r  size_threshold_widthsize_threshold_heightre   max_poly_pointsr   r`  s    r   rF   SeparateMasks.INPUT_TYPES  sW     "*/SUYcd1e)f+0c#VZde2f*g;=$)q2WX+Y#Z	
 		
r   r  r  separaterH   TzSSeparates a mask into multiple masks based on the size of the connected components.c                     SS K n[        R                  " US   US   4[        R                  S9n[	        UR
                  5      S:X  a2  UR                  [        R                  5      nUR                  XA/S5        U$ )Nr   ra   r[   r   )	r  r   rT  r   r   r   r   int32fillPoly)r   r   r   r  r  s        r   polygon_to_maskSeparateMasks.polygon_to_mask2  s^    xxq58,BHH=w}}"nnRXX.GLLy!,r   c                    SS K nUR                  XR                  UR                  5      u  pEU(       d  g [	        XCR
                  S9nUR                  U5      nUR                  US5      nUS-  n	US-  n
S n[        S5      nSn[        U5       H  nX-   S-  nUR                  XS5      n[        U5      U-
  n[        U5      U:  a  Un[        U5      n[        U5      U:  a  US	-  n	O'[        U5      U:  a  US
-  n
OUR                  5       s  $ [        X-
  5      US-  :  d  M    O   Ub  UR                  5       $ UR                  5       $ )Nr   r  Tr(   g?infr  r   g?g?g-C6?)r  r  r  r  r,   r  
convexHullr  r   r   r  r   rw  r   )r   r  
max_pointsr  r  r|  r  hull	perimetermin_epsmax_epsbest_approx	best_diffmax_iterationsr   curr_epsapproxpoints_diffs                     r   r  SeparateMasks.get_mask_polygon;  sK   &&w0A0A3CZCZ[hOO<~~o. MM$-	e#c/%L	 ~&A)Q.H%%dd;Ff+
2K ;)+$,	6{Z'"S.Vz)"S.~~''7$%	F(::' ', )4(?{""$ST\\^Sr   r  r  r  r  re   c                 b   UR                   u  pgn/ n	UR                  5       n[        U5       GH  n
X   R                  5       R	                  5       R                  [        R                  5      n[        R                  " S[        R                  S9n[        R                  R                  XS9u  p[        U5      n[        SUS-   5       GH  nUU:H  R                  [        R                  5      n[        R                  " USS9n[        R                  " USS9n[        R                  " U5      S   SS/   u  nn[        R                  " U5      S   SS/   u  nnUU-
  S-   nUU-
  S-   nUU-   S-  n[         R"                  " S	U S
U SU SU 35        UU:  Ga  UU:  Ga  US:X  a[  U R%                  UU5      nUbE  U R'                  UXx45      n[(        R*                  " UUR,                  S9nU	R/                  UU45        OUS:X  ah  [        R0                  " Xx4[        R                  S9nSUUUS-   2UUS-   24'   [(        R*                  " UUR,                  S9nU	R/                  UU45        O2[(        R*                  " UUR,                  S9nU	R/                  UU45        UR3                  S5        GM     GM     [5        U	5      S:  a=  U	R7                  S S9  U	 Vs/ s H  nUS   PM
     n	n[(        R8                  " U	SS9n U 4$ [(        R:                  " SUR,                  S94$ s  snf )N)r+  r+  r[   )	structurera   rD  r   rl   r   z
Component z: width=z	, height=z, x_pos=r  rs   r  c                     U S   $ r  r   r  s    r   r  (SeparateMasks.separate.<locals>.<lambda>  s    1r   r  ri   )ra   @   r  )r   rl  r   rO   r   r   r   r   rY  int8ro  rp  labelr   anyr   rL  rM  r  r  rr   r   rs   r   rT  r  r   r  r  r  )!r   r  r  r  r  re   r   r   r   	separatedbr  r  labeledncomponentsr  	componentcomponent_mask_nprowscolsy_miny_maxx_minx_maxr   r   
centroid_xr   	poly_maskbox_mask	area_maskr  	out_maskss!                                    r   r  SeparateMasks.separateh  s   **a	zz|qAgkkm))+22288<Gbgg6I#(==#6#6w#6#T G{+D"1kAo6	%,	%9$A$A"(($K!vv/a8vv/a8!xx~a0!R9u!xx~a0!R9u)*#emq0
z)HUG9VHT\]g\hij00V?T5T00"&"7"78I?"[".(,(<(<Wqf(MI(-Yt{{(SI%,,j)-DE#%88QF"((#CABuQweAg!=>#(<<#M!((*h)?@$)LL1B4;;$W	!((*i)@AA; 7 J y>ANN~N.'01y!1yI1I15I:;;{4;;?@@	 2s   #L,r   N)r   r   r   r   r   rF   r   r   r   r   OUTPUT_NODEr   r  r  rr   Tensorr   strr  r   r   r   r   r  r    sy    

 

 LLH HKgK+TZ2AU\\ 2A 2A]` 2Asv 2A  B 2Ar   r  c                   >    \ rS rSr\S 5       rSrSrSrSr	S
S jr
Srg	)ConsolidateMasksKJi  c           
      >    SSSSSSSS.4SSSSSS.4SSSSS	S.4S
.0$ )NrB   r  r   r   r   r   r  r)   ra   )r   r   r   paddingr   rD   s    r   rF   ConsolidateMasksKJ.INPUT_TYPES  sO     "S4QS!TU c!DRT"UV!q4QR#ST	
 	
r   r  consolidaterH   zConsolidates a batch of separate masks by finding the largest group of masks that fit inside a tile of the given width and height (including the padding), and repeating until no more masks can be combined.c                 x  ^^^ UR                   u  pVnUUU4S jn/ n	/ n
[        U5       H  nX   nUR                  SS9UR                  SS9p[        R                  " U5      S   SS/   u  nn[        R                  " U5      S   SS/   u  nnUU-
  S-   nUU-
  S-   nU	R                  UR                  5       UR                  5       UR                  5       UR                  5       4U45        M     U	R                  S S9  / n[        U	5       Hf  u  nnUS   n/ n[        U	5       H7  u  nnUU:X  a  M  U" UUS   5      u  nnU(       d  M&  UR                  U5        M9     UR                  UU45        Mh     UR                  S S9  / n/ nU HE  u  nnU Vs/ s H  nUU;  d  M  UPM     n nUR                  UUU 45        UR                  U 5        MG     UR                  S	 S9  / n!U H  u  n"n#n$U"U!;   a  M  U# Vs/ s H  nUU!;  d  M  UPM     n#nU	U"   S   R                  5       n%U# H  nU%U	U   S   -  n%U!R                  U5        M!     U!R                  U"5        U
R                  U%5        M     [        R                  " S
U S[        U
5       35        [        R                  " U
SS94$ s  snf s  snf )Nc                    > U u  p#pEUu  pgp[        X&5      [        X75      p[        XH5      [        XY5      pU
T-   UT-   :  d  UT-   UT-   :  a  SU 4$ SXX44$ )NFTrk   )r  candidate_coordsr  r  r  r  cx_mincy_mincx_maxcy_maxnx_minny_minnx_maxny_maxr   r#  r   s                 r   	mask_fits1ConsolidateMasksKJ.consolidate.<locals>.mask_fits  st    )/&E%-=*FF /U1CF /U1CF~ 00FVOfwFV4Vf}$&&999r   ra   ri   r   rl   c                     U S   $ r  r   r  s    r   r  0ConsolidateMasksKJ.consolidate.<locals>.<lambda>  s    QqTr   r  c                      [        U S   5      * $ r  r   r  s    r   r  r4    s    QqT
r   c                 >    [        U S   5      * [        U S   5      * 4$ )Nra   r   r6  r  s    r   r  r4    s    QqT
S1YJ'?r   zConsolidated z masks into )r   r   r
  rr   r   r   itemr  rr  extendr  rL  rM  r   r  )&r   r   r   r   r#  r   r   r   r1  r  final_masksr  rz  r  r  r  r  r  r  whfitsr   coordfits_in_boxj	cand_maskrC  seenunique_fitsr  fsuniqmergedmask_idxfitting_masksr|  combined_masks&     ```                                 r   r%  ConsolidateMasksKJ.consolidate  s   ++a	: 	qAA1quuu|$ ;;t,Q/B8LE5 ;;t,Q/B8LE5!A!Auzz|UZZ\5::<VXYZ[  	>*!),HAu!HEK )) 496$UIaL951&&q) !5 KKK() - 			*	+GC!3r!Qd]ArD3R/KK  	?@*5&HmQ6!(5I1&QMI%h/288:M"1a0a  # MM(#}- +6 	}QC|C4D3EFGKQ/11# 4 Js   
J2(J2 
J7J7r   N)r   r   r   )r   r   r   r   r   rF   r   r   r   r   r%  r   r   r   r   r!  r!    s2    
 
 LH H bK82r   r!  c                   B    \ rS rSr\S 5       rSrSrSrSr	Sr
SS jrS	rg
)DrawMaskOnImagei  c                 0    SSSSSS.4S.SS	S
/S	SS.40S.$ )Nr    r  r"   z0, 0, 0z[Color as RGB/RGBA values in range 0-255 or 0.0-1.0, separated by commas. Ex: 255, 0, 0, 128r*   tooltip)r   r  r  rs   rO   gpuDevice to use for processingrA   r   rD   s    r   rF   DrawMaskOnImage.INPUT_TYPES  sL     )&&I  Kh  )i  j u~5Mk/lm
 	
r   r    )r/   applyrH   zKApplies the provided masks to the input images with Alpha Blending support.c           	      z   UR                   u  pVpxUR                   u  pnUS:X  a  [        O[        R                  " S5      nUR	                  5       R                  U5      nUR	                  5       R                  U5      nX:w  d  X:w  a5  [        R                  " UR                  S5      Xg4SS9R                  S5      nXY:  a  UR                  XY-   S-
  U	-  SS5      S U nO
X:  a  US U n/ nUR                  5       n/ nUR                  S5      (       a  UR                  S5      n[        U5      S:X  a#  U Vs/ s H  n[        US-  S	5      S
-  PM     nnO[        U5      S:X  a#  U Vs/ s H  n[        US-  S	5      S
-  PM     nnO[        U5      S:X  a&  S Vs/ s H  n[        UUUS-    S	5      S
-  PM     nnO[        U5      S:X  a&  S Vs/ s H  n[        UUUS-    S	5      S
-  PM     nnO[[!        SU 35      eUR#                  S5       H8  n[%        UR                  5       5      nUR'                  US:  a  US
-  OU5        M:     US S n[        U5      S:X  a  US   OSn[        R(                  " U[        R*                  US9n[-        [/        U5      SS9 H  nUU   n[1        UUS-
  5      nUU   nUR                  S5      U-  nUR                   S   nUS:X  aO  USS S24   nUSSS 24   nUSU-
  -  UU-  -   n [        R2                  " UU5      n![        R4                  " U U!4SS9n"OUSU-
  -  UU-  -   n"UR'                  U"5        M     U(       d#  [        R6                  " SXgU4UR8                  S94$ [        R:                  " USS9R=                  5       n#U#4$ s  snf s  snf s  snf s  snf )NrP  rO   ra   r  rc   #r+  r   r   r]   rG  rf   )r   r   rG  r   )r   r   rG  rf   zInvalid hex color format: r  r:   rh  zDrawMaskOnImage batchrf  rl   .ri   r   r[   )r   rk  rr   rs   r  r   r   r   r   r   r   r   
startswithlstripr   r   
ValueErrorr   r   r   r   r   r	   r   r+   maximumr   rT  r\   r  rO   )$r   r   r  r  rs   r   r   r   r   BMHMWMprocessing_devicein_masks	in_imagesoutput_imagescolor_values	hex_colorr  r   r  valrgb	alpha_val
fill_color	curr_maskimg_idx
curr_imageblend_factorimg_channelsimg_rgbimg_aout_rgbout_amasked_image
out_tensors$                                       r   rS  DrawMaskOnImage.apply  s   [[
aZZ
+1U?KU@S::<??#45KKM$$%67	 7bg}}T^^A%6aV/ZbbcdeH6
r'91a@!DHV|H C  S)I9~">GHiAaCu 4iHY1$>GHiAaCu 4iHY1$KTU9aIa!$4b 9E A9UY1$KWX<aIa!$4b 9E A<X #=eW!EFF [[%AGGI&##39C%K#F & 2A'*<'8A'=LO3	\\#U]]CTU
eAh%<=A I!QUmG"7+J$..r2Y>L%++B/Lq $S"1"W-"37+!Q%56l9RRe\:$yy'5)9rB)Q-=>lAZZ  .! >$ KKA!EKK@BB[[A6::<
~W  IHUXs   :N),N.N3N8r   NrO   )r   r   r   r   r   rF   r   r   r   r   r   rS  r   r   r   r   rL  rL    s5    	
 	
 LLH H_KGr   rL  c                   B    \ rS rSr\S 5       rSrSrSrSr	Sr
SS jrS	rg
)BlockifyMaskiF  c                 4    SSSSSSSS.4S	.S
SS/SSS.40S.$ )Nr  r   r   r   r   ra   z3Size of blocks in pixels (smaller = smaller blocks))r*   r+   r,   r-   rO  )r   
block_sizers   rO   rP  rQ  rN  rA   r   rD   s    r   rF   BlockifyMask.INPUT_TYPESG  sP     '#(b3XY  g\  +]  #^
 u~5Mk/lm	
 	
r   r  r  processrH   zCreates a block mask by dividing the bounding box of each mask into blocks of the specified size and filling in blocks that contain any part of the original mask.c                    US:X  a  [         O[        R                  " S5      nUR                  U5      nUR                  u  pVn[        R
                  " U5      n[        [        U5      SS9 GH  n	X   n
U
S:  nUR                  5       (       d  M$  [        R                  " UR                  SS9SS	9S   n[        R                  " UR                  SS9SS	9S   n[        U5      S:X  d  [        U5      S:X  a  M  US   US
   pUS   US
   nnUU-
  S-   nX-
  S-   n[        SUU-  5      n[        SUU-  5      nUU-  nUU-  n[        R                  " XS-   US9R                  S
S5      n[        R                  " UUS-   US9R                  SS
5      nUU-
  U-  nUU-
  U-  nUR                  SUS-
  5      nUR                  SUS-
  5      nUU-  U-   nXUS-   2UUS-   24   nUU-  n[        R                  " UUS9nUR!                  SUR#                  5       UR#                  5       5        US:  n U U   n!U!R%                  5       XXS-   2UUS-   24'   GM     UR                  SS5      4$ )NrP  rO   zBlockifyMask batchrf  r   ra   ri   T)as_tuplerl   r  )rk  rr   rs   r   r   rR  r	   r   r
  nonzeror   r,   arangeviewr   rT  scatter_add_flattenr   )"r   r   rw  rs   r]  r   r   r   result_masksr   r  	mask_bool	y_indices	x_indicesr  r  r  r  
bbox_widthbbox_heightw_divisionsh_divisionsw_sliceh_slicey_coordsx_coordsw_block_indicesh_block_indices	block_idsmask_region
max_blocksblock_contenthas_content
block_masks"                                     r   ry  BlockifyMask.processX  s   +1U?KU@S*+$)KK!
E''.eJ'.BCA8D qI==??immm&:TJ1MIimmm&:TJ1MI9~"c)n&9$Q<25$Q<25E*J-!+K az!9:Ka
!:;K K/G![0G ||E19=NOTTUWYZ[H||E519=NOTTUVXZ[H  (%/G;O'%/G;O .33A{QGO-33A{QGO (+5GI U1W}eE!Gm;<K %{2J!KK
;LMM&&q)*;*;*={?R?R?TU (!+K$Y/J =G<L<L<NLE'M5q=89o Dr ""1a(**r   r   Nrs  )r   r   r   r   r   rF   r   r   r   r   r   ry  r   r   r   r   ru  ru  F  s8    
 
 LLH H wKA+r   ru  )Arr   torch.nn.functionalnnr   r   rn   r  PILr   r   r   r   scipy.ndimagero  r   r   
contextlibr   ru   r	   rL  comfyr
   comfy.utilsr   r   nodesr   rx   utility.utilityr   r   rv   dirnameabspath__file__ru  rq   rk  rp   r   r   r   r   r  r&  rj  r  r  r  r  r  r*  rK  rV  r  r  r  r  r  r  r  r!  rL  ru  r   r   r   <module>r     s      3 8 8   " 	   " # &    477??277??277??83L#MN //1!557t* t*l* *Xe@ e@N8 8tO@ O@b4@ 4@l!( !(FE( E(Nu( u(nKI KIZF+ F+PII IIV
 
4gM gMR <d dL (%@ %@N" "J$}A }A@J2 J2ZZ ZxS+ S+r   