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

SAHI in workflows #574

Merged
merged 13 commits into from
Aug 15, 2024
Merged

SAHI in workflows #574

merged 13 commits into from
Aug 15, 2024

Conversation

PawelPeczek-Roboflow
Copy link
Collaborator

Description

In this PR we are adding SAHI to workflows in the following way:

  • there is a block with image slicer (private implementation copied from supervision to avoid fragile integration on private interface)
  • there is image stitch block that is capable of merging detections yielded from crops into single detections objects

😄 PROS of the approach:

😢 CONS of the approach:

  • we do not fully re-use supervision implementation
  • we have three blocks instead of one per model - which is harder to initialise and UI would need to start displaying group of blocks as one - please note that @EmilyGavrilenko @hansent

@LinasKo could u please take a look at the implementation to verify that usage of supervision components is as intended

NUANCES (please acknowledge carefully)

stitch block requires reference_image - which is the image used to create crops, which will create the following schema:

dimensionality 1: image -> slicer \ --------------- image -----> stitch -> merged predictions
dimensionality 2:                  \-> model -> predictions            /

Initially I wanted to avoid this additional parameter reference_image - but we need it if we wanted to maintain notion of parent_id in sv.Detections - which is used by such blocks as Detections Consensus and can ensure that whenever
we are blending is coming from the same image - which is helpful to prevent bugs. I tried to remove the problem but that lead me to lineage property being added into Execution Engine entity causing partially breaking change to EE which I wanted to avoid (probably impact would be low, as there are barely no custom plugins created), but stopped the work in this direction as this is labour intensive and potentially not needed if you like the approach. If you don't we need to:

In my opinion this is discussion about tradeoffs:

  • the solution that we have now relies on proper metadata to be passed along with proper inter-dimension-level connections between steps
  • the alternative solution relies on adding more and more payload into data flowing through workflows
    both approaches have pros and cons - I would like to know your opinions on that matter

IMPORTANT
SAHI is not always good approach - please try to plt.imshow() visualisations in integration tests running on cars images to see how improper use is going to lead to terrible results - we should mindfully guide users towards the feature, otherwise people will not like that.

Type of change

Please delete options that are not relevant.

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • This change requires a documentation update

How has this change been tested, please provide a testcase or example of how you tested the change?

  • CI green 🟢
  • new tests

Any specific deployment considerations

For example, documentation changes, usability, usage/costs, secrets, etc.

Docs

  • Docs updated? What were the changes:

@PawelPeczek-Roboflow
Copy link
Collaborator Author

We also need to decide on reasonable defaults for slice size. I bet that 640 may be better than 320, but this is only gut feeling based on assumption that size of input for model is more likely to be 640 than 320.

@hansent
Copy link
Contributor

hansent commented Aug 13, 2024

we have three blocks instead of one per model - which is harder to initialise and UI would need to start displaying group of blocks as one - please note that @EmilyGavrilenko
@thomas

We need this UI change to merge this, or you mean in general this is a pattern we should move towards to make this easier / better UX? Not a trivial UI change in terms of graph/viz editing state I think.

Could we have the individual blocks in addition to a block that handles all of it for ease of use / most common scenario?

@PawelPeczek-Roboflow
Copy link
Collaborator Author

we have three blocks instead of one per model - which is harder to initialise and UI would need to start displaying group of blocks as one - please note that @EmilyGavrilenko
@thomas

We need this UI change to merge this, or you mean in general this is a pattern we should move towards to make this easier / better UX? Not a trivial UI change in terms of graph/viz editing state I think.

I meant changes in UI in the future, but I bet now it will be confusing if we added the blocks from this PR - I bet noone would know how to use it.

Could we have the individual blocks in addition to a block that handles all of it for ease of use / most common scenario?
well, we could, but I really would like to avoid that - as we will be in need to maintain that over time

@EmilyGavrilenko
Copy link
Contributor

we have three blocks instead of one per model - which is harder to initialize and UI would need to start displaying group of blocks as one - please note that @EmilyGavrilenko
@thomas

We need this UI change to merge this, or you mean in general this is a pattern we should move towards to make this easier / better UX? Not a trivial UI change in terms of graph/viz editing state I think.

I meant changes in UI in the future, but I bet now it will be confusing if we added the blocks from this PR - I bet noone would know how to use it.

Could we have the individual blocks in addition to a block that handles all of it for ease of use / most common scenario?
well, we could, but I really would like to avoid that - as we will be in need to maintain that over time

Agree that having 3 blocks will be very confusing from a UI perspective. Couple questions/thoughts:

  1. are there uses for the DetectionsStitch and ImageSlicer blocks outside of SAHI? Should we allow users to add them individually, or only as a SAHI group
  2. in terms of UX, we should have a SAHI block, which adds all 3 blocks to the UI for configuration as a group. However, there's the added issue that we don't have a Model block, and it's currently very difficult to swap one model type out for another.
    • For the ideal user experience, we add a dummy Model block which only allows you to add a supported model type, and then a grouped block type which adds a group of blocks and if one is deleted all of them are.

However, the ideal UX is a much bigger lift, we can start providing value to users with the individual blocks + a blog post to explain how to configure them

@PawelPeczek-Roboflow
Copy link
Collaborator Author

Re: @EmilyGavrilenko comment:

  1. There is usage outside SAHI - illustrated here
  2. I agree with direction of UI and the plan for onboarding individual blocks. I much prefer having blocks doing single things that can be nicely composable, rather than multiple variations of groupped blocks in backend when simplification can be introduced in UI

@PawelPeczek-Roboflow
Copy link
Collaborator Author

Example where SAHI does not work
image

resolution_wh=resolution_wh,
)
re_aligned_predictions.append(re_aligned_detections)
overlap_filter = choose_overlap_filter_strategy(
Copy link
Contributor

Choose a reason for hiding this comment

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

should we be merging / detecting duplicates each time we add boxes rather than once at the end? Maybe that doesn't make a difference?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

we should do it at the end, otherwise we are running unneeded computations I am afraid, besides - this is the implementation of sv.InferenceSlicer that I hope will become part of public interface later on, such that we could replace our duplicate code with sv

if SCALING_RELATIVE_TO_PARENT_KEY in detections.data:
scale = detections[SCALING_RELATIVE_TO_PARENT_KEY][0]
if abs(scale - 1.0) > 1e-4:
raise ValueError(
Copy link
Contributor

Choose a reason for hiding this comment

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

what s an example of this happening?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

if you bring operation of bboxes scaling in between model and stitch, which you should not be doing, but you can through UQL

@classmethod
def describe_outputs(cls) -> List[OutputDefinition]:
return [
OutputDefinition(name="crops", kind=[BATCH_OF_IMAGES_KIND]),
Copy link
Contributor

Choose a reason for hiding this comment

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

I think output should be named slices instead of crops given other naming on block and properties

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

👍

result = execution_engine.run(
runtime_parameters={
"image": [license_plate_image],
"overlap_filtering_strategy": "none",
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
"overlap_filtering_strategy": "none",

not used in workflow

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

👍

Copy link
Contributor

@hansent hansent Aug 15, 2024

Choose a reason for hiding this comment

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

np tests for actual block functionality. I think its OK. since its basically tested in test_workflows_with_sahi.py but maybe add a comment to point to that file in case someone comes in here to understand how this block should behave

Copy link
Contributor

@hansent hansent left a comment

Choose a reason for hiding this comment

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

Let's rename slider output to slices instead of crops but otherwise looks great!

@PawelPeczek-Roboflow PawelPeczek-Roboflow merged commit f422a3e into main Aug 15, 2024
58 checks passed
@PawelPeczek-Roboflow PawelPeczek-Roboflow deleted the feature/inference_slicer_new branch August 15, 2024 14:45
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.

Prediction-level metadata in sv.Detections
3 participants