|
10 | 10 |
|
11 | 11 | from supervision.config import CLASS_NAME_DATA_FIELD |
12 | 12 | from supervision.detection.core import Detections |
13 | | -from supervision.detection.utils._typing import _DetectionDataType |
| 13 | +from supervision.detection.utils._typing import ( |
| 14 | + _DetectionDataType, |
| 15 | + _DetectionDataValueType, |
| 16 | +) |
14 | 17 | from supervision.detection.utils.internal import get_data_item, is_data_equal |
15 | 18 | from supervision.detection.utils.iou_and_nms import ( |
16 | 19 | OverlapMetric, |
@@ -908,51 +911,49 @@ def _get_by_2d_bool_mask(self, mask: npt.NDArray[np.bool_]) -> KeyPoints: |
908 | 911 | data=data_selected, |
909 | 912 | ) |
910 | 913 |
|
911 | | - def __getitem__( |
912 | | - self, |
913 | | - index: Index1D | Index2D | str, |
914 | | - ) -> KeyPoints | npt.NDArray[np.generic] | list[Any] | None: |
915 | | - """ |
916 | | - Get a subset of the KeyPoints object or access an item from its data field. |
917 | | -
|
918 | | - Supports detection-level (skeleton) filtering, keypoint-level (anchor) |
919 | | - filtering, combined tuple indexing, and data field access by string key. |
| 914 | + def get_data(self, key: str) -> _DetectionDataValueType | None: |
| 915 | + """Get a value from the keypoint data dictionary. |
920 | 916 |
|
921 | 917 | Args: |
922 | | - index: The index, indices, or key to access a subset of the KeyPoints |
923 | | - or an item from the data. |
| 918 | + key: Data field name. |
924 | 919 |
|
925 | 920 | Returns: |
926 | | - A subset of the KeyPoints object or an item from the data field. |
927 | | -
|
928 | | - Examples: |
929 | | - ```python |
930 | | - import supervision as sv |
| 921 | + The stored data value, or `None` when the key is absent. |
931 | 922 |
|
932 | | - key_points = sv.KeyPoints(...) |
| 923 | + Example: |
| 924 | + >>> import numpy as np |
| 925 | + >>> from supervision import KeyPoints |
| 926 | + >>> key_points = KeyPoints( |
| 927 | + ... xy=np.array([[[0, 0]]]), |
| 928 | + ... data={"class_name": np.array(["person"])}, |
| 929 | + ... ) |
| 930 | + >>> key_points.get_data("class_name").tolist() |
| 931 | + ['person'] |
| 932 | + """ |
| 933 | + return self.data.get(key) |
933 | 934 |
|
934 | | - # detection-level filtering (returns KeyPoints) |
935 | | - high_conf = key_points[key_points.detection_confidence > 0.5] |
936 | | - class_0 = key_points[key_points.class_id == 0] |
| 935 | + def select( |
| 936 | + self, |
| 937 | + index: Index1D | Index2D, |
| 938 | + ) -> KeyPoints: |
| 939 | + """Get a subset of the KeyPoints object. |
937 | 940 |
|
938 | | - # keypoint-level filtering (returns KeyPoints) |
939 | | - visible = key_points[key_points.keypoint_confidence > 0.3] |
| 941 | + Supports detection-level (skeleton) filtering, keypoint-level (anchor) |
| 942 | + filtering, and combined tuple indexing. |
940 | 943 |
|
941 | | - # indexing |
942 | | - first = key_points[0] |
943 | | - first_two = key_points[0:2] |
944 | | - subset = key_points[[0, 2]] |
| 944 | + Args: |
| 945 | + index: Index, indices, slice, or boolean mask selecting key points. |
945 | 946 |
|
946 | | - # anchor selection (uniform across all skeletons) |
947 | | - nose_and_eyes = key_points[:, [0, 1, 2]] |
| 947 | + Returns: |
| 948 | + A new `KeyPoints` instance containing the selected rows or anchors. |
948 | 949 |
|
949 | | - # data field access |
950 | | - class_names = key_points['class_name'] |
951 | | - ``` |
| 950 | + Example: |
| 951 | + >>> import numpy as np |
| 952 | + >>> from supervision import KeyPoints |
| 953 | + >>> key_points = KeyPoints(xy=np.array([[[0, 1]], [[2, 3]]])) |
| 954 | + >>> key_points.select([1]).xy.tolist() |
| 955 | + [[[2, 3]]] |
952 | 956 | """ |
953 | | - if isinstance(index, str): |
954 | | - return self.data.get(index) |
955 | | - |
956 | 957 | if isinstance(index, np.ndarray) and index.ndim == 2 and index.dtype == bool: |
957 | 958 | return self._get_by_2d_bool_mask(cast(npt.NDArray[np.bool_], index)) |
958 | 959 |
|
@@ -1045,6 +1046,52 @@ def __getitem__( |
1045 | 1046 | data=data_selected, |
1046 | 1047 | ) |
1047 | 1048 |
|
| 1049 | + def __getitem__( |
| 1050 | + self, |
| 1051 | + index: Index1D | Index2D | str, |
| 1052 | + ) -> KeyPoints | npt.NDArray[np.generic] | list[Any] | None: |
| 1053 | + """ |
| 1054 | + Get a subset of the KeyPoints object or access an item from its data field. |
| 1055 | +
|
| 1056 | + Supports detection-level (skeleton) filtering, keypoint-level (anchor) |
| 1057 | + filtering, combined tuple indexing, and data field access by string key. |
| 1058 | +
|
| 1059 | + Args: |
| 1060 | + index: The index, indices, or key to access a subset of the KeyPoints |
| 1061 | + or an item from the data. |
| 1062 | +
|
| 1063 | + Returns: |
| 1064 | + A subset of the KeyPoints object or an item from the data field. |
| 1065 | +
|
| 1066 | + Examples: |
| 1067 | + ```python |
| 1068 | + import supervision as sv |
| 1069 | +
|
| 1070 | + key_points = sv.KeyPoints(...) |
| 1071 | +
|
| 1072 | + # detection-level filtering (returns KeyPoints) |
| 1073 | + high_conf = key_points[key_points.detection_confidence > 0.5] |
| 1074 | + class_0 = key_points[key_points.class_id == 0] |
| 1075 | +
|
| 1076 | + # keypoint-level filtering (returns KeyPoints) |
| 1077 | + visible = key_points[key_points.keypoint_confidence > 0.3] |
| 1078 | +
|
| 1079 | + # indexing |
| 1080 | + first = key_points[0] |
| 1081 | + first_two = key_points[0:2] |
| 1082 | + subset = key_points[[0, 2]] |
| 1083 | +
|
| 1084 | + # anchor selection (uniform across all skeletons) |
| 1085 | + nose_and_eyes = key_points[:, [0, 1, 2]] |
| 1086 | +
|
| 1087 | + # data field access |
| 1088 | + class_names = key_points['class_name'] |
| 1089 | + ``` |
| 1090 | + """ |
| 1091 | + if isinstance(index, str): |
| 1092 | + return self.get_data(index) |
| 1093 | + return self.select(index) |
| 1094 | + |
1048 | 1095 | def __setitem__(self, key: str, value: npt.NDArray[np.generic] | list[Any]) -> None: |
1049 | 1096 | """ |
1050 | 1097 | Set a value in the data dictionary of the `sv.KeyPoints` object. |
@@ -1205,7 +1252,7 @@ def with_nms( |
1205 | 1252 | overlap_metric=overlap_metric, |
1206 | 1253 | ) |
1207 | 1254 |
|
1208 | | - return cast(KeyPoints, self[keep]) |
| 1255 | + return self.select(keep) |
1209 | 1256 |
|
1210 | 1257 | def as_detections( |
1211 | 1258 | self, selected_keypoint_indices: Iterable[int] | None = None |
@@ -1275,6 +1322,6 @@ def as_detections( |
1275 | 1322 | detections = Detections(xyxy=xyxy, confidence=confidence) |
1276 | 1323 | detections.class_id = self.class_id |
1277 | 1324 | detections.data = self.data |
1278 | | - detections = cast(Detections, detections[cast(Any, detections.area) > 0]) |
| 1325 | + detections = detections.select(cast(Any, detections.area) > 0) |
1279 | 1326 |
|
1280 | 1327 | return detections |
0 commit comments