def test_save_frame_data_hdf5(min_labels_slp, tmpdir): labels = Labels(min_labels_slp.labeled_frames) labels.append(LabeledFrame(video=labels.video, frame_idx=1)) labels.suggestions.append(SuggestionFrame(video=labels.video, frame_idx=2)) fn = os.path.join(tmpdir, "test_user_only.slp") labels.save_frame_data_hdf5( fn, format="png", user_labeled=True, all_labeled=False, suggested=False, ) assert Video.from_filename(fn, dataset="video0").embedded_frame_inds == [0] fn = os.path.join(tmpdir, "test_all_labeled.slp") labels.save_frame_data_hdf5( fn, format="png", user_labeled=False, all_labeled=True, suggested=False, ) assert Video.from_filename(fn, dataset="video0").embedded_frame_inds == [0, 1] fn = os.path.join(tmpdir, "test_suggested.slp") labels.save_frame_data_hdf5( fn, format="png", user_labeled=False, all_labeled=False, suggested=True, ) assert Video.from_filename(fn, dataset="video0").embedded_frame_inds == [2] fn = os.path.join(tmpdir, "test_all.slp") labels.save_frame_data_hdf5( fn, format="png", user_labeled=False, all_labeled=True, suggested=True, ) assert Video.from_filename(fn, dataset="video0").embedded_frame_inds == [0, 1, 2]
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 test_safe_frame_loading_all_invalid(): vid = Video.from_filename("video_that_does_not_exist.mp4") idxs, frames = vid.get_frames_safely(list(range(10))) assert idxs == [] assert frames is None
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 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_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 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 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 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_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_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 demo_pipeline(): from sleap import Video vids = [ Video.from_filename("tests/data/videos/centered_pair_small.mp4"), Video.from_filename("tests/data/videos/small_robot.mp4"), ] pipeline = FeatureSuggestionPipeline( per_video=10, scale=0.25, sample_method="random", feature_type="hog", brisk_threshold=120, n_components=5, n_clusters=5, per_cluster=5, ) suggestions = ParallelFeaturePipeline.run(pipeline, vids, parallel=False) print(suggestions)
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_path_fix(tmpdir): labels = Labels() filename = os.path.join(tmpdir, "test.h5") # Add a video without a full path labels.add_video(Video.from_filename("small_robot.mp4")) Labels.save_hdf5(filename=filename, labels=labels) # Pass the path to the directory with the video labels = Labels.load_file(filename, video_search="tests/data/videos/") # Make sure we got the actual video path by searching that directory assert len(labels.videos) == 1 assert labels.videos[0].filename == "tests/data/videos/small_robot.mp4"
def test_path_fix_with_new_full_path(tmpdir): labels = Labels() filename = os.path.join(tmpdir, "test.h5") # Add video with bad filename labels.add_video(Video.from_filename("foo.mp4")) Labels.save_hdf5(filename=filename, labels=labels) # Pass list of full video paths to use instead of those in labels labels = Labels.load_file( filename, video_search=["tests/data/videos/small_robot.mp4"]) # Make sure we got the actual video path by searching that directory assert len(labels.videos) == 1 assert labels.videos[0].filename == "tests/data/videos/small_robot.mp4"
def test_dont_unify_skeletons(): 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)]) labels = Labels(labeled_frames=[lf_a]) labels.extend_from([lf_b], unify=False) ids = skeleton_ids_from_label_instances(labels) # Make sure we still have two distinct skeleton objects assert len(set(ids)) == 2 # Make sure we can serialize this labels.to_dict()
def test_inference_cli_output_path(): inference_task = runners.InferenceTask( trained_job_paths=["model1", "model2"], inference_params=dict(), ) item_for_inference = runners.VideoItemForInference( video=Video.from_filename("video.mp4"), frames=[1, 2, 3], ) # Try with specified output path cli_args, output_path = inference_task.make_predict_cli_call( item_for_inference, output_path="another_output_path.slp", ) assert output_path == "another_output_path.slp" assert "another_output_path.slp" in cli_args
def test_load_file(tmpdir): labels = Labels() filename = os.path.join(tmpdir, "test.h5") labels.add_video(Video.from_filename("small_robot.mp4")) Labels.save_hdf5(filename=filename, labels=labels) # Fix video path from full path labels = load_file(filename, search_paths="tests/data/videos/small_robot.mp4") assert Path(labels.video.filename).samefile("tests/data/videos/small_robot.mp4") # No auto-detect labels = load_file(filename, detect_videos=False) assert labels.video.filename == "small_robot.mp4" # Fix video path by searching in the labels folder tmpvid = tmpdir.join("small_robot.mp4") tmpvid.write("") # dummy file assert load_file(filename).video.filename == tmpvid assert load_file(filename, search_paths=str(tmpdir)).video.filename == tmpvid assert load_file(filename, search_paths=str(tmpvid)).video.filename == tmpvid
def test_unify_skeletons(): 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)]) labels = Labels() labels.extend_from([lf_a], unify=True) labels.extend_from([lf_b], unify=True) ids = skeleton_ids_from_label_instances(labels) # Make sure that skeleton_b got replaced with skeleton_a when we # added the frame with "unify" set assert len(set(ids)) == 1 # Make sure we can serialize this labels.to_dict()
def test_inference_cli_builder(): inference_task = runners.InferenceTask( trained_job_paths=["model1", "model2"], inference_params={"tracking.tracker": "simple"}, ) item_for_inference = runners.VideoItemForInference( video=Video.from_filename("video.mp4"), frames=[1, 2, 3], ) cli_args, output_path = inference_task.make_predict_cli_call( item_for_inference) assert cli_args[0] == "sleap-track" assert cli_args[1] == "video.mp4" assert "model1" in cli_args assert "model2" in cli_args assert "--frames" in cli_args assert "--tracking.tracker" in cli_args assert output_path.startswith("video.mp4") assert output_path.endswith("predictions.slp")
def test_from_filename(): assert type(Video.from_filename(TEST_H5_FILE).backend) == HDF5Video assert type(Video.from_filename(TEST_SMALL_ROBOT_MP4_FILE).backend) == MediaVideo
def test_complex_merge(): 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( Instance(skeleton=dummy_skeleton_b, points=dict(node=Point(3, 3)))) labels_b = Labels() labels_b.append( LabeledFrame(dummy_video_b, frame_idx=0, instances=dummy_instances_b)) # conflict labels_b.append( LabeledFrame(dummy_video_b, frame_idx=1, instances=dummy_instances_b)) # clean merged, extra_a, extra_b = Labels.complex_merge_between(labels_a, labels_b) # Check that we have the cleanly merged frame assert dummy_video_a in merged assert len(merged[dummy_video_a]) == 1 # one merged frame assert len(merged[dummy_video_a][1]) == 2 # with two instances # Check that labels_a includes redundant and clean assert len(labels_a.labeled_frames) == 2 assert len(labels_a.labeled_frames[0].instances) == 1 assert labels_a.labeled_frames[0].instances[0].points[0].x == 1 assert len(labels_a.labeled_frames[1].instances) == 2 assert labels_a.labeled_frames[1].instances[0].points[0].x == 1 assert labels_a.labeled_frames[1].instances[1].points[0].x == 3 # Check that extra_a/b includes the appropriate conflicting instance assert len(extra_a) == 1 assert len(extra_b) == 1 assert len(extra_a[0].instances) == 1 assert len(extra_b[0].instances) == 1 assert extra_a[0].instances[0].points[0].x == 2 assert extra_b[0].instances[0].points[0].x == 3 # Check that objects were unified assert extra_a[0].video == extra_b[0].video # Check resolving the conflict using new Labels.finish_complex_merge(labels_a, extra_b) assert len(labels_a.labeled_frames) == 2 assert len(labels_a.labeled_frames[0].instances) == 2 assert labels_a.labeled_frames[0].instances[1].points[0].x == 3
def test_grayscale_video(): assert Video.from_filename(TEST_SMALL_ROBOT_MP4_FILE, grayscale=True).shape[-1] == 1
def create_video(import_item: Dict[str, Any]) -> Video: return Video.from_filename(**import_item["params"])
def test_backend_extra_kwargs(): Video.from_filename(TEST_H5_FILE, grayscale=True, another_kwarg=False) Video.from_filename( TEST_SMALL_ROBOT_MP4_FILE, dataset="no dataset", fake_kwarg=True )