Make an Earth-observation archive queryable by meaning (free-text and image-to-image search over tiles) and by change over time (construction, clearance, water extent, roads; with onset dating and false-alarm suppression), fully on-prem/offline, with incremental ingestion, geospatial provenance, and an analyst review queue.
- Plan and model choices: docs/PLAN.md
- Architecture note: docs/ARCHITECTURE.md
- Index build + incremental ingestion: docs/INDEX_BUILD.md
- Using the review console: docs/CONSOLE.md
- Model/dataset provenance and licences: docs/PROVENANCE.md
- References and citations: docs/CITATIONS.md
- Presentation figures: docs/figures/
- Auto-generated evaluation report:
netsight report→ docs/EVAL_REPORT.md
export VIRTUAL_ENV= ; uv venv .venv && uv pip install -e .
netsight ingest data/aoi/giga_berlin # GeoTIFF/COG folder → tiles → embeddings → LanceDB
netsight calibrate # fit the training-free retrieval calibration
netsight search "newly built structures near a river" --bbox 13.6,52.3,13.95,52.48 --date-from 2021-01-01
netsight change --bbox=13.70,52.36,13.85,52.42 --date-from 2019-06-01 --date-to 2023-06-01 --run-id berlin
netsight serve # the review console on http://127.0.0.1:8000Review console (netsight serve) — three panes over the same library the CLI uses, and completely
offline: Leaflet is vendored in-repo and the map's imagery layer is the indexed archive itself, served per
acquisition date, so no tile provider or CDN is ever contacted.
| pane | what it does |
|---|---|
| Search | free text, image upload, tile-to-tile "find similar", AOI/date/sensor/quality filters, per-hit ✓/✗ relevance feedback and Rocchio reranking |
| Change | review queue ranked by confidence × √area, before/after evidence panel with the candidate boxed, per-date distance-to-pre-change timeline, spectral and CLIP typing, flags, confirm/reject/unsure with notes, audit trail, provenance-preserving GeoJSON export |
| Discover | HDBSCAN clustering of an area in either embedding space, with exemplars, for unsupervised site discovery |
Text query over the archive. The basemap is the indexed imagery itself — the black area is simply outside what has been ingested, because there is no external tile provider.
Lake Oroville. 82 % of flagged patches share the 2020-10-16 onset — the signature of a bad acquisition. The spectral check (ΔNDVI −0.64 at flat brightness) rules it a real synchronous event, the September 2020 North Complex fire, so the candidates keep their confidence instead of being halved.
Models: RemoteCLIP ViT-L/14 for text-aligned retrieval (chosen over GeoRSCLIP by measurement — RSICD mean recall 36.9 vs 28.6), DINOv3 ViT-L/16 SAT-493M for visual similarity, clustering and dense change features, OmniCloudMask for cloud/shadow masks, and a small change head trained here on LEVIR-CD+ / SYSU-CD / S2Looking. Index: LanceDB (embedded, append-only, versioned, SQL-filterable).
Every design choice that could have gone either way was decided by an evaluation that is in the repo:
- which CLIP head, and which activation — four combinations run on RSICD test (
scripts/eval_retrieval.py) - whether score calibration helps — QB-Norm dynamic inverted softmax and modality-gap mean shift, swept
over β on two galleries (
scripts/eval_calibration.py); DIS ships on at β=20 as a small gain on RSICD and a wash on our own archive, mean shift measurably hurts and ships off - what an analyst click buys — text vs text+1 confirmed positive vs pure image exemplar, per concept
(
scripts/eval_feedback.py) - trained change head vs the training-free z-score — LEVIR-CD+/SYSU-CD/S2Looking/OSCD
(
scripts/train_change_head.py)
Results: docs/EVAL_REPORT.md, regenerated by netsight report.

