-
Notifications
You must be signed in to change notification settings - Fork 14
Open
Description
Right now, LabeledFrame objects in Labels are stored in arbitrary order and may have gaps.
Often, we need to access labeled frames by the video frame index, which we do via this logic:
sleap-io/sleap_io/model/labels.py
Lines 97 to 106 in de9da79
| elif type(key) == tuple and len(key) == 2: | |
| video, frame_idx = key | |
| res = self.find(video, frame_idx) | |
| if len(res) == 1: | |
| return res[0] | |
| elif len(res) == 0: | |
| raise IndexError( | |
| f"No labeled frames found for video {video} and " | |
| f"frame index {frame_idx}." | |
| ) |
sleap-io/sleap_io/model/labels.py
Lines 296 to 340 in de9da79
| def find( | |
| self, | |
| video: Video, | |
| frame_idx: int | list[int] | None = None, | |
| return_new: bool = False, | |
| ) -> list[LabeledFrame]: | |
| """Search for labeled frames given video and/or frame index. | |
| Args: | |
| video: A `Video` that is associated with the project. | |
| frame_idx: The frame index (or indices) which we want to find in the video. | |
| If a range is specified, we'll return all frames with indices in that | |
| range. If not specific, then we'll return all labeled frames for video. | |
| return_new: Whether to return singleton of new and empty `LabeledFrame` if | |
| none are found in project. | |
| Returns: | |
| List of `LabeledFrame` objects that match the criteria. | |
| The list will be empty if no matches found, unless return_new is True, in | |
| which case it contains new (empty) `LabeledFrame` objects with `video` and | |
| `frame_index` set. | |
| """ | |
| results = [] | |
| if frame_idx is None: | |
| for lf in self.labeled_frames: | |
| if lf.video == video: | |
| results.append(lf) | |
| return results | |
| if np.isscalar(frame_idx): | |
| frame_idx = np.array(frame_idx).reshape(-1) | |
| for frame_ind in frame_idx: | |
| result = None | |
| for lf in self.labeled_frames: | |
| if lf.video == video and lf.frame_idx == frame_ind: | |
| result = lf | |
| results.append(result) | |
| break | |
| if result is None and return_new: | |
| results.append(LabeledFrame(video=video, frame_idx=frame_ind)) | |
| return results |
It would be great to have a cache (and ideally a more convenient accessor (e.g., labels.frame[frame_idx] for single video labels) for these cases.
While keeping the cache in sync is a bigger headache, we can follow the recipes in #135 and #136 for explicit control as an escape hatch.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels