Bildverarbeitung & Satellitendaten: Transparente Bereiche speichern (Python, rasterio, shapely, numpy, matplotlib)

Hey Leute,

ich spiele gerade mit Satellitendaten rum und möchte unter anderem das Stadtgebiet München aus einer GeoTIFF-Aufnahme herausschneiden – das klappt soweit auch, indem ich rasterio.mask() nutze. Allerdings möchte ich, dass der Bereich außerhalb der Stadt transparent ist und nicht so :arrow_down_small: aussieht

Das Problem (so wie ich es einschätze) liegt logischerweise darin, dass numpy-Arrays nur die Form eines Tensors annehmen können und die Stadt München leider davon abweicht bzw. dass irgendein Wert, im Falle von GeoTIFF der nodata-Wert, bei mir nodata = 0 (damit hast du nicht gerechnet, stimmt’s? :P), verwendet werden muss, um die Bereiche aufzufüllen, von dem ich nicht annehmen kann, dass er in meiner Geometrie nicht vorkommt, weshalb ich ihn nicht einfach herausfiltern kann. Oder anders gesagt: Wenn ich alles, was nodata/0 entspricht filtere, können Lücken innerhalb des Stadtgebietes auftreten, was ich vermeiden möchte.

Die Metadaten (auch wenn nicht alle für meine Frage notwendig sind) des Bildes lauten:

{
  'driver': 'GTiff',
  'dtype': 'uint16',
  'nodata': 0.0,
  'width': 7711,
  'height': 7821,
  'count': 1,
  'crs': CRS.from_epsg(32632),
  'transform': Affine(30.0, 0.0, 574785.0, 0.0, -30.0, 5532615.0)
}

Mir fallen zwar ein bis zwei Workarounds ein, bspw. dtype ändern, nodata < 0 verwenden, Form herausschneiden, nodata filtern/transparent setzen, dytpe auf Ursprungswert legen, aber schöner wäre natürlich eine direkte/konkrete Lösung. Vielleicht muss man auch den dtype ändern, nodata < 0 verwenden, die Form herausschneiden, Transparenz eif
Deswegen möchte ich euch um Vorschläge bitten. :slight_smile:

Das FSI-Forum kann keine (Geo)TIFF-Dateien verarbeiten, falls ihr mit dem Bild selbst herumexperimentieren möchtet.

Ich habe es inzwischen gelöst, Details folgen.

Wie angekündigt, meine Lösung: Per

with rasterio.open(PFAD', 'r') as src:
    out_image, out_transform = mask(src, geometry, crop=True, filled=False)

wobei geometry die Geometrie, bspw. das Polygon der Münchner Stadtgrenze, enthält. out_image enthält dabei das Bild (einschließlich der nodata-Werte außerhalb von geometry), als auch eine Maske in out_image.mask[0], dh. ein 2D-numpy-bool-Array (im Folgenden mask genannt), das (!) True außerhalb der Geometrie, bspw. des Polygons, und False innerhalb dieser ist. mask kann man per ~mask invertieren und genau das benötigt man für das Außblenden der Bereiche außerhalb. Per matplotlib kann man bspw. Arrays als RGB- und/oder RGBA-Bilder speichern – macht man Zweiteres, muss man lediglich die zuvor per ~mask invertierte Maske als Alpha-Kanal verwenden und man hat’s.


(Die Rot-Gelbe-Farbpalette liegt an meiner Verarbeitung, ich habe obiges Bild gerade nicht anders vorliegen.)