def per_image_fpr(binclf_curves: torch.Tensor) -> torch.Tensor:
    """Compute False Positive Rate (FPR) for each image at each threshold.

    FPR = FP / N = FP / (FP + TN)

    Where:
        - FP: False Positives
        - TN: True Negatives
        - N: Total Negatives (FP + TN)

    Args:
        binclf_curves: Binary classification curves of shape ``(N, K, 2, 2)``
            See :func:`binary_classification_curve`

    Returns:
        FPR values of shape ``(N, K)`` and dtype ``float64`` where:
            - N: number of images
            - K: number of thresholds

        FPR is in descending order since thresholds are sorted ascending.
        FPR will be NaN for fully anomalous images (N = 0).

    Example:
        >>> curves = torch.randint(0, 10, (5, 10, 2, 2))  # 5 imgs, 10 thresh
        >>> fpr = per_image_fpr(curves)
        >>> fpr.shape
        torch.Size([5, 10])
    """
    # shape: (num images, num thresholds)
    fps = binclf_curves[..., 0, 1]
    neg = binclf_curves[..., 0, :].sum(dim=2)

    # it can be `nan` if an anomalous image is fully covered by the mask
    return fps.to(torch.float64) / neg.to(torch.float64)
Compute False Positive Rate (FPR) for each image at each threshold.

    FPR = FP / N = FP / (FP + TN)

    Where:
        - FP: False Positives
        - TN: True Negatives
        - N: Total Negatives (FP + TN)

    Args:
        binclf_curves: Binary classification curves of shape ``(N, K, 2, 2)``
            See :func:`binary_classification_curve`

    Returns:
        FPR values of shape ``(N, K)`` and dtype ``float64`` where:
            - N: number of images
            - K: number of thresholds

        FPR is in descending order since thresholds are sorted ascending.
        FPR will be NaN for fully anomalous images (N = 0).

    Example:
        >>> curves = torch.randint(0, 10, (5, 10, 2, 2))  # 5 imgs, 10 thresh
        >>> fpr = per_image_fpr(curves)
        >>> fpr.shape
        torch.Size([5, 10])
    
src/anomalib/metrics/pimo/binary_classification_curve.py