Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
02cf2e9
add FROM_DIR option to `val split mode` to support a provided val dir…
willyfh Jan 13, 2024
0cadf5e
add a conditional check for the FROM_DIR option of val split mode
willyfh Jan 13, 2024
3913971
add the mvtec loco ad dataset classes
willyfh Jan 13, 2024
1300b18
add the default config file for mvtec loco ad dataset
willyfh Jan 13, 2024
1c5086f
update initialization files to include MVTec LOCO dataset
willyfh Jan 13, 2024
500c7c5
remove unnecessary Path conversion
willyfh Jan 13, 2024
58142f0
add mvtec_loco.yaml to the readme documentation of configs
willyfh Jan 13, 2024
bff9378
add dummy image generation for mvtec loco dataset
willyfh Jan 13, 2024
7025e55
add unit test for mvtec loco dataset
willyfh Jan 13, 2024
514efbc
update changelog to include the addition of mvtec loco dataset
willyfh Jan 13, 2024
f68277c
add mvtec loco dataset to the sphinx-based docs
willyfh Jan 14, 2024
16f215e
fix the malformed table
willyfh Jan 14, 2024
fc35ad8
binarize the masks and avoid the possibility of the merge_mask is None
willyfh Jan 14, 2024
d192c7c
Merge the masks using sum operation without binarization
willyfh Jan 21, 2024
9b466d4
override getitem method to handle binarization and to add additional …
willyfh Jan 21, 2024
7f07bbe
Add saturation config to the datamodule
willyfh Jan 21, 2024
7ac7308
Update the saturation config on the metrics based on the loaded confi…
willyfh Jan 21, 2024
ca5f1a5
add masks as a keyword args to the update method of the AnomalibMetri…
willyfh Jan 21, 2024
c02c256
Shorten the comments to solve ruff issues
willyfh Jan 21, 2024
0865765
Add sPro metric implementation
willyfh Jan 21, 2024
ccb7599
Change the saturation threshold to tensor
willyfh Jan 21, 2024
e0678c0
Handle case with only background/normal images in scoring
willyfh Jan 21, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).

### Added

- Add support for MVTec LOCO AD dataset by @willyfh in https://github.com/openvinotoolkit/anomalib/pull/1635

### Changed

- Changed default inference device to AUTO in https://github.com/openvinotoolkit/anomalib/pull/1534
Expand Down
8 changes: 8 additions & 0 deletions docs/source/markdown/guides/reference/data/image/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,13 @@ Learn more about Kolektor dataset.
Learn more about MVTec 2D dataset
:::

:::{grid-item-card} MVTec LOCO
:link: ./mvtec_loco
:link-type: doc

Learn more about MVTec LOCO dataset
:::

:::{grid-item-card} Visa
:link: ./visa
:link-type: doc
Expand All @@ -47,5 +54,6 @@ Learn more about Visa dataset.
./folder
./kolektor
./mvtec
./mvtec_loco
./visa
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# MVTec LOCO Data

```{eval-rst}
.. automodule:: anomalib.data.image.mvtec_loco
:members:
:show-inheritance:
```
14 changes: 11 additions & 3 deletions src/anomalib/callbacks/metrics.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,7 @@ def setup(
pl_module (AnomalyModule): Anomalib Model that inherits pl LightningModule.
stage (str | None, optional): fit, validate, test or predict. Defaults to None.
"""
del trainer, stage # These variables are not used.

del stage # this variable is not used.
image_metric_names = [] if self.image_metric_names is None else self.image_metric_names
if isinstance(image_metric_names, str):
image_metric_names = [image_metric_names]
Expand All @@ -92,6 +91,8 @@ def setup(
pl_module.image_metrics = create_metric_collection(image_metric_names, "image_")
pl_module.pixel_metrics = create_metric_collection(pixel_metric_names, "pixel_")
self._set_threshold(pl_module)
if hasattr(trainer.datamodule, "saturation_config"):
self._set_saturation_config(pl_module, trainer.datamodule.saturation_config)

def on_validation_epoch_start(
self,
Expand Down Expand Up @@ -166,6 +167,9 @@ def _set_threshold(self, pl_module: AnomalyModule) -> None:
pl_module.image_metrics.set_threshold(pl_module.image_threshold.value.item())
pl_module.pixel_metrics.set_threshold(pl_module.pixel_threshold.value.item())

def _set_saturation_config(self, pl_module: AnomalyModule, saturation_config: dict[int, Any]) -> None:
pl_module.pixel_metrics.set_saturation_config(saturation_config)

def _update_metrics(
self,
image_metric: AnomalibMetricCollection,
Expand All @@ -176,7 +180,11 @@ def _update_metrics(
image_metric.update(output["pred_scores"], output["label"].int())
if "mask" in output and "anomaly_maps" in output:
pixel_metric.to(self.device)
pixel_metric.update(torch.squeeze(output["anomaly_maps"]), torch.squeeze(output["mask"].int()))
pixel_metric.update(
torch.squeeze(output["anomaly_maps"]),
torch.squeeze(output["mask"].int()),
masks=torch.squeeze(output["masks"]) if "masks" in output else None,
)

def _outputs_to_device(self, output: STEP_OUTPUT) -> STEP_OUTPUT | dict[str, Any]:
if isinstance(output, dict):
Expand Down
3 changes: 2 additions & 1 deletion src/anomalib/data/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

from .base import AnomalibDataModule, AnomalibDataset
from .depth import DepthDataFormat, Folder3D, MVTec3D
from .image import BTech, Folder, ImageDataFormat, Kolektor, MVTec, Visa
from .image import BTech, Folder, ImageDataFormat, Kolektor, MVTec, MVTecLoco, Visa
from .predict import PredictDataset
from .video import Avenue, ShanghaiTech, UCSDped, VideoDataFormat

Expand Down Expand Up @@ -62,6 +62,7 @@ def get_datamodule(config: DictConfig | ListConfig) -> AnomalibDataModule:
"Kolektor",
"MVTec",
"MVTec3D",
"MVTecLoco",
"Avenue",
"UCSDped",
"ShanghaiTech",
Expand Down
3 changes: 3 additions & 0 deletions src/anomalib/data/base/datamodule.py
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,9 @@ def _create_val_split(self) -> None:
# converted from random training sample
self.train_data, normal_val_data = random_split(self.train_data, self.val_split_ratio, seed=self.seed)
self.val_data = SyntheticAnomalyDataset.from_dataset(normal_val_data)
elif self.val_split_mode == ValSplitMode.FROM_DIR:
# the val_data is prepared in subclass
pass
elif self.val_split_mode != ValSplitMode.NONE:
msg = f"Unknown validation split mode: {self.val_split_mode}"
raise ValueError(msg)
Expand Down
4 changes: 3 additions & 1 deletion src/anomalib/data/image/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from .folder import Folder
from .kolektor import Kolektor
from .mvtec import MVTec
from .mvtec_loco import MVTecLoco
from .visa import Visa


Expand All @@ -21,11 +22,12 @@ class ImageDataFormat(str, Enum):

MVTEC = "mvtec"
MVTEC_3D = "mvtec_3d"
MVTEC_LOCO = "mvtec_loco"
BTECH = "btech"
KOLEKTOR = "kolektor"
FOLDER = "folder"
FOLDER_3D = "folder_3d"
VISA = "visa"


__all__ = ["BTech", "Folder", "Kolektor", "MVTec", "Visa"]
__all__ = ["BTech", "Folder", "Kolektor", "MVTec", "MVTecLoco", "Visa"]
Loading