def update(self, preds: List[np.ndarray], targets: Union[(np.ndarray, torch.Tensor)]) -> None:
    '\n        :param preds: Sorted by score. (Batch size, bounding boxes by batch, 5(x_min, y_min, x_max, y_max, label))\n        :param targets: (batch size, bounding box count, 5(x_min, y_min, x_max, y_max, label))\n        :return:\n        '
    targets = (targets.cpu().detach().numpy() if isinstance(targets, torch.Tensor) else targets)
    preds_by_class = []
    for pred_bboxes in preds:
        pred_by_class = [[] for _ in range(self._n_classes)]
        for pred_bbox in pred_bboxes:
            pred_by_class[int(pred_bbox[4])].append(pred_bbox)
        preds_by_class.append(pred_by_class)
    for i in range(targets.shape[0]):
        bbox_annotations = targets[i, :, :]
        bbox_annotations = bbox_annotations[(bbox_annotations[:, 4] >= 0)]
        pred_by_class = preds_by_class[i]
        applied_bbox_count_by_classes = [0 for _ in range(self._n_classes)]
        for bbox_annotation in bbox_annotations:
            label = int(bbox_annotation[4])
            pred_bboxes = pred_by_class[label]
            if ((pred_bboxes is None) or (len(pred_bboxes) == 0)):
                self.fn_by_classes[label] += 1
                continue
            is_matched = False
            for pred_bbox in pred_bboxes:
                (overlap, union, iou) = calc_bbox_overlap_union_iou(pred_bbox, bbox_annotation)
                if (iou >= 0.5):
                    applied_bbox_count_by_classes[label] += 1
                    self.tp_by_classes[label] += 1
                    is_matched = True
                    break
            if (not is_matched):
                self.fn_by_classes[label] += 1
        for label in range(self._n_classes):
            self.fp_by_classes[label] += (len(pred_by_class[label]) - applied_bbox_count_by_classes[label])
:param preds: Sorted by score. (Batch size, bounding boxes by batch, 5(x_min, y_min, x_max, y_max, label))
:param targets: (batch size, bounding box count, 5(x_min, y_min, x_max, y_max, label))
:return:
def update(self, preds: List[np.ndarray], targets: Union[(np.ndarray, torch.Tensor)]) -> None:
    '\n        :param preds: Sorted by score. (Batch size, bounding boxes by batch, 5(x_min, y_min, x_max, y_max, label))\n        :param targets: (batch size, bounding box count, 5(x_min, y_min, x_max, y_max, label))\n        :return:\n        '
    targets = (targets.cpu().detach().numpy() if isinstance(targets, torch.Tensor) else targets)
    preds_by_class = []
    for pred_bboxes in preds:
        pred_by_class = [[] for _ in range(self._n_classes)]
        for pred_bbox in pred_bboxes:
            pred_by_class[int(pred_bbox[4])].append(pred_bbox)
        preds_by_class.append(pred_by_class)
    for i in range(targets.shape[0]):
        bbox_annotations = targets[i, :, :]
        bbox_annotations = bbox_annotations[(bbox_annotations[:, 4] >= 0)]
        pred_by_class = preds_by_class[i]
        applied_bbox_count_by_classes = [0 for _ in range(self._n_classes)]
        for bbox_annotation in bbox_annotations:
            label = int(bbox_annotation[4])
            pred_bboxes = pred_by_class[label]
            if ((pred_bboxes is None) or (len(pred_bboxes) == 0)):
                self.fn_by_classes[label] += 1
                continue
            is_matched = False
            for pred_bbox in pred_bboxes:
                (overlap, union, iou) = calc_bbox_overlap_union_iou(pred_bbox, bbox_annotation)
                if (iou >= 0.5):
                    applied_bbox_count_by_classes[label] += 1
                    self.tp_by_classes[label] += 1
                    is_matched = True
                    break
            if (not is_matched):
                self.fn_by_classes[label] += 1
        for label in range(self._n_classes):
            self.fp_by_classes[label] += (len(pred_by_class[label]) - applied_bbox_count_by_classes[label])