Last active
July 30, 2026 09:30
-
-
Save cneud/e1f00a8ba8a0c19a50c6cf17a56a75be to your computer and use it in GitHub Desktop.
Extract images from PAGE-XML
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| from pathlib import Path | |
| from lxml import etree | |
| from PIL import Image | |
| import numpy as np | |
| import cv2 | |
| PAGE_NS = { | |
| "page": "http://schema.primaresearch.org/PAGE/gts/pagecontent/2019-07-15" | |
| } | |
| def parse_points(points_string): | |
| pts = [] | |
| for p in points_string.split(): | |
| x, y = p.split(",") | |
| pts.append((int(x), int(y))) | |
| return np.array(pts, dtype=np.int32) | |
| def extract_graphics(xml_file, image_file, output_dir): | |
| output_dir.mkdir(parents=True, exist_ok=True) | |
| tree = etree.parse(str(xml_file)) | |
| img = Image.open(image_file).convert("RGB") | |
| img_np = np.array(img) | |
| graphic_regions = tree.xpath("//page:GraphicRegion", namespaces=PAGE_NS) | |
| for i, region in enumerate(graphic_regions): | |
| region_id = region.get("id", f"region_{i}") | |
| coords = region.find("page:Coords", namespaces=PAGE_NS) | |
| if coords is None: | |
| continue | |
| polygon = parse_points(coords.get("points")) | |
| x, y, w, h = cv2.boundingRect(polygon) | |
| cropped = img_np[y:y+h, x:x+w] | |
| # shift polygon to cropped coordinates | |
| shifted = polygon - np.array([[x, y]]) | |
| mask = np.zeros((h, w), dtype=np.uint8) | |
| cv2.fillPoly(mask, [shifted], 255) | |
| result = cv2.bitwise_and(cropped, cropped, mask=mask) | |
| # RGBA output | |
| rgba = cv2.cvtColor(result, cv2.COLOR_RGB2RGBA) | |
| rgba[:, :, 3] = mask | |
| outfile = output_dir / f"{image_file.stem}_{region_id}.png" | |
| Image.fromarray(rgba).save(outfile) | |
| print(outfile) | |
| for xml_file in xml_dir.glob("*.xml"): | |
| stem = xml_file.stem | |
| for ext in (".tif", ".jpg", ".png"): | |
| image_file = img_dir / (stem + ext) | |
| if image_file.exists(): | |
| extract_graphics(xml_file, image_file, out_dir) | |
| break | |
| extract_graphics( | |
| xml_dir = Path("./pagexml"), | |
| img_dir = Path("./images"), | |
| out_dir = Path("./graphics") | |
| ) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment