# fomo_confusion_matrix

Python API: `luxonis_train.attached_modules.metrics.confusion_matrix.fomo_confusion_matrix`

The confusion matrix for FOMO, which matches a small box around each predicted point to the target boxes.

## Classes

### FomoConfusionMatrix

Confusion matrix for FOMO keypoint predictions.

 * `Inputs:`: * `keypoints` (`list[Tensor]`): [Ki, 1, 4] per image, `(x, y, prob, class)`, pixels
    * `target_boundingbox` (`Tensor`): [N, 6], `[batch, class, x, y, w, h]`, `xywh` normalized
 * `Outputs:`: * `mcc` (`Tensor`): scalar MCC of the whole matrix, see
   [compute_mcc](https://docs.luxonis.com/software-v3/ai-inference/model-source/training/luxonis-train/luxonis-train-api-reference/attached_modules/metrics/confusion_matrix/utils.md)
    * `confusion_matrix` (`Tensor`): [nclasses + 1, nclasses + 1] counts, rows are targets, last row and column are background
 * `Formula:`:
   [update](https://docs.luxonis.com/software-v3/ai-inference/model-source/training/luxonis-train/luxonis-train-api-reference/attached_modules/metrics/confusion_matrix/fomo_confusion_matrix.md)
   drops each keypoint with a probability below `0.5`. It turns each other keypoint into a box of `5` by `5` pixels around the
   point, clipped to the image.
   [DetectionConfusionMatrix](https://docs.luxonis.com/software-v3/ai-inference/model-source/training/luxonis-train/luxonis-train-api-reference/attached_modules/metrics/confusion_matrix/detection_confusion_matrix.md)
   then counts these boxes with the IoU threshold `0`. So a target box and a keypoint match when the box of the keypoint and the
   target box share an area above `0`. The other rules of
   [DetectionConfusionMatrix](https://docs.luxonis.com/software-v3/ai-inference/model-source/training/luxonis-train/luxonis-train-api-reference/attached_modules/metrics/confusion_matrix/detection_confusion_matrix.md)
   stay the same.

> **References**
> * Source: This project.
 * License: Apache-2.0 (this project)

> **Notes**
> The metric always uses the IoU threshold `0`. An `iou_threshold` other than `None` and `0` logs a warning.

> **Example**
> Attached to a `FOMOHead` in `model.nodes`:

```yaml
- name: FOMOHead
  inputs: [EfficientRep]
  metrics:
    - name: FomoConfusionMatrix
```

 * `Compatible with:`: * Nodes:
   [FOMOHead](https://docs.luxonis.com/software-v3/ai-inference/model-source/training/luxonis-train/luxonis-train-api-reference/nodes/heads/fomo_head.md)

#### Methods

##### init

```python
def __init__(iou_threshold: float | None = None, **kwargs):
```

Initialize the metric with the IoU threshold `0`.

Parameters

 * `iou_threshold` (`float | None`): Ignored. A value other than `None` and `0.0` logs a warning.
 * `**kwargs`: Keyword arguments forwarded to
   [DetectionConfusionMatrix](https://docs.luxonis.com/software-v3/ai-inference/model-source/training/luxonis-train/luxonis-train-api-reference/attached_modules/metrics/confusion_matrix/detection_confusion_matrix.md),
   such as `node`.

##### update

```python
def update(keypoints: list[Tensor], target_boundingbox: Tensor):
```

Turn the keypoints of one batch into boxes and count them.

[keypoints_to_bboxes](https://docs.luxonis.com/software-v3/ai-inference/model-source/training/luxonis-train/luxonis-train-api-reference/utils/boundingbox.md)
drops each keypoint with a probability below `0.5`. It turns each other keypoint into a box of `5` by `5` pixels around the point.
It clips the box to the height and width of
[BaseAttachedModule.original_in_shape](https://docs.luxonis.com/software-v3/ai-inference/model-source/training/luxonis-train/luxonis-train-api-reference/attached_modules/base_attached_module.md).
[DetectionConfusionMatrix.update](https://docs.luxonis.com/software-v3/ai-inference/model-source/training/luxonis-train/luxonis-train-api-reference/attached_modules/metrics/confusion_matrix/detection_confusion_matrix.md)
then counts the boxes.

> **Example**
> One target box of class `0` covers the pixels from `0` to `5`. The first keypoint lies in it. The second keypoint has a probability below `0.5`, so the metric drops it. A `SimpleNamespace` stands in for the node.

```pycon
>>> import torch
>>> from types import SimpleNamespace
>>> node = SimpleNamespace(
...     task=None,
...     n_classes=1,
...     original_in_shape=torch.Size([3, 10, 10]),
... )
>>> metric = FomoConfusionMatrix(node=node)
>>> target = torch.tensor([[0, 0, 0.0, 0.0, 0.5, 0.5]])
>>> points = [
...     torch.tensor([[[2.0, 2.0, 0.9, 0]], [[8.0, 8.0, 0.3, 0]]])
... ]
>>> metric.update(points, target)
>>> metric.confusion_matrix.tolist()
[[1, 0], [0, 0]]
```

Parameters

 * `keypoints` (`list[Tensor]`): The keypoints of each image, of shape `[K_i, 1, 4]`, as `[x, y, probability, class]` in pixels.
   The length of the list is the batch size.
 * `target_boundingbox` (`Tensor`): The `boundingbox` label of the batch, of shape `[N, 6]`, as `[batch_index, class, x, y, w,
   h]`. The values are normalized, and `x` and `y` are the top-left corner. The method writes `xyxy` pixels into it.

#### Attributes

##### supported_tasks
