def test_symmetry(): s1 = Skeleton("s1") s1.add_nodes(["1", "2", "3", "4", "5", "6"]) s1.add_edge("1", "2") s1.add_edge("3", "4") s1.add_edge("5", "6") s1.add_symmetry("1", "5") s1.add_symmetry("3", "6") assert s1.get_symmetry("1").name == "5" assert s1.get_symmetry("5").name == "1" assert s1.get_symmetry("3").name == "6" # Cannot add more than one symmetry to a node with pytest.raises(ValueError): s1.add_symmetry("1", "6") with pytest.raises(ValueError): s1.add_symmetry("6", "1") s1.delete_symmetry("1", "5") assert s1.get_symmetry("1") is None with pytest.raises(ValueError): s1.delete_symmetry("1", "5")
def test_eq(): s1 = Skeleton("s1") s1.add_nodes(["1", "2", "3", "4", "5", "6"]) s1.add_edge("1", "2") s1.add_edge("3", "4") s1.add_edge("5", "6") s1.add_symmetry("3", "6") # Make a copy check that they are equal s2 = copy.deepcopy(s1) assert s1.matches(s2) # Add an edge, check that they are not equal s2 = copy.deepcopy(s1) s2.add_edge("5", "1") assert not s1.matches(s2) # Add a symmetry edge, not equal s2 = copy.deepcopy(s1) s2.add_symmetry("5", "1") assert not s1.matches(s2) # Delete a node s2 = copy.deepcopy(s1) s2.delete_node("5") assert not s1.matches(s2) # Delete and edge, not equal s2 = copy.deepcopy(s1) s2.delete_edge("1", "2") assert not s1.matches(s2)
def test_symmetry(): s1 = Skeleton("s1") s1.add_nodes(["1", "2", "3", "4", "5", "6"]) s1.add_edge("1", "2") s1.add_edge("3", "4") s1.add_edge("5", "6") s1.add_symmetry("1", "5") s1.add_symmetry("3", "6") assert (s1.nodes[0], s1.nodes[4]) in s1.symmetries assert (s1.nodes[2], s1.nodes[5]) in s1.symmetries assert len(s1.symmetries) == 2 assert (0, 4) in s1.symmetric_inds assert (2, 5) in s1.symmetric_inds assert len(s1.symmetric_inds) == 2 assert s1.get_symmetry("1").name == "5" assert s1.get_symmetry("5").name == "1" assert s1.get_symmetry("3").name == "6" # Cannot add more than one symmetry to a node with pytest.raises(ValueError): s1.add_symmetry("1", "6") with pytest.raises(ValueError): s1.add_symmetry("6", "1") s1.delete_symmetry("1", "5") assert s1.get_symmetry("1") is None with pytest.raises(ValueError): s1.delete_symmetry("1", "5")
def stickman(): # Make a skeleton with a space in its name to test things. stickman = Skeleton("Stick man") stickman.add_nodes( ["head", "neck", "body", "right-arm", "left-arm", "right-leg", "left-leg"] ) stickman.add_edge("neck", "head") stickman.add_edge("body", "neck") stickman.add_edge("body", "right-arm") stickman.add_edge("body", "left-arm") stickman.add_edge("body", "right-leg") stickman.add_edge("body", "left-leg") stickman.add_symmetry(node1="left-arm", node2="right-arm") stickman.add_symmetry(node1="left-leg", node2="right-leg") return stickman
def skeleton(): # Create a simple skeleton object skeleton = Skeleton("Fly") skeleton.add_node("head") skeleton.add_node("thorax") skeleton.add_node("abdomen") skeleton.add_node("left-wing") skeleton.add_node("right-wing") skeleton.add_edge(source="head", destination="thorax") skeleton.add_edge(source="thorax", destination="abdomen") skeleton.add_edge(source="thorax", destination="left-wing") skeleton.add_edge(source="thorax", destination="right-wing") skeleton.add_symmetry(node1="left-wing", node2="right-wing") return skeleton
def test_skeleton_node_name_change(): """ Test that and instance is not broken after a node on the skeleton has its name changed. """ s = Skeleton("Test") s.add_nodes(["a", "b", "c", "d", "e"]) s.add_edge("a", "b") instance = Instance(s) instance["a"] = Point(1, 2) instance["b"] = Point(3, 4) # Rename the node s.relabel_nodes({"a": "A"}) # Reference to the old node name should raise a KeyError with pytest.raises(KeyError): instance["a"].x = 2 # Make sure the A now references the same point on the instance assert instance["A"] == Point(1, 2) assert instance["b"] == Point(3, 4)
def test_arborescence(): skeleton = Skeleton() skeleton.add_node("a") skeleton.add_node("b") skeleton.add_node("c") # linear: a -> b -> c skeleton.add_edge("a", "b") skeleton.add_edge("b", "c") assert skeleton.is_arborescence skeleton = Skeleton() skeleton.add_node("a") skeleton.add_node("b") skeleton.add_node("c") # two branches from a: a -> b and a -> c skeleton.add_edge("a", "b") skeleton.add_edge("a", "c") assert skeleton.is_arborescence skeleton = Skeleton() skeleton.add_node("a") skeleton.add_node("b") skeleton.add_node("c") # no edges so too many roots assert not skeleton.is_arborescence assert sorted((n.name for n in skeleton.root_nodes)) == ["a", "b", "c"] # still too many roots: a and c skeleton.add_edge("a", "b") assert not skeleton.is_arborescence assert sorted((n.name for n in skeleton.root_nodes)) == ["a", "c"] skeleton = Skeleton() skeleton.add_node("a") skeleton.add_node("b") skeleton.add_node("c") # cycle skeleton.add_edge("a", "b") skeleton.add_edge("b", "c") skeleton.add_edge("c", "a") assert not skeleton.is_arborescence assert len(skeleton.cycles) == 1 assert len(skeleton.root_nodes) == 0 skeleton = Skeleton() skeleton.add_node("a") skeleton.add_node("b") skeleton.add_node("c") skeleton.add_node("d") # diamond, too many sources leading to d skeleton.add_edge("a", "b") skeleton.add_edge("a", "c") skeleton.add_edge("b", "d") skeleton.add_edge("c", "d") assert not skeleton.is_arborescence assert len(skeleton.cycles) == 0 assert len(skeleton.root_nodes) == 1 assert len(skeleton.in_degree_over_one) == 1
def load_predicted_labels_json_old( data_path: str, parsed_json: dict = None, adjust_matlab_indexing: bool = True, fix_rel_paths: bool = True, ) -> List[LabeledFrame]: """ Load predicted instances from Talmo's old JSON format. Args: data_path: The path to the JSON file. parsed_json: The parsed json if already loaded, so we can save some time if already parsed. adjust_matlab_indexing: Whether to adjust indexing from MATLAB. fix_rel_paths: Whether to fix paths to videos to absolute paths. Returns: List of :class:`LabeledFrame` objects. """ if parsed_json is None: data = json.loads(open(data_path).read()) else: data = parsed_json videos = pd.DataFrame(data["videos"]) predicted_instances = pd.DataFrame(data["predicted_instances"]) predicted_points = pd.DataFrame(data["predicted_points"]) if adjust_matlab_indexing: predicted_instances.frameIdx -= 1 predicted_points.frameIdx -= 1 predicted_points.node -= 1 predicted_points.x -= 1 predicted_points.y -= 1 skeleton = Skeleton() skeleton.add_nodes(data["skeleton"]["nodeNames"]) edges = data["skeleton"]["edges"] if adjust_matlab_indexing: edges = np.array(edges) - 1 for (src_idx, dst_idx) in edges: skeleton.add_edge( data["skeleton"]["nodeNames"][src_idx], data["skeleton"]["nodeNames"][dst_idx], ) if fix_rel_paths: for i, row in videos.iterrows(): p = row.filepath if not os.path.exists(p): p = os.path.join(os.path.dirname(data_path), p) if os.path.exists(p): videos.at[i, "filepath"] = p # Make the video objects video_objects = {} for i, row in videos.iterrows(): if videos.at[i, "format"] == "media": vid = Video.from_media(videos.at[i, "filepath"]) else: vid = Video.from_hdf5( filename=videos.at[i, "filepath"], dataset=videos.at[i, "dataset"] ) video_objects[videos.at[i, "id"]] = vid track_ids = predicted_instances["trackId"].values unique_track_ids = np.unique(track_ids) spawned_on = { track_id: predicted_instances.loc[predicted_instances["trackId"] == track_id][ "frameIdx" ].values[0] for track_id in unique_track_ids } tracks = { i: Track(name=str(i), spawned_on=spawned_on[i]) for i in np.unique(predicted_instances["trackId"].values).tolist() } # A function to get all the instances for a particular video frame def get_frame_predicted_instances(video_id, frame_idx): points = predicted_points is_in_frame = (points["videoId"] == video_id) & ( points["frameIdx"] == frame_idx ) if not is_in_frame.any(): return [] instances = [] frame_instance_ids = np.unique(points["instanceId"][is_in_frame]) for i, instance_id in enumerate(frame_instance_ids): is_instance = is_in_frame & (points["instanceId"] == instance_id) track_id = predicted_instances.loc[ predicted_instances["id"] == instance_id ]["trackId"].values[0] match_score = predicted_instances.loc[ predicted_instances["id"] == instance_id ]["matching_score"].values[0] track_score = predicted_instances.loc[ predicted_instances["id"] == instance_id ]["tracking_score"].values[0] instance_points = { data["skeleton"]["nodeNames"][n]: PredictedPoint( x, y, visible=v, score=confidence ) for x, y, n, v, confidence in zip( *[ points[k][is_instance] for k in ["x", "y", "node", "visible", "confidence"] ] ) } instance = PredictedInstance( skeleton=skeleton, points=instance_points, track=tracks[track_id], score=match_score, ) instances.append(instance) return instances # Get the unique labeled frames and construct a list of LabeledFrame objects for them. frame_keys = list( { (videoId, frameIdx) for videoId, frameIdx in zip( predicted_points["videoId"], predicted_points["frameIdx"] ) } ) frame_keys.sort() labels = [] for videoId, frameIdx in frame_keys: label = LabeledFrame( video=video_objects[videoId], frame_idx=frameIdx, instances=get_frame_predicted_instances(videoId, frameIdx), ) labels.append(label) return labels