| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081 |
- from __future__ import annotations
- import json
- from pathlib import Path
- import xml.etree.ElementTree as ET
- from PIL import Image, ImageDraw
- def parse_ddti_xml(annotation_path: str | Path) -> dict[int, list[list[tuple[int, int]]]]:
- """
- 解析 DDTI 的 xml 标注。
- Returns:
- {image_index: [polygon1, polygon2, ...]}
- """
- annotation_path = Path(annotation_path)
- root = ET.parse(annotation_path).getroot()
- image_to_polygons: dict[int, list[list[tuple[int, int]]]] = {}
- for mark in root.findall("mark"):
- image_text = mark.findtext("image")
- svg_text = mark.findtext("svg")
- if not image_text or not svg_text:
- continue
- image_index = int(image_text)
- try:
- shapes = json.loads(svg_text)
- except json.JSONDecodeError:
- continue
- polygons: list[list[tuple[int, int]]] = []
- for shape in shapes:
- points = shape.get("points", [])
- polygon = []
- for point in points:
- x = int(round(point["x"]))
- y = int(round(point["y"]))
- polygon.append((x, y))
- if len(polygon) >= 3:
- polygons.append(polygon)
- if polygons:
- image_to_polygons[image_index] = polygons
- return image_to_polygons
- def build_ddti_mask(
- image_path: str | Path,
- annotation_path: str | Path,
- image_index: int | None = None,
- fill_value: int = 255,
- ) -> Image.Image:
- """
- 根据 DDTI 的 xml 为指定图像生成二值掩膜。
- """
- image_path = Path(image_path)
- annotation_path = Path(annotation_path)
- image = Image.open(image_path)
- width, height = image.size
- if image_index is None:
- stem = image_path.stem
- if "_" not in stem:
- raise ValueError(f"Cannot infer image index from file name: {image_path.name}")
- _, image_idx_str = stem.split("_", 1)
- image_index = int(image_idx_str)
- polygons_map = parse_ddti_xml(annotation_path)
- polygons = polygons_map.get(int(image_index), [])
- mask = Image.new("L", (width, height), 0)
- draw = ImageDraw.Draw(mask)
- for polygon in polygons:
- draw.polygon(polygon, outline=fill_value, fill=fill_value)
- return mask
- __all__ = ["parse_ddti_xml", "build_ddti_mask"]
|