init-research
Signed-off-by: nq <nq>
This commit is contained in:
File diff suppressed because it is too large
Load Diff
253
readme.md
Normal file
253
readme.md
Normal file
@@ -0,0 +1,253 @@
|
||||
# Pipeline design for detecting blue rectangles in BGtopoVJ and scoring 60k coordinates
|
||||
|
||||
## Executive summary
|
||||
|
||||
The most efficient pipeline is **hybrid and source-aware**, not “pure deep learning from day one.” The prioritized source pass suggests a strong split of responsibilities: use the **per-sheet original raster files** as the canonical training source; use the **Garmin/vector products** as a possible weak-label source if they can be decompiled or converted; use the **processed and merged raster products** for fast visual QA and large-area scanning; and train the final **coordinate-level predictor** on georeferenced centered crops plus detector-derived features. That recommendation comes directly from the BGtopoVJ format inventory, the site’s own build/toolchain references, and the GitHub tooling that already exists for Polish `.mp`, GeoJSON conversion, ECW access, raster tiling, and georeferencing. citeturn22view0turn28view0turn31search1turn19view0turn19view1turn19view2turn19view3turn19view4turn39search0
|
||||
|
||||
The best canonical source for training is **the original per-sheet TIFF plus its `.map` sidecar**, not the mobile/tiled variants. The university mirror states that the underlying data are **1:50,000 Soviet army raster TIF images**, scanned at **250 dpi**, **8-bit**, with an effective **~5.5 m/pixel** resolution, over **544 sheets** and **3240 tiles**. Per-sheet pages expose four downloadable items for each sheet: original raster image, processed raster image, Garmin vector map, and processed raster for MapNav; the original raster directory shows that each sheet is paired with a `.tif` image and a `.map` calibration file. citeturn22view0turn24search1turn28view0turn31search1
|
||||
|
||||
The best first production model is **not** a single end-to-end detector. It is a staged stack: **OpenCV rules** for candidate mining and hard-negative discovery, **YOLOv8s** or **RetinaNet** for scalable symbol detection, **Mask R-CNN** or a small **U-Net** only if fill-style discrimination remains weak, and then a **calibrated coordinate scorer** that converts local detections into the final “should this coordinate have a blue square/rectangle?” probability. The detector literature, official training docs, and calibration literature all support this structure: one-stage models are efficient, RetinaNet explicitly addresses foreground/background imbalance with focal loss, Mask R-CNN adds instance masks with modest overhead, U-Net remains strong for small-mask segmentation with limited data, and temperature scaling is still one of the simplest reliable ways to calibrate probabilities. citeturn40search0turn40search5turn40search6turn41search0turn41search4turn41search6turn42search8turn43search6turn43search8turn43search2turn45search12turn46search4
|
||||
|
||||
A separate pass over adspem.com did **not** surface actionable BGtopoVJ-specific technical material during this research run, and a direct access attempt timed out. In practical terms, that means the design below should be grounded in the much more concrete evidence from entity["company","GitHub","code hosting platform"], the mirrored BGtopoVJ site hosted by the CART Lab at entity["organization","University of Plovdiv Paisii Hilendarski","plovdiv bulgaria"], and the official documentation/original papers that describe the GIS and ML stack. citeturn7view0turn22view0
|
||||
|
||||
## Source triage and acquisition
|
||||
|
||||
A pass over GitHub did not reveal a turnkey “detect blue BGtopoVJ squares” repository, but it **did** reveal several building blocks that materially change the project design. The highest-value repositories are: a **QGIS Polish-format plugin** that can import and export `.mp` files, an **MP-to-GeoJSON converter**, **GDAL-based raster tiling/merging scripts**, a **rio-tiler** wrapper around Rasterio/GDAL for point/part/tile reads, an **ECW GDAL plugin** helper, and **MapWarper** for map rectification/export to GeoTIFF/WMS/tiles. Those tools are exactly the pieces you need if you want a vector-assisted weak-label branch, georeferenced tile extraction, full-area scanning, and human QA over dedicated validation areas. citeturn19view0turn19view1turn19view2turn19view3turn19view4turn39search0turn39search1
|
||||
|
||||
The BGtopoVJ mirror is the authoritative source for map formats and technical metadata. It lists support for **Garmin GPSr**, **Garmin MapSource/BaseCamp**, **ECW**, **JNX**, **MapNav**, **OsmAnd / Locus Map**, **OruxMaps**, **NaviComputer**, **WWW**, and **WMS**. It also states that the project goal was to make popular Soviet military raster maps free to use on Garmin-compatible devices, and that the workflow used tools such as Mapwel, GMapTool, Global Mapper, and cGPSmapper. citeturn22view0turn17search0
|
||||
|
||||
The site’s download section is unusually informative and is directly useful for planning source ingestion. The merged **ECW** product is georeferenced in **UTM zone 35 / WGS84**; the merged **JNX** product is **Geographic / WGS84**; the **MapNav** version is **Mercator** and loads `*.mno` or `*mnm` raster maps; the **OsmAnd/Locus** and **OruxMaps** products expose pre-tiled zoom pyramids; and the **NaviComputer** product is a `.nmap` archive. The page also exposes full archive sizes, which matter for storage planning, and notes that the mobile/offline variants use zoom levels roughly in the **6–14** range. citeturn22view0turn24search1
|
||||
|
||||
The per-sheet pages matter even more than the merged downloads because they expose the data model you want to automate against. Each sheet page lists **original raster image**, **processed raster image**, **vector map suitable for Garmin GPSr devices**, and **processed raster image for MapNav**. The page icons and link behavior indicate that the original and processed raster products are **TIFF-based**, the Garmin map is **IMG-based**, and the MapNav product is packaged separately. The original raster directory listing further shows the crucial pairing of **`.tif` image + `.map` calibration file**, and it also exposes a **`100k/`** subdirectory, which means your ingestion manifest must explicitly separate **1:50k** and **1:100k** materials to avoid symbol-scale leakage. citeturn28view0turn29view0turn29view1turn29view2turn29view3turn31search1
|
||||
|
||||
That `.map` sidecar is not just a nuisance file; it is an advantage. Official OziExplorer documentation says a `.map` file stores the **image path**, **datum**, **projection**, and **calibration/georeferencing** information, and GDAL has a built-in **MAP / OziExplorer** raster driver with georeferencing support. In other words, a per-sheet BGtopoVJ “original raster” is a georeferenceable pair you can parse directly into a robust coordinate-to-pixel pipeline. citeturn37search0turn37search1turn37search2
|
||||
|
||||
The final source-triage conclusion is important: **start with original TIFF+MAP**, not with ECW and not with mobile tile packages, and treat the Garmin/vector branch as a **high-upside auxiliary path**. The reason is that the BGtopoVJ site explicitly says the separate vector archives are based on **BGtopoVJ-v2.00** data, while the merged raster products and the current public release are **v3.00**. That makes vector-derived features or pseudo-labels very useful, but not safe as the sole source of truth unless you version-track them carefully. citeturn22view0
|
||||
|
||||
All format, projection, and packaging details in the following table come from the BGtopoVJ mirror and its per-sheet pages. citeturn22view0turn28view0turn31search1
|
||||
|
||||
| Source product | What you actually get | Why it matters | Recommended use |
|
||||
|---|---|---|---|
|
||||
| Original per-sheet raster | `sheet.tif` + `sheet.map` | Canonical scan, per-sheet georeferencing, closest to source symbology | **Primary training source** |
|
||||
| Processed per-sheet raster | TIFF-based processed raster | Cleaner colors and less noise than original | Weak-label mining, annotator QA |
|
||||
| Garmin vector sheet | IMG-based vector map | Potential vector-assisted pseudo-labels or semantic cross-checks | Auxiliary branch only |
|
||||
| Merged ECW | Country-scale georeferenced raster, UTM 35 / WGS84 | Fast large-area scanning and QA mosaic | Secondary inference source |
|
||||
| Merged JNX | Country-scale georeferenced raster, Geographic / WGS84 | Easier coordinate lookup for some GPS workflows | Secondary/QA only |
|
||||
| MapNav | Mercator raster package | Existing mobile-ready pyramid | Optional QA source |
|
||||
| OsmAnd / Locus | Tiled zoom-pyramid package | Easy casual browsing, but resampled | Human review only |
|
||||
| OruxMaps | Tiled zoom-pyramid package | Useful for spot-checking by area | Human review only |
|
||||
| NaviComputer | `.nmap` archive | Offline browsing | Human review only |
|
||||
| WWW / WMS | Web-served rendering | Useful for dedicated-area validation dashboards | QA and visualization |
|
||||
|
||||
## Data engineering and labeling design
|
||||
|
||||
The central engineering decision is to make the **per-sheet original TIFF+MAP pair** your canonical object space, and to preserve that provenance all the way through the pipeline. The BGtopoVJ changelog says later releases added **despeckling**, improved **contrast**, improved **georeferencing precision**, improved and harmonized **resolution**, reduced tile counts, and a harmonized **32-color palette**. Those improvements are useful operationally, but they are exactly why you should not silently mix “original,” “processed,” “merged ECW,” and “mobile tile” imagery in one training pool without a `source_format` and `source_version` field. citeturn22view0
|
||||
|
||||
For georeferencing and coordinate alignment, use the `.map` sidecar through **GDAL’s MAP driver** or by parsing the OziExplorer file directly, then expose the transform through Rasterio. Rasterio’s transform utilities provide `xy()` and `rowcol()` conversions between pixel and projected/geographic coordinates, while its windowed-reading APIs and window transforms let you extract georeferenced crop windows without loading whole sheets into memory. That is the right primitive for both map-wide scanning and centered-crop extraction around the 60k coordinates. citeturn37search0turn37search1turn47search1turn47search3
|
||||
|
||||
A robust ingestion pipeline should therefore do five things before any ML starts. First, crawl the original-raster directory and per-sheet pages into a **manifest** keyed by `sheet_id`, `scale`, `image_path`, `map_path`, `bounds`, `projection`, `edition_year`, and `source_format`. Second, reject or quarantine the `100k/` materials until the 1:50k pipeline is stable. Third, convert all 60k coordinates into a **single normalized CRS** and then into each candidate sheet’s CRS. Fourth, assign each coordinate to one or more overlapping sheet footprints. Fifth, extract **multi-scale crop windows** around each candidate coordinate from the canonical source, not from screenshots or WMS renderings. citeturn31search1turn37search0turn47search1turn47search3
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
A[Inventory BGtopoVJ files] --> B[Parse TIFF plus MAP georeferencing]
|
||||
B --> C[Build sheet footprints and manifest]
|
||||
C --> D[Align 60k coordinates to sheets]
|
||||
D --> E[Extract centered multi-scale crops]
|
||||
E --> F[Weak-label candidates from color, shape, vectors]
|
||||
F --> G[Human review in CVAT or Label Studio]
|
||||
G --> H[Train detector and optional segmenter]
|
||||
H --> I[Train calibrated coordinate scorer]
|
||||
I --> J[Dedicated-area validation]
|
||||
J --> K[Expand dataset and rescan corpus]
|
||||
```
|
||||
|
||||
For annotation, use a **hierarchical schema**, not a flat explosion of combined classes. Your task description naturally decomposes into geometry, fill style, and color shade; training will be much easier if you keep those separate at the data level even if the first-generation model collapses them into a smaller set. The site itself says BGtopoVJ uses standard Soviet military map symbols, and it points to the English-language **Soviet Topographic Map Symbols** manual as a reference. That is a strong reason to keep room for semantic expansion later, even if you begin with purely visual classes. citeturn22view0turn21search1turn21search10
|
||||
|
||||
| Annotation field | Suggested values | Why it helps |
|
||||
|---|---|---|
|
||||
| `presence` | `positive`, `negative`, `uncertain` | Needed for the final 60k-coordinate decision task |
|
||||
| `shape` | `square`, `rectangle`, `unknown_quad` | Preserves geometry without overfitting early |
|
||||
| `fill_style` | `filled`, `hollow`, `border_emphasis`, `unknown_fill` | Handles your filled/empty/bordered requirement cleanly |
|
||||
| `shade_bin` | `dark_blue`, `blue`, `light_blue`, `cyan_other` | Supports later color-robustness studies |
|
||||
| `annotation_type` | `bbox`, `polygon`, `mask`, `weak_label` | Tracks label reliability |
|
||||
| `source_format` | `orig_tif_map`, `proc_tif_map`, `ecw`, `img_vector` | Prevents silent domain mixing |
|
||||
| `review_status` | `weak`, `verified`, `rejected`, `border_case` | Critical for auditing weak labels |
|
||||
| `uncertain_reason` | `tile_edge`, `sheet_edge`, `low_contrast`, `blue_non_target`, `vector_mismatch`, `other` | Makes the error-analysis loop efficient |
|
||||
|
||||
A good review overlay should make class distinctions obvious to annotators and reviewers. An illustrative overlay convention is below.
|
||||
|
||||
```text
|
||||
Example review overlay on a centered crop
|
||||
|
||||
┌─────────────────────────────────────────────┐
|
||||
│ map background │
|
||||
│ │
|
||||
│ ┌──────┐ │
|
||||
│ │██████│ cyan solid box = filled │
|
||||
│ └──────┘ │
|
||||
│ │
|
||||
│ ┌──────┐ │
|
||||
│ ○ │ │ blue outline = hollow
|
||||
│ coordinate └──────┘ │
|
||||
│ │
|
||||
│ ┏━━━━━━━━┓ │
|
||||
│ ┃ ┃ navy thick outline = border │
|
||||
│ ┗━━━━━━━━┛ │
|
||||
│ │
|
||||
│ - - - dashed yellow box = uncertain │
|
||||
└─────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
For label generation, do **not** start with manual boxing of all 60k points. Start with **weak labels**. The cheapest first pass is a color-and-shape detector in OpenCV: convert to HSV or Lab, threshold the blue/light-blue ranges, clean masks with morphology, recover contours, approximate them to quadrilaterals, and classify them by border occupancy and fill ratio. OpenCV’s `inRange`, contour extraction, polygon approximation, and template matching are all directly relevant here. This weak-label stage will not be your final model, but it will dramatically cut annotation burden and produce the hard negatives you need. citeturn40search6turn40search5turn40search11turn40search0turn40search7
|
||||
|
||||
The GitHub/vector branch can reduce annotation cost even further. Because the university workflow references Mapwel, GMapTool, and Garmin IMG outputs, and because GitHub tooling already exists for **Polish `.mp` import/export** and **MP-to-GeoJSON conversion**, you should explicitly test a side pipeline of **IMG → MP/GeoJSON → candidate features**. If a subset of the target blue symbols survives that conversion as stable vector features or type/style codes, those outputs can become high-quality pseudo-labels or at least a powerful review prior. If they do not, the test still pays for itself by proving that the raster detector must carry the load. citeturn17search0turn19view0turn19view1turn22view0
|
||||
|
||||
For the final coordinate labels, I recommend a strict three-state policy. A coordinate is **positive** if a reviewed target symbol is present in the search neighborhood and the coordinate aligns to that symbol under the project’s chosen tolerance. It is **negative** only if the local crop quality is acceptable and no target symbol is present after review or after a sufficiently reliable detector pass. It is **uncertain** if the coordinate is near a sheet edge, a tile seam, a clipped symbol, a color-ambiguous mark, a candidate produced only by one source domain, or a case where the cartographic placement is visually ambiguous. In practice, uncertain labels should be excluded from first-pass supervised loss and reserved for active-learning review and calibration.
|
||||
|
||||
CVAT is the cleanest annotation front end for this project because its COCO export format natively supports **bounding boxes, polygons, masks, and tracks**, and it emits a predictable zip layout that is easy to feed into PyTorch and Detectron2 pipelines. Label Studio is also viable, especially if your team prefers its export APIs and raw JSON model, but CVAT aligns more naturally with a box-first, mask-optional computer-vision workflow. citeturn46search0turn47search4turn47search5
|
||||
|
||||
## Model options and recommended stack
|
||||
|
||||
Because the target objects are **tiny**, **blue**, and **shape-constrained**, different model families solve different parts of the task well. Classical CV and template matching are excellent for bootstrapping. One-stage detectors are best for scaling to map-wide scans. Two-stage detectors are strong when accuracy on small objects matters more than speed. Segmentation becomes worthwhile only when distinguishing filled versus hollow versus border-emphasis proves difficult from boxes alone. The final coordinate question is best answered by a **hybrid coordinate scorer** that consumes detector outputs rather than by a detector alone. citeturn40search0turn40search5turn40search6turn41search0turn41search4turn42search8turn43search6turn43search8turn45search12turn43search2
|
||||
|
||||
The comparison below combines published model characteristics with practical recommendations for this specific cartographic-symbol task. Published YOLOv8 sizes/speeds come from the Ultralytics model card, and Faster/Mask/Retina benchmark speed-memory figures come from the official MMDetection benchmark documentation. Practical budgets for 1024px map tiles are my estimates, because your tile sizes and augmentations will differ from those benchmark settings. citeturn41search4turn41search6turn42search8
|
||||
|
||||
| Option | Best role | Main advantages | Main limitations | Likely data need | Practical starting point |
|
||||
|---|---|---|---|---|---|
|
||||
| Classical CV with color + contours | Weak-label miner, baseline | Explainable, fast, CPU-only, no training | Brittle to palette drift, blue hydrography, noise | 50–100 reviewed examples to tune thresholds | HSV/Lab thresholding, morphology, contour quad filters |
|
||||
| Template matching | High-precision candidate miner | Very good when symbol shapes are stable | Sensitive to scale, scan noise, and style variation | 20–100 templates/class | Masked normalized cross-correlation across a small scale bank |
|
||||
| YOLOv8n / YOLOv8s | Main production detector | Easy training, strong ecosystem, fast inference | Tiny hollow symbols may need large images and careful tiling | ~1k–3k positive instances | `imgsz=1024–1280`, 100–150 epochs, low color jitter |
|
||||
| Faster R-CNN | Accuracy-first detector | Strong small-object baseline, robust with FPN | Slower inference and heavier training | ~2k–5k positives | ResNet-50-FPN, smaller anchors than COCO defaults |
|
||||
| RetinaNet | Imbalance-aware detector | Focal loss helps with hard negatives | Can be slower than YOLO, still needs tuning | ~2k–5k positives | ResNet-50-FPN, small anchors, hard-negative mining |
|
||||
| Mask R-CNN | Box + mask + fill-style modeling | Distinguishes interior fill and border shape better | More compute, more label structure | ~1k+ verified masks or auto-masks | Use if fill-style errors dominate after box detection |
|
||||
| U-Net on centered crops | Coordinate-centered segmentation | Very strong on local pixel masks with little data | Not a full-scene detector by itself | ~1k–3k crop masks | 256–512 px crops, Dice + BCE or Dice + focal |
|
||||
| Hybrid detector + coordinate scorer | **Recommended final system** | Optimizes the actual end task and supports QA expansion | More moving parts | Moderate | Detector outputs + local crop features + calibration |
|
||||
|
||||
A practical compute view is below. Again, the published figures are not your exact training cost, but they are useful anchors for budget planning. citeturn41search4turn42search8turn41search0
|
||||
|
||||
| Model family | Published reference point | Practical budget for this task |
|
||||
|---|---|---|
|
||||
| YOLOv8n | 3.2M params; 0.99 ms A100 TensorRT at 640px | Good pilot model on a 12–16 GB GPU with 1024px tiles |
|
||||
| YOLOv8s | 11.2M params; 1.20 ms A100 TensorRT at 640px | Best first production detector on a 16–24 GB GPU |
|
||||
| YOLOv8m | 25.9M params; 1.83 ms A100 TensorRT at 640px | Use only if YOLOv8s misses too many small symbols |
|
||||
| Faster R-CNN | Benchmark training memory about 3.0 GB in published setting | Budget 16 GB+ for larger map tiles and stable training |
|
||||
| Mask R-CNN | Benchmark training memory about 3.4 GB in published setting | Budget 16–24 GB if masks are enabled on 1024px tiles |
|
||||
| RetinaNet | Benchmark training memory about 3.9 GB in published setting | Budget 16 GB+ if using hard-negative-heavy training |
|
||||
|
||||
For **hyperparameters**, I would start conservatively and preserve the map’s discriminative color information. For YOLOv8, use **1024 or 1280 px tiles**, **100–150 epochs**, light augmentations, and minimal hue shift because the blue-vs-non-blue distinction is central. Keep flips if symbol semantics allow them, but avoid strong perspective transforms and aggressive mosaics because they can distort cartographic context. For Faster R-CNN/RetinaNet/Mask R-CNN, use a **ResNet-50-FPN** backbone, shrink anchor sizes to cover very small quadrilateral symbols, and start from COCO-pretrained weights via TorchVision or Detectron2. The official TorchVision tutorial is a good reference for custom detection/instance-segmentation datasets, and Detectron2 remains a strong option if you want richer experiment control. citeturn41search0turn41search5turn42search9turn42search6
|
||||
|
||||
My recommended build order is straightforward. First, ship a **rules-only candidate miner** and use it to seed annotation. Second, train a **YOLOv8s detector** on boxes only. Third, if filled vs hollow vs border-emphasis remains an operational error source, add either **Mask R-CNN** or a **small U-Net crop segmenter**. Fourth, train the final **coordinate scorer** on features such as nearest-detection class, confidence, distance, local blue-mask statistics, crop classifier outputs, and source-format flags. That last stage is the part that answers the user’s actual question and should be treated as the system of record.
|
||||
|
||||
If the vector-assisted branch works, it can reduce annotation effort substantially. If it fails, the project still remains viable because the raster branch is already complete enough to support weak labels, human review, and robust detector training.
|
||||
|
||||
## Evaluation and uncertainty
|
||||
|
||||
You need to evaluate **two tasks**, not one. The first task is **global symbol detection** on tiles or sheets. The second task is the real business target: **coordinate-level presence prediction** for the 60k points. For detection, the right core metrics are **precision, recall, F1**, **IoU**, **AP50**, **AP75**, and **mAP@[0.5:0.95]**, ideally reported both overall and by fill-style subclass if you keep them separate. For coordinate scoring, the most important metrics are **precision**, **recall**, **F1**, and **PR-AUC**; if you need trustworthy probabilities, also report **Brier score**, **expected calibration error**, and reliability diagrams after calibration. citeturn41search0turn45search12turn46search4
|
||||
|
||||
Use **spatial cross-validation**, not random crop splits. BGtopoVJ has hundreds of sheets at a common source scale, and its later releases harmonized palette and resolution. If you randomly split crops, you will leak near-duplicate local styles, neighboring map content, and source-specific palette statistics across train and validation sets. The correct split primitive is the **sheet ID** or a larger contiguous geographic block. A good default is **GroupKFold by sheet**, plus one **frozen dedicated validation area** that is never touched during model development. The “dedicated area” should be a contiguous region rather than a random point sample, otherwise deployment risk will be underestimated. citeturn22view0turn31search1
|
||||
|
||||
Class imbalance should be treated as a first-class design issue because there are many blue non-target structures on topographic maps. Your hard negatives will include **rivers, lakes, canals, blue labels, blue linework, and blue outlines that are not the target rectangles/squares**. That is exactly the sort of dense foreground/background skew that RetinaNet’s **focal loss** was designed to address. Even if you choose YOLOv8 as the main detector, the lesson from RetinaNet still applies: populate the training set with **hard negatives**, not just random empty crops. citeturn43search6turn43search11
|
||||
|
||||
For uncertainty, use **calibration**, not just raw detector scores. The calibration literature remains clear that modern neural nets can be overconfident, and that **temperature scaling** is often a simple, strong post-processing fix. In practice, keep a clean validation split, fit a calibrator there, and then expose three operational zones: an **auto-positive** zone, an **auto-negative** zone, and a **human-review** zone in between. If your initial prior belief is that positives among candidate coordinates are around **80–90%**, use that belief to prioritize active-learning review and to set starting thresholds, but let the actual held-out dedicated area determine the final deployed prevalence estimate. citeturn46search4turn46search1
|
||||
|
||||
A simple operating policy is:
|
||||
|
||||
| Score band | Action |
|
||||
|---|---|
|
||||
| `p >= 0.90` | auto-positive |
|
||||
| `0.40 <= p < 0.90` | review unless detector evidence is exceptionally strong |
|
||||
| `0.10 < p < 0.40` | review if region is mission-critical; else uncertain |
|
||||
| `p <= 0.10` | auto-negative |
|
||||
|
||||
Those thresholds are not sacred; they are an operational starting point. Tune them to the precision target you actually care about.
|
||||
|
||||
The dedicated-area validation workflow should be explicit and repeatable. Pick one region that is **symbol-dense** and one region that is **symbol-sparse**. Freeze both. Run full tiling and full 60k-coordinate scoring there. Manually audit **all auto-positives**, **all uncertains**, and a **random sample of auto-negatives**. Only after that audit should you expand to neighboring areas and refresh the weak-label rules. That loop is where most real-world performance gains will come from.
|
||||
|
||||
## Deployment, deliverables, and timeline
|
||||
|
||||
For deployment, there are really two modes. The first is **batch scanning** over whole sheets or a merged raster. The second is **coordinate scoring** for the 60k points. Batch scanning should use georeferenced **windowed reads** aligned to raster block structure, with tile overlap so edge symbols are not missed; Rasterio’s window APIs and rio-tiler’s point/part/tile readers are well-suited to that. Coordinate scoring is lighter: once the sheet assignment is built, you can extract centered windows for the 60k coordinates and score them directly. citeturn47search3turn47search1turn19view4
|
||||
|
||||
For scalability, keep runtime format complexity low. Although BGtopoVJ provides a merged ECW and GDAL supports ECW through the Hexagon SDK, the official GDAL ECW documentation is clear that support depends on the **ECW SDK** and that licensing differs between desktop decode, compression, server deployment, and mobile contexts. That makes ECW fine for ingestion or QA, but a poor long-term training/runtime dependency unless you truly need it. The cleanest path is to ingest once and then standardize your internal processing on **TIFF / VRT / GeoTIFF / COG-like** workflows with Rasterio/GDAL. citeturn47search0turn19view3
|
||||
|
||||
The recommended software stack is therefore:
|
||||
|
||||
| Layer | Recommended tools |
|
||||
|---|---|
|
||||
| Ingestion and reprojection | GDAL, Rasterio, pyproj |
|
||||
| Large-raster windows and tile serving | Rasterio windows, rio-tiler |
|
||||
| Classical CV and weak labeling | OpenCV |
|
||||
| Detection and segmentation | PyTorch, TorchVision, Ultralytics, Detectron2 |
|
||||
| Annotation | CVAT, optionally Label Studio |
|
||||
| GIS QA and map review | QGIS, MapWarper-style overlay workflows |
|
||||
| Vector-assisted parsing | Polish-format/QGIS tooling, MP2GeoJSON, GMapTool-style utilities |
|
||||
|
||||
The concrete deliverables should be treated as first-class outputs, not side effects.
|
||||
|
||||
| Deliverable | Suggested format |
|
||||
|---|---|
|
||||
| Source manifest | `manifest.parquet` or `manifest.csv` with sheet bounds, CRS, source version, paths |
|
||||
| Reviewed symbol dataset | COCO zip for boxes and masks; optional YOLO text export |
|
||||
| Coordinate label table | `coordinates_labels.parquet` with `x`, `y`, `crs`, `sheet_id`, `presence`, `class_attrs`, `review_status` |
|
||||
| Train/val/test splits | `splits.yaml` or `folds.json` grouped by sheet/block |
|
||||
| Weak-label artifacts | `weak_candidates.geojson` or GeoParquet |
|
||||
| Trained detector weights | `model.pt` or `model.pth` |
|
||||
| Calibrator and coordinate scorer | serialized sklearn or PyTorch artifact |
|
||||
| Inference outputs | GeoParquet/GeoJSON/CSV with box geometry, class, confidence, calibrated score |
|
||||
| Reproducible environment | `Dockerfile`, `environment.yml`, `requirements.txt`, `Makefile` |
|
||||
| Validation package | overlay PNGs, HTML report, error slices, dedicated-area audit workbook |
|
||||
|
||||
A good repository skeleton would look like this:
|
||||
|
||||
```text
|
||||
data/
|
||||
raw/
|
||||
interim/
|
||||
tiles/
|
||||
annotations/
|
||||
models/
|
||||
src/
|
||||
01_inventory_bgtopovj.py
|
||||
02_parse_mapfiles.py
|
||||
03_assign_coordinates.py
|
||||
04_extract_tiles.py
|
||||
05_seed_candidates_cv.py
|
||||
06_vector_assisted_labels.py
|
||||
07_export_coco.py
|
||||
08_train_detector.py
|
||||
09_train_segmenter.py
|
||||
10_train_coordinate_scorer.py
|
||||
11_calibrate_eval.py
|
||||
12_infer_batch.py
|
||||
13_build_validation_report.py
|
||||
configs/
|
||||
docker/
|
||||
reports/
|
||||
```
|
||||
|
||||
The timeline below assumes one ML engineer and part-time annotation support.
|
||||
|
||||
| Stage | Practical duration | Main outputs |
|
||||
|---|---|---|
|
||||
| Corpus inventory and georeferencing | 3–5 days | Manifest, sheet footprints, coordinate-to-sheet assignment |
|
||||
| Weak-label miner and pilot review | 1–2 weeks | First reviewed boxes, hard-negative catalog |
|
||||
| First detector baseline | 1 week | YOLOv8s or RetinaNet baseline, initial metrics |
|
||||
| Optional segmentation branch | 1 week | Mask R-CNN or U-Net if fill-style errors remain |
|
||||
| Coordinate scorer and calibration | 3–5 days | Calibrated probabilities and uncertainty policy |
|
||||
| Dedicated-area validation | 3–5 days | Acceptance report, error taxonomy |
|
||||
| Packaging and reproducibility | 2–4 days | Docker/conda environment, scripts, docs |
|
||||
|
||||
Resource planning should be modest but not tiny. The BGtopoVJ archive sizes imply that raw inputs alone are already multi-gigabyte, and derived tiles, masks, overlays, and experiment outputs can easily expand that by an order of magnitude. A practical workstation target is **16+ CPU cores**, **64–128 GB RAM**, **1 GPU with 16–24 GB VRAM**, and **2–4 TB SSD**. If you stay with original per-sheet TIFF+MAP instead of relying on ECW during training, operational complexity drops sharply. citeturn22view0turn31search1turn47search0
|
||||
|
||||
The strongest step-by-step implementation plan is this:
|
||||
|
||||
1. **Inventory canonical sources** from the original per-sheet TIFF+MAP corpus, and freeze a manifest.
|
||||
2. **Normalize CRS handling** for the 60k coordinates and assign them to one or more sheets.
|
||||
3. **Build a weak-label miner** from blue-thresholding, contour filters, and optional vector-assisted pseudo-labels.
|
||||
4. **Review a pilot set** in CVAT and export COCO.
|
||||
5. **Train a YOLOv8s detector** on 1024px tiles with source-aware metadata.
|
||||
6. **Add a mask branch only if needed** for fill-style ambiguity.
|
||||
7. **Train a coordinate scorer** that converts local detections into calibrated probabilities.
|
||||
8. **Freeze a dedicated validation area**, audit it thoroughly, and only then expand to the broader corpus.
|
||||
9. **Package everything reproducibly** in Docker/conda, with manifest + splits + model cards + validation report.
|
||||
|
||||
If I had to choose one default architecture before seeing a single label, I would choose this: **original TIFF+MAP as truth, OpenCV weak-label miner, YOLOv8s as primary detector, calibrated coordinate scorer on top, CVAT for review, and a vector-assisted fallback branch tested early but trusted only after version-mismatch checks**. That design fits the source evidence best, keeps annotation cost under control, and preserves a clean path from pilot work to map-wide deployment.
|
||||
Reference in New Issue
Block a user