Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: Use Perlin ROI to create noise on to the object of interest #1061

Open
wants to merge 23 commits into
base: main
Choose a base branch
from

Conversation

leonardloh
Copy link

Description

  • Provide a summary of the modification as well as the issue that has been resolved. List any dependencies that this modification necessitates.

  • Our aim is to generate fake anomalous images for the validation set, and then use Anomalib's existing adaptive thresholding mechanism. But the current Perlin Noise augmentation will cover the whole image instead of the object of interest.

  • To automatically segment out the ROI Mask of the object given an image and then implement Perlin Noise onto the object only.

Code changes:

  • Subclass Augmenter to create another class call PerlinROIAugmenter
  • Create PerlinROI methods in the PerlinROIAugmenter
  • Enable Dataset to access synthetic type (default: Perlin) from config.yaml

Changes

  • Bug fix (non-breaking change which fixes an issue)
  • Refactor (non-breaking change which refactors the code base)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • This change requires a documentation update

Checklist

  • My code follows the pre-commit style and check guidelines of this project.
  • I have performed a self-review of my code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing tests pass locally with my changes
  • I have added a summary of my changes to the CHANGELOG (not for minor changes, docs and tests).

@github-actions github-actions bot added the Tests label Apr 28, 2023
@leonardloh leonardloh changed the title Feature/augment roi Feature: Use Perlin ROI to create noise on to the object of interest Apr 28, 2023
Copy link
Collaborator

@ashwinvaidya17 ashwinvaidya17 left a comment

Choose a reason for hiding this comment

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

This is a great addition! Thanks. The only thing I am concerned about is the keys in config. It might require some design. But it is something we will have to discuss internally.

@@ -13,9 +13,11 @@ dataset:
transform_config:
train: null
eval: null
test_split_mode: from_dir # options: [from_dir, synthetic]
test_split_mode: synthetic # options: [from_dir, synthetic]
test_synthetic_type: perlin_roi
Copy link
Collaborator

Choose a reason for hiding this comment

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

Maybe these should live under a separate key. Since synthetic is optional test_synthetic_mode probably shouldn't be at the same level as other keys.
How about?

test_split:
    mode: synthetic/from_dir
    optional_key1: ...
    optional_key2: ...
    ...

Copy link

@kxtan kxtan May 1, 2023

Choose a reason for hiding this comment

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

Hi Ashwin, thanks for the suggestion. We will work on the changes and keep you updated.

Indeed, the flexibility to choose various generation methods (test set & validation set) might require further processing during setup, perhaps in a separate discussion/PR.

Copy link
Author

Choose a reason for hiding this comment

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

hi @ashwinvaidya17 can we proceed with this design? We would like your approval before we make any changes as many codes will be impacted.

test_split:  
    mode: synthetic # options: [from_dir, synthetic]
      type: perlin_roi
    ratio: 0.2

Copy link
Collaborator

Choose a reason for hiding this comment

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

Since @djdameln designed this, he might have better insight regarding the design. We can wait for his feedback.

return synthetic_dataset

return make


@pytest.fixture(autouse=True)
def synthetic_dataset_from_samples():
def make_perlinroi_synthetic_dataset():
Copy link
Collaborator

Choose a reason for hiding this comment

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

Since both the methods are very similar, we can use mark.parameterize https://docs.pytest.org/en/6.2.x/parametrize.html#pytest-mark-parametrize-parametrizing-test-functions

Copy link

Choose a reason for hiding this comment

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

Noted, we will work on the changes. Thanks again Ashwin

)
perturbation, mask = self.generate_perturbation(height, width, anomaly_source_path)
perturbations_list.append(Tensor(perturbation).permute((2, 0, 1)))
masks_list.append((Tensor(mask).permute((2, 0, 1)) * thresh_batch))
Copy link
Collaborator

Choose a reason for hiding this comment

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

Except for thresh_batch here this is similar to the base method. Maybe we can just add an if statement in the base class and add this line there.

Copy link

Choose a reason for hiding this comment

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

good idea, added this and removed the child method


def gaussian_blur(self, image: Tensor, transform: A.Compose) -> tuple[Tensor, Tensor]:
"""Generate Gaussian Blur.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Can you also describe the intention behind performing gaussian blur and finding out the thresholds based on it.

Copy link

Choose a reason for hiding this comment

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

we renamed the function generate_roi as it does more than gaussian blur. The intention is to generate the region of interest.


cv2.bitwise_not(thresh)

if thresh[0, 0] & thresh[-1, -1] & thresh[-1, 0] & thresh[0, -1] == 255:
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can you explain this line? From what I understand this inverts the image if the background is white

Copy link

Choose a reason for hiding this comment

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

similar to your understanding: if all four corners of the image are white, we invert the mask.
we added this as a comment in the code base as well



class PerlinROIAugmenter(Augmenter):
def augment_batch(self, batch: Tensor, thresh_batch: Tensor | None = None) -> tuple[Tensor, Tensor]:
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can you add a short description on how this works. Something like, extracts foreground object based on binary thresholding and limits perlin noise augmentation to that region.

Copy link

Choose a reason for hiding this comment

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

added as the docstring for this class

Copy link
Contributor

@djdameln djdameln left a comment

Choose a reason for hiding this comment

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

Thanks. This could be a useful addition to our Perlin noise mechanism. Overall I have the same comments as Ashwin, in that some more explanation about the methods used to obtain the final noise masks could be provided in the docstrings.

@@ -292,8 +294,10 @@ class Folder3D(AnomalibDataModule):
during validation.
Defaults to None.
test_split_mode (TestSplitMode): Setting that determines how the testing subset is obtained.
test_synthetic_type (TestSyntheticType): Method for generating synthetic test data.
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't know if it makes sense to expose these parameters to the 3d datasets. The anomalous augmentations are only applied to the images, not to the 3d point cloud data.

Copy link

Choose a reason for hiding this comment

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

thanks @djdameln, we removed it from this dataset. please let us know if there are more.

"""Generate anomalous augmentations for a batch of input images.

Args:
batch (Tensor): Batch of input images
thresh_batch (Tensor | None, optional): Batch of
Copy link
Contributor

Choose a reason for hiding this comment

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

this parameter description is incomplete

Copy link

Choose a reason for hiding this comment

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

added comment and refactored the class based on @ashwinvaidya17's suggestions

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

7 participants