docs: zwei Fehler im Referenzcode von Aufgabe 4 korrigiert
- Löcher werden über das Vorzeichen der Shoelace-Summe erkannt; die Stichprobe am Konturmittelpunkt versagt bei einer Insel mit Lagune - das Brückenfenster braucht einen Rand, sonst enthält es nur Straßenpixel und die Erkennung löst nie aus Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
6452223c24
commit
fb898b03b3
1 file changed
+17
-7
@@ -701,6 +701,7 @@ from .classify import CLASSES
|
|||||||
from .coords import SLICE
|
from .coords import SLICE
|
||||||
|
|
||||||
ROAD_CLASSES = ("strasse", "weg", "spekulativ")
|
ROAD_CLASSES = ("strasse", "weg", "spekulativ")
|
||||||
|
BRIDGE_MARGIN_PX = 3
|
||||||
|
|
||||||
|
|
||||||
def _to_world(contour: np.ndarray) -> list[tuple[float, float]]:
|
def _to_world(contour: np.ndarray) -> list[tuple[float, float]]:
|
||||||
@@ -718,7 +719,7 @@ def mask_polygons(mask: np.ndarray, min_area: float, simplify: float) -> list[Po
|
|||||||
poly = Polygon(ring).buffer(0)
|
poly = Polygon(ring).buffer(0)
|
||||||
if poly.is_empty or poly.area < min_area:
|
if poly.is_empty or poly.area < min_area:
|
||||||
continue
|
continue
|
||||||
(holes if not _is_outer(mask, contour - 1) else outers).append(poly)
|
(outers if _signed_area(contour - 1) > 0 else holes).append(poly)
|
||||||
result = []
|
result = []
|
||||||
for outer in outers:
|
for outer in outers:
|
||||||
inner = [h.exterior.coords for h in holes if outer.contains(h)]
|
inner = [h.exterior.coords for h in holes if outer.contains(h)]
|
||||||
@@ -726,12 +727,16 @@ def mask_polygons(mask: np.ndarray, min_area: float, simplify: float) -> list[Po
|
|||||||
return [p for p in result if p.geom_type == "Polygon" and p.area >= min_area]
|
return [p for p in result if p.geom_type == "Polygon" and p.area >= min_area]
|
||||||
|
|
||||||
|
|
||||||
def _is_outer(mask: np.ndarray, contour: np.ndarray) -> bool:
|
def _signed_area(contour: np.ndarray) -> float:
|
||||||
"""Innen liegende Konturen umschließen Löcher."""
|
"""Shoelace-Summe in Pixelkoordinaten (Zeile, Spalte).
|
||||||
r, c = contour.mean(axis=0)
|
|
||||||
r = int(np.clip(r, 0, mask.shape[0] - 1))
|
find_contours liefert Außenkonturen und Löcher mit entgegengesetztem Umlaufsinn;
|
||||||
c = int(np.clip(c, 0, mask.shape[1] - 1))
|
das Vorzeichen trennt sie zuverlässig. Eine Stichprobe der Maske am Mittelpunkt der
|
||||||
return bool(mask[r, c])
|
Kontur versagt bei konzentrischen Formen: bei einer Insel mit Lagune liegt der
|
||||||
|
Mittelpunkt der Außenkontur selbst in der Lagune.
|
||||||
|
"""
|
||||||
|
row, col = contour[:, 0], contour[:, 1]
|
||||||
|
return float(0.5 * np.sum(col * np.roll(row, -1) - np.roll(col, -1) * row))
|
||||||
|
|
||||||
|
|
||||||
def land_polygons(labels: np.ndarray) -> list[Polygon]:
|
def land_polygons(labels: np.ndarray) -> list[Polygon]:
|
||||||
@@ -754,6 +759,11 @@ def road_polygons(labels: np.ndarray) -> list[tuple[Polygon, bool]]:
|
|||||||
out = []
|
out = []
|
||||||
for poly in polys:
|
for poly in polys:
|
||||||
r0, c0, r1, c1 = _bbox_px(poly)
|
r0, c0, r1, c1 = _bbox_px(poly)
|
||||||
|
# Ohne Rand enthält das Fenster nur Straßenpixel und damit nie Wasser.
|
||||||
|
r0 = max(r0 - BRIDGE_MARGIN_PX, 0)
|
||||||
|
c0 = max(c0 - BRIDGE_MARGIN_PX, 0)
|
||||||
|
r1 = min(r1 + BRIDGE_MARGIN_PX, water.shape[0] - 1)
|
||||||
|
c1 = min(c1 + BRIDGE_MARGIN_PX, water.shape[1] - 1)
|
||||||
window = water[r0:r1 + 1, c0:c1 + 1]
|
window = water[r0:r1 + 1, c0:c1 + 1]
|
||||||
out.append((poly, bool(window.mean() > 0.3)))
|
out.append((poly, bool(window.mean() > 0.3)))
|
||||||
return out
|
return out
|
||||||
|
|||||||
Reference in new issue
Block a user