Ë
    éÓ^j†„  ã                   óB  — d Z ddlZddlZddlZddlmZmZmZmZm	Z	m
Z
 ddlZddlmZ ddlmZ ddlmZ ddlmZ dd	lmZmZmZ 	 	 	 	 	 d'd
e	eef   de
ee	eef   f   dededee   dede	ee	eef   f   fd„Z ed«       ed«      fZ G d„ dej:                  j<                  «      Z G d„ dej:                  j<                  «      Z  G d„ dej:                  j<                  «      Z! G d„ dej:                  j<                  «      Z"d(d„Z# G d„ dej:                  j<                  «      Z$	 	 	 	 d)dejJ                  de	eef   d ed!ed"ed#ede
ejJ                  e	ejJ                  ejJ                  ejJ                  f   f   fd$„Z& G d%„ d&ej:                  j<                  «      Z'y)*az   NaFlex (NaViT + FlexiViT) Transforms and Collation

Implements PyTorch versions of the transforms described in the NaViT and FlexiViT papers:
- NaViT: https://arxiv.org/abs/2307.14995
- FlexiViT: https://arxiv.org/abs/2212.08013

Enables variable resolution/aspect ratio image handling with efficient patching.

Hacked together by / Copyright 2025, Ross Wightman, Hugging Face
é    N)ÚDictÚListÚOptionalÚSequenceÚTupleÚUnion)ÚImage)Ú
transforms)Ú
functional)ÚInterpolationModeé   )Ústr_to_interp_modeÚcrop_or_padÚcenter_crop_or_padÚimage_hwÚ
patch_sizeÚmax_seq_lenÚdivisible_by_patchÚ	max_ratioÚepsÚreturnc                 ó’  ‡ ‡‡‡‡‡— t        |t        «      r||cŠŠnt        |«      dk7  rt        d«      ‚|\  ŠŠ‰dk  s‰dk  rt        d«      ‚ˆˆ ˆˆfd„Šˆˆˆˆfd„}|dz  }d}||z
  |k\  r||z   d	z  }	 ||	«      r|	}n|	}||z
  |k\  rŒ|}
|�t	        |
|«      }
|
|k  rt        d
«      ‚|
dk\  rt        d«      ‚ ‰|
«      }|
|fS )a  Determine scaling ratio and image size for sequence length constraint.

    Calculates the scaling ratio needed so that when image_hw is scaled,
    the total number of resulting patches does not exceed max_seq_len.

    Args:
        image_hw: Original image dimensions (height, width).
        patch_size: Patch dimensions. If int, patches are square.
        max_seq_len: Maximum allowed sequence length.
        divisible_by_patch: Whether resulting dimensions must be divisible by patch_size.
        max_ratio: Optional cap on scaling ratio to prevent excessive upsampling.
        eps: Convergence threshold for binary search.

    Returns:
        Tuple of (ratio, target_hw) where ratio is the scaling factor and
        target_hw is the resulting (height, width) after scaling.
    é   úCpatch_size tuple must have exactly two elements (patch_h, patch_w).r   z'patch_size dimensions must be positive.c                 óð   •— ‰d   | z  }‰d   | z  }‰r6‰t        j                  |‰z  «      z  }‰t        j                  |‰z  «      z  }t        t        |‰«      «      }t        t        |‰«      «      }||fS )zYScale image_hw by ratio and optionally round dimensions to multiples of patch_h, patch_w.r   r   )ÚmathÚceilÚintÚmax)ÚratioÚscaled_hÚscaled_wr   r   Úpatch_hÚpatch_ws      €€€€úf/var/www/ramen.bs-engineer-server.com/venv/lib/python3.12/site-packages/timm/data/naflex_transforms.pyÚprepare_target_hwz1get_image_size_for_seq.<locals>.prepare_target_hwA   sƒ   ø€ à˜A‘; Ñ&ˆØ˜A‘; Ñ&ˆñ Ø¤§¡¨8°gÑ+=Ó!>Ñ>ˆHØ¤§¡¨8°gÑ+=Ó!>Ñ>ˆHô ”s˜8 WÓ-Ó.ˆÜ”s˜8 WÓ-Ó.ˆà˜Ð!Ð!ó    c                 óB   •—  ‰	| «      \  }}|‰z  }|‰z  }||z  }|‰k  S )zACheck if scaling by 'ratio' keeps patch count within max_seq_len.© )
r    Út_hÚt_wÚnum_patches_hÚnum_patches_wÚseq_lenr   r#   r$   r&   s
         €€€€r%   Úis_feasiblez+get_image_size_for_seq.<locals>.is_feasibleQ   s:   ø€ á$ UÓ+‰ˆˆSð ˜w™ˆØ˜w™ˆØ -Ñ/ˆà˜+Ñ%Ð%r'   g      $@g      Y@g       @z0Binary search failed - image might be too large?z0Binary search failed - image might be too small?)Ú
isinstancer   ÚlenÚ
ValueErrorÚmin)r   r   r   r   r   r   r/   ÚlbÚrbÚmidr    Ú	target_hwr#   r$   r&   s   ` ``        @@@r%   Úget_image_size_for_seqr8      s	  ý€ ô6 �*œcÔ"Ø% zÐˆ‘ô ˆz‹?˜aÒÜÐbÓcÐcØ%Ñˆ�ð �!‚|�w !’|ÜÐBÓCÐC÷"÷ 
&ð 
ˆt‰€BØ	€Bð �‰7�sÒ
Ø�B‰w˜#‰oˆÙ�sÔØ‰BàˆBð �‰7�sÓ
ð €Eð ÐÜ�E˜9Ó%ˆð �‚|ÜÐKÓLÐLØ�‚~ÜÐKÓLÐLñ " %Ó(€IØ�)ÐÐr'   ÚbilinearÚbicubicc                   óš   ‡ — e Zd ZdZ	 	 	 	 ddedededee   dee	e
ee
df   f   d	dfˆ fd
„Zdej                  d	ej                  fd„Zˆ xZS )ÚResizeToSequencezðResize image to fit within a maximum sequence length constraint when patchified.

    This maintains aspect ratio while ensuring the resulting image, when divided into patches,
    will not exceed the specified maximum sequence length.
    Nr   r   r   r   Úinterpolation.r   c                 óÌ   •— t         ‰| �  «        || _        || _        || _        || _        t        |t        «      r"|dk(  rt        | _	        yt        |«      | _	        y|| _	        y)aj  Initialize ResizeToSequence transform.

        Args:
            patch_size: Size of patches.
            max_seq_len: Maximum sequence length constraint.
            divisible_by_patch: Whether dimensions must be divisible by patch_size.
            max_ratio: Optional cap on scaling ratio.
            interpolation: Interpolation method or methods.
        ÚrandomN)ÚsuperÚ__init__r   r   r   r   r0   ÚstrÚ_RANDOM_INTERPOLATIONr=   r   )Úselfr   r   r   r   r=   Ú	__class__s         €r%   rA   zResizeToSequence.__init__„   s]   ø€ ô" 	‰ÑÔØ$ˆŒØ&ˆÔØ"4ˆÔØ"ˆŒÜ�m¤SÔ)Ø Ò(Ü%:�Õ"ä%7¸Ó%F�Õ"à!.ˆDÕr'   Úimgc                 ó¤  — t         j                  j                  |«      \  }}}t        ||f| j                  | j
                  | j                  | j                  ¬«      \  }}t        | j                  t        t        f«      r t        j                  | j                  «      }n| j                  }t         j                  j                  |||d¬«      }|S )z³Resize image to maintain aspect ratio and fit sequence constraint.

        Args:
            img: Input image tensor.

        Returns:
            Resized image tensor.
        )r   r   T)r=   Ú	antialias)r
   r   Úget_dimensionsr8   r   r   r   r   r0   r=   ÚtupleÚlistr?   ÚchoiceÚresize)rD   rF   Ú_ÚhÚwr7   r=   Úresized_imgs           r%   ÚforwardzResizeToSequence.forward£   s±   € ô ×'Ñ'×6Ñ6°sÓ;‰ˆˆ1ˆaä-Ø�ˆFØ�O‰OØ×ÑØ#×6Ñ6Ø—n‘nô
‰ˆˆ9ô �d×(Ñ(¬5´$¨-Ô8Ü"ŸM™M¨$×*<Ñ*<Ó=‰Mà ×.Ñ.ˆMä ×+Ñ+×2Ñ2°3¸	ÐQ^ÐjnÐ2ÓoˆàÐr'   )é   TNr:   )Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   Úboolr   Úfloatr   rB   r   r   rA   ÚtorchÚTensorrR   Ú__classcell__©rE   s   @r%   r<   r<   ~   s�   ø„ ñð  $Ø'+Ø)-ØZcñ/àð/ð ð/ð !%ð	/ð
   ‘ð/ð ! Ð&7¸Ð?PÐRUÐ?UÑ9VÐ!VÑWð/ð õ/ð>˜5Ÿ<™<ð ¨E¯L©L÷ r'   r<   c                   ód   ‡ — e Zd ZdZ	 	 	 	 	 	 	 	 	 	 	 dˆ fd„	Ze	 	 	 	 	 	 dd„«       Zd„ Zd„ Zˆ xZ	S )ÚResizeKeepRatioToSequencezS
    Resize and Keep Aspect Ratio, adapted to fit sequence length constraints.
    c                 ó  •— t         ‰| �  «        || _        || _        || _        t        |«      | _        |dk(  rt        | _        nt        |«      | _        || _
        || _        || _        |	| _        |
| _        || _        y)ua  
        Args:
            patch_size: Size of patches (int or tuple of (patch_h, patch_w))
            max_sequence_len: Maximum allowed sequence length for the resulting image
            divisible_by_patch: If True, ensure dimensions are divisible by patch_size
            longest: Float between 0-1 where 0=shortest side, 1=longest side determines scale
            interpolation: Interpolation method for resizing
            random_scale_prob: Probability of applying random scaling
            random_scale_range: Range for random scaling factor (min, max)
            random_scale_area: If True, scale factors affect area (âˆš factor)
            random_aspect_prob: Probability of applying random aspect ratio jittering
            random_aspect_range: Range for random aspect ratio (min, max)
            max_ratio: Maximum allowed scaling ratio
        r?   N)r@   rA   r   Úmax_sequence_lenr   rY   ÚlongestrC   r=   r   Úrandom_scale_probÚrandom_scale_rangeÚrandom_scale_areaÚrandom_aspect_probÚrandom_aspect_ranger   )rD   r   ra   r   rb   r=   rc   rd   re   rf   rg   r   rE   s               €r%   rA   z"ResizeKeepRatioToSequence.__init__Å   s~   ø€ ô8 	‰ÑÔØ$ˆŒØ 0ˆÔØ"4ˆÔÜ˜W“~ˆŒà˜HÒ$Ü!6ˆDÕä!3°MÓ!BˆDÔà!2ˆÔØ"4ˆÔØ!2ˆÔØ"4ˆÔØ#6ˆÔ Ø"ˆ�r'   c                 óN  — t        j                  | «      dd \  }}t        ||f||||
«      \  }}|\  }}||z  }||z  }t        ||«      |z  t	        ||«      d|z
  z  z   }|dkD  rRt        j
                  «       |k  r;t        j                  |d   |d   «      }|rdt        j                  |«      z  }||f}nd}|dkD  r‘t        j
                  «       |k  rzt        j                  |	d   «      t        j                  |	d   «      f}t        j                  t        j                  |Ž «      }t        j                  |«      }|d   |z  |d   |z  f}t        ||f|«      D ��cg c]  \  }}t        ||z  |z  «      ‘Œ }}}t        |t        «      r||}}n|\  }}t        |d   |«      |d<   t        |d   |«      |d<   |rB|t        j                  |d   |z  «      z  |d<   |t        j                  |d   |z  «      z  |d<   |d   |z  }|d   |z  }||z  }||kD  r„t        j                  ||z  «      }t        |d   |z  «      |d<   t        |d   |z  «      |d<   |rB|t        j                  |d   |z  «      z  |d<   |t        j                  |d   |z  «      z  |d<   |S c c}}w )zGet parameters for resizing.r   Nç      ð?r   )ri   ri   )ÚFrI   r8   r   r3   r?   Úuniformr   ÚsqrtÚlogÚexpÚzipÚroundr0   r   r   ) rF   r   ra   r   rb   rc   rd   re   rf   rg   r   Úimg_hÚimg_wrN   r7   Útarget_hÚtarget_wÚratio_hÚratio_wr    Úratio_factorÚ
log_aspectÚaspect_factorÚdimÚfÚsizeÚphÚpwr,   r-   r.   Ú
scale_backs                                    r%   Ú
get_paramsz$ResizeKeepRatioToSequence.get_paramsó   sã  € ô  ×'Ñ'¨Ó,¨Q¨RÐ0‰ˆˆuô .Ø�EˆNØØØØó
‰ˆˆ9ð 'Ñˆ�(ð ˜UÑ"ˆØ˜UÑ"ˆä�G˜WÓ%¨Ñ/´#°g¸wÓ2GÈ2ÐPWÉ<Ñ2XÑXˆð ˜qÒ ¤V§]¡]£_Ð7HÒ%HÜ!Ÿ>™>Ð*<¸QÑ*?ÐASÐTUÑAVÓWˆLÙ à!¤D§I¡I¨lÓ$;Ñ;�Ø(¨,Ð7‰Là#ˆLð  Ò!¤f§m¡m£oÐ8JÒ&JÜŸ(™(Ð#6°qÑ#9Ó:¼D¿H¹HÐEXÐYZÑE[Ó<\Ð]ˆJÜ ŸH™H¤V§^¡^°ZÐ%@ÓAˆMÜ ŸI™I mÓ4ˆMà(¨™O¨mÑ;¸\È!¹_È}Ñ=\Ð]ˆLô 69¸%À¸ÈÓ5V×W©6¨3°”�c˜E‘k A‘oÕ&ÐWˆÑWô �j¤#Ô&Ø �‰Bà‰FˆB�ô �d˜1‘g˜rÓ"ˆˆQ‰Ü�d˜1‘g˜rÓ"ˆˆQ‰ñ Øœ4Ÿ9™9 T¨!¡W¨r¡\Ó2Ñ2ˆD�‰GØœ4Ÿ9™9 T¨!¡W¨r¡\Ó2Ñ2ˆD�‰Gð ˜Q™ 2™ˆØ˜Q™ 2™ˆØ -Ñ/ˆàÐ%Ò%äŸ™Ð#3°gÑ#=Ó>ˆJÜ˜$˜q™' JÑ.Ó/ˆD�‰GÜ˜$˜q™' JÑ.Ó/ˆD�‰Gñ "ØœtŸy™y¨¨a©°2©Ó6Ñ6��Q‘ØœtŸy™y¨¨a©°2©Ó6Ñ6��Q‘àˆùóC Xs   Å!J!c                 óÆ  — | j                  || j                  | j                  | j                  | j                  | j
                  | j                  | j                  | j                  | j                  | j                  «      }t        | j                  t        t        f«      r t        j                   | j                  «      }n| j                  }t#        j$                  |||«      S )zb
        Resize the image with aspect ratio preservation and sequence length constraints.
        )r€   r   ra   r   rb   rc   rd   re   rf   rg   r   r0   r=   rJ   rK   r?   rL   rj   rM   )rD   rF   r|   r=   s       r%   rR   z!ResizeKeepRatioToSequence.forwardK  s±   € ð �‰ØØ�O‰OØ×!Ñ!Ø×#Ñ#Ø�L‰LØ×"Ñ"Ø×#Ñ#Ø×"Ñ"Ø×#Ñ#Ø×$Ñ$Ø�N‰Nó
ˆô �d×(Ñ(¬5´$¨-Ô8Ü"ŸM™M¨$×*<Ñ*<Ó=‰Mà ×.Ñ.ˆMä�x‰x˜˜T =Ó1Ð1r'   c                 ó*  — t        | j                  t        t        f«      rdnt	        | j                  «      }| j
                  j                  › d| j                  › d| j                  › d| j                  d›d| j                  d›d| j                  d›d�S )	Nr?   ú(patch_size=ú, max_sequence_len=z
, longest=z.3fz, random_scale_prob=z, random_aspect_prob=ú))r0   r=   rJ   rK   rB   rE   rT   r   ra   rb   rc   rf   )rD   Úinterpolate_strs     r%   Ú__repr__z"ResizeKeepRatioToSequence.__repr__d  sœ   € Ü&0°×1CÑ1CÄeÌTÀ]Ô&S™(ÔY\Ð]a×]oÑ]oÓYpˆØ—>‘>×*Ñ*Ð+¨<¸¿¹Ð7Hð I$Ø$(×$9Ñ$9Ð#:ð ;ØŸ<™<¨Ð,ð -%Ø%)×%;Ñ%;¸CÐ$@ð A&Ø&*×&=Ñ&=¸cÐ%BÀ!ð	Eð 	Fr'   )é   rS   Tç        r9   r‰   )g333333ë?gÍÌÌÌÌÌð?Fr‰   ©gÍÌÌÌÌÌì?gÃõ(\�Âñ?N)r‰   )ri   gHáz®Gõ?Fr‰   rŠ   N)
rT   rU   rV   rW   rA   Ústaticmethodr€   rR   r‡   r\   r]   s   @r%   r_   r_   À   sg   ø„ ñð Ø!Ø#ØØ$Ø Ø+Ø#Ø!Ø +Øõ,#ð\ ð !Ø*Ø#Ø!Ø +ØòUó ðUòn2ö2Fr'   r_   c                   ó\   ‡ — e Zd ZdZ	 	 	 d	dedededeeeeeef   f   def
ˆ fd„Z	d„ Z
ˆ xZS )
ÚCenterCropToSequencezVCenter crop the image such that the resulting patch sequence length meets constraints.r   r   r   ÚfillÚpadding_modec                 óh   •— t         ‰| �  «        || _        || _        || _        || _        || _        y ©N)r@   rA   r   r   r   rŽ   r�   )rD   r   r   r   rŽ   r�   rE   s         €r%   rA   zCenterCropToSequence.__init__o  s6   ø€ ô 	‰ÑÔØ$ˆŒØ&ˆÔØ"4ˆÔØˆŒ	Ø(ˆÕr'   c                 óð   — t         j                  j                  |«      \  }}}t        ||f| j                  | j
                  | j                  «      \  }}t        ||| j                  | j                  ¬«      S )zKCenter crop the image to maintain aspect ratio and fit sequence constraint.)rŽ   r�   )
r
   r   rI   r8   r   r   r   r   rŽ   r�   )rD   rF   rN   rO   rP   r7   s         r%   rR   zCenterCropToSequence.forward  si   € ä×'Ñ'×6Ñ6°sÓ;‰ˆˆ1ˆaÜ-Ø�ˆFØ�O‰OØ×ÑØ×#Ñ#ó	
‰ˆˆ9ô " # y°t·y±yÈt×O`ÑO`ÔaÐar'   ©Tr   Úconstant)rT   rU   rV   rW   r   rX   r   r   rB   rA   rR   r\   r]   s   @r%   r�   r�   m  sa   ø„ Ù`ð
 (,Ø56Ø *ñ)àð)ð ð)ð !%ð	)ð
 ˜˜U 3¨¨S =Ñ1Ð1Ñ2ð)ð õ)ö br'   r�   c                   óx   ‡ — e Zd ZdZ	 	 	 ddedededeeeeeef   f   def
ˆ fd„Z	e
d„ «       Zd	„ Zd
efd„Zˆ xZS )ÚRandomCropToSequencea,  Randomly crop and/or pad the image to fit sequence length constraints.

    This maintains aspect ratio while ensuring the resulting image, when divided into patches,
    will not exceed the specified maximum sequence length. Similar to CentralCropToSequence
    but with randomized positioning.
    r   ra   r   rŽ   r�   c                 óh   •— t         ‰| �  «        || _        || _        || _        || _        || _        y)a›  
        Args:
            patch_size: Size of patches (int or tuple of (patch_h, patch_w))
            max_sequence_len: Maximum allowed sequence length for the resulting image
            divisible_by_patch: If True, resulting image dimensions will be multiples of patch_size
            fill: Fill value for padding
            padding_mode: Padding mode ('constant', 'edge', 'reflect', 'symmetric')
        N)r@   rA   r   ra   r   rŽ   r�   )rD   r   ra   r   rŽ   r�   rE   s         €r%   rA   zRandomCropToSequence.__init__•  s6   ø€ ô  	‰ÑÔØ$ˆŒØ 0ˆÔØ"4ˆÔØˆŒ	Ø(ˆÕr'   c           
      ó†  — t         j                  j                  | «      \  }}}||d   z
  }||d   z
  }|dk(  rd}n<t        t	        j
                  t        j                  dt        |«      «      |«      «      }|dk(  rd}||fS t        t	        j
                  t        j                  dt        |«      «      |«      «      }||fS )z!Get random position for crop/pad.r   r   )	r
   r   rI   r   r   Úcopysignr?   ÚrandintÚabs)	rF   Útarget_sizerN   Úimage_heightÚimage_widthÚdelta_heightÚdelta_widthÚtopÚlefts	            r%   r€   zRandomCropToSequence.get_params¬  s»   € ô (2×'<Ñ'<×'KÑ'KÈCÓ'PÑ$ˆˆ<˜Ø# k°!¡nÑ4ˆØ! K°¡NÑ2ˆð ˜1ÒØ‰Cä”d—m‘m¤F§N¡N°1´c¸,Ó6GÓ$HÈ,ÓWÓXˆCà˜!ÒØˆDð �DˆyÐô ”t—}‘}¤V§^¡^°A´s¸;Ó7GÓ%HÈ+ÓVÓWˆDà�DˆyÐr'   c           	      ó0  — t         j                  j                  |«      \  }}}t        ||f| j                  | j
                  | j                  d¬«      \  }}| j                  ||«      \  }}t        ||||d   |d   | j                  | j                  ¬«      S )zTRandomly crop or pad the image to maintain aspect ratio and fit sequence constraint.ri   )r   r   r   )r¡   r¢   ÚheightÚwidthrŽ   r�   )r
   r   rI   r8   r   ra   r   r€   r   rŽ   r�   )rD   rF   rN   rq   rr   r7   r¡   r¢   s           r%   rR   zRandomCropToSequence.forwardÀ  sŸ   € ô %×/Ñ/×>Ñ>¸sÓC‰ˆˆ5�%ô .Ø�EˆNØ�O‰OØ×!Ñ!Ø×#Ñ#Øô
‰ˆˆ9ð —O‘O C¨Ó3‰	ˆˆTô ØØØØ˜Q‘<Ø˜A‘,Ø—‘Ø×*Ñ*ô
ð 	
r'   r   c                 ó‚   — | j                   j                  › d| j                  › d| j                  › d| j                  › d�S )Nrƒ   r„   ú, divisible_by_patch=r…   )rE   rT   r   ra   r   )rD   s    r%   r‡   zRandomCropToSequence.__repr__Ý  sN   € Ø—>‘>×*Ñ*Ð+¨<¸¿¹Ð7Hð I$Ø$(×$9Ñ$9Ð#:ð ;&Ø&*×&=Ñ&=Ð%>¸aðAð 	Br'   r“   )rT   rU   rV   rW   r   rX   r   r   rB   rA   r‹   r€   rR   r‡   r\   r]   s   @r%   r–   r–   �  s„   ø„ ñð (,Ø56Ø *ñ)àð)ð "ð)ð !%ð	)ð
 ˜˜U 3¨¨S =Ñ1Ð1Ñ2ð)ð õ)ð. ñó ðò&
ð:B˜#÷ Br'   r–   c                 óÚ   — t        | t        «      rt        | «      |k7  rt        |› d|› d�«      ‚| d   | d   kD  r0t	        j
                  |j                  «       › d�«       | d   | d   fS | S )Nz  should be a sequence of length ú.r   r   z range reversed. Swapping.)r0   r   r1   r2   ÚwarningsÚwarnÚ
capitalize)ÚvalueÚnameÚlengths      r%   Ú_validate_ranger°   ã  sv   € ä�eœXÔ&¬#¨e«*¸Ò*>Ü˜D˜6Ð!AÀ&ÀÈÐKÓLÐLð ˆQ�x�%˜‘(ÒÜ�‰˜Ÿ™Ó*Ð+Ð+EÐFÔGØ�Q‰x˜˜q™Ð!Ð!à€Lr'   c                   ó®  ‡ — e Zd ZdZ	 	 	 	 	 	 	 	 	 ddeeeeef   f   ded	eeef   d
eeef   deee	f   de
dee   deeeef      defˆ fd„Zedddddddefdej                   d	eeef   d
eeef   dedededede
dee   deeeef      deee	   e	f   deeeeeef   eeef   e	f   fd„«       Zdej                   dej                   fd„Zdefd„Zˆ xZS )ÚRandomResizedCropToSequencea�	  
    Randomly crop the input image to a subregion with varying area and aspect ratio
    (relative to the original), then resize that crop to a target size. The target size
    is determined such that patchifying the resized image (with `patch_size`)
    does not exceed `max_seq_len` patches, while maintaining the aspect ratio of the crop.

    This combines aspects of torchvision's RandomResizedCrop with sequence length constraints.

    Args:
        patch_size (int or tuple[int, int]):
            Patch dimensions (patch_h, patch_w) for sequence length calculation.
        max_seq_len (int):
            Maximum number of patches allowed in the final image.
        scale (tuple[float, float]):
            Range (min, max) of area fraction of the original image to crop.
        ratio (tuple[float, float]):
            Range (min, max) of aspect ratio *multipliers* for the crop, relative
            to the original image's aspect ratio. E.g., (0.75, 1.333) means the
            crop's aspect ratio will be sampled between 0.75*orig_ar and 1.333*orig_ar.
            Uses log-uniform sampling.
        interpolation (str or InterpolationMode):
            Interpolation mode for resizing. Can be 'bilinear', 'bicubic', 'nearest',
            or 'random' (chooses between bilinear and bicubic).
            Defaults to 'bicubic'.
        divisible_by_patch (bool):
            If True, the final image height and width will be multiples of the
            respective patch dimensions. Defaults to True.
        max_ratio (float, optional):
            An optional upper limit on the scaling ratio applied during resizing.
            Prevents excessive upsampling of the initial crop. `max_ratio=1.0`
            prevents any upsampling beyond the cropped size. Defaults to None (no limit).
        final_scale_range (tuple[float, float], optional):
            If provided, applies an *additional* random scaling factor to the
            final target size. The factor is sampled uniformly from this range,
            and multiplied by the size determined by `get_image_size_for_seq`.
            E.g., (0.8, 1.0) means the final size will be between 80% and 100%
            of the maximum feasible size. Defaults to None (use maximum feasible size).
        attempts (int):
            Number of attempts to sample a valid crop geometry before falling back
            to a center crop strategy. Defaults to 10.
    rˆ   rS   TNé
   r   r   Úscaler    r=   r   r   Úfinal_scale_rangeÚattemptsc
                 óÈ  •— t         ‰
| �  «        t        |t        «      r||c| _        | _        n(t        |«      dk7  rt        d«      ‚|\  | _        | _        || _        || _	        || _
        || _        || _        || _        |	| _        t        |t        «      r"|dk(  rt         | _        nt%        |«      | _        n|| _        t'        | j                  d«      | _	        t'        | j                  d«      | _
        | j                  �_t'        | j                  d«      | _        d| j                  d   cxk  r| j                  d	   cxk  rd
k  sn t)        j*                  d«       y y y )Nr   r   r?   r´   r    rµ   r‰   r   r   ri   z?final_scale_range values should ideally be between 0.0 and 1.0.)r@   rA   r0   r   r#   r$   r1   r2   r   r´   r    r   r   rµ   r¶   rB   rC   r=   r   r°   rª   r«   )rD   r   r   r´   r    r=   r   r   rµ   r¶   rE   s             €r%   rA   z$RandomResizedCropToSequence.__init__  sB  ø€ ô 	‰ÑÔÜ�j¤#Ô&Ø)3°ZÐ&ˆDŒL˜$�,ô �:‹ !Ò#Ü Ð!fÓgÐgØ)3Ñ&ˆDŒL˜$œ,Ø&ˆÔØˆŒ
ØˆŒ
Ø"4ˆÔØ"ˆŒØ!2ˆÔØ ˆŒÜ�m¤SÔ)Ø Ò(Ü%:�Õ"ä%7¸Ó%F�Õ"à!.ˆDÔô % T§Z¡Z°Ó9ˆŒ
Ü$ T§Z¡Z°Ó9ˆŒ
ð ×!Ñ!Ð-Ü%4°T×5KÑ5KÐM`Ó%aˆDÔ"ð ˜4×1Ñ1°!Ñ4ÔX¸×8NÑ8NÈqÑ8QÔXÐUXÔXÜ—‘Ð_Õ`ð Yð	 .r'   rF   Úcrop_attemptsr#   r$   r   c                 ó¤  — t        j                  | «      \  }}}|dk  s|dk  rt        d|› d|› �«      ‚||z  }||z  }t        j                  |d   «      t        j                  |d   «      f}t        |«      D ]ú  }|t        j                  |d   |d   «      z  }t        j                  t        j                  |d   |d   «      «      }||z  }t        t        t        j                  ||z  «      «      «      }t        t        t        j                  ||z  «      «      «      }d|cxk  r|k  sŒ¶n Œ¹d|cxk  r|k  sŒÅn ŒÈt        j                  d||z
  «      }t        j                  d||z
  «      } n� ||d   z  }||d   z  }||k  r$|}t        t        t        ||z  «      «      |«      }n-||kD  r$|}t        t        t        ||z  «      «      |«      }n|}|}t        d|«      }t        d|«      }||z
  dz  }||z
  dz  }t        ||f||f|||¬«      \  }}|}|	�û|	\  }}t        j                  ||«      }t        t        |d«      d«      }||z  |z  } ||z  |z  }!|r7|t        j                   | |z  «      z  }"|t        j                   |!|z  «      z  }#n(t        t        | «      «      }"t        t        |!«      «      }#t        |"|«      }"t        |#|«      }#|"|#f}|d   |z  }$|d   |z  }%|$|%z  |kD  r%|}t#        j$                  d	|d
›d|› d|› d|› d�	«       t'        |
t(        t*        f«      rt        j,                  |
«      }
n|
}
||||f||
fS )zP Get parameters for a random sized crop relative to image aspect ratio.
        r   z1Input image must have positive dimensions, got H=z, W=r   r   )r   r   r   r   r‰   ri   zFinal scale randomization (z.2fz) resulted in size z exceeding max_seq_len=z, after rounding. Reverting to feasible size r©   )rj   rI   r2   r   rm   Úranger?   rk   rn   r   rp   rl   rš   r3   r   r8   r   rª   r«   r0   rJ   rK   rL   )&rF   r´   r    r¸   r#   r$   r   r   r   rµ   r=   rN   r¤   r¥   ÚareaÚorig_aspectÚ	log_ratioÚtarget_areaÚaspect_ratio_factorÚaspect_ratioÚcrop_hÚcrop_wr¡   r¢   Úmin_aspect_ratioÚmax_aspect_ratioÚfeasible_ratioÚfeasible_sizeÚ
final_sizeÚmin_scÚmax_scÚscale_factorÚraw_hÚraw_wrs   rt   r,   r-   s&                                         r%   r€   z&RandomResizedCropToSequence.get_paramsJ  sÅ  € ô  ×+Ñ+¨CÓ0Ñˆˆ6�5Ø�QŠ;˜% 1š*ÜÐ QÐRXÐQYÐY]Ð^cÐ]dÐeÓfÐfà˜‰~ˆØ˜f‘nˆÜ—X‘X˜e A™hÓ'¬¯©°%¸±(Ó);Ð<ˆ	ä�}Ó%ò '	)ˆAØ¤§¡°°a±¸%À¹(Ó!CÑCˆKÜ"&§(¡(¬6¯>©>¸)ÀA¹,È	ÐRSÉÓ+UÓ"VÐØ&Ð)<Ñ<ˆLô œœtŸy™y¨°|Ñ)CÓDÓEÓFˆFÜœœtŸy™y¨°|Ñ)CÓDÓEÓFˆFà�6Ô"˜UÖ" q¨6Ô';°VÖ';Ü—n‘n Q¨°©Ó8�Ü—~‘~ a¨°©Ó8�Ùð'	)ð$  +¨U°1©XÑ5ÐØ*¨U°1©XÑ5ÐàÐ-Ò-à�ÜœS¤ vÐ0@Ñ'@Ó!AÓBÀFÓK‘ØÐ/Ò/à�ÜœS¤ vÐ0@Ñ'@Ó!AÓBÀEÓJ‘ð �Ø�ô ˜˜F“^ˆFÜ˜˜F“^ˆFà˜F‘? qÑ(ˆCØ˜F‘N qÑ(ˆDô )?Ø�VÐØ Ð)Ø#Ø1Øô)
Ñ%ˆ˜ð #ˆ
ØÐ(Ø.‰NˆF�FÜ!Ÿ>™>¨&°&Ó9ˆLÜœs <°Ó5°sÓ;ˆLð ˜^Ñ+¨lÑ:ˆEØ˜^Ñ+¨lÑ:ˆEñ "à"¤T§Y¡Y¨u°w©Ó%?Ñ?�Ø"¤T§Y¡Y¨u°w©Ó%?Ñ?‘äœu U›|Ó,�Üœu U›|Ó,�ô ˜8 WÓ-ˆHÜ˜8 WÓ-ˆHØ" HÐ-ˆJð ' q™M¨WÑ4ˆMØ& q™M¨WÑ4ˆMØ Ñ-°Ò<à+�Ü—‘Ð!<¸\È#Ð<NÐNaÐblÐamð  nEð  FQð  ERð  R~ð  Lð  ~Mð  MNð   Oô  Pô �m¤e¬T ]Ô3Ü"ŸM™M¨-Ó8‰Mà)ˆMà�T˜6 6Ð*¨J¸ÐEÐEr'   c                 ó@  — | j                  || j                  | j                  | j                  | j                  | j
                  | j                  | j                  | j                  | j                  ¬«
      \  }}}|\  }}}}t        j                  |||||||d¬«      }	|	S )N)	r´   r    r¸   r#   r$   r   r   rµ   r=   T)r¡   r¢   r¤   r¥   r|   r=   rH   )r€   r´   r    r¶   r#   r$   r   r   rµ   r=   rj   Úresized_crop)
rD   rF   Úcrop_paramsrÇ   r=   r¡   r¢   rÁ   rÂ   Úoutputs
             r%   rR   z#RandomResizedCropToSequence.forward¿  s¤   € à15·±ØØ—*‘*Ø—*‘*ØŸ-™-Ø—L‘LØ—L‘LØ#×6Ñ6Ø×(Ñ(Ø"×4Ñ4Ø×,Ñ,ð 2Aó 2
Ñ.ˆ�Z ð %0Ñ!ˆˆT�6˜6ä—‘ØØØØØØØ'Øô	
ˆð ˆr'   c                 ó@  — t        | j                  t        t        f«      r#dj	                  d„ | j                  D «       «      }nt        | j                  «      }| j                  j                  dz   }|d| j                  › d| j                  › d�z  }|d| j                  › �z  }|d| j                  › �z  }|d| j                  › �z  }|d	|› d
�z  }|d| j                  › �z  }|d| j                  › �z  }|d| j                  › �z  }|d| j                   › �z  }|dz  }|S )Nz, c              3   óV   K  — | ]!  }t        |«      j                  d «      d   –— Œ# y­w)r©   éÿÿÿÿN)rB   Úsplit)Ú.0Úms     r%   ú	<genexpr>z7RandomResizedCropToSequence.__repr__.<locals>.<genexpr>Þ  s"   è ø€ Ò'ZÀ!¬¨A«¯©°SÓ(9¸"Õ(=Ñ'Zùs   ‚')ú(zpatch_size=(r…   z, max_seq_len=z, scale=z, ratio=z, interpolation=[ú]r§   z, max_ratio=z, final_scale_range=z, attempts=)r0   r=   rJ   rK   ÚjoinrB   rE   rT   r#   r$   r   r´   r    r   r   rµ   r¶   )rD   r†   Úformat_strings      r%   r‡   z$RandomResizedCropToSequence.__repr__Ü  s9  € Ü�d×(Ñ(¬5´$¨-Ô8Ø"Ÿi™iÑ'ZÀt×GYÑGYÔ'ZÓZ‰Oä! $×"4Ñ"4Ó5ˆOØŸ™×/Ñ/°#Ñ5ˆØ˜<¨¯© ~°R¸¿¹°~ÀQÐGÑGˆØ˜>¨$×*:Ñ*:Ð);Ð<Ñ<ˆØ˜8 D§J¡J <Ð0Ñ0ˆØ˜8 D§J¡J <Ð0Ñ0ˆØÐ,¨_Ð,=¸QÐ?Ñ?ˆØÐ0°×1HÑ1HÐ0IÐJÑJˆØ˜<¨¯©Ð'7Ð8Ñ8ˆØÐ/°×0FÑ0FÐ/GÐHÑHˆØ˜; t§}¡} oÐ6Ñ6ˆØ˜ÑˆØÐr'   )	rˆ   rS   )g{®Gáz´?ri   )gš™™™™™é?g      ô?r:   TNNr³   )rT   rU   rV   rW   r   r   r   rY   rB   r   rX   r   rA   r‹   rC   rZ   r[   r   r€   rR   r‡   r\   r]   s   @r%   r²   r²   ð  s  ø„ ñ(ðX 35ØØ%0Ø%/Ø7@Ø#'Ø%)Ø;?Øñ-aà˜#˜u S¨# X™Ð.Ñ/ð-að ð-að �U˜E�\Ñ"ð	-að
 �U˜E�\Ñ"ð-að ˜SÐ"3Ð3Ñ4ð-að !ð-að ˜E‘?ð-að $ E¨%°¨,Ñ$7Ñ8ð-að õ-að^ ð
 "$ØØØ#Ø'+Ø)-Ø?CØOdñrFØ—‘ðrFà˜ ˜Ñ&ðrFð ˜ ˜Ñ&ðrFð ð	rFð
 ðrFð ðrFð ðrFð !%ðrFð   ‘ðrFð  (¨¨e°U¨lÑ(;Ñ<ðrFð ! Ð&7Ñ!8Ð:KÐ!KÑLðrFð 
ˆu�S˜#˜s CÐ'Ñ(¨%°°S°©/Ð;LÐLÑ	MòrFó ðrFðh˜5Ÿ<™<ð ¨E¯L©Ló ð:˜#÷ r'   r²   rF   ÚpadÚinclude_infoÚflatten_patchesÚchannels_lastc                 ó¼  — | j                   \  }}}|\  }	}
|rd||	z  dk7  s||
z  dk7  rT|	||	z  z
  |	z  }|
||
z  z
  |
z  }t        j                  j                  j	                  | d|d|f«      } | j                   \  }}}||	z  ||
z  }}|rW| j                  |||	||
«      j                  ddddd«      }|r|j                  d|	|
z  |z  «      n|j                  d|	|
|«      }nV| j                  |||	||
«      j                  ddddd«      }|r|j                  d||	z  |
z  «      n|j                  d||	|
«      }|r¥t        j                  t        j                  |«      t        j                  |«      d¬«      \  }}t        j                  |j                  d«      |j                  d«      gd¬	«      }t        j                  ||z  t        j                  ¬
«      }|||fS |S )aÍ  Patchify a single ``(C, H, W)`` image.

    Args:
        img: Input image tensor of shape ``[C, H, W]``.
        patch_size: Patch dimensions ``(patch_h, patch_w)``.
        pad: Whether to zero-pad to a multiple of patch size.
        include_info: Also return ``(patch_coord, patch_valid)``.
        flatten_patches: If ``True``, returned patches are 2-D ``[N, P*P*C]``;
            otherwise 4-D (unflattened per-patch).
        channels_last: Per-patch flat layout. ``True`` (default) yields ``P-P-C``
            flat; ``False`` yields ``C-P-P`` flat (HF / Gemma4 native). When
            ``flatten_patches=False``, ``True`` returns ``[N, Ph, Pw, C]`` and
            ``False`` returns ``[N, C, Ph, Pw]``.
    r   r   é   r   é   rÓ   Úij)Úindexing)rz   )Údtype)ÚshaperZ   Únnr   rÜ   ÚviewÚpermuteÚreshapeÚmeshgridÚarangeÚstackÚonesrX   )rF   r   rÜ   rÝ   rÞ   rß   ÚcrO   rP   r}   r~   Úpad_hÚpad_wÚnhÚnwÚpatchesÚy_idxÚx_idxÚcoordÚvalids                       r%   Úpatchify_imagerù   ï  sÐ  € ð, �i‰i�G€A€qˆ!Ø�F€Bˆñ ��B‘˜!’˜q 2™v¨š{Ø�a˜"‘f‘ Ñ"ˆØ�a˜"‘f‘ Ñ"ˆÜ�h‰h×!Ñ!×%Ñ% c¨A¨u°a¸Ð+?Ó@ˆØ—)‘)‰ˆˆ1ˆað �"‰W�a˜2‘gˆ€BáØ—(‘(˜1˜b " b¨"Ó-×5Ñ5°a¸¸A¸qÀ!ÓDˆá6E�'—/‘/ " b¨2¡g°¡kÔ2È7Ï?É?Ð[]Ð_aÐceÐghÓKi‰à—(‘(˜1˜b " b¨"Ó-×5Ñ5°a¸¸A¸qÀ!ÓDˆá6E�'—/‘/ " a¨"¡f¨r¡kÔ2È7Ï?É?Ð[]Ð_`ÐbdÐfhÓKiˆáä—~‘~¤e§l¡l°2Ó&6¼¿¹ÀRÓ8HÐSWÔX‰ˆˆuä—‘˜UŸ]™]¨2Ó.°·±¸bÓ0AÐBÈÔJˆä—
‘
˜2 ™7¬%¯*©*Ô5ˆØ˜˜uÐ$Ð$à€Nr'   c                   óP   ‡ — e Zd ZdZ	 	 ddeeeeef   f   dedefˆ fd„Zd„ Z	ˆ xZ
S )ÚPatchifyzSTransform an image into patches with corresponding coordinates and type indicators.r   rÞ   rß   c                 ót   •— t         ‰| �  «        t        |t        «      r|n||f| _        || _        || _        y r‘   )r@   rA   r0   rJ   r   rÞ   rß   )rD   r   rÞ   rß   rE   s       €r%   rA   zPatchify.__init__*  s8   ø€ ô 	‰ÑÔÜ(2°:¼uÔ(E™*ÈJÐXbÐKcˆŒØ.ˆÔØ*ˆÕr'   c                 óâ   — t        |t        j                  «      rt        j                  j	                  |«      }t        || j                  | j                  | j                  ¬«      \  }}}|||dœS )a!  
        Args:
            img: A PIL Image or tensor of shape [C, H, W]

        Returns:
            A dictionary containing:
                - patches: Tensor of shape [N, P*P*C] if flatten_patches=True,
                          or [N, Ph, Pw, C] if flatten_patches=False and channels_last=True
                          or [N, C*P*P] / [N, C, Ph, Pw] if channels_last=False
                - patch_coord: Tensor of shape [N, 2] with (y, x) coordinates
                - patch_valid: Valid indicator (all 1s for non-padding patches)
        )rÞ   rß   )rô   Úpatch_coordÚpatch_valid)	r0   r	   r
   r   Ú	to_tensorrù   r   rÞ   rß   )rD   rF   rô   r÷   rø   s        r%   rR   zPatchify.forward5  sj   € ô �cœ5Ÿ;™;Ô'ä×'Ñ'×1Ñ1°#Ó6ˆCä .ØØ�O‰OØ ×0Ñ0Ø×,Ñ,ô	!
Ñˆ�˜ð Ø Ø ñ
ð 	
r'   )TT)rT   rU   rV   rW   r   r   r   rX   rA   rR   r\   r]   s   @r%   rû   rû   '  sF   ø„ Ù]ð
 %)Ø"&ñ		+à˜c 5¨¨c¨¡?Ð2Ñ3ð	+ð "ð	+ð  õ		+ö
r'   rû   )rˆ   rS   TNgñhãˆµøä>)r   )TTTT)(rW   r   r?   rª   Útypingr   r   r   r   r   r   rZ   ÚPILr	   Útorchvisionr
   Útorchvision.transformsr   rj   Ú!torchvision.transforms.functionalr   r   r   r   r   rX   rY   r8   rC   rç   ÚModuler<   r_   r�   r–   r°   r²   r[   rù   rû   r)   r'   r%   ú<module>r     sï  ðñ	ó Û Û ß ?× ?ã Ý Ý "Ý 2Ý ?ç KÑ Kð
 35ØØ#'Ø%)Øñ^Ø˜˜S˜‘/ð^à˜#˜u S¨# X™Ð.Ñ/ð^ð ð^ð !ð	^ð
 ˜E‘?ð^ð ð^ð ˆ5�%˜˜S˜‘/Ð!Ñ"ó^ñB ,¨JÓ7Ñ9KÈIÓ9VÐWÐ ô?�u—x‘x—‘ô ?ôDjF §¡§¡ô jFôZb˜5Ÿ8™8Ÿ?™?ô bô@SB˜5Ÿ8™8Ÿ?™?ô SBól
ô| %§(¡(§/¡/ô |ðD Ø!Ø $Ø"ñ5Ø�\‰\ð5à˜#˜s˜(‘Oð5ð ð5ð ð	5ð
 ð5ð ð5ð ˆ5�<‰<˜˜uŸ|™|¨U¯\©\¸5¿<¹<ÐGÑHÐHÑIó5ôp*
ˆu�x‰x�‰õ *
r'   