GeoIntel release gates / Compile, test, contracts and builds (push) Successful in 1m49s
GeoIntel release gates / Python and npm vulnerability policy (push) Successful in 21s
GeoIntel release gates / Production AI image, SBOM and container scan (push) Successful in 5m39s
GeoIntel release gates / Deploy exact gated revision to Unraid (push) Failing after 58m43s
128 lines
5.1 KiB
Python
128 lines
5.1 KiB
Python
from __future__ import annotations
|
|
|
|
import json
|
|
import subprocess
|
|
import sys
|
|
from hashlib import sha256
|
|
from pathlib import Path
|
|
|
|
from PIL import Image
|
|
|
|
|
|
SCRIPT = Path(__file__).parents[2] / "scripts" / "build_grayscale_yolo_dataset.py"
|
|
|
|
|
|
def test_grayscale_builder_preserves_labels_and_split(tmp_path: Path) -> None:
|
|
source = tmp_path / "source"
|
|
entries = []
|
|
for split, sample_slug, colour in (("train", "fixture-train", (255, 0, 0)), ("val", "fixture-val", (0, 255, 0))):
|
|
image = source / "images" / split / f"{sample_slug}.png"
|
|
label = source / "labels" / split / f"{sample_slug}.txt"
|
|
image.parent.mkdir(parents=True, exist_ok=True)
|
|
label.parent.mkdir(parents=True, exist_ok=True)
|
|
Image.new("RGB", (8, 8), colour).save(image)
|
|
label.write_text("0 0.5 0.5 0.5 0.5\n", encoding="utf-8")
|
|
entries.append((split, sample_slug, image, label))
|
|
manifest = source / "operator_samples_manifest.json"
|
|
policy = "geointel-training-source-eligibility/v1"
|
|
manifest.write_text(
|
|
json.dumps(
|
|
{
|
|
"immutable": True,
|
|
"training_eligibility": {"policy_version": policy, "status": "eligible", "fixture_mode": True},
|
|
"samples": [
|
|
{
|
|
"sample_slug": sample_slug,
|
|
"split": split,
|
|
"raster_dataset_id": f"raster:{sample_slug}",
|
|
"reference_dataset_id": f"reference:{sample_slug}",
|
|
"training_eligibility": {
|
|
"policy_version": policy,
|
|
"eligible": True,
|
|
"fixture_mode": True,
|
|
"raster": {"eligible": True, "reasons": [], "evidence": {"dataset_id": f"raster:{sample_slug}", "checksum_sha256": "a" * 64, "source_registry_id": "fixture-raster", "source_snapshot_id": "fixture-raster-snapshot"}},
|
|
"reference": {"eligible": True, "reasons": [], "evidence": {"dataset_id": f"reference:{sample_slug}", "checksum_sha256": "b" * 64, "source_registry_id": "fixture-reference", "source_snapshot_id": "fixture-reference-snapshot"}},
|
|
},
|
|
}
|
|
for split, sample_slug, _image, _label in entries
|
|
],
|
|
}
|
|
),
|
|
encoding="utf-8",
|
|
)
|
|
(source / "corpus-freeze.json").write_text(
|
|
json.dumps(
|
|
{
|
|
"schema_version": 2,
|
|
"immutable": True,
|
|
"fixture_mode": True,
|
|
"training_eligibility_policy": policy,
|
|
"manifest_sha256": sha256(manifest.read_bytes()).hexdigest(),
|
|
}
|
|
),
|
|
encoding="utf-8",
|
|
)
|
|
dataset_yaml = source / "dataset.yaml"
|
|
dataset_yaml.write_text(
|
|
f"path: {source}\ntrain: images/train\nval: images/val\nnames:\n 0: building\n",
|
|
encoding="utf-8",
|
|
)
|
|
release_script = SCRIPT.parent / "training_release_manifest.py"
|
|
subprocess.run(
|
|
[
|
|
sys.executable,
|
|
str(release_script),
|
|
"create",
|
|
"--train-yaml",
|
|
str(dataset_yaml),
|
|
"--corpus-manifest",
|
|
str(manifest),
|
|
"--fixture-mode",
|
|
],
|
|
check=True,
|
|
)
|
|
release_path = dataset_yaml.with_name(dataset_yaml.name + ".geointel-training-release.json")
|
|
asset_path = dataset_yaml.with_name(dataset_yaml.name + ".geointel-training-assets.json")
|
|
assets = json.loads(asset_path.read_text(encoding="utf-8"))
|
|
summary = source / "yolo_tile_dataset_summary.json"
|
|
summary.write_text(
|
|
json.dumps(
|
|
{
|
|
"dataset_yaml": str(dataset_yaml.resolve()),
|
|
"training_release_manifest": str(release_path.resolve()),
|
|
"training_release_manifest_sha256": sha256(release_path.read_bytes()).hexdigest(),
|
|
"training_asset_manifest": str(asset_path.resolve()),
|
|
"source_manifest_sha256": sha256(manifest.read_bytes()).hexdigest(),
|
|
"tiles": [
|
|
{"split": entry["split"], "image_path": entry["image_path"], "label_path": entry["label_path"]}
|
|
for entry in assets["entries"]
|
|
],
|
|
}
|
|
),
|
|
encoding="utf-8",
|
|
)
|
|
output = tmp_path / "gray"
|
|
subprocess.run(
|
|
[
|
|
sys.executable,
|
|
str(SCRIPT),
|
|
"--summary",
|
|
str(summary),
|
|
"--train-yaml",
|
|
str(dataset_yaml),
|
|
"--corpus-manifest",
|
|
str(manifest),
|
|
"--fixture-mode",
|
|
"--output-dir",
|
|
str(output),
|
|
],
|
|
check=True,
|
|
)
|
|
converted = Image.open(output / "images" / "train" / "fixture-train.png")
|
|
r, g, b = converted.getpixel((0, 0))
|
|
assert r == g == b
|
|
assert (output / "labels" / "train" / "fixture-train.txt").read_text() == "0 0.5 0.5 0.5 0.5\n"
|
|
evidence = json.loads((output / "grayscale-dataset-evidence.json").read_text())
|
|
assert evidence["converted_tile_count"] == 2
|
|
assert evidence["training_eligible"] is False
|