From 90a26747b6d6266344fb47c9f20b436b2fc716ef Mon Sep 17 00:00:00 2001
From: James Gallagher
Date: Wed, 1 Feb 2023 10:28:49 +0000
Subject: [PATCH 1/3] create stub doc files, refactor docstrings, add
placeholders for examples
---
docs/draw.md | 9 +++++
docs/geometry.md | 0
docs/index.md | 15 ++++----
docs/notebook.md | 3 ++
docs/tools.md | 9 +++++
mkdocs.yml | 8 +++--
supervision/draw/utils.py | 48 ++++++++++++++++++++------
supervision/notebook/utils.py | 13 +++++--
supervision/tools/detections.py | 57 +++++++++++++++++++------------
supervision/tools/line_counter.py | 39 ++++++++++++++-------
10 files changed, 144 insertions(+), 57 deletions(-)
create mode 100644 docs/draw.md
create mode 100644 docs/geometry.md
create mode 100644 docs/notebook.md
create mode 100644 docs/tools.md
diff --git a/docs/draw.md b/docs/draw.md
new file mode 100644
index 00000000..8ba499b1
--- /dev/null
+++ b/docs/draw.md
@@ -0,0 +1,9 @@
+Utilities for drawing on images.
+
+## Draw Line
+
+:::supervision.draw.utils.draw_line
+
+## Draw Rectangle
+
+:::supervision.draw.utils.draw_rectangle
\ No newline at end of file
diff --git a/docs/geometry.md b/docs/geometry.md
new file mode 100644
index 00000000..e69de29b
diff --git a/docs/index.md b/docs/index.md
index 3f1233af..092d38f5 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -9,21 +9,22 @@
-## 👋 hello
+## 👋 Welcome
-A set of easy-to-use utils that will come in handy in any Computer Vision project. **Supervision** is still in
-pre-release stage. 🚧 Keep your eyes open for potential bugs and be aware that at this stage our API is still fluid
-and may change.
+Supervision is a set of easy-to-use utilities that will come in handy in any computer vision project.
-## 💻 install
+**Supervision** is still in
+pre-release stage 🚧 Keep your eyes open for potential bugs and be aware that at this stage our API is still fluid and may change.
-Pip install the supervision package in a
+## 💻 How to Install
+
+You can install `supervision` with pip in a
[**3.10>=Python>=3.7**](https://www.python.org/) environment.
!!! example "Pip install method (recommended)"
```bash
- pip install subervision
+ pip install supervision
```
!!! example "Git clone method (for development)"
diff --git a/docs/notebook.md b/docs/notebook.md
new file mode 100644
index 00000000..ce650120
--- /dev/null
+++ b/docs/notebook.md
@@ -0,0 +1,3 @@
+Utilities to help you build computer vision projects in notebook environments.
+
+:::supervision.notebook.utils.show_frame_in_notebook
\ No newline at end of file
diff --git a/docs/tools.md b/docs/tools.md
new file mode 100644
index 00000000..9274cb0e
--- /dev/null
+++ b/docs/tools.md
@@ -0,0 +1,9 @@
+Useful utilities for common computer vision tasks.
+
+## Helper for Processing Model Detections
+
+:::supervision.tools.detections.Detections
+
+## Count Objects That Pass a Line
+
+:::supervision.tools.line_counter.LineCounter
\ No newline at end of file
diff --git a/mkdocs.yml b/mkdocs.yml
index 46c257de..cbbcac7a 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -19,8 +19,12 @@ extra:
link: https://twitter.com/roboflow
nav:
- - Home: index.md
- - Video: video.md
+ - Home 🏠: index.md
+ - Video 📷: video.md
+ - Notebook Helpers 📓: notebook.md
+ - Draw 🎨: draw.md
+ - Geometry 📐: geometry.md
+ - Tools 🛠: tools.md
theme:
name: 'material'
diff --git a/supervision/draw/utils.py b/supervision/draw/utils.py
index 306e3ef5..ff9e60b8 100644
--- a/supervision/draw/utils.py
+++ b/supervision/draw/utils.py
@@ -11,12 +11,16 @@ def draw_line(
"""
Draws a line on a given scene.
- :param scene: np.ndarray : The scene on which the line will be drawn
- :param start: Point : The starting point of the line
- :param end: Point : The end point of the line
- :param color: Color : The color of the line
- :param thickness: int : The thickness of the line
- :return: np.ndarray : The scene with the line drawn on it
+ Attributes:
+
+ scene (np.ndarray): The scene on which the line will be drawn
+ start (Point): The starting point of the line
+ end (Point): The end point of the line
+ color (Color): The color of the line
+ thickness (int): The thickness of the line
+
+ Returns:
+ np.ndarray: The scene with the line drawn on it
"""
cv2.line(
scene,
@@ -34,11 +38,19 @@ def draw_rectangle(
"""
Draws a rectangle on an image.
- :param scene: np.ndarray : The image on which to draw the rectangle.
- :param rect: Rect : The rectangle to draw.
- :param color: Color : The color of the rectangle.
- :param thickness: int : The thickness of the rectangle border.
- :return: np.ndarray : The image with the rectangle drawn on it.
+ Attributes:
+ scene (np.ndarray): The scene on which the rectangle will be drawn
+ rect (Rect): The rectangle to be drawn
+ color (Color): The color of the rectangle
+ thickness (int): The thickness of the rectangle border
+
+ Returns:
+ np.ndarray: The scene with the rectangle drawn on it
+
+ Example:
+ ```python
+ >>> # TODO: Add example
+ ```
"""
cv2.rectangle(
scene,
@@ -58,6 +70,20 @@ def draw_filled_rectangle(scene: np.ndarray, rect: Rect, color: Color) -> np.nda
:param rect: Rect : The rectangle to be drawn.
:param color: Color : The color of the rectangle.
:return: np.ndarray : The updated scene with the filled rectangle drawn on it.
+
+ Attributes:
+ scene (np.ndarray): The scene on which the rectangle will be drawn
+ rect (Rect): The rectangle to be drawn
+ color (Color): The color of the rectangle
+
+ Returns:
+ np.ndarray: The scene with the rectangle drawn on it
+
+ Example:
+ ```python
+ >>> # TODO: Add example
+ ```
+
"""
cv2.rectangle(
scene,
diff --git a/supervision/notebook/utils.py b/supervision/notebook/utils.py
index 2afc3a63..c50c9842 100644
--- a/supervision/notebook/utils.py
+++ b/supervision/notebook/utils.py
@@ -11,9 +11,16 @@ def show_frame_in_notebook(
"""
Display a frame in Jupyter Notebook using Matplotlib
- :param frame: np.ndarray : The frame to be displayed.
- :param size: Tuple[int, int] : The size of the plot. default:(10,10)
- :param cmap: str : the colormap to use for single channel images. default:gray
+ Attributes:
+ frame (np.ndarray): The frame to be displayed.
+ size (Tuple[int, int]): The size of the plot. default:(10,10)
+ cmap (str): the colormap to use for single channel images. default:gray
+
+ Examples:
+ ```python
+ >>> from supervision.notebook import show_frame_in_notebook
+
+ ```
"""
if frame.ndim == 2:
plt.figure(figsize=size)
diff --git a/supervision/tools/detections.py b/supervision/tools/detections.py
index 2cf54867..72a8edd8 100644
--- a/supervision/tools/detections.py
+++ b/supervision/tools/detections.py
@@ -17,10 +17,11 @@ class Detections:
"""
Data class containing information about the detections in a video frame.
- :param xyxy: np.ndarray : An array of shape (n, 4) containing the bounding boxes coordinates in format [x1, y1, x2, y2]
- :param confidence: np.ndarray : An array of shape (n,) containing the confidence scores of the detections.
- :param class_id: np.ndarray : An array of shape (n,) containing the class ids of the detections.
- :param tracker_id: Optional[np.ndarray] : An array of shape (n,) containing the tracker ids of the detections.
+ Attributes:
+ xyxy (np.ndarray): An array of shape (n, 4) containing the bounding boxes coordinates in format [x1, y1, x2, y2]
+ confidence (np.ndarray): An array of shape (n,) containing the confidence scores of the detections.
+ class_id (np.ndarray): An array of shape (n,) containing the class ids of the detections.
+ tracker_id (Optional[np.ndarray]): An array of shape (n,) containing the tracker ids of the detections.
"""
self.xyxy: np.ndarray = xyxy
self.confidence: np.ndarray = confidence
@@ -69,11 +70,17 @@ class Detections:
"""
Creates a Detections instance from a YOLOv5 output tensor
- :param yolov5_output: np.ndarray : The output tensor from YOLOv5
- :return: Detections : A Detections instance representing the detections in the frame
+ Attributes:
+ yolov5_output (np.ndarray): The output tensor from YOLOv5
+
+ Returns:
Example:
- detections = Detections.from_yolov5(yolov5_output)
+ ```python
+ >>> from supervision.tools.detections import Detections
+
+ >>> detections = Detections.from_yolov5(yolov5_output)
+ ```
"""
xyxy = yolov5_output[:, :4]
confidence = yolov5_output[:, 4]
@@ -82,11 +89,14 @@ class Detections:
def filter(self, mask: np.ndarray, inplace: bool = False) -> Optional[np.ndarray]:
"""
- Filter the detections by applying a mask
+ Filter the detections by applying a mask.
- :param mask: np.ndarray : A mask of shape (n,) containing a boolean value for each detection indicating if it should be included in the filtered detections
- :param inplace: bool : If True, the original data will be modified and self will be returned.
- :return: Optional[np.ndarray] : A new instance of Detections with the filtered detections, if inplace is set to False. None otherwise.
+ Attributes:
+ mask (np.ndarray): A mask of shape (n,) containing a boolean value for each detection indicating if it should be included in the filtered detections
+ inplace (bool): If True, the original data will be modified and self will be returned.
+
+ Returns:
+ Optional[np.ndarray]: A new instance of Detections with the filtered detections, if inplace is set to False. None otherwise.
"""
if inplace:
self.xyxy = self.xyxy[mask]
@@ -120,12 +130,14 @@ class BoxAnnotator:
"""
A class for drawing bounding boxes on an image using detections provided.
- :param color: Union[Color, ColorPalette] : The color to draw the bounding box, can be a single color or a color palette
- :param thickness: int : The thickness of the bounding box lines, default is 2
- :param text_color: Color : The color of the text on the bounding box, default is white
- :param text_scale: float : The scale of the text on the bounding box, default is 0.5
- :param text_thickness: int : The thickness of the text on the bounding box, default is 1
- :param text_padding: int : The padding around the text on the bounding box, default is 5
+ Attributes:
+ color (Union[Color, ColorPalette]): The color to draw the bounding box, can be a single color or a color palette
+ thickness (int): The thickness of the bounding box lines, default is 2
+ text_color (Color): The color of the text on the bounding box, default is white
+ text_scale (float): The scale of the text on the bounding box, default is 0.5
+ text_thickness (int): The thickness of the text on the bounding box, default is 1
+ text_padding (int): The padding around the text on the bounding box, default is 5
+
"""
self.color: Union[Color, ColorPalette] = color
self.thickness: int = thickness
@@ -142,11 +154,14 @@ class BoxAnnotator:
) -> np.ndarray:
"""
Draws bounding boxes on the frame using the detections provided.
+
+ Attributes:
+ frame (np.ndarray): The image on which the bounding boxes will be drawn
+ detections (Detections): The detections for which the bounding boxes will be drawn
+ labels (Optional[List[str]]): An optional list of labels corresponding to each detection. If labels is provided, the confidence score of the detection will be replaced with the label.
- :param frame: np.ndarray : The image on which the bounding boxes will be drawn
- :param detections: Detections : The detections for which the bounding boxes will be drawn
- :param labels: Optional[List[str]] : An optional list of labels corresponding to each detection. If labels is provided, the confidence score of the detection will be replaced with the label.
- :return: np.ndarray : The image with the bounding boxes drawn on it
+ Returns:
+ np.ndarray: The image with the bounding boxes drawn on it
"""
font = cv2.FONT_HERSHEY_SIMPLEX
for i, (xyxy, confidence, class_id, tracker_id) in enumerate(detections):
diff --git a/supervision/tools/line_counter.py b/supervision/tools/line_counter.py
index cfa3ee6d..93a4e0c5 100644
--- a/supervision/tools/line_counter.py
+++ b/supervision/tools/line_counter.py
@@ -9,12 +9,17 @@ from supervision.tools.detections import Detections
class LineCounter:
+ """
+ Count the number of objects that cross a line.
+ """
def __init__(self, start: Point, end: Point):
"""
Initialize a LineCounter object.
- :param start: Point : The starting point of the line.
- :param end: Point : The ending point of the line.
+ Attributes:
+ start (Point): The starting point of the line.
+ end (Point): The ending point of the line.
+
"""
self.vector = Vector(start=start, end=end)
self.tracker_state: Dict[str, bool] = {}
@@ -25,7 +30,9 @@ class LineCounter:
"""
Update the in_count and out_count for the detections that cross the line.
- :param detections: Detections : The detections for which to update the counts.
+ Attributes:
+ detections (Detections): The detections for which to update the counts.
+
"""
for xyxy, confidence, class_id, tracker_id in detections:
# handle detections with no tracker_id
@@ -77,13 +84,15 @@ class LineCounterAnnotator:
"""
Initialize the LineCounterAnnotator object with default values.
- :param thickness: float : The thickness of the line that will be drawn.
- :param color: Color : The color of the line that will be drawn.
- :param text_thickness: float : The thickness of the text that will be drawn.
- :param text_color: Color : The color of the text that will be drawn.
- :param text_scale: float : The scale of the text that will be drawn.
- :param text_offset: float : The offset of the text that will be drawn.
- :param text_padding: int : The padding of the text that will be drawn.
+ Attributes:
+ thickness (float): The thickness of the line that will be drawn.
+ color (Color): The color of the line that will be drawn.
+ text_thickness (float): The thickness of the text that will be drawn.
+ text_color (Color): The color of the text that will be drawn.
+ text_scale (float): The scale of the text that will be drawn.
+ text_offset (float): The offset of the text that will be drawn.
+ text_padding (int): The padding of the text that will be drawn.
+
"""
self.thickness: float = thickness
self.color: Color = color
@@ -97,9 +106,13 @@ class LineCounterAnnotator:
"""
Draws the line on the frame using the line_counter provided.
- :param frame: np.ndarray : The image on which the line will be drawn
- :param line_counter: LineCounter : The line counter that will be used to draw the line
- :return: np.ndarray : The image with the line drawn on it
+ Attributes:
+ frame (np.ndarray): The image on which the line will be drawn.
+ line_counter (LineCounter): The line counter that will be used to draw the line.
+
+ Returns:
+ np.ndarray: The image with the line drawn on it.
+
"""
cv2.line(
frame,
From 61a2f4e0e6c0e54b0fd35daff31ff8e86f613912 Mon Sep 17 00:00:00 2001
From: James Gallagher
Date: Wed, 1 Feb 2023 10:29:00 +0000
Subject: [PATCH 2/3] add requirements.txt
---
requirements.txt | 30 ++++++++++++++++++++++++++++++
1 file changed, 30 insertions(+)
create mode 100644 requirements.txt
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 00000000..4b9058af
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1,30 @@
+certifi==2022.12.7
+charset-normalizer==3.0.1
+click==8.1.3
+colorama==0.4.6
+ghp-import==2.1.0
+griffe==0.25.4
+idna==3.4
+importlib-metadata==6.0.0
+Jinja2==3.1.2
+Markdown==3.3.7
+MarkupSafe==2.1.2
+mergedeep==1.3.4
+mkdocs==1.4.2
+mkdocs-autorefs==0.4.1
+mkdocs-material==9.0.9
+mkdocs-material-extensions==1.1.1
+mkdocstrings==0.20.0
+mkdocstrings-python==0.8.3
+packaging==23.0
+Pygments==2.14.0
+pymdown-extensions==9.9.2
+python-dateutil==2.8.2
+PyYAML==6.0
+pyyaml_env_tag==0.1
+regex==2022.10.31
+requests==2.28.2
+six==1.16.0
+urllib3==1.26.14
+watchdog==2.2.1
+zipp==3.12.0
From 4fbec12b06ee24abf35c71de9f995f472860651d Mon Sep 17 00:00:00 2001
From: James Gallagher
Date: Wed, 1 Feb 2023 14:37:54 +0000
Subject: [PATCH 3/3] run linter
---
supervision/draw/utils.py | 2 +-
supervision/tools/detections.py | 6 +++---
supervision/tools/line_counter.py | 5 +++--
test/draw/test_color.py | 34 +++++++++++++++----------------
test/geometry/test_dataclasses.py | 15 +++-----------
5 files changed, 26 insertions(+), 36 deletions(-)
diff --git a/supervision/draw/utils.py b/supervision/draw/utils.py
index ff9e60b8..ff6c050c 100644
--- a/supervision/draw/utils.py
+++ b/supervision/draw/utils.py
@@ -83,7 +83,7 @@ def draw_filled_rectangle(scene: np.ndarray, rect: Rect, color: Color) -> np.nda
```python
>>> # TODO: Add example
```
-
+
"""
cv2.rectangle(
scene,
diff --git a/supervision/tools/detections.py b/supervision/tools/detections.py
index 72a8edd8..4faaf6cf 100644
--- a/supervision/tools/detections.py
+++ b/supervision/tools/detections.py
@@ -72,13 +72,13 @@ class Detections:
Attributes:
yolov5_output (np.ndarray): The output tensor from YOLOv5
-
+
Returns:
Example:
```python
>>> from supervision.tools.detections import Detections
-
+
>>> detections = Detections.from_yolov5(yolov5_output)
```
"""
@@ -154,7 +154,7 @@ class BoxAnnotator:
) -> np.ndarray:
"""
Draws bounding boxes on the frame using the detections provided.
-
+
Attributes:
frame (np.ndarray): The image on which the bounding boxes will be drawn
detections (Detections): The detections for which the bounding boxes will be drawn
diff --git a/supervision/tools/line_counter.py b/supervision/tools/line_counter.py
index 93a4e0c5..f791c9a6 100644
--- a/supervision/tools/line_counter.py
+++ b/supervision/tools/line_counter.py
@@ -12,6 +12,7 @@ class LineCounter:
"""
Count the number of objects that cross a line.
"""
+
def __init__(self, start: Point, end: Point):
"""
Initialize a LineCounter object.
@@ -92,7 +93,7 @@ class LineCounterAnnotator:
text_scale (float): The scale of the text that will be drawn.
text_offset (float): The offset of the text that will be drawn.
text_padding (int): The padding of the text that will be drawn.
-
+
"""
self.thickness: float = thickness
self.color: Color = color
@@ -112,7 +113,7 @@ class LineCounterAnnotator:
Returns:
np.ndarray: The image with the line drawn on it.
-
+
"""
cv2.line(
frame,
diff --git a/test/draw/test_color.py b/test/draw/test_color.py
index 5ea48abb..723f7043 100644
--- a/test/draw/test_color.py
+++ b/test/draw/test_color.py
@@ -7,27 +7,25 @@ from supervision.draw.color import Color
@pytest.mark.parametrize(
- 'color_hex, expected_result, exception',
+ "color_hex, expected_result, exception",
[
- ('fff', Color.white(), DoesNotRaise()),
- ('#fff', Color.white(), DoesNotRaise()),
- ('ffffff', Color.white(), DoesNotRaise()),
- ('#ffffff', Color.white(), DoesNotRaise()),
- ('f00', Color.red(), DoesNotRaise()),
- ('0f0', Color.green(), DoesNotRaise()),
- ('00f', Color.blue(), DoesNotRaise()),
- ('#808000', Color(r=128, g=128, b=0), DoesNotRaise()),
- ('', None, pytest.raises(ValueError)),
- ('00', None, pytest.raises(ValueError)),
- ('0000', None, pytest.raises(ValueError)),
- ('0000000', None, pytest.raises(ValueError)),
- ('ffg', None, pytest.raises(ValueError)),
- ]
+ ("fff", Color.white(), DoesNotRaise()),
+ ("#fff", Color.white(), DoesNotRaise()),
+ ("ffffff", Color.white(), DoesNotRaise()),
+ ("#ffffff", Color.white(), DoesNotRaise()),
+ ("f00", Color.red(), DoesNotRaise()),
+ ("0f0", Color.green(), DoesNotRaise()),
+ ("00f", Color.blue(), DoesNotRaise()),
+ ("#808000", Color(r=128, g=128, b=0), DoesNotRaise()),
+ ("", None, pytest.raises(ValueError)),
+ ("00", None, pytest.raises(ValueError)),
+ ("0000", None, pytest.raises(ValueError)),
+ ("0000000", None, pytest.raises(ValueError)),
+ ("ffg", None, pytest.raises(ValueError)),
+ ],
)
def test_color_from_hex(
- color_hex,
- expected_result: Optional[Color],
- exception: Exception
+ color_hex, expected_result: Optional[Color], exception: Exception
) -> None:
with exception:
result = Color.from_hex(color_hex=color_hex)
diff --git a/test/geometry/test_dataclasses.py b/test/geometry/test_dataclasses.py
index 5e829877..34821884 100644
--- a/test/geometry/test_dataclasses.py
+++ b/test/geometry/test_dataclasses.py
@@ -4,37 +4,28 @@ from supervision.geometry.dataclasses import Vector, Point
@pytest.mark.parametrize(
- 'vector, point, expected_result',
+ "vector, point, expected_result",
[
(Vector(start=Point(x=0, y=0), end=Point(x=5, y=5)), Point(x=-1, y=1), False),
(Vector(start=Point(x=0, y=0), end=Point(x=5, y=5)), Point(x=6, y=6), False),
(Vector(start=Point(x=0, y=0), end=Point(x=5, y=5)), Point(x=3, y=6), False),
-
(Vector(start=Point(x=5, y=5), end=Point(x=0, y=0)), Point(x=-1, y=1), True),
(Vector(start=Point(x=5, y=5), end=Point(x=0, y=0)), Point(x=6, y=6), False),
(Vector(start=Point(x=5, y=5), end=Point(x=0, y=0)), Point(x=3, y=6), True),
-
(Vector(start=Point(x=0, y=0), end=Point(x=1, y=0)), Point(x=0, y=0), False),
(Vector(start=Point(x=0, y=0), end=Point(x=1, y=0)), Point(x=0, y=-1), True),
(Vector(start=Point(x=0, y=0), end=Point(x=1, y=0)), Point(x=0, y=1), False),
-
(Vector(start=Point(x=1, y=0), end=Point(x=0, y=0)), Point(x=0, y=0), False),
(Vector(start=Point(x=1, y=0), end=Point(x=0, y=0)), Point(x=0, y=-1), False),
(Vector(start=Point(x=1, y=0), end=Point(x=0, y=0)), Point(x=0, y=1), True),
-
(Vector(start=Point(x=1, y=1), end=Point(x=1, y=3)), Point(x=0, y=0), False),
(Vector(start=Point(x=1, y=1), end=Point(x=1, y=3)), Point(x=1, y=4), False),
(Vector(start=Point(x=1, y=1), end=Point(x=1, y=3)), Point(x=2, y=4), True),
-
(Vector(start=Point(x=1, y=3), end=Point(x=1, y=1)), Point(x=0, y=0), True),
(Vector(start=Point(x=1, y=3), end=Point(x=1, y=1)), Point(x=1, y=4), False),
(Vector(start=Point(x=1, y=3), end=Point(x=1, y=1)), Point(x=2, y=4), False),
- ]
+ ],
)
-def test_vector_is_in(
- vector: Vector,
- point: Point,
- expected_result: bool
-) -> None:
+def test_vector_is_in(vector: Vector, point: Point, expected_result: bool) -> None:
result = vector.is_in(point=point)
assert result == expected_result