Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add PIMO #2329

Merged
merged 12 commits into from
Oct 2, 2024
549 changes: 549 additions & 0 deletions notebooks/700_metrics/701a_aupimo.ipynb

Large diffs are not rendered by default.

690 changes: 690 additions & 0 deletions notebooks/700_metrics/roc_pro_pimo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
14 changes: 13 additions & 1 deletion src/anomalib/data/utils/path.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,13 +142,20 @@ def contains_non_printable_characters(path: str | Path) -> bool:
return not printable_pattern.match(str(path))


def validate_path(path: str | Path, base_dir: str | Path | None = None, should_exist: bool = True) -> Path:
def validate_path(
path: str | Path,
base_dir: str | Path | None = None,
should_exist: bool = True,
extensions: tuple[str, ...] | None = None,
) -> Path:
"""Validate the path.

Args:
path (str | Path): Path to validate.
base_dir (str | Path): Base directory to restrict file access.
should_exist (bool): If True, do not raise an exception if the path does not exist.
extensions (tuple[str, ...] | None): Accepted extensions for the path. An exception is raised if the
path does not have one of the accepted extensions. If None, no check is performed. Defaults to None.

Returns:
Path: Validated path.
Expand Down Expand Up @@ -213,6 +220,11 @@ def validate_path(path: str | Path, base_dir: str | Path | None = None, should_e
msg = f"Read or execute permissions denied for the path: {path}"
raise PermissionError(msg)

# Check if the path has one of the accepted extensions
if extensions is not None and path.suffix not in extensions:
msg = f"Path extension is not accepted. Accepted extensions: {extensions}. Path: {path}"
raise ValueError(msg)

return path


Expand Down
3 changes: 3 additions & 0 deletions src/anomalib/metrics/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
from .f1_max import F1Max
from .f1_score import F1Score
from .min_max import MinMax
from .pimo import AUPIMO, PIMO
from .precision_recall_curve import BinaryPrecisionRecallCurve
from .pro import PRO
from .threshold import F1AdaptiveThreshold, ManualThreshold
Expand All @@ -35,6 +36,8 @@
"ManualThreshold",
"MinMax",
"PRO",
"PIMO",
"AUPIMO",
]

logger = logging.getLogger(__name__)
Expand Down
23 changes: 23 additions & 0 deletions src/anomalib/metrics/pimo/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
"""Per-Image Metrics."""

# Original Code
# https://github.com/jpcbertoldo/aupimo
#
# Modified
# Copyright (C) 2024 Intel Corporation
# SPDX-License-Identifier: Apache-2.0

from .binary_classification_curve import ThresholdMethod
from .pimo import AUPIMO, PIMO, AUPIMOResult, PIMOResult

__all__ = [
# constants
"ThresholdMethod",
# result classes
"PIMOResult",
"AUPIMOResult",
# torchmetrics interfaces
"PIMO",
"AUPIMO",
"StatsOutliersPolicy",
]
Loading
Loading