def add_noise(
    x: np.ndarray,
    mask: np.ndarray,
    lbd: float,
    theta: np.ndarray,
    clip: bool = True,
) -> tuple[np.ndarray, np.ndarray, np.ndarray]:
    """
    Combines the image and noise to create a perturbed image.

    :param x: Input image.
    :param mask: Mask image.
    :param lbd: lambda multiplier for the perturbation.
    :param theta: The perturbation.
    :param clip: Whether to clip the perturbation.
    :return: image with perturbation, perturbation, mask
    """
    import cv2

    theta_full = cv2.resize(theta, (x.shape[1], x.shape[0])).astype(float)
    if len(theta_full.shape) < 3:
        theta_full = theta_full[:, :, np.newaxis]
    comb = x + lbd * theta_full

    mask_full = cv2.resize(mask, (x.shape[1], x.shape[0])).astype(float)
    if len(mask_full.shape) < 3:
        mask_full = mask_full[:, :, np.newaxis]
    mask_full = np.where(mask_full > 0.5, 1.0, 0.0)

    if clip:
        comb = np.clip(comb, 0, 1)

    pert = np.where(mask_full > 0.5, comb, 0)
    return comb, pert, mask_full

    Combines the image and noise to create a perturbed image.

    :param x: Input image.
    :param mask: Mask image.
    :param lbd: lambda multiplier for the perturbation.
    :param theta: The perturbation.
    :param clip: Whether to clip the perturbation.
    :return: image with perturbation, perturbation, mask
    
art/attacks/evasion/graphite/utils.py