diff --git a/docs/changelog.md b/docs/changelog.md
index 47d160aa..024edd1a 100644
--- a/docs/changelog.md
+++ b/docs/changelog.md
@@ -1,3 +1,83 @@
+### 0.21.0 Jun 5, 2024
+
+- Added [#500](https://github.com/roboflow/supervision/pull/500): [`sv.Detections.with_nmm`](https://supervision.roboflow.com/develop/detection/core/#supervision.detection.core.Detections.with_nmm) to perform non-maximum merging on the current set of object detections.
+
+- Added [#1221](https://github.com/roboflow/supervision/pull/1221): [`sv.Detections.from_lmm`](https://supervision.roboflow.com/develop/detection/core/#supervision.detection.core.Detections.from_lmm) allowing to parse Large Multimodal Model (LMM) text result into [`sv.Detections`](https://supervision.roboflow.com/develop/detection/core/) object. For now `from_lmm` supports only [PaliGemma](https://colab.research.google.com/github/roboflow-ai/notebooks/blob/main/notebooks/how-to-finetune-paligemma-on-detection-dataset.ipynb) result parsing.
+
+```python
+import supervision as sv
+
+paligemma_result = " cat"
+detections = sv.Detections.from_lmm(
+ sv.LMM.PALIGEMMA,
+ paligemma_result,
+ resolution_wh=(1000, 1000),
+ classes=['cat', 'dog']
+)
+detections.xyxy
+# array([[250., 250., 750., 750.]])
+
+detections.class_id
+# array([0])
+```
+
+- Added [#1236](https://github.com/roboflow/supervision/pull/1236): [`sv.VertexLabelAnnotator`](https://supervision.roboflow.com/develop/keypoint/annotators/#supervision.keypoint.annotators.EdgeAnnotator.annotate) allowing to annotate every vertex of a keypoint skeleton with custom text and color.
+
+```python
+import supervision as sv
+
+image = ...
+key_points = sv.KeyPoints(...)
+
+edge_annotator = sv.EdgeAnnotator(
+ color=sv.Color.GREEN,
+ thickness=5
+)
+annotated_frame = edge_annotator.annotate(
+ scene=image.copy(),
+ key_points=key_points
+)
+```
+
+- Added [#1147](https://github.com/roboflow/supervision/pull/1147): [`sv.KeyPoints.from_inference`](https://supervision.roboflow.com/develop/keypoint/core/#supervision.keypoint.core.KeyPoints.from_inference) allowing to create [`sv.KeyPoints`](https://supervision.roboflow.com/develop/keypoint/core/#supervision.keypoint.core.KeyPoints) from [Inference](https://github.com/roboflow/inference) result.
+
+- Added [#1138](https://github.com/roboflow/supervision/pull/1138): [`sv.KeyPoints.from_yolo_nas`](https://supervision.roboflow.com/develop/keypoint/core/#supervision.keypoint.core.KeyPoints.from_yolo_nas) allowing to create [`sv.KeyPoints`](https://supervision.roboflow.com/develop/keypoint/core/#supervision.keypoint.core.KeyPoints) from [YOLO-NAS](https://github.com/Deci-AI/super-gradients/blob/master/YOLONAS.md) result.
+
+- Added [#1163](https://github.com/roboflow/supervision/pull/1163): [`sv.mask_to_rle`](https://supervision.roboflow.com/develop/datasets/utils/#supervision.dataset.utils.rle_to_mask) and [`sv.rle_to_mask`](https://supervision.roboflow.com/develop/datasets/utils/#supervision.dataset.utils.rle_to_mask) allowing for easy conversion between mask and rle formats.
+
+- Changed [#1236](https://github.com/roboflow/supervision/pull/1236): [`sv.InferenceSlicer`](https://supervision.roboflow.com/develop/detection/tools/inference_slicer/) allowing to select overlap filtering strategy (`NONE`, `NON_MAX_SUPPRESSION` and `NON_MAX_MERGE`).
+
+- Changed [#1178](https://github.com/roboflow/supervision/pull/1178): [`sv.InferenceSlicer`](https://supervision.roboflow.com/develop/detection/tools/inference_slicer/) adding instance segmentation model support.
+
+```python
+import cv2
+import numpy as np
+import supervision as sv
+from inference import get_model
+
+model = get_model(model_id="yolov8x-seg-640")
+image = cv2.imread()
+
+def callback(image_slice: np.ndarray) -> sv.Detections:
+ results = model.infer(image_slice)[0]
+ return sv.Detections.from_inference(results)
+
+slicer = sv.InferenceSlicer(callback = callback)
+detections = slicer(image)
+
+mask_annotator = sv.MaskAnnotator()
+label_annotator = sv.LabelAnnotator()
+
+annotated_image = mask_annotator.annotate(
+ scene=image, detections=detections)
+annotated_image = label_annotator.annotate(
+ scene=annotated_image, detections=detections)
+```
+
+- Changed [#1228](https://github.com/roboflow/supervision/pull/1228): [`sv.LineZone`](https://supervision.roboflow.com/develop/detection/tools/line_zone/) making it 10-20 times faster, depending on the use case.
+
+- Changed [#1163](https://github.com/roboflow/supervision/pull/1163): [`sv.DetectionDataset.from_coco`](https://supervision.roboflow.com/develop/datasets/core/#supervision.dataset.core.DetectionDataset.from_coco) and [`sv.DetectionDataset.as_coco`](https://supervision.roboflow.com/develop/datasets/core/#supervision.dataset.core.DetectionDataset.as_coco) adding support for run-length encoding (RLE) mask format.
+
### 0.20.0 April 24, 2024
- Added [#1128](https://github.com/roboflow/supervision/pull/1128): [`sv.KeyPoints`](/0.20.0/keypoint/core/#supervision.keypoint.core.KeyPoints) to provide initial support for pose estimation and broader keypoint detection models.
diff --git a/mkdocs.yml b/mkdocs.yml
index 19d6a4fd..96728971 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -35,15 +35,15 @@ extra_css:
nav:
- - Home: index.md
- - How to:
+ - Supervision: index.md
+ - Learn:
- Detect and Annotate: how_to/detect_and_annotate.md
- Save Detections: how_to/save_detections.md
- Filter Detections: how_to/filter_detections.md
- Detect Small Objects: how_to/detect_small_objects.md
- Track Objects on Video: how_to/track_objects.md
- - API:
+ - Reference - Code API:
- Detection and Segmentation:
- Core: detection/core.md
- Annotators: detection/annotators.md
@@ -79,7 +79,7 @@ nav:
- Contributing: contributing.md
- Code of Conduct: code_of_conduct.md
- License: license.md
- - Changelog:
+ - Release Notes:
- Changelog: changelog.md
- Deprecated: deprecated.md
diff --git a/pyproject.toml b/pyproject.toml
index 640d462e..59d4176d 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[tool.poetry]
name = "supervision"
-version = "0.21.0rc5"
+version = "0.21.0"
description = "A set of easy-to-use utils that will come in handy in any Computer Vision project"
authors = ["Piotr Skalski "]
maintainers = ["Piotr Skalski "]
diff --git a/supervision/detection/core.py b/supervision/detection/core.py
index 7b2e8ba9..37dde153 100644
--- a/supervision/detection/core.py
+++ b/supervision/detection/core.py
@@ -1239,7 +1239,9 @@ class Detections:
Raises:
AssertionError: If `confidence` is None or `class_id` is None and
class_agnostic is False.
- """
+
+ { align=center width="800" }
+ """ # noqa: E501 // docs
if len(self) == 0:
return self
diff --git a/supervision/detection/lmm.py b/supervision/detection/lmm.py
index 0278fc00..5f61db0a 100644
--- a/supervision/detection/lmm.py
+++ b/supervision/detection/lmm.py
@@ -41,7 +41,7 @@ def from_paligemma(
) -> Tuple[np.ndarray, Optional[np.ndarray], np.ndarray]:
w, h = resolution_wh
pattern = re.compile(
- r"(?) ([\w\s]+)"
+ r"(?) ([\w\s\-]+)"
)
matches = pattern.findall(result)
matches = np.array(matches) if matches else np.empty((0, 5))
diff --git a/supervision/detection/utils.py b/supervision/detection/utils.py
index 2b58655e..5b92aedd 100644
--- a/supervision/detection/utils.py
+++ b/supervision/detection/utils.py
@@ -155,6 +155,25 @@ def clip_boxes(xyxy: np.ndarray, resolution_wh: Tuple[int, int]) -> np.ndarray:
np.ndarray: A numpy array of shape `(N, 4)` where each row
corresponds to a bounding box with coordinates clipped to fit
within the frame resolution.
+
+ Examples:
+ ```python
+ import numpy as np
+ import supervision as sv
+
+ xyxy = np.array([
+ [10, 20, 300, 200],
+ [15, 25, 350, 450],
+ [-10, -20, 30, 40]
+ ])
+
+ sv.clip_boxes(xyxy=xyxy, resolution_wh=(320, 240))
+ # array([
+ # [ 10, 20, 300, 200],
+ # [ 15, 25, 320, 240],
+ # [ 0, 0, 30, 40]
+ # ])
+ ```
"""
result = np.copy(xyxy)
width, height = resolution_wh
@@ -181,6 +200,23 @@ def pad_boxes(xyxy: np.ndarray, px: int, py: Optional[int] = None) -> np.ndarray
np.ndarray: A numpy array of shape `(N, 4)` where each row corresponds to a
bounding box with coordinates padded according to the provided padding
values.
+
+ Examples:
+ ```python
+ import numpy as np
+ import supervision as sv
+
+ xyxy = np.array([
+ [10, 20, 30, 40],
+ [15, 25, 35, 45]
+ ])
+
+ sv.pad_boxes(xyxy=xyxy, px=5, py=10)
+ # array([
+ # [ 5, 10, 35, 50],
+ # [10, 15, 40, 55]
+ # ])
+ ```
"""
if py is None:
py = px
@@ -553,7 +589,7 @@ def scale_boxes(
[30, 30, 40, 40]
])
- scaled_bb = sv.scale_boxes(xyxy=xyxy, factor=1.5)
+ sv.scale_boxes(xyxy=xyxy, factor=1.5)
# array([
# [ 7.5, 7.5, 22.5, 22.5],
# [27.5, 27.5, 42.5, 42.5]
diff --git a/test/detection/test_lmm.py b/test/detection/test_lmm.py
index 129aa44b..4448d8db 100644
--- a/test/detection/test_lmm.py
+++ b/test/detection/test_lmm.py
@@ -76,7 +76,27 @@ from supervision.detection.lmm import from_paligemma
None,
np.array(["black cat"]).astype(np.dtype("U")),
),
- ), # correct response; no classes
+ ), # correct response; class name with space; no classes
+ (
+ " black-cat",
+ (1000, 1000),
+ None,
+ (
+ np.array([[250.0, 250.0, 750.0, 750.0]]),
+ None,
+ np.array(["black-cat"]).astype(np.dtype("U")),
+ ),
+ ), # correct response; class name with hyphen; no classes
+ (
+ " black_cat",
+ (1000, 1000),
+ None,
+ (
+ np.array([[250.0, 250.0, 750.0, 750.0]]),
+ None,
+ np.array(["black_cat"]).astype(np.dtype("U")),
+ ),
+ ), # correct response; class name with underscore; no classes
(
" cat ;",
(1000, 1000),