o  i@sdZddlmZddlmZmZmZddlmZddl m Z ddl Z ddl Z ddlmZmZmZmZmZmZmZmZmZmZmZddlmZdd lmZmZdd lm Z m!Z!dd l"m#Z#m$Z$m%Z%dd l&m'Z'm(Z(dd l)m*Z*ddl+m,Z,m-Z-m.Z.m/Z/m0Z0m1Z1ddl2m3Z3ddl4m5Z5m6Z6m7Z7ddl8m9Z9m:Z:ddl;mZ>m?Z?m@Z@ddlAmBZBmCZCddlDmEZEmFZFgdZGeBHZIGddde5e3ZJGddde5e3ZKGddde5e3ZLGddde5e3ZMGdddeMZNGd d!d!e5e3ZOGd"d#d#e7e5e3ZPGd$d%d%e5e3ZQGd&d'd'e7e5e3ZRGd(d)d)e5ZSGd*d+d+e5ZTGd,d-d-e5ZUGd.d/d/e6e5ZVGd0d1d1e5e3ZWGd2d3d3e7e5e3ZXeKZYZZeLZ[Z\eOZ]Z^ePZ_Z`eMZaZbeQZcZdeRZeZfeSZgZheTZiZjeUZkZleVZmZneWZoZpeXZqZreJZsZtdS)4z A collection of dictionary-based wrappers around the "vanilla" transforms for box operations defined in :py:class:`monai.apps.detection.transforms.array`. Class names are ended with 'd' to denote dictionary-based transforms. ) annotations)HashableMappingSequence)deepcopy)AnyN) AffineBox BoxToMaskClipBoxToImageConvertBoxModeConvertBoxToStandardModeFlipBox MaskToBox RotateBox90SpatialCropBoxStandardizeEmptyBoxZoomBox)convert_box_to_mask)KeysCollection SequenceStr) DtypeLikeNdarrayOrTensor) COMPUTE_DTYPEBoxModeclip_boxes_to_image) MetaTensorget_track_meta)orientation_ras_lps)FlipRandFlipRandZoomRotate90 SpatialCropZoom)InvertibleTransform) MapTransform RandomizableRandomizableTransform)#generate_pos_neg_label_crop_centersmap_binary_to_indices)InterpolateMode NumpyPadMode ensure_tupleensure_tuple_repfall_back_tuple)PostFix TraceKeys)convert_data_typeconvert_to_tensor)*StandardizeEmptyBoxdStandardizeEmptyBoxDStandardizeEmptyBoxDictConvertBoxModedConvertBoxModeDConvertBoxModeDictConvertBoxToStandardModedConvertBoxToStandardModeDConvertBoxToStandardModeDictAffineBoxToImageCoordinatedAffineBoxToImageCoordinateDAffineBoxToImageCoordinateDictZoomBoxdZoomBoxD ZoomBoxDict RandZoomBoxd RandZoomBoxDRandZoomBoxDictFlipBoxdFlipBoxD FlipBoxDict RandFlipBoxd RandFlipBoxDRandFlipBoxDictClipBoxToImagedClipBoxToImageDClipBoxToImageDict BoxToMaskd BoxToMaskD BoxToMaskDict MaskToBoxd MaskToBoxD MaskToBoxDictRandCropBoxByPosNegLabeldRandCropBoxByPosNegLabelDRandCropBoxByPosNegLabelDict RotateBox90d RotateBox90DRotateBox90DictRandRotateBox90dRandRotateBox90DRandRotateBox90Dictcs8eZdZdZddfd d ZdddZdddZZS)r3a Dictionary-based wrapper of :py:class:`monai.apps.detection.transforms.array.StandardizeEmptyBox`. When boxes are empty, this transform standardize it to shape of (0,4) or (0,6). Example: .. code-block:: python data = {"boxes": torch.ones(0,), "image": torch.ones(1, 128, 128, 128)} box_converter = StandardizeEmptyBoxd(box_keys=["boxes"], box_ref_image_keys="image") box_converter(data) Fbox_keysrbox_ref_image_keysstrallow_missing_keysboolreturnNonecs4t||t|}t|dkrtd||_dS)ap Args: box_keys: Keys to pick data for transformation. box_ref_image_keys: The single key that represents the reference image to which ``box_keys`` are attached. allow_missing_keys: don't raise exception if key is missing. See also :py:class:`monai.apps.detection,transforms.array.ConvertBoxToStandardMode` |Please provide a single key for box_ref_image_keys. All boxes of box_keys are attached to box_ref_image_keys.N)super__init__r,len ValueErrorr^)selfr]r^r`box_ref_image_keys_tuple __class__l/home/dell461/cl/sdc2/last_ska_mid/HISourceFinder-master-l/src/monai/apps/detection/transforms/dictionary.pyrgts   zStandardizeEmptyBoxd.__init__data"Mapping[Hashable, NdarrayOrTensor]dict[Hashable, NdarrayOrTensor]cCsNt|}t||jjd}t|d|_||D] }|||||<q|S)Nrd) spatial_dims)dictrhr^shaper converter key_iterator)rjrpdrskeyrnrnro__call__s  zStandardizeEmptyBoxd.__call__cCst|SNrtrjrprnrnroinverseszStandardizeEmptyBoxd.inverse)F)r]rr^r_r`rarbrcrprqrbrr__name__ __module__ __qualname____doc__rgrzr~ __classcell__rnrnrlror3fs  r3cs>eZdZdZ   ddfd d ZdddZdddZZS)r6a Dictionary-based wrapper of :py:class:`monai.apps.detection.transforms.array.ConvertBoxMode`. This transform converts the boxes in src_mode to the dst_mode. Example: .. code-block:: python data = {"boxes": torch.ones(10,4)} # convert boxes with format [xmin, ymin, xmax, ymax] to [xcenter, ycenter, xsize, ysize]. box_converter = ConvertBoxModed(box_keys=["boxes"], src_mode="xyxy", dst_mode="ccwh") box_converter(data) NFr]rsrc_mode$str | BoxMode | type[BoxMode] | Nonedst_moder`rarbrccs t||t||d|_dS)a Args: box_keys: Keys to pick data for transformation. src_mode: source box mode. If it is not given, this func will assume it is ``StandardMode()``. It follows the same format with ``src_mode`` in :class:`~monai.apps.detection.transforms.array.ConvertBoxMode` . dst_mode: target box mode. If it is not given, this func will assume it is ``StandardMode()``. It follows the same format with ``src_mode`` in :class:`~monai.apps.detection.transforms.array.ConvertBoxMode` . allow_missing_keys: don't raise exception if key is missing. See also :py:class:`monai.apps.detection,transforms.array.ConvertBoxMode` rrN)rfrgr rv)rjr]rrr`rlrnrorgszConvertBoxModed.__init__rprqrrcCsLt|}||D]}|||||<|j|||jj|jjddq |S)N)srcdst extra_info)rtrwrvpush_transformrrrjrprxryrnrnrorzs  zConvertBoxModed.__call__cCsnt|}||D]+}|||}|tjd|tjd}}t||d}|||||<|||q |S)Nrrrrtrwget_most_recent_transformr0 EXTRA_INFOr pop_transform)rjrprxrytrrrinverse_converterrnrnror~s  zConvertBoxModed.inverse)NNF) r]rrrrrr`rarbrcrrrnrnrlror6s r6cs<eZdZdZ  ddfd d ZdddZdddZZS)r9aq Dictionary-based wrapper of :py:class:`monai.apps.detection.transforms.array.ConvertBoxToStandardMode`. Convert given boxes to standard mode. Standard mode is "xyxy" or "xyzxyz", representing box format of [xmin, ymin, xmax, ymax] or [xmin, ymin, zmin, xmax, ymax, zmax]. Example: .. code-block:: python data = {"boxes": torch.ones(10,6)} # convert boxes with format [xmin, xmax, ymin, ymax, zmin, zmax] to [xmin, ymin, zmin, xmax, ymax, zmax] box_converter = ConvertBoxToStandardModed(box_keys=["boxes"], mode="xxyyzz") box_converter(data) NFr]rmoderr`rarbrccst||t|d|_dS)a Args: box_keys: Keys to pick data for transformation. mode: source box mode. If it is not given, this func will assume it is ``StandardMode()``. It follows the same format with ``src_mode`` in :class:`~monai.apps.detection.transforms.array.ConvertBoxMode` . allow_missing_keys: don't raise exception if key is missing. See also :py:class:`monai.apps.detection,transforms.array.ConvertBoxToStandardMode` )rN)rfrgr rv)rjr]rr`rlrnrorgsz"ConvertBoxToStandardModed.__init__rprqrrcCsFt|}||D]}|||||<|j||d|jjidq |S)Nrr)rtrwrvrrrrnrnrorzs z"ConvertBoxToStandardModed.__call__cCs^t|}||D]#}|||}|tjd}td|d}|||||<|||q |S)Nrrr)rjrprxryrZ original_moderrnrnror~s  z!ConvertBoxToStandardModed.inverseNF)r]rrrr`rarbrcrrrnrnrlror9s r9csJeZdZdZddedfdfdd ZdddZdddZdddZZ S) r<a Dictionary-based transform that converts box in world coordinate to image coordinate. Args: box_keys: Keys to pick box data for transformation. The box mode is assumed to be ``StandardMode``. box_ref_image_keys: The single key that represents the reference image to which ``box_keys`` are attached. remove_empty: whether to remove the boxes that are actually empty allow_missing_keys: don't raise exception if key is missing. image_meta_key: explicitly indicate the key of the corresponding metadata dictionary. for example, for data with key `image`, the metadata by default is in `image_meta_dict`. the metadata is a dictionary object which contains: filename, affine, original_shape, etc. it is a string, map to the `box_ref_image_key`. if None, will try to construct meta_keys by `box_ref_image_key_{meta_key_postfix}`. image_meta_key_postfix: if image_meta_keys=None, use `box_ref_image_key_{postfix}` to fetch the metadata according to the key data, default is `meta_dict`, the metadata is a dictionary object. For example, to handle key `image`, read/write affine matrices from the metadata `image_meta_dict` dictionary's `affine` field. affine_lps_to_ras: default ``False``. Yet if 1) the image is read by ITKReader, and 2) the ITKReader has affine_lps_to_ras=True, and 3) the box is in world coordinate, then set ``affine_lps_to_ras=True``. FNr]rr^r_r`raimage_meta_key str | Noneimage_meta_key_postfixaffine_lps_to_rasrbrccsVt||t|}t|dkrtd||_|p |d||_t|_||_ dS)Nrdre_) rfrgr,rhrir^rrconverter_to_image_coordinater)rjr]r^r`rrrrkrlrnrorgs   z$AffineBoxToImageCoordinated.__init__rpMapping[Hashable, torch.Tensor]$tuple[NdarrayOrTensor, torch.Tensor]c Cst|}|j}t||jtr||jj}n||vr||}nt|dd|vr2td|d|d}|jr=t|}t |t j ^}}t | t}||fS)NzI is not found. Please check whether it is the correct the image meta key.affinez'affine' is not found in zL. Please check whether it is the correct the image meta key.)rtr isinstancer^rmetarirrr1torchTensorr~tor) rjrprxmeta_key meta_dictraffine_tr inv_affine_trnrnroextract_affine-s"  z*AffineBoxToImageCoordinated.extract_affinerqrrcCsTt|}||\}}||D]}|j|||d||<|j||d|idq|SNrrr)rtrrwrrrjrprxrrryrnrnrorzI z$AffineBoxToImageCoordinated.__call__cCsVt|}||D]}|||}|dd}t|||d||<|||q |S)Nrrr)rtrwrrr)rjrprxry transformrrnrnror~Ss  z#AffineBoxToImageCoordinated.inverser]rr^r_r`rarrrrrrarbrc)rprrbrr) rrrrDEFAULT_POST_FIXrgrrzr~rrnrnrlror<s   r<cs6eZdZdZddedfdfdd ZdddZZS)AffineBoxToWorldCoordinateda Dictionary-based transform that converts box in image coordinate to world coordinate. Args: box_keys: Keys to pick box data for transformation. The box mode is assumed to be ``StandardMode``. box_ref_image_keys: The single key that represents the reference image to which ``box_keys`` are attached. remove_empty: whether to remove the boxes that are actually empty allow_missing_keys: don't raise exception if key is missing. image_meta_key: explicitly indicate the key of the corresponding metadata dictionary. for example, for data with key `image`, the metadata by default is in `image_meta_dict`. the metadata is a dictionary object which contains: filename, affine, original_shape, etc. it is a string, map to the `box_ref_image_key`. if None, will try to construct meta_keys by `box_ref_image_key_{meta_key_postfix}`. image_meta_key_postfix: if image_meta_keys=None, use `box_ref_image_key_{postfix}` to fetch the metadata according to the key data, default is `meta_dict`, the metadata is a dictionary object. For example, to handle key `image`, read/write affine matrices from the metadata `image_meta_dict` dictionary's `affine` field. affine_lps_to_ras: default ``False``. Yet if 1) the image is read by ITKReader, and 2) the ITKReader has affine_lps_to_ras=True, and 3) the box is in world coordinate, then set ``affine_lps_to_ras=True``. FNr]rr^r_r`rarrrrrbrccs"t||||||t|_dSr{)rfrgrconverter_to_world_coordinate)rjr]r^r`rrrrlrnrorgts  z$AffineBoxToWorldCoordinated.__init__rprqrrcCsTt|}||\}}||D]}|j|||d||<|j||d|idq|Sr)rtrrwrrrrnrnrorzrz$AffineBoxToWorldCoordinated.__call__rr)rrrrrrgrzrrnrnrlror]srcsFeZdZdZejejdddfd fdd Zd!ddZ d!ddZ Z S)"r?a Dictionary-based transform that zooms input boxes and images with the given zoom scale. Args: image_keys: Keys to pick image data for transformation. box_keys: Keys to pick box data for transformation. The box mode is assumed to be ``StandardMode``. box_ref_image_keys: Keys that represent the reference images to which ``box_keys`` are attached. zoom: The zoom factor along the spatial axes. If a float, zoom is the same for each spatial axis. If a sequence, zoom should contain one value for each spatial axis. mode: {``"nearest"``, ``"nearest-exact"``, ``"linear"``, ``"bilinear"``, ``"bicubic"``, ``"trilinear"``, ``"area"``} The interpolation mode. Defaults to ``"area"``. See also: https://pytorch.org/docs/stable/generated/torch.nn.functional.interpolate.html It also can be a sequence of string, each element corresponds to a key in ``keys``. padding_mode: available modes for numpy array:{``"constant"``, ``"edge"``, ``"linear_ramp"``, ``"maximum"``, ``"mean"``, ``"median"``, ``"minimum"``, ``"reflect"``, ``"symmetric"``, ``"wrap"``, ``"empty"``} available modes for PyTorch Tensor: {``"constant"``, ``"reflect"``, ``"replicate"``, ``"circular"``}. One of the listed string values or a user supplied function. Defaults to ``"constant"``. The mode to pad data after zooming. See also: https://numpy.org/doc/1.18/reference/generated/numpy.pad.html https://pytorch.org/docs/stable/generated/torch.nn.functional.pad.html align_corners: This only has an effect when mode is 'linear', 'bilinear', 'bicubic' or 'trilinear'. Default: None. See also: https://pytorch.org/docs/stable/generated/torch.nn.functional.interpolate.html It also can be a sequence of bool or None, each element corresponds to a key in ``keys``. keep_size: Should keep original size (pad if needed), default is True. allow_missing_keys: don't raise exception if key is missing. kwargs: other arguments for the `np.pad` or `torch.pad` function. note that `np.pad` treats channel dimension as the first dimension. NTF image_keysrr]r^zoomSequence[float] | floatrr padding_mode align_corners#Sequence[bool | None] | bool | None keep_sizerar`kwargsrrbrcc  st||_t||_t|j|j| t|t|j|_t|t|j|_t|t|j|_ t|t|j|_ t d||d| |_ ||_ dS)Nrrrn)r,rr]rfrgr-rhr^rrrr#zoomerr) rjrr]r^rrrrrr`rrlrnrorgs  zZoomBoxd.__init__rprdict[Hashable, torch.Tensor]c Cst|}t|j|jD]D\}}||jdd}ddt|jj|D}ddt||D|j_t|jj|jd|||d||<|j |||jj|ddd q t|j |j |j |j D]\}}} } |j|||| | d ||<q[|S) NrdcS g|] \}}tt||qSrnintround.0zssrnrnro  z%ZoomBoxd.__call__..cSg|] \}}|t|qSrnfloatrrdsrnrnrorrsrc_spatial_sizebox_keyrrtyper)rrr)rtzipr]r^rurrrrrrrrr) rjrprxrbox_ref_image_keyrdst_spatial_sizeryrrrrnrnrorzs$ zZoomBoxd.__call__c Cst|}||D]R}|j||dd}|tjdd}|dkr*|j||||<|dkr[t |tjd}|tjd}t d| |jj d }||||d ||<| ||q |S) NFcheckr image_keyrrrrdrr)rtrwrr0rgetrr~nparrayrtolistrr) rjrprxryrkey_typerrbox_inverse_transformrnrnror~s zZoomBoxd.inverse)rrr]rr^rrrrrrrrrrrar`rarrrbrcrprrbr) rrrrr*AREAr+EDGErgrzr~rrnrnrlror?s% r?cs^eZdZdZejZdddejej dddfd,ddZ d-d.fd#d$ Z d/d(d)Z d/d*d+Z ZS)0rBa Dictionary-based transform that randomly zooms input boxes and images with given probability within given zoom range. Args: image_keys: Keys to pick image data for transformation. box_keys: Keys to pick box data for transformation. The box mode is assumed to be ``StandardMode``. box_ref_image_keys: Keys that represent the reference images to which ``box_keys`` are attached. prob: Probability of zooming. min_zoom: Min zoom factor. Can be float or sequence same size as image. If a float, select a random factor from `[min_zoom, max_zoom]` then apply to all spatial dims to keep the original spatial shape ratio. If a sequence, min_zoom should contain one value for each spatial axis. If 2 values provided for 3D data, use the first value for both H & W dims to keep the same zoom ratio. max_zoom: Max zoom factor. Can be float or sequence same size as image. If a float, select a random factor from `[min_zoom, max_zoom]` then apply to all spatial dims to keep the original spatial shape ratio. If a sequence, max_zoom should contain one value for each spatial axis. If 2 values provided for 3D data, use the first value for both H & W dims to keep the same zoom ratio. mode: {``"nearest"``, ``"nearest-exact"``, ``"linear"``, ``"bilinear"``, ``"bicubic"``, ``"trilinear"``, ``"area"``} The interpolation mode. Defaults to ``"area"``. See also: https://pytorch.org/docs/stable/generated/torch.nn.functional.interpolate.html It also can be a sequence of string, each element corresponds to a key in ``keys``. padding_mode: available modes for numpy array:{``"constant"``, ``"edge"``, ``"linear_ramp"``, ``"maximum"``, ``"mean"``, ``"median"``, ``"minimum"``, ``"reflect"``, ``"symmetric"``, ``"wrap"``, ``"empty"``} available modes for PyTorch Tensor: {``"constant"``, ``"reflect"``, ``"replicate"``, ``"circular"``}. One of the listed string values or a user supplied function. Defaults to ``"constant"``. The mode to pad data after zooming. See also: https://numpy.org/doc/1.18/reference/generated/numpy.pad.html https://pytorch.org/docs/stable/generated/torch.nn.functional.pad.html align_corners: This only has an effect when mode is 'linear', 'bilinear', 'bicubic' or 'trilinear'. Default: None. See also: https://pytorch.org/docs/stable/generated/torch.nn.functional.interpolate.html It also can be a sequence of bool or None, each element corresponds to a key in ``keys``. keep_size: Should keep original size (pad if needed), default is True. allow_missing_keys: don't raise exception if key is missing. kwargs: other args for `np.pad` API, note that `np.pad` treats channel dimension as the first dimension. more details: https://numpy.org/doc/1.18/reference/generated/numpy.pad.html 皙?g?g?NTFrrr]r^probrmin_zoomrmax_zoomrrrrrrrar`rrrbrcc Kst||_t||_t||j|j| t||t|t|j|_t dd||| d| |_ t|t|j|_ t|t|j|_ t| t|j|_ | |_dS)N?)rrrrrn)r,rr]r%rgr'r-rhr^r rand_zoomrrrr) rjrr]r^rrrrrrrr`rrnrnrorgs    zRandZoomBoxd.__init__seed int | Nonestatenp.random.RandomState | Nonecs t|||j|||Sr{)rfset_random_staterrjrrrlrnror9szRandZoomBoxd.set_random_staterprrc Cslt|}||}|dkr|S|d|j||t|j|jD]G\}}|jrj||jdd}ddt|jj |D}ddt||D|j_ t |jj |j d|||d||<|j |||jj |dd d q#t|j |j|j|jD]=\}} } } |jr|j||| | | d d ||<n t||td ||<tr|jr|j||d dni} |j ||| d qv|S)NrnrdcSrrnrrrnrnrorMrz)RandZoomBoxd.__call__..cSrrnrrrnrnrorNrrrrrrF)rrr randomize track_metar)rt first_keyrrrr]r^ _do_transformru_zoomrrrrrrrr2rr) rjrprxrrrrrryrrrxformrnrnrorz>sB    zRandZoomBoxd.__call__c Cst|}||D]i}|j||dd}|tjdd}|tjrr|dkrA|||}||j |tj|j ||||<|dkrrt |tjd}|tjd}td||j jd } | |||d ||<|||q |S) NFrrrrrrrrr)rtrwrr0rr DO_TRANSFORMrapplied_operationsappendrr~rrrrr) rjrprxryrrrrrrrnrnror~is"  zRandZoomBoxd.inverse)rrr]rr^rrrrrrrrrrrrrrrar`rarrrbrcNN)rrrrrbrBr)rrrrr backendr*rr+rrgrrzr~rrnrnrlrorBs'  +rBcsBeZdZdZejZ  ddfdd ZdddZdddZZ S)rEa Dictionary-based transform that flip boxes and images. Args: image_keys: Keys to pick image data for transformation. box_keys: Keys to pick box data for transformation. The box mode is assumed to be ``StandardMode``. box_ref_image_keys: Keys that represent the reference images to which ``box_keys`` are attached. spatial_axis: Spatial axes along which to flip over. Default is None. allow_missing_keys: don't raise exception if key is missing. NFrrr]r^ spatial_axisSequence[int] | int | Noner`rarbrccs\t||_t||_t|j|j|t|t|j|_t|d|_ t |j j d|_ dSN)r) r,rr]rfrgr-rhr^rflipperr r box_flipper)rjrr]r^rr`rlrnrorgs   zFlipBoxd.__init__rprrcCs~t|}|jD] }|||||<qt|j|jD]"\}}||jdd}||||||<|j|||dddq|S)Nrdr spatial_sizerr) rtrrrr]r^rurr)rjrprxryrrrrnrnrorzs zFlipBoxd.__call__cCst|}||D]>}|j||dd}|tjidd}|dkr,|j||||<|dkrG|tjd}||||||<| ||q |SNFrrrrr) rtrwrrr0rrr~rrrjrprxryrrrrnrnror~s zFlipBoxd.inverser) rrr]rr^rrrr`rarbrcr) rrrrrrrgrzr~rrnrnrlrorEs   rEcsPeZdZdZejZ   d d!ddZd"d#fdd Zd$ddZd$ddZ Z S)%rHa@ Dictionary-based transform that randomly flip boxes and images with the given probabilities. Args: image_keys: Keys to pick image data for transformation. box_keys: Keys to pick box data for transformation. The box mode is assumed to be ``StandardMode``. box_ref_image_keys: Keys that represent the reference images to which ``box_keys`` are attached. prob: Probability of flipping. spatial_axis: Spatial axes along which to flip over. Default is None. allow_missing_keys: don't raise exception if key is missing. rNFrrr]r^rrrrr`rarbrccCsdt||_t||_t||j|j|t||t|t|j|_t |d|_ t |d|_ dSr) r,rr]r%rgr'r-rhr^rrr r)rjrr]r^rrr`rnrnrorgs   zRandFlipBoxd.__init__rrrrcst|||Sr{)rfrrrlrnrorszRandFlipBoxd.set_random_staterprrcCst|}|d|jD]4}|jr|||||<n t||td||<tr@|jr5|j||ddni}|j|||dq t |j |j D]%\}}||j dd}|jrb| |||||<|j|||dddqH|S)NrFrrrdrr)rtrrrrr2rrrrr]r^rur)rjrprxry xform_inforrrrnrnrorzs   zRandFlipBoxd.__call__c Cst|}||D]X}|j||dd}|tjdd}|tjrY|dkrD|jd|||||<Wdn1s?wY|dkrY|tjd}| |||||<|j ||ddq |Sr) rtrwrr0rrrrtrace_transformrrrrnrnror~s zRandFlipBoxd.inverse)rNF)rrr]rr^rrrrrr`rarbrcr)rrrrrbrHr) rrrrrrrgrrzr~rrnrnrlrorHs   rHcs2eZdZdZ  ddfd d ZdddZZS)rKa Dictionary-based wrapper of :py:class:`monai.apps.detection.transforms.array.ClipBoxToImage`. Clip the bounding boxes and the associated labels/scores to makes sure they are within the image. There might be multiple keys of labels/scores associated with one key of boxes. Args: box_keys: The single key to pick box data for transformation. The box mode is assumed to be ``StandardMode``. label_keys: Keys that represent the labels corresponding to the ``box_keys``. Multiple keys are allowed. box_ref_image_keys: The single key that represents the reference image to which ``box_keys`` and ``label_keys`` are attached. remove_empty: whether to remove the boxes that are actually empty allow_missing_keys: don't raise exception if key is missing. Example: .. code-block:: python ClipBoxToImaged( box_keys="boxes", box_ref_image_keys="image", label_keys=["labels", "scores"], remove_empty=True ) TFr]r label_keysr^ remove_emptyrar`rbrccstt|}t|dkrtdt|}t|dkrtdt||_t|||d|_|d|_t|d|_ dS)NrdfPlease provide a single key for box_keys. All label_keys are attached to this box_keys.zPlease provide a single key for box_ref_image_keys. All box_keys and label_keys are attached to this box_ref_image_keys.rr) r,rhrirrfrgr]r^r clipper)rjr]rr^rr`box_keys_tuplerkrlrnrorg(s     zClipBoxToImaged.__init__rprqrrcspt||jjdd}fdd|jD}||j||\|j<}t|j|D]\}}||<q-S)Nrdcg|]}|qSrnrnr label_keyrxrnrorFz,ClipBoxToImaged.__call__..)rtr^rurr r]r)rjrprlabelsZclipped_labelsrZclipped_labels_irnrrorzCs zClipBoxToImaged.__call__)TF) r]rrrr^rrrar`rarbrcrrrrrrgrzrrnrnrlrorKs rKcs2eZdZdZ  ddfdd ZdddZZS)rNa Dictionary-based wrapper of :py:class:`monai.apps.detection.transforms.array.BoxToMask`. Pairs with :py:class:`monai.apps.detection.transforms.dictionary.MaskToBoxd` . Please make sure the same ``min_fg_label`` is used when using the two transforms in pairs. The output ``d[box_mask_key]`` will have background intensity 0, since the following operations may pad 0 on the border. This is the general solution for transforms that need to be applied on images and boxes simultaneously. It is performed with the following steps. 1) use ``BoxToMaskd`` to covert boxes and labels to box_masks; 2) do transforms, e.g., rotation or cropping, on images and box_masks together; 3) use ``MaskToBoxd`` to convert box_masks back to boxes and labels. Args: box_keys: Keys to pick box data for transformation. The box mode is assumed to be ``StandardMode``. box_mask_keys: Keys to store output box mask results for transformation. Same length with ``box_keys``. label_keys: Keys that represent the labels corresponding to the ``box_keys``. Same length with ``box_keys``. box_ref_image_keys: Keys that represent the reference images to which ``box_keys`` are attached. min_fg_label: min foreground box label. ellipse_mask: bool. - If True, it assumes the object shape is close to ellipse or ellipsoid. - If False, it assumes the object shape is close to rectangle or cube and well occupies the bounding box. - If the users are going to apply random rotation as data augmentation, we suggest setting ellipse_mask=True See also Kalra et al. "Towards Rotation Invariance in Object Detection", ICCV 2021. allow_missing_keys: don't raise exception if key is missing. Example: .. code-block:: python # This code snippet creates transforms (random rotation and cropping) on boxes, labels, and image together. import numpy as np from monai.transforms import Compose, RandRotated, RandSpatialCropd, DeleteItemsd transforms = Compose( [ BoxToMaskd( box_keys="boxes", label_keys="labels", box_mask_keys="box_mask", box_ref_image_keys="image", min_fg_label=0, ellipse_mask=True ), RandRotated(keys=["image","box_mask"],mode=["nearest","nearest"], prob=0.2,range_x=np.pi/6,range_y=np.pi/6,range_z=np.pi/6, keep_size=True,padding_mode="zeros" ), RandSpatialCropd(keys=["image","box_mask"],roi_size=128, random_size=False), MaskToBoxd( box_mask_keys="box_mask", box_keys="boxes", label_keys="labels", min_fg_label=0 ) DeleteItemsd(keys=["box_mask"]), ] ) Fr]r box_mask_keysrr^ min_fg_labelr ellipse_maskrar`rbrccst||t||_t||_t||_t|jt|jkr,t|jks1tdtdt|t|j|_ |d|_ t |j |d|_ dS)NDPlease make sure len(label_keys)==len(box_keys)==len(box_mask_keys)!rdbg_labelr) rfrgr,r]rrrhrir-r^rr rv)rjr]rrr^rrr`rlrnrorgs   $ zBoxToMaskd.__init__rprqrrcCsnt|}t|j|j|j|jD]%\}}}}||jdd}||||||||<|||j8<q|SNrd) rtrr]rrr^rurvr)rjrprxrr box_mask_keyrrrnrnrorzszBoxToMaskd.__call__)FF)r]rrrrrr^rrrrrar`rarbrcrrrnrnrlrorNNs ?rNcs8eZdZdZejejdfdfdd ZdddZZ S)rQa Dictionary-based wrapper of :py:class:`monai.apps.detection.transforms.array.MaskToBox`. Pairs with :py:class:`monai.apps.detection.transforms.dictionary.BoxToMaskd` . Please make sure the same ``min_fg_label`` is used when using the two transforms in pairs. This is the general solution for transforms that need to be applied on images and boxes simultaneously. It is performed with the following steps. 1) use ``BoxToMaskd`` to covert boxes and labels to box_masks; 2) do transforms, e.g., rotation or cropping, on images and box_masks together; 3) use ``MaskToBoxd`` to convert box_masks back to boxes and labels. Args: box_keys: Keys to pick box data for transformation. The box mode is assumed to be ``StandardMode``. box_mask_keys: Keys to store output box mask results for transformation. Same length with ``box_keys``. label_keys: Keys that represent the labels corresponding to the ``box_keys``. Same length with ``box_keys``. min_fg_label: min foreground box label. box_dtype: output dtype for box_keys label_dtype: output dtype for label_keys allow_missing_keys: don't raise exception if key is missing. Example: .. code-block:: python # This code snippet creates transforms (random rotation and cropping) on boxes, labels, and images together. import numpy as np from monai.transforms import Compose, RandRotated, RandSpatialCropd, DeleteItemsd transforms = Compose( [ BoxToMaskd( box_keys="boxes", label_keys="labels", box_mask_keys="box_mask", box_ref_image_keys="image", min_fg_label=0, ellipse_mask=True ), RandRotated(keys=["image","box_mask"],mode=["nearest","nearest"], prob=0.2,range_x=np.pi/6,range_y=np.pi/6,range_z=np.pi/6, keep_size=True,padding_mode="zeros" ), RandSpatialCropd(keys=["image","box_mask"],roi_size=128, random_size=False), MaskToBoxd( box_mask_keys="box_mask", box_keys="boxes", label_keys="labels", min_fg_label=0 ) DeleteItemsd(keys=["box_mask"]), ] ) Fr]rrrrr box_dtypeDtypeLike | torch.dtype label_dtyper`rarbrccst||t||_t||_t||_t|jt|jkr,t|jks1tdtd|d|_t |j||d|_ ||_ dS)Nrrd)rrr) rfrgr,r]rrrhrirrrvr)rjr]rrrrrr`rlrnrorgs   $  zMaskToBoxd.__init__rprqrrcCsVt|}t|j|j|jD]\}}}|||j7<|||\||<||<q |Sr{)rtrr]rrrrv)rjrprxrrrrnrnrorzs zMaskToBoxd.__call__)r]rrrrrrrrrrrr`rarbrcr) rrrrrfloat32longrgrzrrnrnrlrorQs6rQc @sZeZdZdZdddddddddeddf d6d"d#Zd7d)d*Z   d8d9d/d0Zd:d4d5ZdS);rTa Crop random fixed sized regions that contains foreground boxes. Suppose all the expected fields specified by `image_keys` have same shape, and add `patch_index` to the corresponding meta data. And will return a list of dictionaries for all the cropped images. If a dimension of the expected spatial size is bigger than the input image size, will not crop that dimension. So the cropped result may be smaller than the expected size, and the cropped results of several images may not have exactly the same shape. Args: image_keys: Keys to pick image data for transformation. They need to have the same spatial size. box_keys: The single key to pick box data for transformation. The box mode is assumed to be ``StandardMode``. label_keys: Keys that represent the labels corresponding to the ``box_keys``. Multiple keys are allowed. spatial_size: the spatial size of the crop region e.g. [224, 224, 128]. if a dimension of ROI size is bigger than image size, will not crop that dimension of the image. if its components have non-positive values, the corresponding size of `data[label_key]` will be used. for example: if the spatial size of input data is [40, 40, 40] and `spatial_size=[32, 64, -1]`, the spatial size of output data will be [32, 40, 40]. pos: used with `neg` together to calculate the ratio ``pos / (pos + neg)`` for the probability to pick a foreground voxel as a center rather than a background voxel. neg: used with `pos` together to calculate the ratio ``pos / (pos + neg)`` for the probability to pick a foreground voxel as a center rather than a background voxel. num_samples: number of samples (crop regions) to take in each list. whole_box: Bool, default True, whether we prefer to contain at least one whole box in the cropped foreground patch. Even if True, it is still possible to get partial box if there are multiple boxes in the image. thresh_image_key: if thresh_image_key is not None, use ``label == 0 & thresh_image > image_threshold`` to select the negative sample(background) center. so the crop center will only exist on valid image area. image_threshold: if enabled thresh_image_key, use ``thresh_image > image_threshold`` to determine the valid image content area. fg_indices_key: if provided pre-computed foreground indices of `label`, will ignore above `image_key` and `image_threshold`, and randomly select crop centers based on them, need to provide `fg_indices_key` and `bg_indices_key` together, expect to be 1 dim array of spatial indices after flattening. a typical usage is to call `FgBgToIndicesd` transform first and cache the results. bg_indices_key: if provided pre-computed background indices of `label`, will ignore above `image_key` and `image_threshold`, and randomly select crop centers based on them, need to provide `fg_indices_key` and `bg_indices_key` together, expect to be 1 dim array of spatial indices after flattening. a typical usage is to call `FgBgToIndicesd` transform first and cache the results. meta_keys: explicitly indicate the key of the corresponding metadata dictionary. used to add `patch_index` to the meta dict. for example, for data with key `image`, the metadata by default is in `image_meta_dict`. the metadata is a dictionary object which contains: filename, original_shape, etc. it can be a sequence of string, map to the `keys`. if None, will try to construct meta_keys by `key_{meta_key_postfix}`. meta_key_postfix: if meta_keys is None, use `key_{postfix}` to fetch the metadata according to the key data, default is `meta_dict`, the metadata is a dictionary object. used to add `patch_index` to the meta dict. allow_smaller: if `False`, an exception will be raised if the image is smaller than the requested ROI in any dimension. If `True`, any smaller dimensions will be set to match the cropped size (i.e., no cropping in that dimension). allow_missing_keys: don't raise exception if key is missing. rrdTNgFrrr]r_rrSequence[int] | intposrneg num_samplesr whole_boxrathresh_image_keyrimage_thresholdfg_indices_keybg_indices_key meta_keysKeysCollection | Nonemeta_key_postfix allow_smallerr`rbrccCsJt||_t|jdkrtdt||j|t|}t|dkr&td|d|_t||_||_|dks;|dkrFtd|d|d||dkrPtd||||_ |dkrctd |d||_ ||_ | |_ | |_ | |_| |_| durtdt|jnt| |_t|jt|jkrtd t|t|j|_d|_||_dS) Nrdz+At least one image_keys should be provided.rrz)pos and neg must be nonnegative, got pos=z neg=.z%Incompatible values: pos=0 and neg=0.z6num_samples needs to be positive int, got num_samples=z.meta_keys should have the same length as keys.)r,rrhrir%rgr]r spatial_size_ pos_ratior#r$r%r&r'r(r-r)r+centersr,)rjrr]rrr!r"r#r$r%r&r'r(r)r+r,r`r rnrnrorg+s>     " z"RandCropBoxByPosNegLabeld.__init__boxesr image_size Sequence[int] np.ndarrayc Cst|}t|tj^}}tj|td}t|ddd|ft}t|dd|dft}t |D]} |j sm|dd| f|j | dd|dd| f<|dd| f|j | dd|dd| |f<q7|dd| f|j | dd|dd| f<t |dd| f|dd| f|dd| f<|dd| f|j | d|dd| |f<t |dd| |f|dd| f|dd| |f<q7t||dd\}}|S)N)dtyperdTr )rhr1rndarray zeros_likerceilastypefloorranger$rminimummaximumr) rjr1r2rsboxes_nprZextended_boxesZ boxes_startZ boxes_stopaxisrnrnrogenerate_fg_center_boxes_npes"   .4.0. z5RandCropBoxByPosNegLabeld.generate_fg_center_boxes_np fg_indicesNdarrayOrTensor | None bg_indices thresh_imagec Cs|dus|dur5|||}t|t|jd|ddd}tj|ddddddf}t|||j\}} n|}|} t|j |j |j ||| |j |j |_dS)NrFrT)r@keepdimsrd.)rArronesruamaxr)r&r(rr#r/Rr,r0) rjr1r2rBrDrEZextended_boxes_npZmask_img fg_indices_ bg_indices_rnrnrors&  z#RandCropBoxByPosNegLabeld.randomizerpr"list[dict[Hashable, torch.Tensor]]cst||jdjdd}t|j||_|j}fdd|jD}|jdur2 |jdnd}|j dur@ |j dnd}|j rJ|j nd}| ||||||j dur^tdfddt|jD}t|j D]g\} } t|| <tt| |jd} dd| jD} d dt| j|D} d dt| | D}t|d } |jD] }| ||| |<qt|d }|||\|| |j<}t|j|D] \}}||| |<qqo|S) Nrrdcr rnrnr rrnrorrz6RandCropBoxByPosNegLabeld.__call__..z!no available ROI centers to crop.csg|]}tqSrnr|)rrrrnrorr) roi_centerroi_sizecSsg|]}t|jdqS)r)maxstart)rsrnrnrorscSsg|] \}}t|j|qSrn)minstop)rrQZ image_size_arnrnrorrcSs"g|] \}}tt|t|qSrn)slicer)rrQernrnrors") roi_slices)rtrrur.r.rr]rr'popr(r%rr0rir<r# enumeraterr"tupleslicesrr)rjrpr2r1rrBrDrEresultsicentercropperZ crop_startZcrop_endZ crop_slicesrZ boxcropperZcropped_labelsrZcropped_labels_irnrrorzs6      z"RandCropBoxByPosNegLabeld.__call__)"rrr]r_rrrr r!rr"rr#rr$rar%rr&rr'rr(rr)r*r+r_r,rar`rarbrc)r1rr2r3rbr4)NNN) r1rr2r3rBrCrDrCrErCrbrc)rprrbrL) rrrrrrgrArrzrnrnrnrorTs*: : !rTcsDeZdZdZejZ   ddfdd ZdddZdddZZ S)rWa Input boxes and images are rotated by 90 degrees in the plane specified by ``spatial_axes`` for ``k`` times Args: image_keys: Keys to pick image data for transformation. box_keys: Keys to pick box data for transformation. The box mode is assumed to be ``StandardMode``. box_ref_image_keys: Keys that represent the reference images to which ``box_keys`` are attached. k: number of times to rotate by 90 degrees. spatial_axes: 2 int numbers, defines the plane to rotate with 2 spatial axes. Default (0, 1), this is the first two axis in spatial dimensions. allow_missing_keys: don't raise exception if key is missing. rdrrdFrrr]r^kr spatial_axestuple[int, int]r`rarbrccsXt||_t||_t|j|j|t|t|j|_t|||_ t |||_ dSr{) r,rr]rfrgr-rhr^r! img_rotatorr box_rotator)rjrr]r^r`rar`rlrnrorgs  zRotateBox90d.__init__rprcCst|}t|j|jD]I\}}t||jdd}||||||<|jjddkrI||jj d||jj d||jj d<||jj d<|j |||dddq |j D] }|||||<qX|S)Nrdr6rrrr) rtrr]r^listrurdrcr`rarr)rjrprxryrrrnrnrorzs zRotateBox90d.__call__rc Cst|}||D]H}|j||dd}|tjdd}d|jj}|dkr0|j||||<|dkrQ|tjd}t ||j j }||||||<| ||q |S)NFrrrrr) rtrwrr0rrrcr`r~rrdrar) rjrprxryrrnum_times_to_rotaterinverse_transformrnrnror~s  zRotateBox90d.inverse)rdr_F)rrr]rr^rr`rrarbr`rarbrcrprrbrr) rrrrrrrgrzr~rrnrnrlrorWs rWcsReZdZdZejZ    d!d"ddZd#ddZd$d%fdd Zd&dd Z Z S)'rZan With probability `prob`, input boxes and images are rotated by 90 degrees in the plane specified by `spatial_axes`. Args: image_keys: Keys to pick image data for transformation. box_keys: Keys to pick box data for transformation. The box mode is assumed to be ``StandardMode``. box_ref_image_keys: Keys that represent the reference images to which ``box_keys`` are attached. prob: probability of rotating. (Default 0.1, with 10% probability it returns a rotated array.) max_k: number of rotations will be sampled from `np.random.randint(max_k) + 1`. (Default 3) spatial_axes: 2 int numbers, defines the plane to rotate with 2 spatial axes. Default: (0, 1), this is the first two axis in spatial dimensions. allow_missing_keys: don't raise exception if key is missing. rr_Frrr]r^rrmax_krrarbr`rarbrccCs^t||_t||_t||j|j|t||||_||_d|_t |t |j|_ dS)Nr) r,rr]r%rgr'rkra_rand_kr-rhr^)rjrr]r^rrkrar`rnrnrorg"s  zRandRotateBox90d.__init__rprc CsP|t|}|jddkr|St|j|j}t|j|j}t|j|jD]H\}}|j rnt ||j dd}||||||<|jddkra||jd||jd||jd<||jd<|j |||j|dddq&|j D]3}|j r|j r|||nt||td||<tr|j r|j||d d ni}|j |||dqr|S) Nrfrrdr6r)rand_krrrrFr)rrtrlrrar!rr]r^rrerurrr2rr) rjrprxrdrcryrrrrnrnrorz7s:   zRandRotateBox90d.__call__N Any | Nonecs$|j|jd|_tddSr)rIrandintrkrlrfrr}rlrnror]szRandRotateBox90d.randomizerc Cst|}|jddkr |S||D]]}|j||dd}|tjdd}|tjro|dkrD|j||dd}t |||tj||<|dkro|tjd}d|}|tjd } t ||j } | ||| ||<|||q|S) NrfrFrrrrrmr) rtrlrwrr0rrrrr!rhrra) rjrprxryrrrZnum_times_rotatedrgrrhrnrnror~as&   zRandRotateBox90d.inverse)rrjr_F)rrr]rr^rrrrkrrarbr`rarbrcrir{)rprnrbrcr) rrrrrrrgrzrr~rrnrnrlrorZs &rZ)ur __future__rcollections.abcrrrcopyrtypingrnumpyrrZ%monai.apps.detection.transforms.arrayrr r r r r rrrrrZ'monai.apps.detection.transforms.box_opsr monai.configrrmonai.config.type_definitionsrrmonai.data.box_utilsrrrmonai.data.meta_tensorrrmonai.data.utilsrmonai.transformsrrr r!r"r#monai.transforms.inverser$monai.transforms.transformr%r&r'monai.transforms.utilsr(r) monai.utilsr*r+r,r-r.monai.utils.enumsr/r0monai.utils.type_conversionr1r2__all__rrr3r6r9r<rr?rBrErHrKrNrQrTrWrZr7r8r:r;r@rArCrDr=r>rFrGrIrJrLrMrOrPrRrSrUrVrXrYr[r\r4r5rnrnrnrosl   4    -,87\0g>P=ZNUDk