def loss_gradient(
        self, x: np.ndarray, y: list[dict[str, np.ndarray]], standardise_output: bool = False, **kwargs
    ) -> np.ndarray:
        """
        Compute the gradient of the loss function w.r.t. `x`.

        :param x: Samples of shape (nb_samples, height, width, nb_channels).
        :param y: Targets of format `list[dict[str, np.ndarray]]`, one for each input image. The fields of the dict are
                  as follows:

                 - boxes [N, 4]: the boxes in [y1, x1, y2, x2] in scale [0, 1] (`standardise_output=False`) or
                                 [x1, y1, x2, y2] in image scale (`standardise_output=True`) format,
                                 with 0 <= x1 < x2 <= W and 0 <= y1 < y2 <= H.
                 - labels [N]: the labels for each image in TensorFlow (`standardise_output=False`) or PyTorch
                               (`standardise_output=True`) format

        :param standardise_output: True if `y` is provided in standardised PyTorch format. Box coordinates will be
                                   scaled back to [0, 1], label index will be decreased by 1 and the boxes will be
                                   changed from [x1, y1, x2, y2] to [y1, x1, y2, x2] format, with
                                   0 <= x1 < x2 <= W and 0 <= y1 < y2 <= H.
        :return: Loss gradients of the same shape as `x`.
        """
        import tensorflow as tf

        # Only do loss_gradient if is_training is False
        if self.is_training:
            raise NotImplementedError(
                "This object detector was loaded in training mode and therefore not support loss_gradient."
            )

        if standardise_output:
            from art.estimators.object_detection.utils import convert_pt_to_tf

            y = convert_pt_to_tf(y=y, height=x.shape[1], width=x.shape[2])

        # Apply preprocessing
        x_preprocessed, _ = self._apply_preprocessing(x, y=None, fit=False)

        groundtruth_boxes_list = [tf.convert_to_tensor(y[i]["boxes"]) for i in range(x.shape[0])]

        groundtruth_classes_list = [
            tf.one_hot(groundtruth_class, self._model.num_classes, on_value=1.0, off_value=0.0)
            for groundtruth_class in [tf.convert_to_tensor(y[i]["labels"]) for i in range(x.shape[0])]
        ]

        groundtruth_weights_list = [[1] * len(y[i]["labels"]) for i in range(x.shape[0])]

        self._model.provide_groundtruth(
            groundtruth_boxes_list=groundtruth_boxes_list,
            groundtruth_classes_list=groundtruth_classes_list,
            groundtruth_weights_list=groundtruth_weights_list,
        )

        with tf.GradientTape() as tape:

            x_preprocessed = tf.convert_to_tensor(x_preprocessed)
            tape.watch(x_preprocessed)

            preprocessed_images, true_image_shapes = self._model.preprocess(x_preprocessed)
            predictions = self._model.predict(preprocessed_images, true_image_shapes)
            losses = self._model.loss(predictions, true_image_shapes)

            loss = None
            for loss_name in self.attack_losses:
                if loss is None:
                    loss = losses[loss_name]
                else:
                    loss = loss + losses[loss_name]

        grads = tape.gradient(loss, x_preprocessed)

        grads = self._apply_preprocessing_gradient(x, grads)
        assert grads.shape == x_preprocessed.shape

        return grads

        Compute the gradient of the loss function w.r.t. `x`.

        :param x: Samples of shape (nb_samples, height, width, nb_channels).
        :param y: Targets of format `list[dict[str, np.ndarray]]`, one for each input image. The fields of the dict are
                  as follows:

                 - boxes [N, 4]: the boxes in [y1, x1, y2, x2] in scale [0, 1] (`standardise_output=False`) or
                                 [x1, y1, x2, y2] in image scale (`standardise_output=True`) format,
                                 with 0 <= x1 < x2 <= W and 0 <= y1 < y2 <= H.
                 - labels [N]: the labels for each image in TensorFlow (`standardise_output=False`) or PyTorch
                               (`standardise_output=True`) format

        :param standardise_output: True if `y` is provided in standardised PyTorch format. Box coordinates will be
                                   scaled back to [0, 1], label index will be decreased by 1 and the boxes will be
                                   changed from [x1, y1, x2, y2] to [y1, x1, y2, x2] format, with
                                   0 <= x1 < x2 <= W and 0 <= y1 < y2 <= H.
        :return: Loss gradients of the same shape as `x`.
        
art/estimators/object_detection/tensorflow_v2_faster_rcnn.py