99from torch .nn .functional import grid_sample , interpolate , pad as torch_pad
1010
1111from torchvision import tv_tensors
12+ from torchvision .tv_tensors ._bounding_boxes import CLAMPING_MODE_TYPE
1213from torchvision .transforms import _functional_pil as _FP
1314from torchvision .transforms ._functional_tensor import _pad_symmetric
1415from torchvision .transforms .functional import (
@@ -521,6 +522,7 @@ def resize_bounding_boxes(
521522 size : Optional [list [int ]],
522523 max_size : Optional [int ] = None ,
523524 format : tv_tensors .BoundingBoxFormat = tv_tensors .BoundingBoxFormat .XYXY ,
525+ clamping_mode : CLAMPING_MODE_TYPE = "hard" , # TODOBB soft
524526) -> tuple [torch .Tensor , tuple [int , int ]]:
525527 # We set the default format as `tv_tensors.BoundingBoxFormat.XYXY`
526528 # to ensure backward compatibility.
@@ -546,7 +548,7 @@ def resize_bounding_boxes(
546548 transformed_points = xyxyxyxy_boxes .mul (ratios )
547549 out_bboxes = _parallelogram_to_bounding_boxes (transformed_points )
548550 out_bboxes = clamp_bounding_boxes (
549- out_bboxes , format = tv_tensors .BoundingBoxFormat .XYXYXYXY , canvas_size = (new_height , new_width )
551+ out_bboxes , format = tv_tensors .BoundingBoxFormat .XYXYXYXY , canvas_size = (new_height , new_width ), clamping_mode = clamping_mode ,
550552 )
551553 return (
552554 convert_bounding_box_format (
@@ -572,7 +574,7 @@ def _resize_bounding_boxes_dispatch(
572574 inpt : tv_tensors .BoundingBoxes , size : Optional [list [int ]], max_size : Optional [int ] = None , ** kwargs : Any
573575) -> tv_tensors .BoundingBoxes :
574576 output , canvas_size = resize_bounding_boxes (
575- inpt .as_subclass (torch .Tensor ), format = inpt .format , canvas_size = inpt .canvas_size , size = size , max_size = max_size
577+ inpt .as_subclass (torch .Tensor ), format = inpt .format , canvas_size = inpt .canvas_size , size = size , max_size = max_size , clamping_mode = inpt . clamping_mode
576578 )
577579 return tv_tensors .wrap (output , like = inpt , canvas_size = canvas_size )
578580
@@ -1098,6 +1100,7 @@ def _affine_bounding_boxes_with_expand(
10981100 shear : list [float ],
10991101 center : Optional [list [float ]] = None ,
11001102 expand : bool = False ,
1103+ clamping_mode : CLAMPING_MODE_TYPE = "hard" , # TODOBB soft
11011104) -> tuple [torch .Tensor , tuple [int , int ]]:
11021105 if bounding_boxes .numel () == 0 :
11031106 return bounding_boxes , canvas_size
@@ -1176,7 +1179,7 @@ def _affine_bounding_boxes_with_expand(
11761179 new_width , new_height = _compute_affine_output_size (affine_vector , width , height )
11771180 canvas_size = (new_height , new_width )
11781181
1179- out_bboxes = clamp_bounding_boxes (out_bboxes , format = intermediate_format , canvas_size = canvas_size )
1182+ out_bboxes = clamp_bounding_boxes (out_bboxes , format = intermediate_format , canvas_size = canvas_size , clamping_mode = clamping_mode )
11801183 out_bboxes = convert_bounding_box_format (
11811184 out_bboxes , old_format = intermediate_format , new_format = format , inplace = True
11821185 ).reshape (original_shape )
@@ -1197,6 +1200,7 @@ def affine_bounding_boxes(
11971200 scale : float ,
11981201 shear : list [float ],
11991202 center : Optional [list [float ]] = None ,
1203+ clamping_mode : CLAMPING_MODE_TYPE = "hard" , # TODOBB soft
12001204) -> torch .Tensor :
12011205 out_box , _ = _affine_bounding_boxes_with_expand (
12021206 bounding_boxes ,
@@ -1208,6 +1212,7 @@ def affine_bounding_boxes(
12081212 shear = shear ,
12091213 center = center ,
12101214 expand = False ,
1215+ clamping_mode = clamping_mode ,
12111216 )
12121217 return out_box
12131218
@@ -1231,6 +1236,7 @@ def _affine_bounding_boxes_dispatch(
12311236 scale = scale ,
12321237 shear = shear ,
12331238 center = center ,
1239+ clamping_mode = inpt .clamping_mode ,
12341240 )
12351241 return tv_tensors .wrap (output , like = inpt )
12361242
@@ -1723,6 +1729,7 @@ def pad_bounding_boxes(
17231729 canvas_size : tuple [int , int ],
17241730 padding : list [int ],
17251731 padding_mode : str = "constant" ,
1732+ clamping_mode : CLAMPING_MODE_TYPE = "hard" , # TODOBB soft
17261733) -> tuple [torch .Tensor , tuple [int , int ]]:
17271734 if padding_mode not in ["constant" ]:
17281735 # TODO: add support of other padding modes
@@ -1745,7 +1752,7 @@ def pad_bounding_boxes(
17451752 width += left + right
17461753 canvas_size = (height , width )
17471754
1748- return clamp_bounding_boxes (bounding_boxes , format = format , canvas_size = canvas_size ), canvas_size
1755+ return clamp_bounding_boxes (bounding_boxes , format = format , canvas_size = canvas_size , clamping_mode = clamping_mode ), canvas_size
17491756
17501757
17511758@_register_kernel_internal (pad , tv_tensors .BoundingBoxes , tv_tensor_wrapper = False )
@@ -1758,6 +1765,7 @@ def _pad_bounding_boxes_dispatch(
17581765 canvas_size = inpt .canvas_size ,
17591766 padding = padding ,
17601767 padding_mode = padding_mode ,
1768+ clamping_mode = inpt .clamping_mode
17611769 )
17621770 return tv_tensors .wrap (output , like = inpt , canvas_size = canvas_size )
17631771
@@ -1836,6 +1844,7 @@ def crop_bounding_boxes(
18361844 left : int ,
18371845 height : int ,
18381846 width : int ,
1847+ clamping_mode : CLAMPING_MODE_TYPE = "hard" , # TODOBB soft
18391848) -> tuple [torch .Tensor , tuple [int , int ]]:
18401849
18411850 # Crop or implicit pad if left and/or top have negative values:
@@ -1854,15 +1863,15 @@ def crop_bounding_boxes(
18541863 if format == tv_tensors .BoundingBoxFormat .XYXYXYXY :
18551864 bounding_boxes = _parallelogram_to_bounding_boxes (bounding_boxes )
18561865
1857- return clamp_bounding_boxes (bounding_boxes , format = format , canvas_size = canvas_size ), canvas_size
1866+ return clamp_bounding_boxes (bounding_boxes , format = format , canvas_size = canvas_size , clamping_mode = clamping_mode ), canvas_size
18581867
18591868
18601869@_register_kernel_internal (crop , tv_tensors .BoundingBoxes , tv_tensor_wrapper = False )
18611870def _crop_bounding_boxes_dispatch (
18621871 inpt : tv_tensors .BoundingBoxes , top : int , left : int , height : int , width : int
18631872) -> tv_tensors .BoundingBoxes :
18641873 output , canvas_size = crop_bounding_boxes (
1865- inpt .as_subclass (torch .Tensor ), format = inpt .format , top = top , left = left , height = height , width = width
1874+ inpt .as_subclass (torch .Tensor ), format = inpt .format , top = top , left = left , height = height , width = width , clamping_mode = inpt . clamping_mode
18661875 )
18671876 return tv_tensors .wrap (output , like = inpt , canvas_size = canvas_size )
18681877
@@ -2066,6 +2075,7 @@ def perspective_bounding_boxes(
20662075 startpoints : Optional [list [list [int ]]],
20672076 endpoints : Optional [list [list [int ]]],
20682077 coefficients : Optional [list [float ]] = None ,
2078+ clamping_mode : CLAMPING_MODE_TYPE = "hard" , # TODOBB soft
20692079) -> torch .Tensor :
20702080 if bounding_boxes .numel () == 0 :
20712081 return bounding_boxes
@@ -2130,7 +2140,7 @@ def perspective_bounding_boxes(
21302140 out_bbox_mins , out_bbox_maxs = torch .aminmax (transformed_points , dim = 1 )
21312141 out_bboxes = torch .cat ([out_bbox_mins , out_bbox_maxs ], dim = 1 )
21322142
2133- out_bboxes = clamp_bounding_boxes (out_bboxes , format = intermediate_format , canvas_size = canvas_size )
2143+ out_bboxes = clamp_bounding_boxes (out_bboxes , format = intermediate_format , canvas_size = canvas_size , clamping_mode = clamping_mode )
21342144
21352145 out_bboxes = convert_bounding_box_format (
21362146 out_bboxes , old_format = intermediate_format , new_format = format , inplace = True
@@ -2185,6 +2195,7 @@ def _perspective_bounding_boxes_dispatch(
21852195 startpoints = startpoints ,
21862196 endpoints = endpoints ,
21872197 coefficients = coefficients ,
2198+ clamping_mode = inpt .clamping_mode ,
21882199 )
21892200 return tv_tensors .wrap (output , like = inpt )
21902201
@@ -2377,6 +2388,7 @@ def elastic_bounding_boxes(
23772388 format : tv_tensors .BoundingBoxFormat ,
23782389 canvas_size : tuple [int , int ],
23792390 displacement : torch .Tensor ,
2391+ clamping_mode : CLAMPING_MODE_TYPE = "hard" , # TODOBB soft
23802392) -> torch .Tensor :
23812393 expected_shape = (1 , canvas_size [0 ], canvas_size [1 ], 2 )
23822394 if not isinstance (displacement , torch .Tensor ):
@@ -2432,6 +2444,7 @@ def elastic_bounding_boxes(
24322444 out_bboxes ,
24332445 format = intermediate_format ,
24342446 canvas_size = canvas_size ,
2447+ clamping_mode = clamping_mode
24352448 )
24362449
24372450 return convert_bounding_box_format (
@@ -2444,7 +2457,7 @@ def _elastic_bounding_boxes_dispatch(
24442457 inpt : tv_tensors .BoundingBoxes , displacement : torch .Tensor , ** kwargs
24452458) -> tv_tensors .BoundingBoxes :
24462459 output = elastic_bounding_boxes (
2447- inpt .as_subclass (torch .Tensor ), format = inpt .format , canvas_size = inpt .canvas_size , displacement = displacement
2460+ inpt .as_subclass (torch .Tensor ), format = inpt .format , canvas_size = inpt .canvas_size , displacement = displacement , clamping_mode = inpt . clamping_mode
24482461 )
24492462 return tv_tensors .wrap (output , like = inpt )
24502463
0 commit comments