Skip to content

Commit

Permalink
Revert "Merge main to v2 (#2464)"
Browse files Browse the repository at this point in the history
This reverts commit 818fa5a.
  • Loading branch information
samet-akcay committed Dec 11, 2024
1 parent 818fa5a commit aaa1502
Show file tree
Hide file tree
Showing 8 changed files with 320 additions and 408 deletions.
7 changes: 7 additions & 0 deletions docs/source/markdown/guides/how_to/pipelines/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@ This section contains tutorials on how to use different pipelines of Anomalib an
:margin: 1 1 0 0
:gutter: 1

:::{grid-item-card} {octicon}`stack` Tiled Ensemble
:link: ./tiled_ensemble
:link-type: doc

Learn more about how to use the tiled ensemble pipelines.
:::

:::{grid-item-card} {octicon}`gear` Custom Pipeline
:link: ./custom_pipeline
:link-type: doc
Expand Down
157 changes: 157 additions & 0 deletions docs/source/markdown/guides/how_to/pipelines/tiled_ensemble.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
# Tiled ensemble

This guide will show you how to use **The Tiled Ensemble** method for anomaly detection. For more details, refer to the official [Paper](https://openaccess.thecvf.com/content/CVPR2024W/VAND/html/Rolih_Divide_and_Conquer_High-Resolution_Industrial_Anomaly_Detection_via_Memory_Efficient_CVPRW_2024_paper.html).

The tiled ensemble approach reduces memory consumption by dividing input images into a grid of tiles and training a dedicated model for each tile location.
It is compatible with any existing image anomaly detection model without the need for any modification of the underlying architecture.

![Tiled ensemble flow](../../../../images/tiled_ensemble/ensemble_flow.png)

```{note}
This feature is experimental and may not work as expected.
For any problems refer to [Issues](https://github.com/openvinotoolkit/anomalib/issues) and feel free to ask any question in [Discussions](https://github.com/openvinotoolkit/anomalib/discussions).
```

## Training

You can train a tiled ensemble using the training script located inside `tools/tiled_ensemble` directory:

```{code-block} bash
python tools/tiled_ensemble/train_ensemble.py \
--config tools/tiled_ensemble/ens_config.yaml
```

By default, the Padim model is trained on **MVTec AD bottle** category using image size of 256x256, divided into non-overlapping 128x128 tiles.
You can modify these parameters in the [config file](#ensemble-configuration).

## Evaluation

After training, you can evaluate the tiled ensemble on test data using:

```{code-block} bash
python tools/tiled_ensemble/eval.py \
--config tools/tiled_ensemble/ens_config.yaml \
--root path_to_results_dir
```

Ensure that `root` points to the directory containing the training results, typically `results/padim/mvtec/bottle/runX`.

## Ensemble configuration

Tiled ensemble is configured using `ens_config.yaml` file in the `tools/tiled_ensemble` directory.
It contains general settings and tiled ensemble specific settings.

### General

General settings at the top of the config file are used to set up the random `seed`, `accelerator` (device) and the path to where results will be saved `default_root_dir`.

```{code-block} yaml
seed: 42
accelerator: "gpu"
default_root_dir: "results"
```

### Tiling

This section contains the following settings, used for image tiling:

```{code-block} yaml
tiling:
tile_size: 256
stride: 256
```

These settings determine the tile size and stride. Another important parameter is image_size from `data` section later in the config. It determines the original size of the image.

Input image is split into tiles, where each tile is of shape set by `tile_size` and tiles are taken with step set by `stride`.
For example: having image_size: 512, tile_size: 256, and stride: 256, results in 4 non-overlapping tile locations.

### Normalization and thresholding

Next up are the normalization and thresholding settings:

```{code-block} yaml
normalization_stage: image
thresholding:
method: F1AdaptiveThreshold
stage: image
```

- **Normalization**: Can be applied per each tile location separately (`tile` option), after combining prediction (`image` option), or skipped (`none` option).

- **Thresholding**: Can also be applied at different stages, but it is limited to `tile` and `image`. Another setting for thresholding is the method used. It can be specified as a string or by the class path.

### Data

The `data` section is used to configure the input `image_size` and other parameters for the dataset used.

```{code-block} yaml
data:
class_path: anomalib.data.MVTec
init_args:
root: ./datasets/MVTec
category: bottle
train_batch_size: 32
eval_batch_size: 32
num_workers: 8
task: segmentation
transform: null
train_transform: null
eval_transform: null
test_split_mode: from_dir
test_split_ratio: 0.2
val_split_mode: same_as_test
val_split_ratio: 0.5
image_size: [256, 256]
```

Refer to [Data](../../reference/data/image/index.md) for more details on parameters.

### SeamSmoothing

This section contains settings for `SeamSmoothing` block of pipeline:

```{code-block} yaml
SeamSmoothing:
apply: True
sigma: 2
width: 0.1
```

SeamSmoothing job is responsible for smoothing of regions where tiles meet - called tile seams.

- **apply**: If True, smoothing will be applied.
- **sigma**: Controls the sigma of Gaussian filter used for smoothing.
- **width**: Sets the percentage of the region around the seam to be smoothed.

### TrainModels

The last section `TrainModels` contains the setup for model training:

```{code-block} yaml
TrainModels:
model:
class_path: Fastflow
metrics:
pixel: AUROC
image: AUROC
trainer:
max_epochs: 500
callbacks:
- class_path: lightning.pytorch.callbacks.EarlyStopping
init_args:
patience: 42
monitor: pixel_AUROC
mode: max
```

- **Model**: Specifies the model used. Refer to [Models](../../reference/models/image/index.md) for more details on the model parameters.
- **Metrics**: Defines evaluation metrics for pixel and image level.
- **Trainer**: _optional_ parameters, used to control the training process. Refer to [Engine](../../reference/engine/index.md) for more details.
322 changes: 49 additions & 273 deletions notebooks/700_metrics/701b_aupimo_advanced_i.ipynb

Large diffs are not rendered by default.

152 changes: 18 additions & 134 deletions notebooks/700_metrics/701c_aupimo_advanced_ii.ipynb

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/anomalib/models/components/base/export_mixin.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ def to_onnx(
dynamic_axes = (
{"input": {0: "batch_size"}, "output": {0: "batch_size"}}
if input_size
else {"input": {0: "batch_size", 2: "height", 3: "weight"}, "output": {0: "batch_size"}}
else {"input": {0: "batch_size", 2: "height", 3: "width"}, "output": {0: "batch_size"}}
)
onnx_path = export_root / "model.onnx"
# apply pass through the model to get the output names
Expand Down
43 changes: 43 additions & 0 deletions tools/tiled_ensemble/ens_config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
seed: 42
accelerator: "gpu"
default_root_dir: "results"

tiling:
tile_size: [128, 128]
stride: 128

normalization_stage: image # on what level we normalize, options: [tile, image, none]
thresholding:
method: F1AdaptiveThreshold # refer to documentation for thresholding methods
stage: image # stage at which we apply threshold, options: [tile, image]

data:
class_path: anomalib.data.MVTec
init_args:
root: ./datasets/MVTec
category: bottle
train_batch_size: 32
eval_batch_size: 32
num_workers: 8
task: segmentation
transform: null
train_transform: null
eval_transform: null
test_split_mode: from_dir
test_split_ratio: 0.2
val_split_mode: same_as_test
val_split_ratio: 0.5
image_size: [256, 256]

SeamSmoothing:
apply: True # if this is applied, area around tile seams are is smoothed
sigma: 2 # sigma of gaussian filter used to smooth this area
width: 0.1 # width factor, multiplied by tile dimension gives the region width around seam which will be smoothed

TrainModels:
model:
class_path: Padim

metrics:
pixel: AUROC
image: AUROC
28 changes: 28 additions & 0 deletions tools/tiled_ensemble/eval.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
"""Run tiled ensemble prediction."""

# Copyright (C) 2024 Intel Corporation
# SPDX-License-Identifier: Apache-2.0

from pathlib import Path

from jsonargparse import ArgumentParser

from anomalib.pipelines.tiled_ensemble import EvalTiledEnsemble


def get_parser() -> ArgumentParser:
"""Create a new parser if none is provided."""
parser = ArgumentParser()
parser.add_argument("--config", type=str | Path, help="Configuration file path.", required=True)
parser.add_argument("--root", type=str | Path, help="Weights file path.", required=True)

return parser


if __name__ == "__main__":
args = get_parser().parse_args()

print("Running tiled ensemble test pipeline.")
# pass the path to root dir with checkpoints
test_pipeline = EvalTiledEnsemble(args.root)
test_pipeline.run(args)
17 changes: 17 additions & 0 deletions tools/tiled_ensemble/train.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
"""Run tiled ensemble training."""

# Copyright (C) 2024 Intel Corporation
# SPDX-License-Identifier: Apache-2.0

from anomalib.pipelines.tiled_ensemble import EvalTiledEnsemble, TrainTiledEnsemble

if __name__ == "__main__":
print("Running tiled ensemble train pipeline")
train_pipeline = TrainTiledEnsemble()
# run training
train_pipeline.run()

print("Running tiled ensemble test pipeline.")
# pass the root dir from train run to load checkpoints
test_pipeline = EvalTiledEnsemble(train_pipeline.root_dir)
test_pipeline.run()

0 comments on commit aaa1502

Please sign in to comment.