# utils

Python API: `luxonis_train.attached_modules.metrics.utils`

Helpers for the keypoint metrics.

[merge_bbox_kpt_targets](https://docs.luxonis.com/software-v3/ai-inference/model-source/training/luxonis-train/luxonis-train-api-reference/attached_modules/metrics/utils.md)
merges the box label and the keypoint label into one tensor.
[fix_empty_tensor](https://docs.luxonis.com/software-v3/ai-inference/model-source/training/luxonis-train/luxonis-train-api-reference/attached_modules/metrics/utils.md)
reshapes an empty one-dimensional tensor to the shape `[1, 0]`.

## Functions

### fix_empty_tensor

```python
def fix_empty_tensor(tensor: Tensor) -> Tensor:
```

Reshape an empty one-dimensional tensor to the shape `[1, 0]`.

The keypoint metrics call this function on the tensors that they append to their list states. An empty tensor of shape `[0]` can
cause problems in DDP mode. The function returns every other tensor unchanged.

> **Example**
> ```pycon
>>> import torch
>>> fix_empty_tensor(torch.zeros(0)).shape
torch.Size([1, 0])
>>> fix_empty_tensor(torch.zeros(0, 3)).shape
torch.Size([0, 3])
```

Parameters

 * `tensor` (`Tensor`): The tensor to check.

Returns

 * `Tensor`: A view of shape `[1, 0]` when `tensor` is empty and one-dimensional, otherwise `tensor` itself.

### merge_bbox_kpt_targets

```python
def merge_bbox_kpt_targets(target_boundingbox: Tensor, target_keypoints: Tensor, *, device: torch.device | None = None) -> Tensor:
```

Merge the bounding box and keypoint labels into one tensor.

The function converts the boxes from `xywh`, where `x` and `y` are the top-left corner, to `xyxy`. It keeps the normalized coordinates. Row `i` of the result merges row `i` of both labels.

> **Example**
> ```pycon
>>> import torch
>>> boxes = torch.tensor([[0.0, 3.0, 0.25, 0.25, 0.5, 0.25]])
>>> keypoints = torch.tensor([[0.0, 0.5, 0.375, 2.0]])
>>> merge_bbox_kpt_targets(boxes, keypoints).tolist()
[[0.0, 3.0, 0.25, 0.25, 0.75, 0.5, 0.5, 0.375, 2.0]]
```

Parameters

 * `target_boundingbox` (`Tensor`): The box label, of shape `[N, 6]`, with rows `[batch_index, class, x, y, w, h]`.
 * `target_keypoints` (`Tensor`): The keypoint label, of shape `[N, 1 + 3K]`, with rows `[batch_index, x_1, y_1, v_1, ..., x_K,
   y_K, v_K]`, in the row order of `target_boundingbox`.
 * `device` (`torch.device | None`): The device of the result. `None` selects the default device of `torch`.

Returns

 * `Tensor`: A new floating point tensor of shape `[N, 6 + 3K]`, with rows `[batch_index, class, x1, y1, x2, y2, x_1, y_1, v_1,
   ...]`.
