facebookresearch/detectron2 · error · NotImplementedError

Unknown geometric structure {}

Error message

Unknown geometric structure {}

What it means

While converting Cityscapes annotation polygons, shapely's difference/union produced an object that is neither Polygon nor MultiPolygon (e.g. GeometryCollection containing lines/points, or empty geometry). The converter cannot turn it into COCO polygon lists, so it raises NotImplementedError.

Source

Thrown at detectron2/data/datasets/cityscapes.py:215

                polygons_union = polygons_union.union(poly)
                continue

            # Take non-overlapping part of the polygon
            poly_wo_overlaps = poly.difference(polygons_union)
            if poly_wo_overlaps.is_empty:
                continue
            polygons_union = polygons_union.union(poly)

            anno = {}
            anno["iscrowd"] = label_name.endswith("group")
            anno["category_id"] = label.id

            if isinstance(poly_wo_overlaps, Polygon):
                poly_list = [poly_wo_overlaps]
            elif isinstance(poly_wo_overlaps, MultiPolygon):
                poly_list = poly_wo_overlaps.geoms
            else:
                raise NotImplementedError("Unknown geometric structure {}".format(poly_wo_overlaps))

            poly_coord = []
            for poly_el in poly_list:
                # COCO API can work only with exterior boundaries now, hence we store only them.
                # TODO: store both exterior and interior boundaries once other parts of the
                # codebase support holes in polygons.
                poly_coord.append(list(chain(*poly_el.exterior.coords)))
            anno["segmentation"] = poly_coord
            (xmin, ymin, xmax, ymax) = poly_wo_overlaps.bounds

            anno["bbox"] = (xmin, ymin, xmax, ymax)
            anno["bbox_mode"] = BoxMode.XYXY_ABS

            annos.append(anno)
    else:
        # See also the official annotation parsing scripts at
        # https://github.com/mcordts/cityscapesScripts/blob/master/cityscapesscripts/evaluation/instances2dict.py  # noqa
        with PathManager.open(instance_id_file, "rb") as f:

View on GitHub (pinned to a2f4a8771a)

Solutions

  1. Fix or regenerate the offending *_polygons.json annotation file (inspect which image id fails from the traceback)
  2. Upgrade/downgrade detectron2 — later versions handle GeometryCollection and filter degenerate parts
  3. Preprocess: filter out annotations whose polygon difference yields empty or non-polygonal geometry before conversion

Example fix

// before
poly_wo_overlaps = polys[i].difference(offsetcrowns_union)
// after (defensive)
if isinstance(poly_wo_overlaps, (Polygon, MultiPolygon)) and not poly_wo_overlaps.is_empty:
    ...proceed...
else:
    continue  # skip degenerate annotation
Defensive patterns

Strategy: validation

Validate before calling

from shapely.geometry import Polygon, MultiPolygon
ok = isinstance(poly_wo_overlaps, (Polygon, MultiPolygon)) and not poly_wo_overlaps.is_empty

Type guard

def is_convertible_polygon(g) -> bool:
    return (isinstance(g, (Polygon, MultiPolygon))
            and not g.is_empty
            and g.area > 0)

Try / catch

try:
    dicts = _cityscapes_files_to_dict(...)
except NotImplementedError as e:
    log.warning(f'skipping malformed cityscapes file: {e}')

Prevention

When it happens

Trigger: Loading Cityscapes labels via _cityscapes_files_to_dict on an image whose instance polygons, after overlap removal, degenerate into a GeometryCollection or empty geometry (tiny/degenerate masks, self-intersecting or sliver polygons).

Common situations: Corrupted or manually edited Cityscapes label files; annotations with near-zero-area or overlapping degenerate polygons; shapely version behavior differences producing GeometryCollection from difference().

Related errors


AI-assisted analysis of facebookresearch/detectron2@a2f4a8771a (2026-08-27). Data as JSON: /api/errors/a5b3d40bc2b22ac9. Report an issue: GitHub.