From a set of original boxes and encoded relative box offsets, Args: rel_codes: encoded boxes, Nx(4*num_box_reg) or Nx(6*num_box_reg) torch tensor. reference_boxes: reference boxes, Nx4 or Nx6 torch tensor. The box mode is assumed to be ``StandardMode``
(self, rel_codes: Tensor, reference_boxes: Tensor)
| 196 | return pred_boxes |
| 197 | |
| 198 | def decode_single(self, rel_codes: Tensor, reference_boxes: Tensor) -> Tensor: |
| 199 | """ |
| 200 | From a set of original boxes and encoded relative box offsets, |
| 201 | |
| 202 | Args: |
| 203 | rel_codes: encoded boxes, Nx(4*num_box_reg) or Nx(6*num_box_reg) torch tensor. |
| 204 | reference_boxes: reference boxes, Nx4 or Nx6 torch tensor. The box mode is assumed to be ``StandardMode`` |
| 205 | |
| 206 | Return: |
| 207 | decoded boxes, Nx(4*num_box_reg) or Nx(6*num_box_reg) torch tensor. The box mode will to be ``StandardMode`` |
| 208 | """ |
| 209 | reference_boxes = reference_boxes.to(rel_codes.dtype) |
| 210 | offset = reference_boxes.shape[-1] |
| 211 | |
| 212 | pred_boxes = [] |
| 213 | boxes_cccwhd: torch.Tensor = convert_box_mode( |
| 214 | reference_boxes, src_mode=StandardMode, dst_mode=CenterSizeMode |
| 215 | ) # type: ignore[assignment] |
| 216 | |
| 217 | for axis in range(self.spatial_dims): |
| 218 | whd_axis = boxes_cccwhd[:, axis + self.spatial_dims] |
| 219 | ctr_xyz_axis = boxes_cccwhd[:, axis] |
| 220 | dxyz_axis = rel_codes[:, axis::offset] / self.weights[axis] |
| 221 | dwhd_axis = rel_codes[:, self.spatial_dims + axis :: offset] / self.weights[axis + self.spatial_dims] |
| 222 | # Prevent sending too large values into torch.exp() |
| 223 | dwhd_axis = torch.clamp(dwhd_axis.to(COMPUTE_DTYPE), max=self.boxes_xform_clip) |
| 224 | |
| 225 | pred_ctr_xyx_axis = dxyz_axis * whd_axis[:, None] + ctr_xyz_axis[:, None] |
| 226 | pred_whd_axis = torch.exp(dwhd_axis) * whd_axis[:, None] |
| 227 | pred_whd_axis = pred_whd_axis.to(dxyz_axis.dtype) # type: ignore[union-attr] |
| 228 | |
| 229 | # When convert float32 to float16, Inf or Nan may occur |
| 230 | if torch.isnan(pred_whd_axis).any() or torch.isinf(pred_whd_axis).any(): |
| 231 | raise ValueError("pred_whd_axis is NaN or Inf.") |
| 232 | |
| 233 | # Distance from center to box's corner. |
| 234 | c_to_c_whd_axis = ( |
| 235 | torch.tensor(0.5, dtype=pred_ctr_xyx_axis.dtype, device=pred_whd_axis.device) * pred_whd_axis # type: ignore[arg-type] |
| 236 | ) |
| 237 | |
| 238 | pred_boxes.append(pred_ctr_xyx_axis - c_to_c_whd_axis) |
| 239 | pred_boxes.append(pred_ctr_xyx_axis + c_to_c_whd_axis) |
| 240 | |
| 241 | pred_boxes = pred_boxes[::2] + pred_boxes[1::2] |
| 242 | pred_boxes_final = torch.stack(pred_boxes, dim=2).flatten(1) |
| 243 | return pred_boxes_final |