def _get_losses(
        self,
        x: np.ndarray,
        y: list[dict[str, np.ndarray | "torch.Tensor"]],
        reduction: str = "sum",
    ) -> tuple[dict[str, "torch.Tensor" | int | list["torch.Tensor"]], list["torch.Tensor"], list["torch.Tensor"]]:
        """
        Get the loss tensor output of the model including all preprocessing.

        :param x: Samples of shape (nb_samples, nb_frames, height, width, nb_channels).
        :param y: Target values of format `list[dict[str, np.ndarray]]`, one dictionary for each input image. The keys
                  of the dictionary are:

                  - boxes [N_FRAMES, 4]: the boxes in [x1, y1, x2, y2] format, with 0 <= x1 < x2 <= W and
                                         0 <= y1 < y2 <= H.
        :param reduction: Specifies the reduction to apply to the output: 'none' | 'sum'.
                          'none': no reduction will be applied.
                          'sum': the output will be summed.
        :return: Loss dictionary, list of input tensors, and list of gradient tensors.
        """
        import torch

        self._model.train()

        # Apply preprocessing
        if self.all_framework_preprocessing:
            if isinstance(x, torch.Tensor):
                raise NotImplementedError

            if y is not None and isinstance(y[0]["boxes"], np.ndarray):
                y_tensor = []
                for i, y_i in enumerate(y):
                    y_t = {}
                    y_t["boxes"] = torch.from_numpy(y_i["boxes"]).float().to(self.device)  # type: ignore
                    y_tensor.append(y_t)
            else:
                y_tensor = y  # type: ignore

            image_tensor_list_grad = []
            y_preprocessed = []
            inputs_t: list["torch.Tensor"] = []

            for i in range(x.shape[0]):
                if self.clip_values is not None:
                    x_grad = torch.from_numpy(x[i]).to(self.device).float()
                else:
                    x_grad = torch.from_numpy(x[i]).to(self.device).float()
                x_grad.requires_grad = True
                image_tensor_list_grad.append(x_grad)
                x_grad_1 = torch.unsqueeze(x_grad, dim=0)
                x_preprocessed_i, y_preprocessed_i = self._apply_preprocessing(
                    x_grad_1, y=[y_tensor[i]], fit=False, no_grad=False
                )
                x_preprocessed_i = torch.squeeze(x_preprocessed_i)
                y_preprocessed.append(y_preprocessed_i[0])
                inputs_t.append(x_preprocessed_i)

        elif isinstance(x, np.ndarray):
            raise NotImplementedError
        else:
            raise NotImplementedError("Combination of inputs and preprocessing not supported.")

        labels_t = y_preprocessed  # type: ignore

        if isinstance(y[0]["boxes"], np.ndarray):
            y_init = torch.from_numpy(y[0]["boxes"]).to(self.device)
        else:
            y_init = y[0]["boxes"]

        loss_list = []

        for i in range(x.shape[0]):
            x_i = inputs_t[i]
            y_pred = self._track(x=x_i, y_init=y_init[i])
            gt_bb = labels_t[i]["boxes"]
            loss = torch.nn.L1Loss(size_average=False)(y_pred.float(), gt_bb.float())
            loss_list.append(loss)

        loss_dict: dict[str, "torch.Tensor" | int | list["torch.Tensor"]] = {}
        if reduction == "sum":
            loss_dict["torch.nn.L1Loss"] = sum(loss_list)
        elif reduction == "none":
            loss_dict["torch.nn.L1Loss"] = loss_list
        else:
            raise ValueError("Reduction not recognised.")

        return loss_dict, inputs_t, image_tensor_list_grad

        Get the loss tensor output of the model including all preprocessing.

        :param x: Samples of shape (nb_samples, nb_frames, height, width, nb_channels).
        :param y: Target values of format `list[dict[str, np.ndarray]]`, one dictionary for each input image. The keys
                  of the dictionary are:

                  - boxes [N_FRAMES, 4]: the boxes in [x1, y1, x2, y2] format, with 0 <= x1 < x2 <= W and
                                         0 <= y1 < y2 <= H.
        :param reduction: Specifies the reduction to apply to the output: 'none' | 'sum'.
                          'none': no reduction will be applied.
                          'sum': the output will be summed.
        :return: Loss dictionary, list of input tensors, and list of gradient tensors.
        
art/estimators/object_tracking/pytorch_goturn.py