File size: 2,782 Bytes
1558db5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
"""Evaluate semantic predictions and render a compact comparison image."""

import json
from pathlib import Path

import matplotlib.pyplot as plt
import numpy as np
import yaml


ROOT = Path(__file__).resolve().parents[1]


def main():
    with (ROOT / "conf" / "config.yaml").open(encoding="utf-8") as handle:
        config = yaml.safe_load(handle)
    input_dir = ROOT / config["paths"]["inference_dir"]
    required = [input_dir / "predictions.npy", input_dir / "targets.npy"]
    missing = [str(path.relative_to(ROOT)) for path in required if not path.exists()]
    if missing:
        raise FileNotFoundError(
            f"Missing inference outputs: {missing}. Run `python scripts/inference.py` first."
        )
    predictions = np.load(input_dir / "predictions.npy")
    targets = np.load(input_dir / "targets.npy")
    classes = config["data"]["num_classes"]
    intersections = np.zeros(classes, dtype=np.float64)
    unions = np.zeros(classes, dtype=np.float64)
    for class_id in range(classes):
        predicted = predictions == class_id
        expected = targets == class_id
        intersections[class_id] = np.logical_and(predicted, expected).sum()
        unions[class_id] = np.logical_or(predicted, expected).sum()
    per_class_iou = np.divide(intersections, unions, out=np.zeros_like(intersections), where=unions > 0)
    metadata_path = input_dir / "metadata.npz"
    metadata = np.load(metadata_path) if metadata_path.exists() else None
    metrics = {
        "pixel_accuracy": float((predictions == targets).mean()),
        "mean_iou": float(per_class_iou.mean()),
        "per_class_iou": per_class_iou.tolist(),
        "samples": int(len(predictions)),
        "data_source": str(metadata["data_source"]) if metadata is not None else "unknown",
        "protocol": str(metadata["protocol"]) if metadata is not None else "unknown",
    }
    output_dir = ROOT / config["paths"]["evaluation_dir"]
    output_dir.mkdir(parents=True, exist_ok=True)
    with (output_dir / "metrics.json").open("w", encoding="utf-8") as handle:
        json.dump(metrics, handle, indent=2)
    figure, axes = plt.subplots(2, 2, figsize=(7, 7))
    for index, axis in enumerate(axes.flat):
        sample = index // 2
        image = targets[sample] if index % 2 == 0 else predictions[sample]
        axis.imshow(image, vmin=0, vmax=classes - 1, cmap="terrain")
        axis.set_title(("Target" if index % 2 == 0 else "Prediction") + f" {sample}")
        axis.axis("off")
    figure.tight_layout()
    figure.savefig(output_dir / "comparison.png", dpi=120)
    plt.close(figure)
    print(f"pixel_accuracy={metrics['pixel_accuracy']:.6f} mean_iou={metrics['mean_iou']:.6f}")
    print(f"evaluation={output_dir.relative_to(ROOT)}")


if __name__ == "__main__":
    main()