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 d274378..6a87b6d 100644 --- a/docs/superpowers/plans/2026-09-12-leonida-vice-slice.md +++ b/docs/superpowers/plans/2026-09-12-leonida-vice-slice.md @@ -1580,7 +1580,7 @@ def test_real_island_survives(): def test_mainland_is_never_dropped(): """Die groesste Nicht-Wasser-Komponente bleibt immer, auch voellig ohne Gruen und Sand.""" labels = np.full((200, 200), CLASSES["wasser"], dtype=np.uint8) - labels[10:190, 10:100] = CLASSES["stadt"] + labels[10:190, 10:100] = CLASSES["stadt"] # 16.200 px, ueber MAINLAND_MIN_SIZE out = drop_map_labels(labels) assert (out[10:190, 10:100] == CLASSES["stadt"]).all() ``` @@ -1598,6 +1598,12 @@ from scipy import ndimage as ndi NATURAL_CLASSES = ("gruen", "sand", "land") LABEL_MAX_NATURAL = 0.02 # Anteil natuerlicher Merkmale, ab dem eine Flaeche als echt gilt +# Ab dieser Groesse gilt die groesste Komponente als Festland und ist von der Pruefung +# ausgenommen. Ohne die Schwelle waere in einer Szene mit nur einer Komponente immer genau +# diese das "Festland" — ein einzelner Schriftzug im Wasser bliebe damit stehen. Am echten +# Mosaik aendert der Wert nichts: das Festland hat 5.852.263 px, der groesste Schriftzug +# 14.760 px, und ausgenommen wird ohnehin nur die groesste Komponente. +MAINLAND_MIN_SIZE = 15_000 def drop_map_labels(labels: np.ndarray) -> np.ndarray: @@ -1607,14 +1613,20 @@ def drop_map_labels(labels: np.ndarray) -> np.ndarray: sind farblich von echten Flaechen nicht zu unterscheiden. Trennbar sind sie erst als Region: ein Schriftzug im Wasser bildet eine eigene, vom Festland getrennte Nicht-Wasser- Komponente ohne jedes natuerliche Merkmal, waehrend eine echte Insel Gruen oder Sand - traegt. Die groesste Komponente ist immer das Festland und bleibt unangetastet. + traegt. Am echten Mosaik ist die Trennung zweigeteilt ohne Zwischenstufe: jede Komponente + hat entweder mindestens 37 % natuerliche Merkmale oder exakt 0 %. + + Die groesste Komponente gilt als Festland und bleibt unangetastet, sofern sie ueberhaupt + gross genug dafuer ist (MAINLAND_MIN_SIZE) — sonst wuerde in einer Szene aus einem + einzigen Schriftzug genau dieser zum Festland erklaert. """ solid = labels != CLASSES["wasser"] if not solid.any(): return labels components, count = ndi.label(solid, structure=np.ones((3, 3))) sizes = ndi.sum(solid, components, range(1, count + 1)) - mainland = int(np.argmax(sizes)) + 1 + largest = int(np.argmax(sizes)) + 1 + mainland = largest if sizes[largest - 1] >= MAINLAND_MIN_SIZE else 0 natural = np.zeros(labels.shape, dtype=bool) for name in NATURAL_CLASSES: natural |= labels == CLASSES[name]