Skip to content

Conversation

@rajeshgangireddy
Copy link
Contributor

@rajeshgangireddy rajeshgangireddy commented Oct 15, 2025

πŸ“ Description

This is based on #2928
I have closed that PR and started this new one with additional changes.

✨ Changes

Select what type of change your PR is:

  • πŸš€ New feature (non-breaking change which adds functionality)
  • 🐞 Bug fix (non-breaking change which fixes an issue)
  • πŸ”„ Refactor (non-breaking change which refactors the code base)
  • ⚑ Performance improvements
  • 🎨 Style changes (code style/formatting)
  • πŸ§ͺ Tests (adding/modifying tests)
  • πŸ“š Documentation update
  • πŸ“¦ Build system changes
  • 🚧 CI/CD configuration
  • πŸ”§ Chore (general maintenance)
  • πŸ”’ Security update
  • πŸ’₯ Breaking change (fix or feature that would cause existing functionality to not work as expected)

βœ… Checklist

Before you submit your pull request, please make sure you have completed the following steps:

  • πŸ“š I have made the necessary updates to the documentation (if applicable).
  • πŸ§ͺ I have written tests that support my changes and prove that my fix is effective or my feature works (if applicable).
  • 🏷️ My PR title follows conventional commit format.

For more information about code review checklists, see the Code Review Checklist.

alfieroddan and others added 11 commits September 8, 2025 18:32
…chCore, Padim, Dfkde (open-edge-platform#2913)

* refactor patchcore, use list instead of cat

* typo in patchcore

Signed-off-by: Alfie Roddan <51797647+alfieroddan@users.noreply.github.com>

* padim model to now use cat instead of list

Signed-off-by: Alfie Roddan <51797647+alfieroddan@users.noreply.github.com>

* dfm and padim update cat to list

Signed-off-by: Alfie Roddan <51797647+alfieroddan@users.noreply.github.com>

* add dfkde cat to list changes

Signed-off-by: Alfie Roddan <51797647+alfieroddan@users.noreply.github.com>

* change assert from memory bank to list size, fix pre-commit issues

Signed-off-by: Alfie Roddan <51797647+alfieroddan@users.noreply.github.com>

---------

Signed-off-by: Alfie Roddan <51797647+alfieroddan@users.noreply.github.com>
Signed-off-by: StarPlatinum7 <2732981250@qq.com>
Signed-off-by: StarPlatinum7 <2732981250@qq.com>
Signed-off-by: StarPlatinum7 <2732981250@qq.com>
Signed-off-by: StarPlatinum7 <2732981250@qq.com>
…#2920)

* added histogram of anomaly scores

* Update src/anomalib/metrics/anomaly_score_distribution.py

Co-authored-by: Samet Akcay <samet.akcay@intel.com>
Signed-off-by: Aimira Baitieva <63813435+abc-125@users.noreply.github.com>

* Update anomaly_score_distribution.py

* Update anomaly_score_distribution.py

* Fixed pre-commit checks

---------

Signed-off-by: Aimira Baitieva <63813435+abc-125@users.noreply.github.com>
Co-authored-by: Samet Akcay <samet.akcay@intel.com>
Signed-off-by: StarPlatinum7 <2732981250@qq.com>
* added pg and pb metrics

* fixed typos

* Update __init__.py

* Update __init__.py - removed duplicate

* Update pg_pb.py

* Fixed pre-commit checks

---------

Co-authored-by: Samet Akcay <samet.akcay@intel.com>
Co-authored-by: Rajesh Gangireddy <rajesh.gangireddy@intel.com>
Signed-off-by: StarPlatinum7 <2732981250@qq.com>
Copilot AI review requested due to automatic review settings October 15, 2025 14:43

This comment was marked as outdated.

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Rajesh Gangireddy <rajesh.gangireddy@intel.com>
Copilot AI review requested due to automatic review settings October 15, 2025 14:44
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Rajesh Gangireddy <rajesh.gangireddy@intel.com>
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.


Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Rajesh Gangireddy <rajesh.gangireddy@intel.com>
Copilot AI review requested due to automatic review settings October 15, 2025 14:46
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 3 comments.


Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

Copilot AI review requested due to automatic review settings October 15, 2025 14:54
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 2 comments.


Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

@rajeshgangireddy
Copy link
Contributor Author

Thanks to @StarPlatinum7 for the contribution.

@rajeshgangireddy
Copy link
Contributor Author

PS : I am yet to fully test this as a post processor with an with anomalib model.

Copilot AI review requested due to automatic review settings October 15, 2025 15:06
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 4 comments.


Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

@StarPlatinum7
Copy link

StarPlatinum7 commented Oct 15, 2025

Thanks for your review!This strategy is proposed in AnomalyNCD (CVPR2025).And I have test mebin as a post processor like this:

from anomalib.models import Patchcore
from anomalib.engine import Engine
from anomalib.post_processing import MEBinPostProcessor
datamodule = MVTecAD(
    category='bottle', # category in mvtec dataset
    root = "./mvtec_anomaly_detection", # path where dataset is stored
    train_batch_size = 16,
    eval_batch_size = 16,
)
engine = Engine(
    default_root_dir = './output', # path where results are saved

)
model = Patchcore(
    post_processor=MEBinPostProcessor(
        sample_rate=4,
        min_interval_len=4,
        erode=True
    )
)
engine.train(datamodule=datamodule, model=model)

@rajeshgangireddy rajeshgangireddy marked this pull request as draft October 17, 2025 09:08
…check if implementation matches author's implementation
Copilot AI review requested due to automatic review settings October 21, 2025 15:10
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 3 comments.


Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

Comment on lines +19 to +22
Example:
>>> from anomalib.post_processing import MEBinPostProcessor
>>> from anomalib.data import InferenceBatch
>>> import torch
Copy link

Copilot AI Oct 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Duplicate 'Example:' label on consecutive lines. Remove one of the duplicate labels.

Suggested change
Example:
>>> from anomalib.post_processing import MEBinPostProcessor
>>> from anomalib.data import InferenceBatch
>>> import torch
>>> from anomalib.post_processing import MEBinPostProcessor
>>> from anomalib.data import InferenceBatch
>>> import torch
>>> import torch

Copilot uses AI. Check for mistakes.
Comment on lines +154 to +156
Stable Interval: A continuous threshold range in which the number of connected components remains constant,
and the length of the threshold range is greater than or equal to the given length threshold
(min_interval_len).
Copy link

Copilot AI Oct 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The docstring contains a 'Stable Interval' definition that appears to be part of the description rather than a separate section. Consider integrating this into the main description or using a Note/Warning block for clarity.

Suggested change
Stable Interval: A continuous threshold range in which the number of connected components remains constant,
and the length of the threshold range is greater than or equal to the given length threshold
(min_interval_len).
A "stable interval" is defined as a continuous threshold range in which the number of connected components remains constant,
and the length of the threshold range is greater than or equal to the given minimum interval length (`min_interval_len`).

Copilot uses AI. Check for mistakes.
(min_interval_len).

Args:
anomaly_num_sequence (list): Sequence of connected component counts
Copy link

Copilot AI Oct 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Type hint 'list' is not specific. Should be 'list[int]' to match the actual usage.

Suggested change
anomaly_num_sequence (list): Sequence of connected component counts
anomaly_num_sequence (list[int]): Sequence of connected component counts

Copilot uses AI. Check for mistakes.
@rajeshgangireddy rajeshgangireddy marked this pull request as ready for review October 23, 2025 07:41
@StarPlatinum7
Copy link

You can resolve the conflict by replacing the file tests/unit/post_processing/test_mebin_post_processor.py with the following code:

# SPDX-License-Identifier: Apache-2.0

"""Test the MEBinPostProcessor class."""

from unittest.mock import MagicMock, Mock, patch

import numpy as np
import pytest
import torch

from anomalib.data import InferenceBatch
from anomalib.post_processing import MEBinPostProcessor


class TestMEBinPostProcessor:
    """Test the MEBinPostProcessor class."""

    @staticmethod
    def test_initialization_default_params() -> None:
        """Test MEBinPostProcessor initialization with default parameters."""
        processor = MEBinPostProcessor()

        assert processor.sample_rate == 4
        assert processor.min_interval_len == 4
        assert processor.erode is True

    @staticmethod
    @pytest.mark.parametrize(
        ("sample_rate", "min_interval_len", "erode"),
        [
            (2, 3, True),
            (8, 6, False),
            (1, 1, True),
        ],
    )
    def test_initialization_custom_params(
        sample_rate: int,
        min_interval_len: int,
        erode: bool,
    ) -> None:
        """Test MEBinPostProcessor initialization with custom parameters."""
        processor = MEBinPostProcessor(
            sample_rate=sample_rate,
            min_interval_len=min_interval_len,
            erode=erode,
        )

        assert processor.sample_rate == sample_rate
        assert processor.min_interval_len == min_interval_len
        assert processor.erode == erode

    @staticmethod
    @patch("anomalib.post_processing.mebin_post_processor.MEBin")
    def test_forward_mebin_parameters(mock_mebin: MagicMock) -> None:
        """Test that MEBin is called with correct parameters."""
        # Setup mock
        mock_mebin_instance = Mock()
        mock_mebin_instance.binarize_anomaly_maps.return_value = (
            [np.array([[0, 0], [1, 1]], dtype=np.uint8)],
            [0.5],
        )
        mock_mebin.return_value = mock_mebin_instance

        # Create test data
        anomaly_maps = torch.rand(1, 1, 4, 4)
        predictions = InferenceBatch(
            pred_score=torch.tensor([0.8]),
            pred_label=torch.tensor([1]),
            anomaly_map=anomaly_maps,
            pred_mask=None,
        )

        # Test with custom parameters
        processor = MEBinPostProcessor(
            sample_rate=8,
            min_interval_len=6,
            erode=False,
        )
        _ = processor.forward(predictions)

        # Verify MEBin was called with correct parameters
        mock_mebin.assert_called_once_with(
            anomaly_map_list=mock_mebin.call_args[1]["anomaly_map_list"],
            sample_rate=8,
            min_interval_len=6,
            erode=False,
        )

    @staticmethod
    @patch("anomalib.post_processing.mebin_post_processor.MEBin")
    def test_forward_binary_mask_conversion(mock_mebin: MagicMock) -> None:
        """Test that binary masks are properly converted to 0/1 values."""
        # Setup mock to return masks with values > 0
        mock_mebin_instance = Mock()
        mock_mebin_instance.binarize_anomaly_maps.return_value = (
            [np.array([[0, 128], [255, 64]], dtype=np.uint8)],
            [0.5],
        )
        mock_mebin.return_value = mock_mebin_instance

        # Create test data
        anomaly_maps = torch.rand(1, 1, 2, 2)
        predictions = InferenceBatch(
            pred_score=torch.tensor([0.8]),
            pred_label=torch.tensor([1]),
            anomaly_map=anomaly_maps,
            pred_mask=None,
        )

        # Test forward pass
        processor = MEBinPostProcessor()
        result = processor.forward(predictions)

        # Verify that all values are either 0 or 1
        unique_values = torch.unique(result.pred_mask)
        assert torch.all((unique_values == 0) | (unique_values == 1))

    @staticmethod
    def test_forward_missing_anomaly_map() -> None:
        """Test that ValueError is raised when anomaly_map is None."""
        # Create test data without anomaly_map
        predictions = InferenceBatch(
            pred_score=torch.tensor([0.8]),
            pred_label=torch.tensor([1]),
            anomaly_map=None,
            pred_mask=None,
        )

        # Test forward pass should raise ValueError
        processor = MEBinPostProcessor()
        with pytest.raises(ValueError, match="Anomaly map is required for MEBin post-processing"):
            processor.forward(predictions)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants