MCPcopy Create free account
hub / github.com/PolyU-ChenLab/UniPixel / remove_object

Method remove_object

sam2/sam2_video_predictor.py:936–1012  ·  view source on GitHub ↗

Remove an object id from the tracking state. If strict is True, we check whether the object id actually exists and raise an error if it doesn't exist.

(self, inference_state, obj_id, strict=False, need_output=True)

Source from the content-addressed store, hash-verified

934
935 @torch.inference_mode()
936 def remove_object(self, inference_state, obj_id, strict=False, need_output=True):
937 """
938 Remove an object id from the tracking state. If strict is True, we check whether
939 the object id actually exists and raise an error if it doesn't exist.
940 """
941 old_obj_idx_to_rm = inference_state["obj_id_to_idx"].get(obj_id, None)
942 updated_frames = []
943 # Check whether this object_id to remove actually exists and possibly raise an error.
944 if old_obj_idx_to_rm is None:
945 if not strict:
946 return inference_state["obj_ids"], updated_frames
947 raise RuntimeError(f"Cannot remove object id {obj_id} as it doesn't exist. "
948 f"All existing object ids: {inference_state['obj_ids']}.")
949
950 # If this is the only remaining object id, we simply reset the state.
951 if len(inference_state["obj_id_to_idx"]) == 1:
952 self.reset_state(inference_state)
953 return inference_state["obj_ids"], updated_frames
954
955 # There are still remaining objects after removing this object id. In this case,
956 # we need to delete the object storage from inference state tensors.
957 # Step 0: clear the input on those frames where this object id has point or mask input
958 # (note that this step is required as it might downgrade conditioning frames to
959 # non-conditioning ones)
960 obj_input_frames_inds = set()
961 obj_input_frames_inds.update(inference_state["point_inputs_per_obj"][old_obj_idx_to_rm])
962 obj_input_frames_inds.update(inference_state["mask_inputs_per_obj"][old_obj_idx_to_rm])
963 for frame_idx in obj_input_frames_inds:
964 self.clear_all_prompts_in_frame(inference_state, frame_idx, obj_id, need_output=False)
965
966 # Step 1: Update the object id mapping (note that it must be done after Step 0,
967 # since Step 0 still requires the old object id mappings in inference_state)
968 old_obj_ids = inference_state["obj_ids"]
969 old_obj_inds = list(range(len(old_obj_ids)))
970 remain_old_obj_inds = old_obj_inds.copy()
971 remain_old_obj_inds.remove(old_obj_idx_to_rm)
972 new_obj_ids = [old_obj_ids[old_idx] for old_idx in remain_old_obj_inds]
973 new_obj_inds = list(range(len(new_obj_ids)))
974 # build new mappings
975 old_idx_to_new_idx = dict(zip(remain_old_obj_inds, new_obj_inds))
976 inference_state["obj_id_to_idx"] = dict(zip(new_obj_ids, new_obj_inds))
977 inference_state["obj_idx_to_id"] = dict(zip(new_obj_inds, new_obj_ids))
978 inference_state["obj_ids"] = new_obj_ids
979
980 # Step 2: For per-object tensor storage, we shift their obj_idx in the dict keys.
981 def _map_keys(container):
982 new_kvs = []
983 for k in old_obj_inds:
984 v = container.pop(k)
985 if k in old_idx_to_new_idx:
986 new_kvs.append((old_idx_to_new_idx[k], v))
987 container.update(new_kvs)
988
989 _map_keys(inference_state["point_inputs_per_obj"])
990 _map_keys(inference_state["mask_inputs_per_obj"])
991 _map_keys(inference_state["output_dict_per_obj"])
992 _map_keys(inference_state["temp_output_dict_per_obj"])
993 _map_keys(inference_state["frames_tracked_per_obj"])

Callers

nothing calls this directly

Tested by

no test coverage detected