material-raster: prefer authoritative land-cover masks over satellite color - #100
Merged
Merged
Conversation
…ver satellite color A full scene bundle already ships the scene pipeline's OSM + ML (unet-efficientnet) land-cover as per-cell masks — foliage_mask.png (land class 0..5: tree/grass/shrub -> foliage, rock, bare -> soil), roads.png / water.png / open_fields.png (alpha masks) — which is far more accurate than a satellite color heuristic (it has the real OSM waterways + true vegetation, not muted-green false positives). - segment_from_masks(bundle, rows, cols): build the material_id grid from those masks when present, priority (later wins) open_air default -> open_fields=soil -> foliage classes -> water -> roads =open_air (you drive on roads, even through vegetation/fields); downsample to the grid by MAJORITY class, flip to row 0 == min_y. Returns None if the masks are absent (a lean bundle). - from_bundle now PREFERS the masks and falls back to classify(satellite.png) only when they are missing (e.g. the lean DBG bundle the demo/harness ship). Same material.json format either way; the C++ cvc::nav segmenter mirrors this logic for byte-parity. - Refactor the material.json write into _write() shared by generate() + from_bundle(). Austin (full bundle, mask-derived): open_air 81% / foliage 16.5% / water 2.2% (found the OSM creek the color classifier missed) vs the satellite heuristic's over-tagged foliage 31%. 4 new tests (mask mapping+priority+flip, absent->None, satellite fallback). 8/8, black/ruff clean.
…riented) write_preview flips rows for DISPLAY so the tag map reads north-up like the satellite / a human map; the material_id DATA is unchanged and stays sim-oriented (row 0 == world min_y), aligned with occupancy (verified: occupancy_from_model rasterizes row = (y-min_y)*sy, and world building footprints match the satellite only under a rows-flip). The south-up preview was the only thing that looked mirrored; the raster itself samples correctly.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Upgrade
grl-snam material-raster(and the shared logic the new C++ cvc::nav version will mirror) to prefer the bundle's authoritative land-cover masks over the satellite color heuristic, per the source-strategy decision.Why
A full scene bundle already ships the scene pipeline's OSM + ML (unet-efficientnet-b4) land cover as per-cell masks — far more accurate than classifying
satellite.png:foliage_mask.png— per-pixel land class (1 tree / 2 grass / 4 shrub → foliage; 3 rock; 5 bare → soil)roads.png/water.png/open_fields.png— alpha masks (roads → open_air, water → water, open_fields → soil)The color heuristic over-tagged foliage (31%, from muted-green urban tones) and missed the OSM waterways; the masks give the real vegetation (16.5%) and the actual creek.
What
segment_from_masks(bundle, rows, cols)— buildmaterial_idfrom the masks when present. Priority (later wins):open_airdefault →open_fields=soil → foliage classes → water → roads=open_air (you drive on roads, even through vegetation/fields). Downsampled by majority class, flipped to row 0 == worldmin_y. ReturnsNoneif masks absent.from_bundlenow prefers the masks and falls back toclassify(satellite.png)only when they're missing (the lean DBG bundle the demo/harness ship). Samematerial.jsonformat either way — the C++ cvc::nav segmenter mirrors this for byte-parity._write().Validated
Austin full bundle (mask-derived): open_air 81% / foliage 16.5% / water 2.2% — visually tracks the OSM land cover incl. the creek. 4 new tests (mask mapping+priority+flip, absent→None, satellite fallback); 8/8, black/ruff clean.