Renamed overlap strategy, added into InferenceSlicer docs page

This commit is contained in:
Linas Kondrackis 2024-05-29 15:53:04 +03:00
parent f0e88b1982
commit 4dc001d9bf
4 changed files with 53 additions and 14 deletions

View File

@ -5,3 +5,7 @@ comments: true
# InferenceSlicer
:::supervision.detection.tools.inference_slicer.InferenceSlicer
# Overlap Handling Strategy
:::supervision.detection.utils.OverlapHandlingStrategy

View File

@ -46,7 +46,7 @@ from supervision.detection.tools.json_sink import JSONSink
from supervision.detection.tools.polygon_zone import PolygonZone, PolygonZoneAnnotator
from supervision.detection.tools.smoother import DetectionsSmoother
from supervision.detection.utils import (
OverlapFilter,
OverlapHandlingStrategy,
box_iou_batch,
box_non_max_merge,
box_non_max_suppression,

View File

@ -1,12 +1,18 @@
import warnings
from concurrent.futures import ThreadPoolExecutor, as_completed
from typing import Callable, Optional, Tuple
from typing import Callable, Optional, Tuple, Union
import numpy as np
from supervision.detection.core import Detections
from supervision.detection.utils import OverlapFilter, move_boxes, move_masks
from supervision.detection.utils import (
OverlapHandlingStrategy,
move_boxes,
move_masks,
validate_overlapping_handling_strategy,
)
from supervision.utils.image import crop_image
from supervision.utils.internal import SupervisionWarnings
def move_detections(
@ -51,7 +57,7 @@ class InferenceSlicer:
`(width, height)`.
overlap_ratio_wh (Tuple[float, float]): Overlap ratio between consecutive
slices in the format `(width_ratio, height_ratio)`.
overlap_filter (OverlapFilter): Strategy for
overlap_handling_strategy (Union[OverlapHandlingStrategy, str]): Strategy for
filtering or merging overlapping detections in slices.
iou_threshold (float): Intersection over Union (IoU) threshold
used when filtering by overlap.
@ -71,14 +77,20 @@ class InferenceSlicer:
callback: Callable[[np.ndarray], Detections],
slice_wh: Tuple[int, int] = (320, 320),
overlap_ratio_wh: Tuple[float, float] = (0.2, 0.2),
overlap_filter: OverlapFilter = OverlapFilter.NON_MAX_SUPPRESSION,
overlap_handling_strategy: Union[
OverlapHandlingStrategy, str
] = OverlapHandlingStrategy.NON_MAX_SUPPRESSION,
iou_threshold: float = 0.5,
thread_workers: int = 1,
):
overlap_handling_strategy = validate_overlapping_handling_strategy(
overlap_handling_strategy
)
self.slice_wh = slice_wh
self.overlap_ratio_wh = overlap_ratio_wh
self.iou_threshold = iou_threshold
self.overlap_filter = overlap_filter
self.overlap_handling_strategy = overlap_handling_strategy
self.callback = callback
self.thread_workers = thread_workers
@ -130,14 +142,20 @@ class InferenceSlicer:
detections_list.append(future.result())
merged = Detections.merge(detections_list=detections_list)
if self.overlap_filter == OverlapFilter.NONE:
if self.overlap_handling_strategy == OverlapHandlingStrategy.NONE:
return merged
elif self.overlap_filter == OverlapFilter.NON_MAX_SUPPRESSION:
elif (
self.overlap_handling_strategy
== OverlapHandlingStrategy.NON_MAX_SUPPRESSION
):
return merged.with_nms(threshold=self.iou_threshold)
elif self.overlap_filter == OverlapFilter.NON_MAX_MERGE:
elif self.overlap_handling_strategy == OverlapHandlingStrategy.NON_MAX_MERGE:
return merged.with_nmm(threshold=self.iou_threshold)
else:
warnings.warn(f"Invalid overlap filter strategy: {self.overlap_filter}")
warnings.warn(
f"Invalid overlap filter strategy: {self.overlap_handling_strategy}",
category=SupervisionWarnings,
)
return merged
def _run_callback(self, image, offset) -> Detections:

View File

@ -1059,17 +1059,34 @@ def contains_multiple_segments(
return number_of_labels > 2
class OverlapFilter(Enum):
class OverlapHandlingStrategy(Enum):
"""
Enum specifying the strategy for filtering overlapping detections.
Attributes:
NONE: Do not filter detections based on overlap.
NON_MAX_SUPPRESSION: Filter detections using non-max suppression.
NON_MAX_MERGE: Merge detections with non-max-merging instead of
discarding them.
NON_MAX_SUPPRESSION: Filter detections using non-max suppression. This means,
detections that overlap by more than a set threshold will be discarded,
except for the one with the highest confidence.
NON_MAX_MERGE: Merge detections with non-max-merging. This means,
detections that overlap by more than a set threshold will be merged
into a single detection.
"""
NONE = "none"
NON_MAX_SUPPRESSION = "non_max_suppression"
NON_MAX_MERGE = "non_max_merge"
def validate_overlapping_handling_strategy(
strategy: Union[OverlapHandlingStrategy, str],
) -> OverlapHandlingStrategy:
if isinstance(strategy, str):
try:
strategy = OverlapHandlingStrategy(strategy.lower())
except ValueError:
raise ValueError(
f"Invalid strategy value: {strategy}. Must be one of "
f"{[e.value for e in OverlapHandlingStrategy]}"
)
return strategy