Support larger operator training samples
GeoIntel CI / docs-smoke (push) Has been cancelled
GeoIntel CI / contract-smoke (push) Has been cancelled

This commit is contained in:
Codex
2026-07-09 13:28:54 +02:00
parent a20d9b70c7
commit a1b33555b9
7 changed files with 120 additions and 11 deletions
+63 -4
View File
@@ -12,7 +12,7 @@ import argparse
import json
import os
import sys
from dataclasses import dataclass
from dataclasses import dataclass, replace
from pathlib import Path
from typing import Any
@@ -196,6 +196,24 @@ def parse_args() -> argparse.Namespace:
default="operator_samples_manifest.json",
help="Manifest filename written inside output-dir.",
)
parser.add_argument(
"--width",
type=int,
default=int(os.environ.get("OPERATOR_SAMPLE_WIDTH", "512")),
help="Orthophoto WMS output width in pixels. Use larger values for operator training datasets.",
)
parser.add_argument(
"--height",
type=int,
default=int(os.environ.get("OPERATOR_SAMPLE_HEIGHT", "512")),
help="Orthophoto WMS output height in pixels. Use larger values for operator training datasets.",
)
parser.add_argument(
"--half-size-scale",
type=float,
default=float(os.environ.get("OPERATOR_SAMPLE_HALF_SIZE_SCALE", "1")),
help="Multiplier applied to each documented AOI half-size in meters.",
)
return parser.parse_args()
@@ -229,6 +247,25 @@ def selected_samples(raw: str) -> list[OperatorSample]:
return [SAMPLES[slug] for slug in slugs]
def apply_sample_overrides(
sample: OperatorSample,
*,
width: int,
height: int,
half_size_scale: float,
) -> OperatorSample:
if width <= 0 or height <= 0:
raise SystemExit("--width and --height must be positive integers")
if half_size_scale <= 0:
raise SystemExit("--half-size-scale must be greater than zero")
return replace(
sample,
width=width,
height=height,
half_size_m=sample.half_size_m * half_size_scale,
)
def sample_bounds(sample: OperatorSample) -> tuple[tuple[float, float, float, float], list[float]]:
lambert = Transformer.from_crs("EPSG:4326", "EPSG:31370", always_xy=True)
wgs84 = Transformer.from_crs("EPSG:31370", "EPSG:4326", always_xy=True)
@@ -273,6 +310,12 @@ def geojson_feature_count(path: Path) -> int:
return len(payload.get("features") or [])
def sample_artifact_paths(sample: OperatorSample, output_dir: Path) -> tuple[Path, Path]:
ortho_path = output_dir / f"{sample.slug}_orthophoto_wms_{sample.width}.tif"
reference_path = output_dir / f"{sample.slug}_grb_gbg_buildings.geojson"
return ortho_path, reference_path
def fetch_orthophoto(sample: OperatorSample, ortho_path: Path, lambert_bbox: tuple[float, float, float, float]) -> str:
minx, miny, maxx, maxy = lambert_bbox
wms_params = {
@@ -352,8 +395,7 @@ def fetch_reference(sample: OperatorSample, reference_path: Path, geo_bbox: list
def prepare_sample(sample: OperatorSample, output_dir: Path, force: bool) -> dict[str, Any]:
ortho_path = output_dir / f"{sample.slug}_orthophoto_wms_512.tif"
reference_path = output_dir / f"{sample.slug}_grb_gbg_buildings.geojson"
ortho_path, reference_path = sample_artifact_paths(sample, output_dir)
lambert_bbox, geo_bbox = sample_bounds(sample)
skip_existing = ortho_path.exists() and reference_path.exists() and not force
@@ -370,6 +412,8 @@ def prepare_sample(sample: OperatorSample, output_dir: Path, force: bool) -> dic
"center_lon": sample.center_lon,
"center_lat": sample.center_lat,
"half_size_m": sample.half_size_m,
"width": sample.width,
"height": sample.height,
"sample_role": sample.sample_role,
"allow_empty_reference": sample.allow_empty_reference,
"raster_path": str(ortho_path),
@@ -416,13 +460,28 @@ def main() -> int:
ensure_gis_dependencies()
output_dir: Path = args.output_dir
output_dir.mkdir(parents=True, exist_ok=True)
samples = [prepare_sample(sample, output_dir, force=args.force) for sample in selected_samples(args.samples)]
samples = [
prepare_sample(
apply_sample_overrides(
sample,
width=args.width,
height=args.height,
half_size_scale=args.half_size_scale,
),
output_dir,
force=args.force,
)
for sample in selected_samples(args.samples)
]
write_readme(output_dir, samples)
manifest = {
"schema_version": 1,
"description": "GeoIntel operator real-data samples for configured-YOLO QA validation.",
"output_dir": str(output_dir),
"sample_width": args.width,
"sample_height": args.height,
"half_size_scale": args.half_size_scale,
"samples": samples,
}
manifest_path = output_dir / args.manifest_name