Skip to content

Commit

Permalink
Merge v1.0.1 to main (#1905)
Browse files Browse the repository at this point in the history
* Update CHANGELOG.md (#1899)

* Update __init__.py

* Fix metric bug (#1900)

* check metrics by name instead of key

* remove prefix from temp metric collection

* 🔒 Bump onnx version as the previous version caused security issues (#1907)

* 📚 Add action to check broken links (#1838)

* Fix broken links

* Add link checker

* Fix link in template

* linter

* nightly check

---------

Co-authored-by: Samet Akcay <samet.akcay@intel.com>

* Use LabelName ENUM for label assignment (#1881)

* Use LabelName ENUM for label assignment

* Update src/anomalib/deploy/inferencers/torch_inferencer.py

Co-authored-by: Samet Akcay <samet.akcay@intel.com>

---------

Co-authored-by: Samet Akcay <samet.akcay@intel.com>

* Changed prediction label assignment for OpenVINO inferencer (#1872)

* Update openvino_inferencer.py

Fixed incorrect label assignment.
Was True/False, now it's "Anomalous/Normal" as for the PyTorch inferencer in torch_inferencer.py

* Fix ruff

---------

Co-authored-by: Samet <samet.akcay@intel.com>

* Bump onnx version as the previous version caused security issues

---------

Co-authored-by: Alexander Dokuchaev <alexander.dokuchaev@intel.com>
Co-authored-by: TurboJonte <turbojonte@gmail.com>

* Add: fix image transform to float (#1902)

* 📚 Add action to check broken links (#1838)

* Fix broken links

* Add link checker

* Fix link in template

* linter

* nightly check

---------

Co-authored-by: Samet Akcay <samet.akcay@intel.com>

* Use LabelName ENUM for label assignment (#1881)

* Use LabelName ENUM for label assignment

* Update src/anomalib/deploy/inferencers/torch_inferencer.py

Co-authored-by: Samet Akcay <samet.akcay@intel.com>

---------

Co-authored-by: Samet Akcay <samet.akcay@intel.com>

* Changed prediction label assignment for OpenVINO inferencer (#1872)

* Update openvino_inferencer.py

Fixed incorrect label assignment.
Was True/False, now it's "Anomalous/Normal" as for the PyTorch inferencer in torch_inferencer.py

* Fix ruff

---------

Co-authored-by: Samet <samet.akcay@intel.com>

* Add: fix image transform to float

Signed-off-by: Bepitic <bepitic@gmail.com>

* upd: video dtpe transform from torchvision

Signed-off-by: Bepitic <bepitic@gmail.com>

* Added the scale.

Signed-off-by: Bepitic <bepitic@gmail.com>

* Update src/anomalib/data/base/video.py

Co-authored-by: Dick Ameln <amelndjd@gmail.com>

---------

Signed-off-by: Bepitic <bepitic@gmail.com>
Co-authored-by: Alexander Dokuchaev <alexander.dokuchaev@intel.com>
Co-authored-by: Samet Akcay <samet.akcay@intel.com>
Co-authored-by: TurboJonte <turbojonte@gmail.com>
Co-authored-by: Dick Ameln <amelndjd@gmail.com>

* Fix video bug and add tests (#1910)

* 📚 Add action to check broken links (#1838)

* Fix broken links

* Add link checker

* Fix link in template

* linter

* nightly check

---------

Co-authored-by: Samet Akcay <samet.akcay@intel.com>

* squeeze temporal dimension when clip length is 1

* add unit test for video input tensor dtype

* add test for single frame clips

* update changelog

* add author

---------

Co-authored-by: Alexander Dokuchaev <alexander.dokuchaev@intel.com>
Co-authored-by: Samet Akcay <samet.akcay@intel.com>

* Temporarily set devices to 1

* 🐞 Add greyscale conversion (#1911)

Add greyscale conversion

Signed-off-by: Ashwin Vaidya <ashwinnitinvaidya@gmail.com>

* 🐞 Fix publish workflow (#1912)

Disable tty prompt for gpg import

Signed-off-by: Ashwin Vaidya <ashwinnitinvaidya@gmail.com>

---------

Signed-off-by: Bepitic <bepitic@gmail.com>
Signed-off-by: Ashwin Vaidya <ashwinnitinvaidya@gmail.com>
Co-authored-by: Dick Ameln <dick.ameln@intel.com>
Co-authored-by: Alexander Dokuchaev <alexander.dokuchaev@intel.com>
Co-authored-by: TurboJonte <turbojonte@gmail.com>
Co-authored-by: Paco <bepitic@gmail.com>
Co-authored-by: Dick Ameln <amelndjd@gmail.com>
Co-authored-by: Ashwin Vaidya <ashwin.vaidya@intel.com>
  • Loading branch information
7 people authored Mar 27, 2024
1 parent 6be4c80 commit e35b574
Show file tree
Hide file tree
Showing 14 changed files with 106 additions and 19 deletions.
6 changes: 4 additions & 2 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,17 @@ jobs:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
- uses: actions/setup-python@v4
with:
python-version: "3.10"
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install setuptools wheel twine
- name: Import GPG Key
run: |
echo "${{ secrets.GPG_PRIVATE_KEY }}" | base64 --decode | gpg --import
echo "${{ secrets.GPG_PRIVATE_KEY }}" | base64 --decode | gpg --import --batch --yes --no-tty
- name: Build and sign distribution
run: |
Expand Down
42 changes: 41 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,49 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).

### Fixed

- Use right interpolation method in WinCLIP resize (<https://github.com/openvinotoolkit/anomalib/pull/1889>)
### New Contributors

**Full Changelog**:

## [v1.0.1] - Unreleased

### Added

- Add requirements into `pyproject.toml` & Refactor anomalib install `get_requirements` by @harimkang in https://github.com/openvinotoolkit/anomalib/pull/1808

### Changed

- 📚 Update the getting started notebook by @samet-akcay in https://github.com/openvinotoolkit/anomalib/pull/1800
- 🔨Refactored-assert-statements-with-explicit-error-handling by @sahusiddharth in https://github.com/openvinotoolkit/anomalib/pull/1825
- 🔨Made-imagenette-path-configurable-in-config by @sahusiddharth in https://github.com/openvinotoolkit/anomalib/pull/1833
- 🛠️ Update changelog by @ashwinvaidya17 in https://github.com/openvinotoolkit/anomalib/pull/1842
- Remove input_size argument from models #1827 by @Shakib-IO in https://github.com/openvinotoolkit/anomalib/pull/1856
- 🚀 Allow validation splits from training data by @davnn in https://github.com/openvinotoolkit/anomalib/pull/1865
- 🛠️ Ensure images are loaded in RGB format by @davnn in https://github.com/openvinotoolkit/anomalib/pull/1866
- 🔨 Update OpenVINO predict to handle normalization inside the method. by @samet-akcay in https://github.com/openvinotoolkit/anomalib/pull/1875
- ✨ Upgrade TorchMetrics by @ashwinvaidya17 in https://github.com/openvinotoolkit/anomalib/pull/1879
- Address minor WinCLIP issues by @djdameln in https://github.com/openvinotoolkit/anomalib/pull/1889

### Deprecated

### Fixed

- 🐞 Fix single-frame video input size by [@djdameln](https://github.com/djdameln) (<https://github.com/openvinotoolkit/anomalib/pull/1910>)
- 🐞 Fix dobot notebook by @djdameln in https://github.com/openvinotoolkit/anomalib/pull/1852
- 🐞 Fix CLI config and update the docs. by @samet-akcay in https://github.com/openvinotoolkit/anomalib/pull/1886
- 🐞 Fix the error if the device in masks_to_boxes is not both CPU and CUDA by @danylo-boiko in https://github.com/openvinotoolkit/anomalib/pull/1839
- 🐞 Hot-fix wrong requirement for setup.py by @harimkang in https://github.com/openvinotoolkit/anomalib/pull/1823
- 🐞 Use right interpolation method in WinCLIP resize (<https://github.com/openvinotoolkit/anomalib/pull/1889>)
- 🐞 Fix the error if the device in masks_to_boxes is not both CPU and CUDA by @danylo-boiko in https://github.com/openvinotoolkit/anomalib/pull/1839

### New Contributors

- @sahusiddharth made their first contribution in https://github.com/openvinotoolkit/anomalib/pull/1825
- @Shakib-IO made their first contribution in https://github.com/openvinotoolkit/anomalib/pull/1856
- @davnn made their first contribution in https://github.com/openvinotoolkit/anomalib/pull/1866

**Full Changelog**: https://github.com/openvinotoolkit/anomalib/compare/v1.0.0...v1.0.1

## [v1.0.0] - 2024-02-29

### Added
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ core = [
"torchmetrics==0.10.3",
"open-clip-torch>=2.23.0",
]
openvino = ["openvino-dev>=2023.0", "nncf>=2.5.0", "onnx>=1.13.1"]
openvino = ["openvino-dev>=2023.0", "nncf>=2.5.0", "onnx>=1.16.0"]
loggers = [
"comet-ml>=3.31.7",
"gradio>=4",
Expand Down
2 changes: 1 addition & 1 deletion requirements/openvino.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
openvino-dev>=2023.0
nncf>=2.5.0
onnx>=1.13.1
onnx>=1.16.0
2 changes: 1 addition & 1 deletion src/anomalib/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

from enum import Enum

__version__ = "1.1.0dev"
__version__ = "1.0.1"


class LearningType(str, Enum):
Expand Down
9 changes: 2 additions & 7 deletions src/anomalib/callbacks/metrics.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,14 +91,9 @@ def setup(
if isinstance(pl_module, AnomalyModule):
pl_module.image_metrics = create_metric_collection(image_metric_names, "image_")
if hasattr(pl_module, "pixel_metrics"): # incase metrics are loaded from model checkpoint
new_metrics = create_metric_collection(pixel_metric_names, "pixel_")
new_metrics = create_metric_collection(pixel_metric_names)
for name in new_metrics:
# Ruff is ignored as
# >>> name not in pl_module.pixel_metrics
# True
# >>> name not in pl_module.pixel_metrics.keys()
# False
if name not in pl_module.pixel_metrics.keys(): # noqa: SIM118
if name not in pl_module.pixel_metrics:
pl_module.pixel_metrics.add_metrics(new_metrics[name])
else:
pl_module.pixel_metrics = create_metric_collection(pixel_metric_names, "pixel_")
Expand Down
5 changes: 5 additions & 0 deletions src/anomalib/data/base/video.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import torch
from pandas import DataFrame
from torchvision.transforms.v2 import Transform
from torchvision.transforms.v2.functional import to_dtype_video
from torchvision.tv_tensors import Mask

from anomalib import TaskType
Expand Down Expand Up @@ -153,6 +154,7 @@ def __getitem__(self, index: int) -> dict[str, str | torch.Tensor]:
msg = "self.indexer must be an instance of ClipsIndexer."
raise TypeError(msg)
item = self.indexer.get_item(index)
item["image"] = to_dtype_video(video=item["image"], scale=True)
# include the untransformed image for visualization
item["original_image"] = item["image"].to(torch.uint8)

Expand All @@ -167,6 +169,9 @@ def __getitem__(self, index: int) -> dict[str, str | torch.Tensor]:
elif self.transform:
item["image"] = self.transform(item["image"])

# squeeze temporal dimensions in case clip length is 1
item["image"] = item["image"].squeeze(0)

# include only target frame in gt
if self.clip_length_in_frames > 1 and self.target_frame != VideoTargetFrame.ALL:
item = self._select_targets(item)
Expand Down
2 changes: 1 addition & 1 deletion src/anomalib/data/utils/image.py
Original file line number Diff line number Diff line change
Expand Up @@ -371,7 +371,7 @@ def read_mask(path: str | Path, as_tensor: bool = False) -> torch.Tensor | np.nd
>>> type(mask)
<class 'torch.Tensor'>
"""
image = Image.open(path)
image = Image.open(path).convert("L")
return Mask(to_image(image).squeeze() / 255, dtype=torch.uint8) if as_tensor else np.array(image)


Expand Down
3 changes: 3 additions & 0 deletions src/anomalib/engine/engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,9 @@ def _setup_trainer(self, model: AnomalyModule) -> None:
# Setup anomalib callbacks to be used with the trainer
self._setup_anomalib_callbacks()

# Temporarily set devices to 1 to avoid issues with multiple processes
self._cache.args["devices"] = 1

# Instantiate the trainer if it is not already instantiated
if self._trainer is None:
self._trainer = Trainer(**self._cache.args)
Expand Down
2 changes: 1 addition & 1 deletion src/anomalib/metrics/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ def metric_collection_from_dicts(metrics: dict[str, dict[str, Any]], prefix: str

def create_metric_collection(
metrics: list[str] | dict[str, dict[str, Any]],
prefix: str | None,
prefix: str | None = None,
) -> AnomalibMetricCollection:
"""Create a metric collection from a list of metric names or dictionaries.
Expand Down
26 changes: 25 additions & 1 deletion tests/unit/data/base/video.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
# Copyright (C) 2023-2024 Intel Corporation
# SPDX-License-Identifier: Apache-2.0


import pytest
import torch

from anomalib.data import AnomalibDataModule

Expand Down Expand Up @@ -46,3 +46,27 @@ def test_get_item_returns_correct_keys_and_shapes(self, datamodule: AnomalibData
assert len(batch["label"]) == 4
assert batch["mask"].shape == (4, 256, 256)
assert batch["mask"].shape == (4, 256, 256)

@pytest.mark.parametrize("subset", ["train", "val", "test"])
def test_item_dtype(self, datamodule: AnomalibDataModule, subset: str) -> None:
"""Test that the input tensor is of float type and scaled between 0-1."""
# Get the dataloader.
dataloader = getattr(datamodule, f"{subset}_dataloader")()

# Get the first batch.
batch = next(iter(dataloader))
clip = batch["image"]
assert clip.dtype == torch.float32
assert clip.min() >= 0
assert clip.max() <= 1

@pytest.mark.parametrize("clip_length_in_frames", [1])
def test_single_frame_squeezed(self, datamodule: AnomalibDataModule) -> None:
"""Test that the temporal dimension is squeezed when the clip lenght is 1."""
# Get the dataloader.
dataloader = datamodule.train_dataloader()

# Get the first batch.
batch = next(iter(dataloader))
clip = batch["image"]
assert clip.shape == (4, 3, 256, 256)
8 changes: 7 additions & 1 deletion tests/unit/data/video/test_avenue.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,17 @@ class TestAvenue(_TestAnomalibVideoDatamodule):
"""Avenue Datamodule Unit Tests."""

@pytest.fixture()
def datamodule(self, dataset_path: Path, task_type: TaskType) -> Avenue:
def clip_length_in_frames(self) -> int:
"""Return the number of frames in each clip."""
return 2

@pytest.fixture()
def datamodule(self, dataset_path: Path, task_type: TaskType, clip_length_in_frames: int) -> Avenue:
"""Create and return a Avenue datamodule."""
_datamodule = Avenue(
root=dataset_path / "avenue",
gt_dir=dataset_path / "avenue" / "ground_truth_demo",
clip_length_in_frames=clip_length_in_frames,
image_size=256,
task=task_type,
num_workers=0,
Expand Down
8 changes: 7 additions & 1 deletion tests/unit/data/video/test_shanghaitech.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,17 @@ class TestShanghaiTech(_TestAnomalibVideoDatamodule):
"""ShanghaiTech Datamodule Unit Tests."""

@pytest.fixture()
def datamodule(self, dataset_path: Path, task_type: TaskType) -> ShanghaiTech:
def clip_length_in_frames(self) -> int:
"""Return the number of frames in each clip."""
return 2

@pytest.fixture()
def datamodule(self, dataset_path: Path, task_type: TaskType, clip_length_in_frames: int) -> ShanghaiTech:
"""Create and return a Shanghai datamodule."""
_datamodule = ShanghaiTech(
root=dataset_path / "shanghaitech",
scene=1,
clip_length_in_frames=clip_length_in_frames,
image_size=(256, 256),
train_batch_size=4,
eval_batch_size=4,
Expand Down
8 changes: 7 additions & 1 deletion tests/unit/data/video/test_ucsdped.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,17 @@ class TestUCSDped(_TestAnomalibVideoDatamodule):
"""UCSDped Datamodule Unit Tests."""

@pytest.fixture()
def datamodule(self, dataset_path: Path, task_type: TaskType) -> UCSDped:
def clip_length_in_frames(self) -> int:
"""Return the number of frames in each clip."""
return 2

@pytest.fixture()
def datamodule(self, dataset_path: Path, task_type: TaskType, clip_length_in_frames: int) -> UCSDped:
"""Create and return a UCSDped datamodule."""
_datamodule = UCSDped(
root=dataset_path / "ucsdped",
category="dummy",
clip_length_in_frames=clip_length_in_frames,
task=task_type,
image_size=256,
train_batch_size=4,
Expand Down

0 comments on commit e35b574

Please sign in to comment.