
    ^j                        d Z ddlmZ ddlmZ ddlmZ ddlZddlZddl	Z	ddl
mZ ddlmZ ddlmZmZmZ dd	lmZ dd
lmZmZ ddlmZ  e       ZddZddZddZ	 	 	 d 	 	 	 	 	 	 	 	 	 d!dZd"dZd#dZ G d de	j>                  j@                        Z  G d de!      Z"dd	 	 	 	 	 	 	 d$dZ#	 	 	 	 	 	 	 	 d%	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 d&dZ$	 	 	 	 	 	 	 	 d%	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 d&dZ%d'dZ&d(dZ'd'dZ(y))zCOCO dataset which returns image_id for evaluation.

Mostly copy-paste from https://github.com/pytorch/vision/blob/13b35ff/references/detection/coco_utils.py
    )annotations)Path)AnyN)Image)Tensor)ComposeToDtypeToImage)
AUG_CONFIG)AlbumentationsWrapper	Normalize)
get_loggerc                @    t        |       dz  dz  j                         S )Ntrain_annotations.coco.json)r   exists)dataset_dirs    _/var/www/ramen.bs-engineer-server.com/venv/lib/python3.12/site-packages/rfdetr/datasets/coco.pyis_valid_coco_datasetr   '   s!    '*BBJJLL    c                   | j                   j                         D ch c]3  \  }}|j                  d      s|j                  d      s)t        |      5 }}}|rt	        |      S | j
                  j                         D ]O  }|j                  d      st        |j                  dd            dkD  s3|j                  t        |d                Q t	        |      S c c}}w )zLReturn sorted COCO category ids that carry keypoint metadata or annotations.	keypointsskeletonnum_keypointsr   category_id)catsitemsgetintsortedannsvaluesadd)cococat_idcategorycategory_ids
annotations        r   _category_ids_with_keypointsr)   +   s     -1IIOO,=(kAZ^f^j^jku^vFL  l##ii&&( =
>>+&#jnn_a.P*QTU*USM!:;<= ,s   *C	Cc                $   t        |xs g       }t        |      D cg c]  \  }}|dkD  s| }}}|st        d      t        |       }|st        d      t	        |      t	        |      kD  r$t        dt	        |       dt	        |       d      t        d | j                  j                         D              }t        t	        |      t        |      dz         }t               }	i }
t        ||      D ]>  \  }}||k\  rt        d	| d
| dt	        |       d      ||
|<   |	j                  |       @ t        |      D cg c]	  }||	vs| }}|D ],  }||
v r|st        d| d      |j                  d      |
|<   . |
S c c}}w c c}w )a  Map COCO category ids onto model label slots that have keypoint capacity.

    RF-DETR keypoint schemas are indexed by model label. The preview person-keypoint schema is ``[17]``: label slot
    ``0`` owns the 17 COCO person keypoints. Legacy checkpoints may still use a background-first ``[0, 17]`` schema
    where slot ``0`` is reserved (0 keypoints) and slot ``1`` is person. This helper maps keypoint-bearing categories
    onto slots with a non-zero keypoint count (``count > 0``), so both layouts keep supervision aligned. For multi-class
    keypoint training supply e.g. ``[17, 4]`` where each non-zero entry corresponds to a keypoint-bearing category in
    ascending COCO category ID order.
    r   zKeypoint COCO dataset requested, but num_keypoints_per_class has no active keypoint slots. Provide a schema such as [17] for the keypoint preview model.zKeypoint COCO dataset has no keypoint category metadata and no keypoint annotations. Expected COCO categories with a 'keypoints' field or annotations with 'keypoints'/'num_keypoints'.z<Keypoint COCO dataset has more keypoint-bearing categories (z) than active schema slots (zR). Multi-class keypoint training needs an explicit num_keypoints_per_class schema.c              3  2   K   | ]  }t        |        y w)N)r   ).0r%   s     r   	<genexpr>z,_build_keypoint_cat2label.<locals>.<genexpr>X   s     GFCKGs      zKeypoint schema slot z for category_id z# exceeds the detected class count (zE). Pass num_classes large enough to include this keypoint label slot.z>No free model label slots remain for non-keypoint category_id .)list	enumerate
ValueErrorr)   lenr    r   keysmaxsetzipr#   rangepop)r$   num_keypoints_per_classschemaidxcountactive_slotskeypoint_cat_idssorted_cat_idsrequired_slotsassigned_slots	cat2labelr%   slot
free_slotss                 r   _build_keypoint_cat2labelrF   9   s    )/R0F*3F*;IJCuqyCILIL
 	

 4D9q
 	
 s<00$%&&B3|CTBU V^^
 	
 Gdiinn6FGGN^,c,.?!.CDN"uN "I,l; !>!'v->vh G'((mo  !	&4 ! $)#8W4D<V$WJW  .Y]^d]eefghh&NN1-	&. U JD Xs   FF	FFc                    | ||z  z  }|sg dng d}|D cg c]  }||z   	 }}|D cg c]
  }||z  |z   }	}|	D cg c]  }|||z  dz  k\  s| }	}|	S c c}w c c}w c c}w )N)r   r.            )rH   rI   rJ   r   r.   rK   rL   rM      rK    )

resolutionexpanded_scales
patch_sizenum_windowsbase_num_patches_per_windowoffsetsoffsetscalesscaleproposed_scaless
             r   compute_multi_scale_scalesr\   q   s     #-k1I"J1@)FlGAHIv)F2IFIEKLEuz)K7LOL*ezK7ORS7S.SO   JLs   AAA!A!c                :    t        | t              xr
 d| v xr d| v S )u:  Check whether a COCO segmentation entry is in RLE format.

    RLE annotations are dicts with ``"counts"`` and ``"size"`` keys, as opposed to polygon annotations which are lists
    of coordinate arrays. This is a structural check only — it verifies key presence but does not validate value types.
    A dict with counts=None will pass this check but fail downstream in convert_coco_poly_to_mask.

    Args:
        segmentation: A single COCO segmentation annotation entry.

    Returns:
        ``True`` if the entry looks like an RLE dict, ``False`` otherwise.
    countssize)
isinstancedict)segmentations    r   _is_rlerc      s&     lD)ah,.Fa6UaKaar   c                   ddl m} g }| D ]s  }|t        |t              sEt	        |      dk(  r7|j                  t        j                  ||ft        j                               [t        |      rq|d   }t        |t        t        t        f      s"t        dt        |      j                  d      t        |t        t        f      r|g}n(|j!                  |||      g}n|j!                  |||      }|j#                  |      }|j$                  dk  r|d   }t        j&                  |t        j                        }|j)                  d	
      j+                  t        j                        }|j                  |       v t	        |      dk(  r(t        j                  d||ft        j                        S t        j,                  |d
      S )a  Convert COCO segmentation annotations to a binary mask tensor of shape ``[N, H, W]``.

    Supports both polygon and RLE (Run-Length Encoding) annotation formats. Polygon annotations (lists of coordinate
    arrays) are rasterised via ``pycocotools.mask.frPyObjects``.  RLE annotations (dicts with ``"counts"`` and
    ``"size"`` keys; ``counts`` may be str or bytes for compressed RLE, or list of ints for uncompressed RLE) are
    decoded directly, skipping the polygon-to-RLE conversion step.

    Args:
        segmentations: Per-instance segmentation annotations.  Each element is
            either a polygon list (``[[x1, y1, x2, y2, ...], ...]``), an RLE dict (``{"counts": ..., "size": [H, W]}``),
            or ``None`` / empty for instances without a mask. Dicts must be valid COCO RLE annotations with non-empty
            ``"counts"`` and ``"size"`` fields.
        height: Image height in pixels (used for polygon rasterisation).
        width: Image width in pixels (used for polygon rasterisation).

    Returns:
        A ``uint8`` tensor of shape ``(N, H, W)`` where each slice is a binary mask for one instance.  Returns a ``(0,
        H, W)`` tensor when *segmentations* is empty.
    r   Ndtyper^   z-RLE segmentation has unsupported counts type z; expected str, bytes, or listrL   ).NrK   dim)pycocotools.maskmaskr`   ra   r3   appendtorchzerosuint8rc   strbytesr0   r2   type__name__frPyObjectsdecodendim	as_tensoranytostack)	segmentationsheightwidth	coco_maskmasksrb   r^   rlesrj   s	            r   convert_coco_poly_to_maskr      s   ( )E% 
<(F3|K\`aKaLLfe_EKKHI< !(+FfsE4&89 CDLDYDYC\ ]3 3  &3,/$~ "--lFEJK((vuED%99q=	?Dt5;;7xxAx!!%++.T56 5zQ{{Avu-U[[AA;;u!$$r   c                  X     e Zd ZdZ	 	 	 	 d	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 d fdZd fdZ xZS )CocoDetectionu	  COCO detection dataset with optional sparse-to-contiguous category ID remapping.

    Extends ``torchvision.datasets.CocoDetection`` with two additions:

    1. A pluggable transform pipeline (``transforms``) applied after the raw
       annotation conversion handled by :class:`ConvertCoco`.
    2. Optional remapping of sparse COCO category IDs to contiguous 0-based label
       indices via ``remap_category_ids``.

    COCO category IDs are sparse (1–90 with gaps such as 12, 26, 29 …).  When a model has only *N* output slots the IDs
    cannot be used directly as tensor indices — doing so causes out-of-bounds errors in the matcher and loss. Setting
    ``remap_category_ids=True`` builds a ``cat2label`` mapping from the annotation file so that IDs are remapped to the
    range ``[0, N)``.  The reverse ``label2cat`` mapping is attached to the underlying COCO API object so that
    :class:`~rfdetr.datasets.coco_eval.CocoEvaluator` can convert predicted label indices back to the original category
    IDs required by pycocotools.

    ``remap_category_ids`` should be ``True`` for Roboflow / custom datasets (via :func:`build_roboflow_from_coco`) and
    ``False`` (the default) when evaluating pretrained models that were trained with the convention that model output
    slot *k* corresponds directly to COCO category ID *k*.

    Args:
        img_folder: Path to the directory containing the dataset images.
        ann_file: Path to the COCO-format JSON annotation file.
        transforms: Transform pipeline applied to ``(image, target)`` pairs after
            annotation conversion.  ``None`` means no additional transforms.
        include_masks: If ``True``, decode polygon segmentation masks into binary
            tensors and include them in the target dict under the ``"masks"`` key.
        include_keypoints: If ``True``, parse COCO keypoints and include them in
            the target dict under the ``"keypoints"`` key.
        num_keypoints_per_class: Optional keypoint schema describing the number of
            keypoints per class. When provided, keypoints are padded/truncated to ``max(num_keypoints_per_class)``.
        remap_category_ids: If ``True``, build a ``cat2label`` mapping from the
            annotation file that remaps sparse category IDs to contiguous 0-based label indices.  The reverse mapping is
            stored as ``label2cat`` on both this object and the underlying COCO API object.  Defaults to ``False``.
    c                P   t         t        |   ||       || _        || _        || _        |r|rt        | j                  |      | _        nOt        t        | j                  j                  j                                     D 	ci c]  \  }}	|	|
 c}	}| _        | j                  j                         D 	
ci c]  \  }	}
|
|	
 c}
}	| _        t        | j                  d| j                         nd | _        d | _        t!        ||| j                  |      | _        y c c}	}w c c}
}	w )N	label2cat)include_masksinclude_keypointsrC   r:   )superr   __init___transformsr   r   rF   r$   rC   r1   r    r   r4   r   r   setattrConvertCocoprepare)self
img_folderann_file
transformsr   r   r:   remap_category_idsir%   label	__class__s              r   r   zCocoDetection.__init__   s     	mT+JA%*!2 !:499F]!^=FvdiinnNaNaNcGd=e!f	6&!)!fAEAUAUAWXeVmXDNDII{DNN;!DN!DN"'/nn$;	
 "gXs   D7D"c                    t         t        |   |      \  }}| j                  |   }||d}| j	                  ||      \  }}| j
                  | j                  ||      \  }}||fS )N)image_idr   )r   r   __getitem__idsr   r   )r   r<   imgtargetr   r   s        r   r   zCocoDetection.__getitem__  sq    M4<SAV88C=&v>ll3/V' **37KCF{r   )FFNF)r   
str | Pathr   r   r   z
Any | Noner   boolr   r   r:   list[int] | Noner   r   returnNone)r<   r   r   ztuple[Any, Any])rr   
__module____qualname____doc__r   r   __classcell__)r   s   @r   r   r      su    "R $"'48#( 
 
  
 	 

  
   
 "2 
 ! 
 
 
D	 	r   r   c                  <    e Zd ZdZ	 	 	 	 d	 	 	 	 	 	 	 	 	 ddZddZy)r   u  Convert a raw COCO annotation dict into model-ready tensors.

    Accepts the ``(image, target)`` pair produced by ``torchvision.datasets.CocoDetection`` and returns the same image
    alongside a target dict containing:

    - ``"boxes"`` – ``(N, 4)`` float32 tensor in absolute ``[x_min, y_min, x_max, y_max]`` format.
    - ``"labels"`` – ``(N,)`` int64 tensor of class indices.
    - ``"image_id"`` – scalar int64 tensor.
    - ``"area"`` – ``(N,)`` float32 tensor of annotation areas (used by COCO eval).
    - ``"iscrowd"`` – ``(N,)`` int64 tensor (0 = instance, 1 = crowd).
    - ``"masks"`` – ``(N, H, W)`` bool tensor of binary segmentation masks, only
      present when ``include_masks=True``.
    - ``"keypoints"`` – ``(N, K, 3)`` float32 tensor in COCO keypoint format,
      only present when ``include_keypoints=True``.

    Crowd annotations (``iscrowd=1``) and degenerate boxes (zero width or height after clamping to image boundaries) are
    filtered out.

    Args:
        include_masks: If ``True``, decode segmentation annotations (polygon or
            RLE format) into binary masks and include them in the returned target dict.
        cat2label: Optional mapping from COCO ``category_id`` values to contiguous
            0-based label indices.  When ``None`` (default) the raw ``category_id`` values are used as labels directly,
            which is correct for datasets whose IDs are already 0-indexed.  Pass a non-``None`` mapping for sparse
            COCO-style datasets (e.g. IDs 1–90 with gaps) so that labels stay within the model's output range.
        num_keypoints_per_class: Optional keypoint schema. When provided, keypoints
            are padded/truncated to ``max(num_keypoints_per_class)`` in each annotation.
    Nc                f    || _         || _        || _        |t        |d      | _        y d| _        y )Nr   )default)r   r   rC   r5   r   )r   r   r   rC   r:   s        r   r   zConvertCoco.__init__:  s8     +!2"H_HkS!8!Dqrr   c           	     :
   |j                   \  }}|d   }t        j                  |g      }|d   }|D cg c]  }d|vs	|d   dk(  s| }}|D cg c]  }|d   	 }}t        j                  |t        j                        j	                  dd      }|d d d	d fxx   |d d d d	f   z  cc<   |d d dd d	f   j                  d|
       |d d dd d	f   j                  d|
       g }	|D ]s  }|d   }
t        | dd       N|
| j                  vr!t        d|
 d|j                  d       d      |	j                  | j                  |
          c|	j                  |
       u t        j                  |	t        j                        }	|d d df   |d d df   kD  |d d d	f   |d d df   kD  z  }||   }|	|   }	i }||d<   |	|d<   ||d<   t        j                  |D cg c]  }|d   	 c}      }t        j                  |D cg c]  }d|v r|d   nd c}      }||   |d<   ||   |d<   d }| j                  r| j                  }|dk(  r*|D ]%  }|j                  d      }|t        |      dz  } n g }|D ]  }|j                  d      }|7|j                  t        j                  |dft        j                               Mt        j                  |t        j                        j	                  dd      }|j                   d   |k  rKt        j                  |dft        j                        }||d |j                   d    |j                  |       |j                  |d |         t        |      dkD  rt        j"                  |d      }n(t        j                  d|dft        j                        }||   |d<   | j$                  rt        |      dkD  r{d|d   v rt|D cg c]  }|j                  dg        }}t'        |||      }|j)                         dkD  r	||   |d<   nWt        j                  d||ft        j*                        |d<   n+t        j                  d||ft        j*                        |d<   |d   j-                         |d<   ||d   |   |d<   t        j                  t/        |      t/        |      g      |d<   t        j                  t/        |      t/        |      g      |d<   ||fS c c}w c c}w c c}w c c}w c c}w )Nr   r   iscrowdr   bboxre   rJ   rM   rK   )minr5   r.   r   rC   zUnknown category_id z for image_id zR encountered in annotations. Check that your category mapping matches the dataset.rL   boxeslabelsarear   rg   rb   r~   	orig_sizer_   )r_   rl   rv   float32reshapeclamp_getattrrC   KeyErrorr   rk   int64r   r   r3   rm   shapery   r   r   numelrn   r   r   )r   imager   whr   annoobjr   classesr   keepr   r   keypoint_keepr   r   keypoint_tensorsraw_keypointskeypoint_tensorpaddedkeypoints_outrz   r~   s                           r   __call__zConvertCoco.__call__F  s   zz1*%??H:.m$#Sy';s9~QR?RSS(,-V--U]];CCBJaea!e$aAg!+aAg!+ 
	,Cm,Kt[$/;dnn4".{m>&**U_J`Ia bl l  t~~k:;{+
	, //'=adeAqDk)eAqDkE!Q$K.GHd$-w"x%z t<F<=//X\"]QTY#5E3y>1#L"]^dv#DMy'+!! ..M! C # 4I ,(+I!(;	 .0 I # 4 ($++EKK8JRWR_R_,`a"'//-u}}"U"]"]^`bc"d"((+m;"[[-);5==QF9HF5_22156$++F3 ''(GHI #$q( %,<! D %Qq,A W"/"5F; 4y1}47!:HL M!< M M1-AF;;=1$&+DkF7O&+kk1a)5;;&OF7O"'++q!Qiu{{"Kw$Wo224F7O("(/-"@w#oos1vs1v.>?{#a&#a&)9:vf}y T->  ="]T !Ns#   TTT	TT*T)FFNN)
r   r   r   r   rC   zdict[int, int] | Noner:   r   r   r   )r   zImage.Imager   zdict[str, Any]r   z"tuple[Image.Image, dict[str, Any]])rr   r   r   r   r   r   rQ   r   r   r   r     sV    > $"'+/48
s
s  
s )	
s
 "2
s 

sdr   r   )max_sizec               F   |rBdd| D cg c]	  }d||di c}ii}ddddg diidd| D cg c]  }d	d
dg||di c}iigii}nK|xs d}t        |       dk(  r| d   n| }dddd|iidd|iigii}ddddg diid	d
dgd
d
didd|iidd|iigii}dd||giigS c c}w c c}w )u  Build the training resize pipeline as an Albumentations config list.

    Expresses the ``RandomSelect(resize_a, Compose([resize_b1, crop, resize_b2]))`` pattern as a config-driven
    ``OneOf``/``Sequential`` for use with :meth:`AlbumentationsWrapper.from_config`.

    Two branches are selected with equal probability:

    - **Option A** – direct resize to the target scale(s).
    - **Option B** – resize to an intermediate scale (400/500/600 px), crop,
      then resize to the target scale.

    Divisibility padding (rounding ``H``/``W`` up to a multiple of ``patch_size * num_windows``) is handled by the batch
    collator via :func:`~rfdetr.utilities.tensors.make_collate_fn`, not here.

    Args:
        scales: Target resize scales in pixels.
        square: If ``True``, produce square output using ``A.Resize``
            (one random scale from *scales*).  If ``False``, preserve aspect ratio using ``A.SmallestMaxSize`` with an
            optional long-side cap.
        max_size: Maximum long-side size for non-square resizes.  Defaults to
            ``1333`` when *square* is ``False``.

    Returns:
        A single-element list containing a ``OneOf`` config entry.
    OneOfr   Resizer{   r|   
SequentialSmallestMaxSizer   )i  i  X  RandomSizedCropi  r   )min_max_heightr{   r|   5  r.   r   LongestMaxSize)r3   )rY   squarer   soption_aoption_bcap
size_params           r   _build_train_resize_configr     s\   > fUQ*CDU$
 &_(EF()/+$% "3Sz]^ij4k l+"
$
  $'*6{a'7&)V
&Z(@A%
C'89
 &_(EF&C:QT_b(cd&Z(@A%
C'89		
 |h%9:;<<S V+s
   BBc
                   t               }
t        t        j                  d      }t	               }|g}|r.t        ||||      }|r|d   g}t        j                  d|        | dk(  ri||nt        }t        j                  t        |dd            }g |}|st        j                  ||		      }|g |z  }||
|gz  }|s||gz  }t        |      S | d
v r2t        j                  dd|iidddiig      }t        g ||
||      S | dk(  r.t        j                  d||dig      }t        g ||
||      S t        d|        )u  Build the standard COCO transform pipeline for a given dataset split.

    Returns a composed transform that resizes images to the target ``resolution`` (with optional multi-scale jitter),
    applies Albumentations-based augmentations during training, and normalises pixel values with ImageNet statistics.

    For the ``"train"`` split the pipeline uses a two-branch ``OneOf`` between a direct resize and a resize →
    random-crop → resize sequence (built via :func:`_build_train_resize_config`), followed by the augmentation stack and
    normalisation.  For ``"val"``, ``"test"``, and ``"val_speed"`` only resize and normalisation are applied — no
    augmentation.

    When *gpu_postprocess* is ``True``, both the Albumentations augmentation wrappers and the ``Normalize`` step are
    omitted from the ``"train"`` pipeline. The ``RFDETRDataModule`` then applies augmentation and normalization on the
    device in ``on_after_batch_transfer`` instead.

    Args:
        image_set: Dataset split identifier — ``"train"``, ``"val"``, ``"test"``,
            or ``"val_speed"``.
        resolution: Target short-side resolution in pixels.  During validation the
            longest side is capped at 1333 px to preserve aspect ratio.
        multi_scale: If ``True``, sample the resize target from a range of scales
            computed by :func:`compute_multi_scale_scales` instead of using a single fixed size.
        expanded_scales: Passed to :func:`compute_multi_scale_scales`; broadens the
            scale range when ``multi_scale=True``.
        skip_random_resize: When ``multi_scale=True``, use only the largest scale
            and skip random selection among multiple scales.
        patch_size: Model patch size used by :func:`compute_multi_scale_scales` to
            ensure all candidate resolutions are compatible with the backbone.
        num_windows: Number of attention windows; used by
            :func:`compute_multi_scale_scales` to derive candidate resolutions.
        aug_config: Albumentations augmentation config dict passed to
            :class:`~rfdetr.datasets.transforms.AlbumentationsWrapper`.  Falls back to the default
            :data:`~rfdetr.datasets.aug_configs.AUG_CONFIG` when ``None``.
        gpu_postprocess: When ``True``, skip Albumentations augmentation wrappers and
            ``Normalize`` from the CPU pipeline.  The ``RFDETRDataModule`` then applies both augmentation and
            normalization on the GPU in ``on_after_batch_transfer``.  Has no effect on val/test splits.

    Returns:
        A :class:`torchvision.transforms.v2.Compose` pipeline ready to be passed to :class:`CocoDetection`.

        .. note::
            This pipeline does **not** guarantee that output ``H`` and ``W`` are divisible by ``patch_size *
            num_windows``.  Divisibility is enforced at the batch level by the DataLoader collate function.  If you
            apply these transforms outside of :class:`~rfdetr.training.module_data.RFDETRDataModule`, pass the result
            through :func:`~rfdetr.utilities.tensors.nested_tensor_from_tensor_list` with ``block_size=patch_size *
            num_windows``, or use :func:`~rfdetr.utilities.tensors.make_collate_fn` with that value.

    Raises:
        ValueError: If ``image_set`` is not one of the recognised split names.
    TrZ   rJ   z(Using multi-scale training with scales: r   Fr   )r   r   keypoint_flip_pairs)valtestr   r   r   	val_speedr   r   unknown r
   r	   rl   r   r   r\   loggerinfor   r   from_configr   r   r2   	image_setrR   multi_scalerS   skip_random_resizerT   rU   
aug_configgpu_postprocessr   to_imageto_float	normalizerY   resolved_aug_configresize_wrapperspipelineaug_wrapperss                     r   make_coco_transformsr     s   z yHu}}D1HI\F+JU`aRj\F>vhGHG,6,Bj
/;;&vedK
 &_%0<<#9LL ,'HXx((#Hx  O#/;;"Z$<=!J#56
 HH(HHHiHIIK/;;hS]hrHs=t<uvHH(HHHiHII
x	{+
,,r   c
                    t               }
t        t        j                  d      }t	               }|g}|r.t        ||||      }|r|d   g}t        j                  d|        | dk(  rh||nt        }t        j                  t        |d            }g |}|st        j                  ||	      }|g |z  }||
|gz  }|s||gz  }t        |      S | dv r.t        j                  d	||d
ig      }t        g ||
||      S t        d|        )a	  Create COCO transforms with square resizing where the output size is divisible by 64.

    This function builds a torchvision-style transform pipeline for COCO images that resizes them to square shapes
    suitable for models that require spatial dimensions divisible by 64. It supports multi-scale training and optional
    random resizing and cropping for the training split.

    When *gpu_postprocess* is ``True``, both the Albumentations augmentation wrappers and the ``Normalize`` step are
    omitted from the ``"train"`` pipeline. The ``RFDETRDataModule`` then applies augmentation and normalization on the
    device in ``on_after_batch_transfer`` instead.

    Args:
        image_set: Dataset split identifier. Expected values are "train", "val",
            "test", or "val_speed". Each split uses a slightly different transform pipeline suited for training or
            evaluation.
        resolution: Base square resolution (in pixels) to which images are resized.
        multi_scale: If True, enable multi-scale training by sampling from a set of
            square resolutions instead of a single fixed size.
        expanded_scales: If True, expand the range of scales used during
            multi-scale training. Passed through to ``compute_multi_scale_scales``.
        skip_random_resize: If True and ``multi_scale`` is enabled, use only the
            largest scale returned by ``compute_multi_scale_scales`` and skip random selection among multiple scales.
        patch_size: Patch size used by ``compute_multi_scale_scales`` when
            determining valid square resolutions (typically related to the model's patch embedding or stride).
        num_windows: Number of windows used by ``compute_multi_scale_scales`` to
            derive the list of candidate square resolutions.
        aug_config: Augmentation configuration dictionary compatible with
            :class:`~rfdetr.datasets.transforms.AlbumentationsWrapper`. If ``None``, the default
            :data:`~rfdetr.datasets.aug_configs.AUG_CONFIG` is used.
        gpu_postprocess: When ``True``, skip Albumentations augmentation wrappers and
            ``Normalize`` from the CPU pipeline.  The ``RFDETRDataModule`` then applies both augmentation and
            normalization on the GPU in ``on_after_batch_transfer``.  Has no effect on val/test splits.

    Returns:
        A ``Compose`` object containing the composed image transforms appropriate for the specified ``image_set``.
    Tr   rJ   z:Using multi-scale training with square resize and scales: r   )r   r   )r   r   r   r   r   r   r   r   s                     r   "make_coco_transforms_square_div_64r   c  sG   ^ yHu}}D1HI\F+JU`aRj\FPQWPXYZG,6,Bj
/;;<VW]fj<kl%_%0<<#9LL ,'HXx((#Hx  00/;;hS]hrHs=t<uvHH(HHHiHII
x	{+
,,r   c                L   t        t        |dd       xs |j                        }|j                         s(t        j                  d| d       t        d| d      t        |dd      }|rdnd}|dz  |d	z  | d
z  f|dz  |d	z  | dz  f|dz  |d	z  dz  fd}|| j                  d      d      \  }}t        |dd      }	t        |dd      }
|}t        |dg       }t        |dd       }t        |dg       xs g }t        |dd      }t        |      }||k7  r|dk(  rt        j                  d       |dk7  }|	rut        j                  d|  d|        t        ||t        | ||j                  |j                  |j                   |j                   |j"                  |||
      |
|||      }|S t        j                  d|  d|        t        ||t%        | ||j                  |j                  |j                   |j                   |j"                  |||
      |
|||      }|S )Nr   z
COCO path  does not existuse_grouppose_keypointsFperson_keypoints	instances	train2017r   z_train2017.jsonval2017z_val2017.jsontest2017zimage_info_test-dev2017.jsonr   r   r   _r   square_resize_div_64segmentation_headr:   r   r   augmentation_backendcpuzaugmentation_backend='auto' resolved to 'cpu' because CUDA or kornia is unavailable; disabling GPU postprocess transforms and retaining CPU normalization.zBuilding COCO * dataset with square resize at resolution r   rS   r   rT   rU   r   r   r   r   r   r   r:   r    dataset at resolution )r   r   	coco_pathr   r   errorFileNotFoundErrorsplit%_resolve_runtime_augmentation_backendwarningr   r   r   r   rS   do_random_resize_via_paddingrT   rU   r   )r   argsrR   roothas_keypointsmodePATHSr   r   r   r   r   r:   r   r   r   resolved_augmentation_backendr   datasets                      r   
build_cocor    s   mT2DdnnED;;=z$78*TF/ BCC D";UCM!.KD$d]&:v_=U&UVy $"6D69O"OP
"D=$8;Y$YZE !!5a!89J"4)?GD"5u=M%%d,ErJ|T2J%,T3H"%M%SQS"4)?G$IJ^$_!$(<<A^bgAgT	
 4u<OnYK/YZdYefg9 ,, $ 4 4'+'H'H#H?? ,,% /$7 (/$;  1+
` N1 	nYK/FzlST+ ,, $ 4 4'+'H'H#H?? ,,% /$7 (/$;  1+
. Nr   c                    ddl m}  ||       S )a  Resolve ``augmentation_backend`` at runtime for dataset builders.

    Thin wrapper around :func:`rfdetr.datasets.kornia_transforms.resolve_augmentation_backend` kept for
    backward-compatibility with callers in ``yolo.py``.

    ``"auto"`` becomes ``"gpu"`` only when CUDA and Kornia are both available, otherwise ``"cpu"``. Explicit
    ``"cpu"``/``"gpu"`` values pass through.
    r   )resolve_augmentation_backend)!rfdetr.datasets.kornia_transformsr  )backendr  s     r   r
  r
    s     O'00r   c                   t        |j                        }|j                         s(t        j	                  d| d       t        d| d      |dz  |dz  dz  f|dz  |dz  dz  f|dz  |dz  dz  fd}|| j                  d      d	      \  }}t        |d
d      }t        |dd      }t        |dd      }	t        |dd      }
t        |dd      }t        |dd      }t        |dd      }t        |dd      }t        |dg       }t        |dg       xs g }t        |dd      }t        t        |dd            }|dk7  }|rCt        j                  d|  d|        t        ||t        | ||	|
| |||||
      |||d      }|S t        j                  d|  d |        t        ||t        | ||	|
| |||||
      |||d      }|S )!zBuild a Roboflow COCO-format dataset.

    This uses Roboflow's standard directory structure (train/valid/test folders with _annotations.coco.json).
    zRoboflow dataset path r   r   r   validr   r   r   r   r   Fr   r   rS   r  rT      rU   rM   r   r:   r   r   Nr   r  zBuilding Roboflow r  r  Tr  r  )r   r   r   r   r  r  r	  r   r
  r   r   r   r   )r   r  rR   r  r  r   r   r   r   r   rS   r  rT   rU   r   r:   r   r   r  r   r  s                        r   build_roboflow_from_cocor    sZ   
   !D;;=-dV?CD"8o NOO .$.3K"KLww1I IJv0H HIE !!5a!89J"4)?GD"5u=M$u5Kd$5u=O#*41OQV#W |R0J$q1K&?G%d,ErJ%,T3H"%M%SQS|T2J$I'RVXnpuJv$w!3u<O(3]^h]ijk9' /'C#C%'% /$7 (/$;#%
T N+ 	(3J:,WX+' /'C#C%'% /$7 (/$;#%
( Nr   )r   ro   r   r   )r$   r   r   	list[int])r$   r   r:   r   r   zdict[int, int])Fr  rM   )
rR   r   rS   r   rT   r   rU   r   r   r  )rb   r   r   r   )rz   z	list[Any]r{   r   r|   r   r   r   )rY   r  r   r   r   z
int | Noner   zlist[dict[str, Any]])FFFr  rM   NFN)r   ro   rR   r   r   r   rS   r   r   r   rT   r   rU   r   r   z dict[str, dict[str, Any]] | Noner   r   r   r   r   r   )r   ro   r  r   rR   r   r   r   )r  ro   r   ro   ))r   
__future__r   pathlibr   typingr   rl   torch.utils.datatorchvisionPILr   r   torchvision.transforms.v2r   r	   r
   rfdetr.datasets.aug_configsr   rfdetr.datasets.transformsr   r   rfdetr.utilities.loggerr   r   r   r)   rF   r\   rc   r   datasetsr   objectr   r   r   r   r  r
  r  rQ   r   r   <module>r*     s3  
 #        ? ? 2 G .	M 5t "	  	
 "b 4%nPK((66 PfN& Nj  	K=K= K= 	K=
 K=b !$37!,0e-e-e- e- 	e-
 e- e- e- 1e- e- *e- e-V !$37!,0M-M-M- M- 	M-
 M- M- M- 1M- M- *M- M-`Rj1Lr   