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)
| 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"]) |
nothing calls this directly
no test coverage detected