diff --git a/docs/superpowers/plans/2026-09-12-leonida-vice-slice.md b/docs/superpowers/plans/2026-09-12-leonida-vice-slice.md index 65b4e8d..ed298a3 100644 --- a/docs/superpowers/plans/2026-09-12-leonida-vice-slice.md +++ b/docs/superpowers/plans/2026-09-12-leonida-vice-slice.md @@ -534,6 +534,13 @@ def test_unknown_pixels_are_filled_from_neighbours(): labels = classify(img) assert (labels == CLASSES["stadt"]).all() +def test_reports_the_share_of_unknown_pixels(): + img = block(PALETTE["stadt"], 16) + img[7:9, 7:9] = (255, 0, 255) # 4 von 256 Pixeln passen zu keiner Farbe + labels, share = classify(img, report_unknown=True) + assert (labels == CLASSES["stadt"]).all() + assert abs(share - 4 / 256) < 1e-9 + def test_shares_sum_to_one(): img = np.concatenate([block(PALETTE["wasser"], 8), block(PALETTE["land"], 8)], axis=1) shares = class_shares(classify(img)) @@ -569,18 +576,23 @@ UNKNOWN = 255 MAX_DELTA_E = 14.0 # darüber gilt ein Pixel als unbekannt (Beschriftung, Icon, Kante) -def classify(rgb: np.ndarray) -> np.ndarray: - """Ordnet jedes Pixel der nächsten Palettenfarbe zu; Ausreißer werden aufgefüllt.""" +def classify(rgb: np.ndarray, report_unknown: bool = False): + """Ordnet jedes Pixel der nächsten Palettenfarbe zu; Ausreißer werden aufgefüllt. + + Mit report_unknown=True kommt zusätzlich der Anteil der Pixel zurück, die vor dem + Auffüllen zu keiner Legendenfarbe passten. Aufgabe 6 bricht darüber bei über 5 % ab. + """ lab = rgb2lab(rgb.astype(np.float32) / 255.0) ref = rgb2lab(np.array([list(PALETTE.values())], dtype=np.float32) / 255.0)[0] dist = np.linalg.norm(lab[:, :, None, :] - ref[None, None, :, :], axis=3) labels = dist.argmin(axis=2).astype(np.uint8) unknown = dist.min(axis=2) > MAX_DELTA_E + share = float(unknown.mean()) if unknown.any(): # Nächstes bekanntes Pixel übernehmen. idx = ndi.distance_transform_edt(unknown, return_distances=False, return_indices=True) labels = labels[tuple(idx)] - return labels + return (labels, share) if report_unknown else labels def class_shares(labels: np.ndarray) -> dict[str, float]: