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

Add option to prune bboxes based on % area in Crop ROI #5368

Merged
merged 9 commits into from
Mar 15, 2024

Conversation

5had3z
Copy link
Contributor

@5had3z 5had3z commented Mar 12, 2024

Category:

New feature

Description:

Following on #5366, I made some modifications to RandomBBoxCropImpl to enable pruning bboxes based on their remaining area within the ROI, while leaving the option to use the original centroid algorithm (which is currently default). This simply finds the intersection between the crop and bbox and divides this by the bbox area. The bbox is kept if this result is above a threshold.

Some results of this change are also shown in the aforementioned thread.

Additional information:

Affected modules and functionalities:

Added new argument to random_bbox_crop, namely bbox_prune, which is a float that signals to use the old algorithm (by default), or the new algorithm.

Key points relevant for the review:

Naming things is a difficult part of CS, I just copied my original "one new parameter" implementation that has overloaded functionality. We can change it to a string to signal which algoirthm, and add another parameter for the threshold tolerance. Always better to have more than one opinion on API design.

Tests:

I intend to add some more tests to operator_2/test_random_bbox_crop.py.

  • Existing tests apply
  • New tests added
    • Python tests
    • GTests
    • Benchmark
    • Other
  • N/A

Checklist

Documentation

  • Existing documentation applies
  • Documentation updated
    • Docstring
    • Doxygen
    • RST
    • Jupyter
    • Other
  • N/A

DALI team only

Requirements

  • Implements new requirements
  • Affects existing requirements
  • N/A

REQ IDs: N/A

JIRA TASK: N/A

false);
false)
.AddOptionalArg<float>("bbox_prune",
R"code(Controls how bboxes are pruned from the ROI. Valid values of `bbox_prune` are `-1.f`
Copy link
Contributor

Choose a reason for hiding this comment

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

How about instead of using -1 as an off value, call ArgumentDefined to learn if the argument was used at all?

@jantonguirao jantonguirao self-assigned this Mar 12, 2024
@JanuszL JanuszL self-assigned this Mar 12, 2024
@JanuszL
Copy link
Contributor

JanuszL commented Mar 12, 2024

Hi @5had3z,

Thank you for your contribution. Let us check it and share our comments with you soon.

@jantonguirao
Copy link
Contributor

Hi @5had3z. Thanks a lot for your contribution. I took the liberty to propose some changes to the API, which I put in a PR to this branch: 5had3z#1

The change is to separate the two filtering methods with bbox_prune_by_centroid and bbox_prune_area_threshold so that they can be applied independently and avoid having magic values (-1).

@5had3z
Copy link
Contributor Author

5had3z commented Mar 12, 2024

Hi @5had3z. Thanks a lot for your contribution. I took the liberty to propose some changes to the API, which I put in a PR to this branch: 5had3z#1

The change is to separate the two filtering methods with bbox_prune_by_centroid and bbox_prune_area_threshold so that they can be applied independently and avoid having magic values (-1).

Hi @jantonguirao, I prefer @JanuszL's suggestion for testing the presence of a bbox_prune_area_threshold argument specified by the user to switch between algorithms. With your current implementation, the user has to explicitly set bbox_prune_by_centroid=False to only get the by-area branch. The bbox_prune_area_threshold_ > 0.0f branch condition also ommits the inherent option of no pruning of any boxes with some presence in the ROI (setting this as epsilon will also do the job, but setting this as "greater than zero" is simpler). I don't think it makes sense run both algorithms at the same time anyway.

Two Args

# No args, Prune by centroid - OK
outputs= fn.random_bbox_crop(*args)
# Specify threshold, dominated by centroid pruning - OOPS
outputs = fn.random_bbox_crop(*args, bbox_prune_area_threshold=0.1)
# Both Args, Prune by area - OK
outputs = fn.random_bbox_crop(*args, bbox_prune_area_threshold=0.1, bbox_prune_by_centroid=False)

Testing for Presence of area

# No args, Prune by centroid - OK
outputs= fn.random_bbox_crop(*args)
# Specify threshold, Prune by area - OK
outputs = fn.random_bbox_crop(*args, bbox_prune_area_threshold=0.1)

@jantonguirao
Copy link
Contributor

Hi @5had3z. Thanks a lot for your contribution. I took the liberty to propose some changes to the API, which I put in a PR to this branch: 5had3z#1
The change is to separate the two filtering methods with bbox_prune_by_centroid and bbox_prune_area_threshold so that they can be applied independently and avoid having magic values (-1).

Hi @jantonguirao, I prefer @JanuszL's suggestion for testing the presence of a bbox_prune_area_threshold argument specified by the user to switch between algorithms. With your current implementation, the user has to explicitly set bbox_prune_by_centroid=False to only get the by-area branch. The bbox_prune_area_threshold_ > 0.0f branch condition also ommits the inherent option of no pruning of any boxes with some presence in the ROI (setting this as epsilon will also do the job, but setting this as "greater than zero" is simpler). I don't think it makes sense run both algorithms at the same time anyway.

Two Args

# No args, Prune by centroid - OK
outputs= fn.random_bbox_crop(*args)
# Specify threshold, dominated by centroid pruning - OOPS
outputs = fn.random_bbox_crop(*args, bbox_prune_area_threshold=0.1)
# Both Args, Prune by area - OK
outputs = fn.random_bbox_crop(*args, bbox_prune_area_threshold=0.1, bbox_prune_by_centroid=False)

Testing for Presence of area

# No args, Prune by centroid - OK
outputs= fn.random_bbox_crop(*args)
# Specify threshold, Prune by area - OK
outputs = fn.random_bbox_crop(*args, bbox_prune_area_threshold=0.1)

Sure, that works as well. Let's just avoid the magic value for the default behaviour and explicitly check if the argument was provided or not.

@5had3z
Copy link
Contributor Author

5had3z commented Mar 13, 2024

Ironically the "meta-test" of my python intersection function was the problem that had me the most stuck. Accidentially had any(shape) < 0 instead of any(shape < 0) resulting in double -ve sides being reported as positive area, and the initial "zero" intersection tests were boxes touching corners.

@5had3z 5had3z marked this pull request as ready for review March 13, 2024 11:54
5had3z and others added 7 commits March 14, 2024 09:23
Signed-off-by: Bryce Ferenczi <frenzi@hotmail.com.au>
Signed-off-by: Bryce Ferenczi <frenzi@hotmail.com.au>
…te docs.

Signed-off-by: Bryce Ferenczi <frenzi@hotmail.com.au>
…ools.product, remove mutable defaults from SynthDataPipeline and make keyword only (original default placed in appropriate areas).

Signed-off-by: Bryce Ferenczi <frenzi@hotmail.com.au>
Signed-off-by: Bryce Ferenczi <frenzi@hotmail.com.au>
Co-authored-by: Janusz Lisiecki <39967756+JanuszL@users.noreply.github.com>
Signed-off-by: Bryce Ferenczi <frenzi@hotmail.com.au>
…ling underscores from local lambda vars.

Signed-off-by: Bryce Ferenczi <frenzi@hotmail.com.au>
for i, bbox in enumerate(bboxes):
intersec = intersection(bbox, crop_box)
box_area = np.prod(bbox[ndim:] - bbox[:ndim])
if intersec / box_area > thresh:
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
if intersec / box_area > thresh:
if intersec / box_area >= thresh:

I guess the tests need to be updated as well.

….0 to test parameterization, 1.0 has freezing issues in the test, but works as expected on normal datasets...

Signed-off-by: Bryce Ferenczi <frenzi@hotmail.com.au>
dali/operators/image/crop/bbox_crop.cc Outdated Show resolved Hide resolved
dali/operators/image/crop/bbox_crop.cc Outdated Show resolved Hide resolved
Signed-off-by: Bryce Ferenczi <frenzi@hotmail.com.au>
@jantonguirao
Copy link
Contributor

!build

@dali-automaton
Copy link
Collaborator

CI MESSAGE: [13523046]: BUILD STARTED

@dali-automaton
Copy link
Collaborator

CI MESSAGE: [13523046]: BUILD PASSED

@JanuszL JanuszL merged commit 2d9961e into NVIDIA:main Mar 15, 2024
7 checks passed
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.

None yet

4 participants