Skip to content

Commit 59d3898

Browse files
authored
Revert "Merge main to v2 (#2464)"
This reverts commit 818fa5a.
1 parent 818fa5a commit 59d3898

File tree

8 files changed

+320
-408
lines changed

8 files changed

+320
-408
lines changed

docs/source/markdown/guides/how_to/pipelines/index.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,13 @@ This section contains tutorials on how to use different pipelines of Anomalib an
66
:margin: 1 1 0 0
77
:gutter: 1
88

9+
:::{grid-item-card} {octicon}`stack` Tiled Ensemble
10+
:link: ./tiled_ensemble
11+
:link-type: doc
12+
13+
Learn more about how to use the tiled ensemble pipelines.
14+
:::
15+
916
:::{grid-item-card} {octicon}`gear` Custom Pipeline
1017
:link: ./custom_pipeline
1118
:link-type: doc
Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
# Tiled ensemble
2+
3+
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).
4+
5+
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.
6+
It is compatible with any existing image anomaly detection model without the need for any modification of the underlying architecture.
7+
8+
![Tiled ensemble flow](../../../../images/tiled_ensemble/ensemble_flow.png)
9+
10+
```{note}
11+
This feature is experimental and may not work as expected.
12+
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).
13+
```
14+
15+
## Training
16+
17+
You can train a tiled ensemble using the training script located inside `tools/tiled_ensemble` directory:
18+
19+
```{code-block} bash
20+
21+
python tools/tiled_ensemble/train_ensemble.py \
22+
--config tools/tiled_ensemble/ens_config.yaml
23+
```
24+
25+
By default, the Padim model is trained on **MVTec AD bottle** category using image size of 256x256, divided into non-overlapping 128x128 tiles.
26+
You can modify these parameters in the [config file](#ensemble-configuration).
27+
28+
## Evaluation
29+
30+
After training, you can evaluate the tiled ensemble on test data using:
31+
32+
```{code-block} bash
33+
34+
python tools/tiled_ensemble/eval.py \
35+
--config tools/tiled_ensemble/ens_config.yaml \
36+
--root path_to_results_dir
37+
38+
```
39+
40+
Ensure that `root` points to the directory containing the training results, typically `results/padim/mvtec/bottle/runX`.
41+
42+
## Ensemble configuration
43+
44+
Tiled ensemble is configured using `ens_config.yaml` file in the `tools/tiled_ensemble` directory.
45+
It contains general settings and tiled ensemble specific settings.
46+
47+
### General
48+
49+
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`.
50+
51+
```{code-block} yaml
52+
seed: 42
53+
accelerator: "gpu"
54+
default_root_dir: "results"
55+
```
56+
57+
### Tiling
58+
59+
This section contains the following settings, used for image tiling:
60+
61+
```{code-block} yaml
62+
63+
tiling:
64+
tile_size: 256
65+
stride: 256
66+
```
67+
68+
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.
69+
70+
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`.
71+
For example: having image_size: 512, tile_size: 256, and stride: 256, results in 4 non-overlapping tile locations.
72+
73+
### Normalization and thresholding
74+
75+
Next up are the normalization and thresholding settings:
76+
77+
```{code-block} yaml
78+
normalization_stage: image
79+
thresholding:
80+
method: F1AdaptiveThreshold
81+
stage: image
82+
```
83+
84+
- **Normalization**: Can be applied per each tile location separately (`tile` option), after combining prediction (`image` option), or skipped (`none` option).
85+
86+
- **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.
87+
88+
### Data
89+
90+
The `data` section is used to configure the input `image_size` and other parameters for the dataset used.
91+
92+
```{code-block} yaml
93+
data:
94+
class_path: anomalib.data.MVTec
95+
init_args:
96+
root: ./datasets/MVTec
97+
category: bottle
98+
train_batch_size: 32
99+
eval_batch_size: 32
100+
num_workers: 8
101+
task: segmentation
102+
transform: null
103+
train_transform: null
104+
eval_transform: null
105+
test_split_mode: from_dir
106+
test_split_ratio: 0.2
107+
val_split_mode: same_as_test
108+
val_split_ratio: 0.5
109+
image_size: [256, 256]
110+
```
111+
112+
Refer to [Data](../../reference/data/image/index.md) for more details on parameters.
113+
114+
### SeamSmoothing
115+
116+
This section contains settings for `SeamSmoothing` block of pipeline:
117+
118+
```{code-block} yaml
119+
SeamSmoothing:
120+
apply: True
121+
sigma: 2
122+
width: 0.1
123+
124+
```
125+
126+
SeamSmoothing job is responsible for smoothing of regions where tiles meet - called tile seams.
127+
128+
- **apply**: If True, smoothing will be applied.
129+
- **sigma**: Controls the sigma of Gaussian filter used for smoothing.
130+
- **width**: Sets the percentage of the region around the seam to be smoothed.
131+
132+
### TrainModels
133+
134+
The last section `TrainModels` contains the setup for model training:
135+
136+
```{code-block} yaml
137+
TrainModels:
138+
model:
139+
class_path: Fastflow
140+
141+
metrics:
142+
pixel: AUROC
143+
image: AUROC
144+
145+
trainer:
146+
max_epochs: 500
147+
callbacks:
148+
- class_path: lightning.pytorch.callbacks.EarlyStopping
149+
init_args:
150+
patience: 42
151+
monitor: pixel_AUROC
152+
mode: max
153+
```
154+
155+
- **Model**: Specifies the model used. Refer to [Models](../../reference/models/image/index.md) for more details on the model parameters.
156+
- **Metrics**: Defines evaluation metrics for pixel and image level.
157+
- **Trainer**: _optional_ parameters, used to control the training process. Refer to [Engine](../../reference/engine/index.md) for more details.

notebooks/700_metrics/701b_aupimo_advanced_i.ipynb

Lines changed: 49 additions & 273 deletions
Large diffs are not rendered by default.

notebooks/700_metrics/701c_aupimo_advanced_ii.ipynb

Lines changed: 18 additions & 134 deletions
Large diffs are not rendered by default.

src/anomalib/models/components/base/export_mixin.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ def to_onnx(
125125
dynamic_axes = (
126126
{"input": {0: "batch_size"}, "output": {0: "batch_size"}}
127127
if input_size
128-
else {"input": {0: "batch_size", 2: "height", 3: "weight"}, "output": {0: "batch_size"}}
128+
else {"input": {0: "batch_size", 2: "height", 3: "width"}, "output": {0: "batch_size"}}
129129
)
130130
onnx_path = export_root / "model.onnx"
131131
# apply pass through the model to get the output names

tools/tiled_ensemble/ens_config.yaml

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
seed: 42
2+
accelerator: "gpu"
3+
default_root_dir: "results"
4+
5+
tiling:
6+
tile_size: [128, 128]
7+
stride: 128
8+
9+
normalization_stage: image # on what level we normalize, options: [tile, image, none]
10+
thresholding:
11+
method: F1AdaptiveThreshold # refer to documentation for thresholding methods
12+
stage: image # stage at which we apply threshold, options: [tile, image]
13+
14+
data:
15+
class_path: anomalib.data.MVTec
16+
init_args:
17+
root: ./datasets/MVTec
18+
category: bottle
19+
train_batch_size: 32
20+
eval_batch_size: 32
21+
num_workers: 8
22+
task: segmentation
23+
transform: null
24+
train_transform: null
25+
eval_transform: null
26+
test_split_mode: from_dir
27+
test_split_ratio: 0.2
28+
val_split_mode: same_as_test
29+
val_split_ratio: 0.5
30+
image_size: [256, 256]
31+
32+
SeamSmoothing:
33+
apply: True # if this is applied, area around tile seams are is smoothed
34+
sigma: 2 # sigma of gaussian filter used to smooth this area
35+
width: 0.1 # width factor, multiplied by tile dimension gives the region width around seam which will be smoothed
36+
37+
TrainModels:
38+
model:
39+
class_path: Padim
40+
41+
metrics:
42+
pixel: AUROC
43+
image: AUROC

tools/tiled_ensemble/eval.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
"""Run tiled ensemble prediction."""
2+
3+
# Copyright (C) 2024 Intel Corporation
4+
# SPDX-License-Identifier: Apache-2.0
5+
6+
from pathlib import Path
7+
8+
from jsonargparse import ArgumentParser
9+
10+
from anomalib.pipelines.tiled_ensemble import EvalTiledEnsemble
11+
12+
13+
def get_parser() -> ArgumentParser:
14+
"""Create a new parser if none is provided."""
15+
parser = ArgumentParser()
16+
parser.add_argument("--config", type=str | Path, help="Configuration file path.", required=True)
17+
parser.add_argument("--root", type=str | Path, help="Weights file path.", required=True)
18+
19+
return parser
20+
21+
22+
if __name__ == "__main__":
23+
args = get_parser().parse_args()
24+
25+
print("Running tiled ensemble test pipeline.")
26+
# pass the path to root dir with checkpoints
27+
test_pipeline = EvalTiledEnsemble(args.root)
28+
test_pipeline.run(args)

tools/tiled_ensemble/train.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
"""Run tiled ensemble training."""
2+
3+
# Copyright (C) 2024 Intel Corporation
4+
# SPDX-License-Identifier: Apache-2.0
5+
6+
from anomalib.pipelines.tiled_ensemble import EvalTiledEnsemble, TrainTiledEnsemble
7+
8+
if __name__ == "__main__":
9+
print("Running tiled ensemble train pipeline")
10+
train_pipeline = TrainTiledEnsemble()
11+
# run training
12+
train_pipeline.run()
13+
14+
print("Running tiled ensemble test pipeline.")
15+
# pass the root dir from train run to load checkpoints
16+
test_pipeline = EvalTiledEnsemble(train_pipeline.root_dir)
17+
test_pipeline.run()

0 commit comments

Comments
 (0)