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 _parse_annotation(annotation_object: ET.Element) -> dt.Annotation: """ Parses the given XML element and returns the corresponding annotation. Parameters -------- annotation_object: xml.etree.ElementTree.Element The element to convert into an annotation. Returns ------- darwin.datatypes.AnnotationFile An AnnotationFile with the parsed information from the XML element. Raises ------ ValueError If a mandatory chield element is missing or is empty. Mandatory child elements are: name, bndbox, xmin, xmax, ymin and ymax. """ class_name = _find_text_value(annotation_object, "name") bndbox = _find_element(annotation_object, "bndbox") xmin = int(float(_find_text_value(bndbox, "xmin"))) xmax = int(float(_find_text_value(bndbox, "xmax"))) ymin = int(float(_find_text_value(bndbox, "ymin"))) ymax = int(float(_find_text_value(bndbox, "ymax"))) return dt.make_bounding_box(class_name, xmin, ymin, xmax - xmin, ymax - ymin)
def _to_bbox_annotation(bbox: Dict[str, Any], title: str) -> Annotation: x: float = cast(float, bbox.get("left")) y: float = cast(float, bbox.get("top")) width: float = cast(float, bbox.get("width")) height: float = cast(float, bbox.get("height")) return make_bounding_box(title, x, y, width, height)
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_object): class_name = annotation_object.find("name").text bndbox = annotation_object.find("bndbox") xmin = int(bndbox.find("xmin").text) xmax = int(bndbox.find("xmax").text) ymin = int(bndbox.find("ymin").text) ymax = int(bndbox.find("ymax").text) return dt.make_bounding_box(class_name, xmin, ymin, xmax - xmin, ymax - ymin)
def _to_bbox_annotation(bbox: Dict[str, Any], classes: List[Dict[str, Any]]) -> Annotation: points: Dict[str, float] = cast(Dict[str, float], bbox.get("points")) x: float = cast(float, points.get("x1")) y: float = cast(float, points.get("y1")) w: float = abs(cast(float, points.get("x2")) - cast(float, points.get("x1"))) h: float = abs(cast(float, points.get("y1")) - cast(float, points.get("y2"))) class_id: int = cast(int, bbox.get("classId")) instance_class: Dict[str, Any] = _find_class(class_id, classes) name: str = str(instance_class.get("name")) attributes: Optional[SubAnnotation] = _get_attributes(bbox, instance_class) subannotations: Optional[List[SubAnnotation]] = None if attributes: subannotations = [attributes] return make_bounding_box(f"{name}-bbox", x, y, w, h, subannotations)
def _parse_annotation(annotation): annotation_type = annotation["type"] annotation_label = annotation["label"] if annotation_type not in ["box", "class"]: raise ValueError( f"Unknown supported annotation type: {annotation_type}") if len(annotation["metadata"]["system"]["snapshots_"]) > 1: raise ValueError( "multiple snapshots per annotations are not supported") # Class is metadata that we can ignore if annotation_type == "class": return if annotation_type == "box": coords = annotation["coordinates"] x1, y1 = coords[0]["x"], coords[0]["y"] x2, y2 = coords[1]["x"], coords[1]["y"] return dt.make_bounding_box(annotation_label, x1, y1, x2 - x1, y2 - y1)
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