def parse_darwin_annotation( annotation: Dict[str, Any]) -> Optional[dt.Annotation]: name: str = annotation["name"] main_annotation: Optional[dt.Annotation] = None if "polygon" in annotation: bounding_box = annotation.get("bounding_box") if "additional_paths" in annotation["polygon"]: paths = [annotation["polygon"]["path"] ] + annotation["polygon"]["additional_paths"] main_annotation = dt.make_complex_polygon(name, paths, bounding_box) else: main_annotation = dt.make_polygon(name, annotation["polygon"]["path"], bounding_box) elif "complex_polygon" in annotation: bounding_box = annotation.get("bounding_box") if "additional_paths" in annotation["complex_polygon"]: paths = annotation["complex_polygon"]["path"] + annotation[ "complex_polygon"]["additional_paths"] main_annotation = dt.make_complex_polygon(name, paths, bounding_box) else: main_annotation = dt.make_complex_polygon( name, annotation["complex_polygon"]["path"], bounding_box) elif "bounding_box" in annotation: bounding_box = annotation["bounding_box"] main_annotation = dt.make_bounding_box(name, bounding_box["x"], bounding_box["y"], bounding_box["w"], bounding_box["h"]) elif "tag" in annotation: main_annotation = dt.make_tag(name) elif "line" in annotation: main_annotation = dt.make_line(name, annotation["line"]["path"]) elif "keypoint" in annotation: main_annotation = dt.make_keypoint(name, annotation["keypoint"]["x"], annotation["keypoint"]["y"]) elif "ellipse" in annotation: main_annotation = dt.make_ellipse(name, annotation["ellipse"]) elif "cuboid" in annotation: main_annotation = dt.make_cuboid(name, annotation["cuboid"]) elif "skeleton" in annotation: main_annotation = dt.make_skeleton(name, annotation["skeleton"]["nodes"]) if not main_annotation: print(f"[WARNING] Unsupported annotation type: '{annotation.keys()}'") return None if "instance_id" in annotation: main_annotation.subs.append( dt.make_instance_id(annotation["instance_id"]["value"])) if "attributes" in annotation: main_annotation.subs.append( dt.make_attributes(annotation["attributes"])) if "text" in annotation: main_annotation.subs.append(dt.make_text(annotation["text"]["text"])) return main_annotation
def parse_annotation( annotation: Dict[str, Any], category_lookup_table: Dict[str, Any]) -> Optional[dt.Annotation]: category = category_lookup_table[annotation["category_id"]] segmentation = annotation["segmentation"] iscrowd = annotation.get("iscrowd") == 1 if iscrowd: print("Warning, unsupported RLE, skipping") return None if len(segmentation) == 0 and len(annotation["bbox"]) == 4: x, y, w, h = map(int, annotation["bbox"]) return dt.make_bounding_box(category["name"], x, y, w, h) elif len(segmentation) == 0 and len(annotation["bbox"]) == 1 and len( annotation["bbox"][0]) == 4: x, y, w, h = map(int, annotation["bbox"][0]) return dt.make_bounding_box(category["name"], x, y, w, h) elif isinstance(segmentation, dict): print( "warning, converting complex coco rle mask to polygon, could take some time" ) if isinstance(segmentation["counts"], list): mask = rle_decode(segmentation["counts"], segmentation["size"][::-1]) else: counts = decode_binary_rle(segmentation["counts"]) mask = rle_decode(counts, segmentation["size"][::-1]) _labels, external, _internal = find_contours(mask) paths = [] for external_path in external: # skip paths with less than 2 points if len(external_path) // 2 <= 2: continue path = [] points = iter(external_path) while True: try: x, y = next(points), next(points) path.append({"x": x, "y": y}) except StopIteration: break paths.append(path) return dt.make_complex_polygon(category["name"], paths) elif isinstance(segmentation, list): path = [] points = iter(segmentation[0] if isinstance(segmentation[0], list ) else segmentation) while True: try: x, y = next(points), next(points) path.append({"x": x, "y": y}) except StopIteration: break return dt.make_polygon(category["name"], path) else: return None
def _to_polygon_annotation(polygon: Dict[str, Any], classes: List[Dict[str, Any]]) -> Annotation: data: List[float] = cast(List[float], polygon.get("points")) class_id: int = cast(int, polygon.get("classId")) instance_class: Dict[str, Any] = _find_class(class_id, classes) name: str = str(instance_class.get("name")) points: List[Point] = _map_to_list(_tuple_to_point, _group_to_list(data, 2, 0)) attributes: Optional[SubAnnotation] = _get_attributes(polygon, instance_class) subannotations: Optional[List[SubAnnotation]] = None if attributes: subannotations = [attributes] return make_polygon(f"{name}-polygon", points, None, subannotations)
def test_it_returns_annotation_with_default_params(): class_name: str = "class_name" points: List[Point] = [{ "x": 1, "y": 2 }, { "x": 3, "y": 4 }, { "x": 1, "y": 2 }] annotation = make_polygon(class_name, points) assert_annoation_class(annotation, class_name, "polygon") path = annotation.data.get("path") assert path == points
def parse_annotation(annotation, category_lookup_table): category = category_lookup_table[annotation["category_id"]] segmentation = annotation["segmentation"] iscrowd = annotation.get("iscrowd") == 1 if iscrowd: print("Warning, unsupported RLE, skipping") return None if len(segmentation) == 0 and len(annotation["bbox"]) == 4: x, y, w, h = map(int, annotation["bbox"]) return dt.make_bounding_box(category["name"], x, y, w, h) elif len(segmentation) > 1: print("warning, converting complex coco rle mask to polygon, could take some time") mask = rle_decoding(segmentation["counts"], segmentation["size"]) _labels, external, _internal = find_contours(mask) paths = [] for external_path in external: path = [] points = iter(external_path) while True: try: x, y = next(points), next(points) path.append({"x": x, "y": y}) except StopIteration: break paths.append(path) return dt.make_complex_polygon(category["name"], paths) elif len(segmentation) == 1: path = [] points = iter(segmentation[0]) while True: try: x, y = next(points), next(points) path.append({"x": x, "y": y}) except StopIteration: break return dt.make_polygon(category["name"], path) else: return None
def test_it_returns_annotation_with_bounding_box(): class_name: str = "class_name" points: List[Point] = [{ "x": 1, "y": 2 }, { "x": 3, "y": 4 }, { "x": 1, "y": 2 }] bbox: Dict[str, float] = {"x": 1, "y": 2, "w": 2, "h": 2} annotation = make_polygon(class_name, points, bbox) assert_annoation_class(annotation, class_name, "polygon") path = annotation.data.get("path") assert path == points class_bbox = annotation.data.get("bounding_box") assert class_bbox == bbox
def build_annotation(annotation_file, annotation_id, annotation: dt.Annotation, categories): annotation_type = annotation.annotation_class.annotation_type if annotation_type == "polygon": sequences = convert_polygons_to_sequences(annotation.data["path"], rounding=False) x_coords = [s[0::2] for s in sequences] y_coords = [s[1::2] for s in sequences] min_x = np.min([np.min(x_coord) for x_coord in x_coords]) min_y = np.min([np.min(y_coord) for y_coord in y_coords]) max_x = np.max([np.max(x_coord) for x_coord in x_coords]) max_y = np.max([np.max(y_coord) for y_coord in y_coords]) w = max_x - min_x + 1 h = max_y - min_y + 1 # Compute the area of the polygon poly_area = np.sum([ polygon_area(x_coord, y_coord) for x_coord, y_coord in zip(x_coords, y_coords) ]) return { "id": annotation_id, "image_id": annotation_file.seq, "category_id": categories[annotation.annotation_class.name], "segmentation": sequences, "area": poly_area, "bbox": [min_x, min_y, w, h], "iscrowd": 0, "extra": build_extra(annotation), } elif annotation_type == "complex_polygon": mask = np.zeros( (annotation_file.image_height, annotation_file.image_width)) sequences = convert_polygons_to_sequences(annotation.data["paths"]) draw_polygon(mask, sequences, 1) counts = rle_encode(mask) x_coords = [s[0::2] for s in sequences] y_coords = [s[1::2] for s in sequences] min_x = np.min([np.min(x_coord) for x_coord in x_coords]) min_y = np.min([np.min(y_coord) for y_coord in y_coords]) max_x = np.max([np.max(x_coord) for x_coord in x_coords]) max_y = np.max([np.max(y_coord) for y_coord in y_coords]) w = max_x - min_x + 1 h = max_y - min_y + 1 return { "id": annotation_id, "image_id": annotation_file.seq, "category_id": categories[annotation.annotation_class.name], "segmentation": { "counts": counts, "size": [annotation_file.image_height, annotation_file.image_width] }, "area": 0, "bbox": [min_x, min_y, w, h], "iscrowd": 1, "extra": build_extra(annotation), } elif annotation_type == "tag": pass elif annotation_type == "bounding_box": x = annotation.data["x"] y = annotation.data["y"] w = annotation.data["w"] h = annotation.data["h"] return build_annotation( annotation_file, annotation_id, dt.make_polygon( annotation.annotation_class.name, [{ "x": x, "y": y }, { "x": x + w, "y": y }, { "x": x + w, "y": y + h }, { "x": x, "y": y + h }], ), categories, ) else: print(f"skipping unsupported annotation_type '{annotation_type}'")
def _to_polygon_annotation(polygon: List[Point], title: str) -> Annotation: return make_polygon(title, polygon, None)