Skip to content

Commit

Permalink
(3a -> 3) Add method to match instances across views (#1579)
Browse files Browse the repository at this point in the history
* Update  methods to allow triangulating multiple instances at once

* Return instances and coords as a dictionary with cams

* Update get_instance_across_views to handle multiple frames

* [wip] Update calculate reprojected points to support multiple frames

* Finish support for multi-frame reprojection

* Remove code to put in next PR

* (3b -> 3a) Add method to get single instance permutations (#1586)

* Add method to get single instance permutations

* Append a dummy instance for missing instances

* Correct 'permutations' to 'products'

* (3c -> 3b) Add method to test instance grouping (#1599)

* (3d -> 3c) Add method for multi instance products (#1605)

* (3e -> 3a) Add `InstanceGroup` class (#1618)

* Add method to get single instance permutations

* Add method and (failing) test to get instance grouping

* Append a dummy instance for missing instances

* Update tests to accept a dummy instance

* Add initial InstanceGroup class

* Few extra tests for `InstanceGroup`

* Remember instance grouping after testing hypotheses

* Use reconsumable iterator for reprojected coords

* Only triangulate user instances, add fixture, update tests

* Normalize instance reprojection errors

* Add `locked`, `_dummy_instance`, `numpy`, and `update_points`

* Allow `PredictedPoint`s to be updated as well

* Add tests for new attributes and methods

* Add methods to create, add, replace, and remove instances

* Use PredictedInstance for new/dummy instances

* (3f -> 3e) Add `FrameGroup` class  (#1665)

* (3g -> 3f) Use frame group for triangulation (#1693)

* Only use user-`Instance`s for triangulation

* Remove unused code

* Use `LabeledFrame` class instead of dummy labeled frame

* Limit which methods can update `Labels.labeled_frames`

* Update cache when Labels. remove_session_video

* Remove RecordingSession.instance_groups

* [wip] Maintain cached FrameGroup dictionaries

* Add unique name (per FrameGroup) requirement for InstanceGroup

* Lint

* Fix remove_video bug

* Add RecordingSession.new_frame_group method

* Add TODO comments for later

* Fix RecordingSesssion.remove_video bug

* Remove FrameGroup._frame_idx_registry class attribute
  • Loading branch information
roomrys authored Apr 18, 2024
1 parent a2326d3 commit 2f56a1c
Show file tree
Hide file tree
Showing 10 changed files with 1,607 additions and 746 deletions.
461 changes: 83 additions & 378 deletions sleap/gui/commands.py

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion sleap/gui/dialogs/delete.py
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ def _delete(self, lf_inst_list: List[Tuple[LabeledFrame, Instance]]):
for lf, inst in lf_inst_list:
self.context.labels.remove_instance(lf, inst, in_transaction=True)
if not lf.instances:
self.context.labels.remove(lf)
self.context.labels.remove_frame(lf=lf, update_cache=False)

# Update caches since we skipped doing this after each deletion
self.context.labels.update_cache()
Expand Down
25 changes: 23 additions & 2 deletions sleap/instance.py
Original file line number Diff line number Diff line change
Expand Up @@ -500,7 +500,6 @@ def _points_dict_to_array(
)
try:
parray[skeleton.node_to_index(node)] = point
# parray[skeleton.node_to_index(node.name)] = point
except:
logger.debug(
f"Could not set point for node {node} in {skeleton} "
Expand Down Expand Up @@ -729,9 +728,31 @@ def update_points(self, points: np.ndarray, exclude_complete: bool = False):
for point_new, points_old, node_name in zip(
points, self._points, self.skeleton.node_names
):

# Skip if new point is nan or old point is complete
if np.isnan(point_new).any() or (exclude_complete and points_old.complete):
continue
points_dict[node_name] = Point(x=point_new[0], y=point_new[1])

# Grab the x, y from the new point and visible, complete from the old point
x, y = point_new
visible = points_old.visible
complete = points_old.complete

# Create a new point and add to the dict
if type(self._points) == PredictedPointArray:
# TODO(LM): The point score is meant to rate the confidence of the
# prediction, but this method updates from triangulation.
score = points_old.score
point_obj = PredictedPoint(
x=x, y=y, visible=visible, complete=complete, score=score
)
else:
point_obj = Point(x=x, y=y, visible=visible, complete=complete)

# Update the points dict
points_dict[node_name] = point_obj

# Update the points
if len(points_dict) > 0:
Instance._points_dict_to_array(points_dict, self._points, self.skeleton)

Expand Down
Loading

0 comments on commit 2f56a1c

Please sign in to comment.