def _generate_params_for_single_input(
        self, x: np.ndarray, y: int | None = None
    ) -> tuple[AdversarialObject | None, int | None]:
        """
        Generate adversarial example params for a single image.

        :param x: Image to attack as a tensor (NRGB = (1, ...))
        :param y: Correct class of the image. If not provided, it is set to the prediction of the model.
        :return: Adversarial object params and adversarial class number.
        """

        image = np.expand_dims(x, 0)
        prediction = self.estimator.predict(image)
        if y is not None:
            actual_class = y
        else:
            actual_class = prediction.argmax()
        actual_class_confidence = prediction[0][actual_class]

        for _ in range(self.random_initializations):
            laser_params, predicted_class = self._attack_single_image(image, actual_class, actual_class_confidence)
            if laser_params is not None:
                logger.info("Found adversarial params: %s", laser_params)
                return laser_params, predicted_class
        logger.warning("Couldn't find adversarial laser parameters")

        return None, None

        Generate adversarial example params for a single image.

        :param x: Image to attack as a tensor (NRGB = (1, ...))
        :param y: Correct class of the image. If not provided, it is set to the prediction of the model.
        :return: Adversarial object params and adversarial class number.
        
art/attacks/evasion/laser_attack/laser_attack.py