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

Detections _get_item_() does not handle index arrays of booleans correctly for data dictionary in Detections object. #1061

Closed
2 tasks done
rolson24 opened this issue Mar 28, 2024 · 3 comments
Labels
api:detection bug Something isn't working

Comments

@rolson24
Copy link
Contributor

rolson24 commented Mar 28, 2024

Search before asking

  • I have searched the Supervision issues and found no similar bug report.

Bug

When I tried to use boolean array indexing to get specific detections from a Detections object, the data field sometimes returns the wrong values (everything is the second value) and sometimes it just doesn't work. See output of code:

valid detections data: {'random': array([0.69156142, 0.43520246, 0.08080701, 0.32277943]), 'Dataset': ['Roboflow 100', 'Roboflow 100', 'Roboflow 100', 'Roboflow 100']}
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
[<ipython-input-6-6cae6894f883>](https://localhost:8080/#) in <cell line: 31>()
     29 # This does not run
     30 detection_inds = np.asarray([True, False, True, False], dtype = bool)
---> 31 print(f"valid detections data: {detections[detection_inds].data}")

4 frames
[/usr/local/lib/python3.10/dist-packages/supervision/detection/core.py](https://localhost:8080/#) in __getitem__(self, index)
    928         if isinstance(index, int):
    929             index = [index]
--> 930         return Detections(
    931             xyxy=self.xyxy[index],
    932             mask=self.mask[index] if self.mask is not None else None,

/usr/local/lib/python3.10/dist-packages/supervision/detection/core.py in __init__(self, xyxy, mask, confidence, class_id, tracker_id, data)

[/usr/local/lib/python3.10/dist-packages/supervision/detection/core.py](https://localhost:8080/#) in __post_init__(self)
     88 
     89     def __post_init__(self):
---> 90         validate_detections_fields(
     91             xyxy=self.xyxy,
     92             mask=self.mask,

[/usr/local/lib/python3.10/dist-packages/supervision/detection/utils.py](https://localhost:8080/#) in validate_detections_fields(xyxy, mask, class_id, confidence, tracker_id, data)
    750     validate_confidence(confidence, n)
    751     validate_tracker_id(tracker_id, n)
--> 752     validate_data(data, n)
    753 
    754 

[/usr/local/lib/python3.10/dist-packages/supervision/detection/utils.py](https://localhost:8080/#) in validate_data(data, n)
    724         if isinstance(value, list):
    725             if len(value) != n:
--> 726                 raise ValueError(f"Length of list for key '{key}' must be {n}")
    727         elif isinstance(value, np.ndarray):
    728             if value.ndim == 1 and value.shape[0] != n:

ValueError: Length of list for key 'Dataset' must be 2

Environment

  • Supervision 0.18.0 - google colab

Minimal Reproducible Example

https://colab.research.google.com/drive/1C-wlttD-awePYPTCCPmMfIEtME9o3dN7?usp=sharing

import numpy as np

import supervision as sv
import random


bboxes = np.asarray(([1,50,50,100], [40,30,70,80], [3,90,150,120], [95,50,140,100]))
confidence = np.asarray([.8, .75, .69, .99])
class_id = np.asarray([2, 4, 2, 29])
data = {"random": np.asarray([random.random(), random.random(), random.random(), random.random()]), "Dataset": ["KITTI", "Roboflow 100", "nuScenes", "COCO"]}
detections = sv.Detections.empty()
detections.xyxy = bboxes
detections.confidence = confidence
detections.class_id = class_id
detections.data = data

""" example might be filtering out detections that have a certain class by doing
    this:
      dog_class = 4
      detections = detections[detection.class_id != dog_class]

    (detections.class_id != dog_class with return a np.ndarray of type bool)
"""

# This runs but is incorrect
detection_inds = np.asarray([True, True, True, True], dtype = bool)
print(f"valid detections data: {detections[detection_inds].data}")

# This does not run
detection_inds = np.asarray([True, False, True, False], dtype = bool)
print(f"valid detections data: {detections[detection_inds].data}")

Additional

I am pretty sure this is because of how the get_data_item() function in the Detections.utils file is handling indexes that are numpy arrays. I think it's a pretty simple fix, and I can submit a PR.

Are you willing to submit a PR?

  • Yes I'd like to help by submitting a PR!
@rolson24 rolson24 added the bug Something isn't working label Mar 28, 2024
@SkalskiP
Copy link
Collaborator

Hi @rolson24! 👋🏻 good catch! I conducted my own test, and its results confirm your conclusions.

import numpy as np
import supervision as sv

xyxy = np.array([
    [100, 100, 110, 110],
    [200, 200, 220, 220],
    [300, 300, 330, 330],
    [400, 400, 440, 440],
    [500, 500, 550, 550]
], dtype=float)

confidence = np.array([
    0.1, 0.2, 0.3, 0.4, 0.5
], dtype=float)

class_id = np.array([
    1, 2, 3, 4, 5
], dtype=int)

letter = [
    'a', 'b', 'c', 'd', 'e'
]

detections = sv.Detections(
    xyxy=xyxy,
    class_id=class_id,
    confidence=confidence,
    data={
        "letter": letter
    }
)

detections[[1, 2]]

# Detections(
#     xyxy=array([
#         [200., 200., 220., 220.],
#         [300., 300., 330., 330.]]), 
#     mask=None, 
#     confidence=array([0.2, 0.3]), 
#     class_id=array([2, 3]), 
#     tracker_id=None, 
#     data={'letter': ['b', 'c']}
# )
# OK.

detections[np.array([1, 2])]

# Detections(
#     xyxy=array([
#         [200., 200., 220., 220.],
#         [300., 300., 330., 330.]]), 
#     mask=None, 
#     confidence=array([0.2, 0.3]), 
#     class_id=array([2, 3]), 
#     tracker_id=None, 
#     data={'letter': ['b', 'c']}
# )
# OK.

detections[np.array([1, 1, 1, 1, 1])]

# Detections(
#     xyxy=array([
#         [200., 200., 220., 220.],
#         [200., 200., 220., 220.],
#         [200., 200., 220., 220.],
#         [200., 200., 220., 220.],
#         [200., 200., 220., 220.]]), 
#     mask=None, 
#     confidence=array([0.2, 0.2, 0.2, 0.2, 0.2]), 
#     class_id=array([2, 2, 2, 2, 2]), 
#     tracker_id=None, 
#     data={'letter': ['b', 'b', 'b', 'b', 'b']}
# )
# OK.

detections[np.array([True, True, True, True, True], dtype=bool)]

# Detections(
#     xyxy=array([
#         [100., 100., 110., 110.],
#         [200., 200., 220., 220.],
#         [300., 300., 330., 330.],
#         [400., 400., 440., 440.],
#         [500., 500., 550., 550.]]), 
#     mask=None, 
#     confidence=array([0.1, 0.2, 0.3, 0.4, 0.5]), 
#     class_id=array([1, 2, 3, 4, 5]), 
#     tracker_id=None, 
#     data={'letter': ['b', 'b', 'b', 'b', 'b']}
# )
# WRONG DATA.

detections[np.array([False, False, False, False, False], dtype=bool)]

# ---------------------------------------------------------------------------
# ValueError                                Traceback (most recent call last)
# [<ipython-input-26-634699880563>](https://localhost:8080/#) in <cell line: 1>()
# ----> 1 detections[np.array([False, False, False, False, False], dtype=bool)]
# 
# 4 frames
# [/usr/local/lib/python3.10/dist-packages/supervision/detection/utils.py](https://localhost:8080/#) in validate_data(data, n)
#     724         if isinstance(value, list):
#     725             if len(value) != n:
# --> 726                 raise ValueError(f"Length of list for key '{key}' must be {n}")
#     727         elif isinstance(value, np.ndarray):
#     728             if value.ndim == 1 and value.shape[0] != n:
# 
# ValueError: Length of list for key 'letter' must be 0

SkalskiP added a commit that referenced this issue Mar 28, 2024
@SkalskiP
Copy link
Collaborator

It was fixed with #1062. Merging!

@rolson24
Copy link
Contributor Author

Great! Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
api:detection bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants