def test_many_tracks_hdf5(tmpdir): labels = Labels() filename = os.path.join(tmpdir, "test.h5") labels.tracks = [Track(spawned_on=i, name=f"track {i}") for i in range(4000)] Labels.save_hdf5(filename=filename, labels=labels)
def run_tracker(frames, tracker): sig = inspect.signature(tracker.track) takes_img = "img" in sig.parameters # t0 = time.time() new_lfs = [] # Run tracking on every frame for lf in frames: # Clear the tracks for inst in lf.instances: inst.track = None track_args = dict(untracked_instances=lf.instances) if takes_img: track_args["img"] = lf.video[lf.frame_idx] else: track_args["img"] = None new_lf = LabeledFrame( frame_idx=lf.frame_idx, video=lf.video, instances=tracker.track(**track_args), ) new_lfs.append(new_lf) # if lf.frame_idx % 100 == 0: print(lf.frame_idx, time.time()-t0) # print(time.time() - t0) new_labels = Labels() new_labels.extend(new_lfs) return new_labels
def test_many_videos_hdf5(tmpdir): labels = Labels() filename = os.path.join(tmpdir, "test.h5") labels.videos = [Video.from_filename(f"video {i}.mp4") for i in range(3000)] Labels.save_hdf5(filename=filename, labels=labels)
def loadProjectFile(self, filename: Optional[str] = None): """ Loads given labels file into GUI. Args: filename: The path to the saved labels dataset. If None, then don't do anything. Returns: None: """ if len(filename) == 0: return gui_video_callback = Labels.make_gui_video_callback( search_paths=[os.path.dirname(filename)]) has_loaded = False labels = None if type(filename) == Labels: labels = filename filename = None has_loaded = True else: try: labels = Labels.load_file(filename, video_search=gui_video_callback) has_loaded = True except ValueError as e: print(e) QMessageBox(text=f"Unable to load {filename}.").exec_() if has_loaded: self.loadLabelsObject(labels, filename)
def test_save_labels_with_frame_data(multi_skel_vid_labels, tmpdir, format): """ Test saving and loading a labels dataset with frame data included as JSON. """ # Lets take a subset of the labels so this doesn't take too long multi_skel_vid_labels.labeled_frames = multi_skel_vid_labels.labeled_frames[ 5:30] filename = os.path.join(tmpdir, "test.json") Labels.save_json( multi_skel_vid_labels, filename=filename, save_frame_data=True, frame_data_format=format, ) # Load the data back in loaded_labels = Labels.load_json(f"{filename}.zip") # Check that we have the same thing _check_labels_match(multi_skel_vid_labels, loaded_labels, format=format) # Make sure we can load twice loaded_labels = Labels.load_json(f"{filename}.zip")
def test_labels_json(tmpdir, multi_skel_vid_labels): json_file_path = os.path.join(tmpdir, "dataset.json") if os.path.isfile(json_file_path): os.remove(json_file_path) # Save to json Labels.save_json(labels=multi_skel_vid_labels, filename=json_file_path) # Make sure the filename is there assert os.path.isfile(json_file_path) # Lets load the labels back in and make sure we haven't lost anything. loaded_labels = Labels.load_json(json_file_path) # Check that we have the same thing _check_labels_match(multi_skel_vid_labels, loaded_labels) # Check that we don't have the very same objects assert not multi_skel_vid_labels.skeletons[0] is loaded_labels.skeletons[0] assert not multi_skel_vid_labels.nodes[3] in loaded_labels.nodes assert not multi_skel_vid_labels.videos[0] is loaded_labels.videos[0] # Reload json using objects from original labels # We'll also test load_file() here loaded_labels = Labels.load_file(json_file_path, match_to=multi_skel_vid_labels) # Check that we now do have the same objects assert multi_skel_vid_labels.skeletons[0] in loaded_labels.skeletons assert multi_skel_vid_labels.nodes[3] in loaded_labels.nodes assert multi_skel_vid_labels.videos[0] in loaded_labels.videos
def test_hdf5_empty_save(tmpdir): labels = Labels() filename = os.path.join(tmpdir, "test.h5") Labels.save_hdf5(filename=filename, labels=labels) dummy_video = Video.from_filename("foo.mp4") labels.videos.append(dummy_video) Labels.save_hdf5(filename=filename, labels=labels)
def test_labels_hdf5(multi_skel_vid_labels, tmpdir): labels = multi_skel_vid_labels filename = os.path.join(tmpdir, "test.h5") Labels.save_hdf5(filename=filename, labels=labels) loaded_labels = Labels.load_hdf5(filename=filename) _check_labels_match(labels, loaded_labels)
def test_load_labels_json_old(tmpdir): new_file_path = os.path.join(tmpdir, "centered_pair_v2.json") # Function to run some checks on loaded labels def check_labels(labels): skel_node_names = [ "head", "neck", "thorax", "abdomen", "wingL", "wingR", "forelegL1", "forelegL2", "forelegL3", "forelegR1", "forelegR2", "forelegR3", "midlegL1", "midlegL2", "midlegL3", "midlegR1", "midlegR2", "midlegR3", "hindlegL1", "hindlegL2", "hindlegL3", "hindlegR1", "hindlegR2", "hindlegR3", ] # Do some basic checks assert len(labels) == 70 # Make sure we only create one video object and it works assert len({label.video for label in labels}) == 1 assert labels[0].video.get_frame(0).shape == (384, 384, 1) # Check some frame objects. assert labels[0].frame_idx == 0 assert labels[40].frame_idx == 573 # Check the skeleton assert labels[0].instances[0].skeleton.node_names == skel_node_names labels = Labels.load_json("tests/data/json_format_v1/centered_pair.json") check_labels(labels) # Save out to new JSON format Labels.save_json(labels, new_file_path) # Reload and check again. new_labels = Labels.load_json(new_file_path) check_labels(new_labels)
def test_local_path_save(tmpdir, monkeypatch): filename = "test.h5" # Set current working directory (monkeypatch isolates other tests) monkeypatch.chdir(tmpdir) # Try saving with relative path Labels.save_file(filename=filename, labels=Labels()) assert os.path.exists(os.path.join(tmpdir, filename))
def test_duplicate_skeletons_serializing(): vid = Video.from_filename("foo.mp4") skeleton_a = Skeleton.load_json("tests/data/skeleton/fly_skeleton_legs.json") skeleton_b = Skeleton.load_json("tests/data/skeleton/fly_skeleton_legs.json") lf_a = LabeledFrame(vid, frame_idx=2, instances=[Instance(skeleton_a)]) lf_b = LabeledFrame(vid, frame_idx=3, instances=[Instance(skeleton_b)]) new_labels = Labels(labeled_frames=[lf_a, lf_b]) new_labels_json = new_labels.to_dict()
def test_instance_access(): labels = Labels() dummy_skeleton = Skeleton() dummy_video = Video(backend=MediaVideo) dummy_video2 = Video(backend=MediaVideo) for i in range(10): labels.append( LabeledFrame( dummy_video, frame_idx=i, instances=[Instance(dummy_skeleton), Instance(dummy_skeleton)], )) for i in range(10): labels.append( LabeledFrame( dummy_video2, frame_idx=i, instances=[ Instance(dummy_skeleton), Instance(dummy_skeleton), Instance(dummy_skeleton), ], )) assert len(labels.all_instances) == 50 assert len(list(labels.instances(video=dummy_video))) == 20 assert len(list(labels.instances(video=dummy_video2))) == 30
def test_distinct_skeletons_serializing(): vid = Video.from_filename("foo.mp4") skeleton_a = Skeleton.load_json("tests/data/skeleton/fly_skeleton_legs.json") skeleton_b = Skeleton.load_json("tests/data/skeleton/fly_skeleton_legs.json") skeleton_b.add_node("foo") lf_a = LabeledFrame(vid, frame_idx=2, instances=[Instance(skeleton_a)]) lf_b = LabeledFrame(vid, frame_idx=3, instances=[Instance(skeleton_b)]) new_labels = Labels(labeled_frames=[lf_a, lf_b]) # Make sure we can serialize this new_labels_json = new_labels.to_dict()
def test_has_missing_videos(): labels = Labels() labels.add_video(Video.from_filename("small_robot.mp4")) assert labels.has_missing_videos labels = Labels() labels.add_video(Video.from_filename("tests/data/videos/small_robot.mp4")) assert not labels.has_missing_videos
def main(): import argparse parser = argparse.ArgumentParser() parser.add_argument("data_path", help="Path to labels json file") args = parser.parse_args() video_callback = Labels.make_video_callback( [os.path.dirname(args.data_path)]) labels = Labels.load_file(args.data_path, video_search=video_callback) print(f"Labeled frames: {len(labels)}") print(f"Tracks: {len(labels.tracks)}") print(f"Video files:") total_user_frames = 0 for vid in labels.videos: lfs = labels.find(vid) first_idx = min((lf.frame_idx for lf in lfs)) last_idx = max((lf.frame_idx for lf in lfs)) tracks = {inst.track for lf in lfs for inst in lf} concurrent_count = max((len(lf.instances) for lf in lfs)) user_frames = labels.get_labeled_frame_count(vid, "user") total_user_frames += user_frames print(f" {vid.filename}") print(f" labeled frames from {first_idx} to {last_idx}") print(f" labeled frames: {len(lfs)}") print(f" user labeled frames: {user_frames}") print(f" tracks: {len(tracks)}") print(f" max instances in frame: {concurrent_count}") print(f"Total user labeled frames: {total_user_frames}") if labels.provenance: print() print(f"Provenance:") for key, value in labels.provenance.items(): print(f" {key}: {value}")
def test_labels_append_hdf5(multi_skel_vid_labels, tmpdir): labels = multi_skel_vid_labels filename = os.path.join(tmpdir, "test.h5") # Save each frame of the Labels dataset one by one in append # mode for label in labels: # Just do the first 20 to speed things up if label.frame_idx > 20: break Labels.save_hdf5(filename=filename, labels=Labels([label]), append=True) # Now load the dataset and make sure we get the same thing we started # with. loaded_labels = Labels.load_hdf5(filename=filename) _check_labels_match(labels, loaded_labels)
def test_hdf5_from_predicted(multi_skel_vid_labels, tmpdir): labels = multi_skel_vid_labels filename = os.path.join(tmpdir, "test.h5") # Add some predicted instances to create from_predicted links for frame_num, frame in enumerate(labels): if frame_num % 20 == 0: frame.instances[ 0].from_predicted = PredictedInstance.from_instance( frame.instances[0], float(frame_num)) frame.instances.append(frame.instances[0].from_predicted) # Save and load, compare the results Labels.save_hdf5(filename=filename, labels=labels) loaded_labels = Labels.load_hdf5(filename=filename) for frame_num, frame in enumerate(loaded_labels): if frame_num % 20 == 0: assert frame.instances[0].from_predicted.score == float(frame_num)
def test_save_labels_and_frames_hdf5(multi_skel_vid_labels, tmpdir): # Lets take a subset of the labels so this doesn't take too long labels = multi_skel_vid_labels labels.labeled_frames = labels.labeled_frames[5:30] filename = os.path.join(tmpdir, "test.h5") Labels.save_hdf5(filename=filename, labels=labels, save_frame_data=True) loaded_labels = Labels.load_hdf5(filename=filename) _check_labels_match(labels, loaded_labels) # Rename file (after closing videos) for vid in loaded_labels.videos: vid.close() filerename = os.path.join(tmpdir, "test_rename.h5") os.rename(filename, filerename) # Make sure we open can after rename loaded_labels = Labels.load_hdf5(filename=filerename)
def test_labels_merge(): dummy_video = Video(backend=MediaVideo) dummy_skeleton = Skeleton() dummy_skeleton.add_node("node") labels = Labels() dummy_frames = [] # Add 10 instances with different points (so they aren't "redundant") for i in range(10): instance = Instance(skeleton=dummy_skeleton, points=dict(node=Point(i, i))) dummy_frame = LabeledFrame(dummy_video, frame_idx=0, instances=[instance]) dummy_frames.append(dummy_frame) labels.labeled_frames.extend(dummy_frames) assert len(labels) == 10 assert len(labels.labeled_frames[0].instances) == 1 labels.merge_matching_frames() assert len(labels) == 1 assert len(labels.labeled_frames[0].instances) == 10
def test_multivideo_tracks(): vid_a = Video.from_filename("foo.mp4") vid_b = Video.from_filename("bar.mp4") skeleton = Skeleton.load_json("tests/data/skeleton/fly_skeleton_legs.json") track_a = Track(spawned_on=2, name="A") track_b = Track(spawned_on=3, name="B") inst_a = Instance(track=track_a, skeleton=skeleton) inst_b = Instance(track=track_b, skeleton=skeleton) lf_a = LabeledFrame(vid_a, frame_idx=2, instances=[inst_a]) lf_b = LabeledFrame(vid_b, frame_idx=3, instances=[inst_b]) labels = Labels(labeled_frames=[lf_a, lf_b]) # Try setting video B instance to track used in video A labels.track_swap(vid_b, new_track=track_a, old_track=track_b, frame_range=(3, 4)) assert inst_b.track == track_a
def test_merge_predictions(): dummy_video_a = Video.from_filename("foo.mp4") dummy_video_b = Video.from_filename("foo.mp4") dummy_skeleton_a = Skeleton() dummy_skeleton_a.add_node("node") dummy_skeleton_b = Skeleton() dummy_skeleton_b.add_node("node") dummy_instances_a = [] dummy_instances_a.append( Instance(skeleton=dummy_skeleton_a, points=dict(node=Point(1, 1))) ) dummy_instances_a.append( Instance(skeleton=dummy_skeleton_a, points=dict(node=Point(2, 2))) ) labels_a = Labels() labels_a.append( LabeledFrame(dummy_video_a, frame_idx=0, instances=dummy_instances_a) ) dummy_instances_b = [] dummy_instances_b.append( Instance(skeleton=dummy_skeleton_b, points=dict(node=Point(1, 1))) ) dummy_instances_b.append( PredictedInstance( skeleton=dummy_skeleton_b, points=dict(node=Point(3, 3)), score=1 ) ) labels_b = Labels() labels_b.append( LabeledFrame(dummy_video_b, frame_idx=0, instances=dummy_instances_b) ) # Frames have one redundant instance (perfect match) and all the # non-matching instances are different types (one predicted, one not). merged, extra_a, extra_b = Labels.complex_merge_between(labels_a, labels_b) assert len(merged[dummy_video_a]) == 1 assert len(merged[dummy_video_a][0]) == 1 # the predicted instance was merged assert not extra_a assert not extra_b
def finishMerge(self): """ Finishes merge process, possibly resolving conflicts. This is connected to `accepted` signal. Args: None. Raises: ValueError: If no valid merge method was selected in dialog. Returns: None. """ merge_method = self.merge_method.currentText() if merge_method == USE_BASE_STRING: Labels.finish_complex_merge(self.base_labels, self.extra_base) elif merge_method == USE_NEW_STRING: Labels.finish_complex_merge(self.base_labels, self.extra_new) elif merge_method in (USE_NEITHER_STRING, CLEAN_STRING): Labels.finish_complex_merge(self.base_labels, []) else: raise ValueError("No valid merge method selected.") self.accept()
def test_labels_predicted_hdf5(multi_skel_vid_labels, tmpdir): labels = multi_skel_vid_labels filename = os.path.join(tmpdir, "test.h5") # Lets promote some of these Instances to predicted instances for label in labels: for i, instance in enumerate(label.instances): if i % 2 == 0: label.instances[i] = PredictedInstance.from_instance( instance, 0.3) # Lets also add some from_predicted values for label in labels: label.instances[1].from_predicted = label.instances[0] # Try adding a node to the skeleton labels.skeletons[0].add_node("new node") # Save and compare the results Labels.save_hdf5(filename=filename, labels=labels) loaded_labels = Labels.load_hdf5(filename=filename) _check_labels_match(labels, loaded_labels) # Try deleting nodes from the skeleton node = labels.skeletons[0].nodes[-1] labels.skeletons[0].delete_node(node) node = labels.skeletons[0].nodes[-1] labels.skeletons[0].delete_node(node) # Save and compare the results Labels.save_hdf5(filename=filename, labels=labels) loaded_labels = Labels.load_hdf5(filename=filename) _check_labels_match(labels, loaded_labels)
def __init__(self, labels_path: Optional[str] = None, *args, **kwargs): """Initialize the app. Args: labels_path: Path to saved :class:`Labels` dataset. Returns: None. """ super(MainWindow, self).__init__(*args, **kwargs) self.state = GuiState() self.labels = Labels() self.commands = CommandContext(state=self.state, app=self, update_callback=self.on_data_update) self._menu_actions = dict() self._buttons = dict() self._child_windows = dict() self.overlays = dict() self.state.connect("filename", self.setWindowTitle) self.state["skeleton"] = Skeleton() self.state["labeled_frame"] = None self.state["filename"] = None self.state["show labels"] = True self.state["show edges"] = True self.state["edge style"] = "Line" self.state["fit"] = False self.state["color predicted"] = prefs["color predicted"] self._initialize_gui() if labels_path: self.loadProjectFile(labels_path)
def test_provenance(tmpdir): labels = Labels(provenance=dict(source="test_provenance")) filename = os.path.join(tmpdir, "test.slp") # Add a video without a full path labels.add_video(Video.from_filename("small_robot.mp4")) Labels.save_file(filename=filename, labels=labels) labels = Labels.load_file(filename) print(labels.provenance) assert labels.provenance["source"] == "test_provenance"
def test_many_suggestions_hdf5(tmpdir): labels = Labels() filename = os.path.join(tmpdir, "test.h5") video = Video.from_filename("foo.mp4") labels.videos = [video] labels.suggestions = [SuggestionFrame(video, i) for i in range(3000)] Labels.save_hdf5(filename=filename, labels=labels)
def multi_skel_vid_labels(hdf5_vid, small_robot_mp4_vid, skeleton, stickman): """ Build a big list of LabeledFrame objects and wrap it in Labels class. Args: hdf5_vid: An HDF5 video fixture small_robot_mp4_vid: An MP4 video fixture skeleton: A fly skeleton. stickman: A stickman skeleton Returns: The Labels object containing all the labeled frames """ labels = [] stick_tracks = [ Track(spawned_on=0, name=f"Stickman {i}") for i in range(6) ] fly_tracks = [Track(spawned_on=0, name=f"Fly {i}") for i in range(6)] # Make some tracks None to test that fly_tracks[3] = None stick_tracks[2] = None for f in range(500): vid = [hdf5_vid, small_robot_mp4_vid][f % 2] label = LabeledFrame(video=vid, frame_idx=f % vid.frames) fly_instances = [] for i in range(6): fly_instances.append( Instance(skeleton=skeleton, track=fly_tracks[i])) for node in skeleton.nodes: fly_instances[i][node] = Point(x=i % vid.width, y=i % vid.height) stickman_instances = [] for i in range(6): stickman_instances.append( Instance(skeleton=stickman, track=stick_tracks[i])) for node in stickman.nodes: stickman_instances[i][node] = Point(x=i % vid.width, y=i % vid.height) label.instances = stickman_instances + fly_instances labels.append(label) labels = Labels(labels) return labels
def simple_predictions(): video = Video.from_filename("video.mp4") skeleton = Skeleton() skeleton.add_node("a") skeleton.add_node("b") track_a = Track(0, "a") track_b = Track(0, "b") labels = Labels() instances = [] instances.append( PredictedInstance( skeleton=skeleton, score=2, track=track_a, points=dict(a=PredictedPoint(1, 1, score=0.5), b=PredictedPoint(1, 1, score=0.5)), )) instances.append( PredictedInstance( skeleton=skeleton, score=5, track=track_b, points=dict(a=PredictedPoint(1, 1, score=0.7), b=PredictedPoint(1, 1, score=0.7)), )) labeled_frame = LabeledFrame(video, frame_idx=0, instances=instances) labels.append(labeled_frame) instances = [] instances.append( PredictedInstance( skeleton=skeleton, score=3, track=track_a, points=dict(a=PredictedPoint(4, 5, score=1.5), b=PredictedPoint(1, 1, score=1.0)), )) instances.append( PredictedInstance( skeleton=skeleton, score=6, track=track_b, points=dict(a=PredictedPoint(6, 13, score=1.7), b=PredictedPoint(1, 1, score=1.0)), )) labeled_frame = LabeledFrame(video, frame_idx=1, instances=instances) labels.append(labeled_frame) return labels
def removal_test_labels(): skeleton = Skeleton() video = Video(backend=MediaVideo) lf_user_only = LabeledFrame( video=video, frame_idx=0, instances=[Instance(skeleton=skeleton)] ) lf_pred_only = LabeledFrame( video=video, frame_idx=1, instances=[PredictedInstance(skeleton=skeleton)] ) lf_both = LabeledFrame( video=video, frame_idx=2, instances=[Instance(skeleton=skeleton), PredictedInstance(skeleton=skeleton)], ) labels = Labels([lf_user_only, lf_pred_only, lf_both]) return labels
def test_deserialize_suggestions(small_robot_mp4_vid, tmpdir): dummy_video = small_robot_mp4_vid dummy_skeleton = Skeleton() dummy_instance = Instance(dummy_skeleton) dummy_frame = LabeledFrame(dummy_video, frame_idx=0, instances=[dummy_instance]) labels = Labels() labels.append(dummy_frame) suggestions = VideoFrameSuggestions.suggest( labels=labels, params=dict(method="sample", per_video=13) ) labels.set_suggestions(suggestions) filename = os.path.join(tmpdir, "new_suggestions.h5") Labels.save_file(filename=filename, labels=labels) new_suggestion_labels = Labels.load_file(filename) assert len(suggestions) == len(new_suggestion_labels.suggestions) assert [frame.frame_idx for frame in suggestions] == [ frame.frame_idx for frame in new_suggestion_labels.suggestions ]