# GeoAI Workbench Current Context Last updated: 2026-08-24 This file is the current project snapshot for new Codex tasks. Keep it concise and replace stale facts instead of appending a conversation diary. ## Project Identity - Repository: `E:\AllWorkProject\geoai-workbench` - Technical foundation: [opengeos/geoai](https://github.com/opengeos/geoai), PyPI package `geoai-py`, import name `geoai`. - Purpose: build independently runnable GeoAI capability Demos for drone and remote-sensing workflows, then evaluate integration with existing products. - Product repositories in scope for later integration: - `E:\AllWorkProject\drone_project\ztzf-drone-web\applications\command-center-dashboard` - `E:\AllWorkProject\drone_project\ztzf-drone-web\applications\drone-web-manage` - Capability classification: A = direct `geoai-py`; B = GeoAI plus ecosystem libraries; C = product/service capability consuming GeoAI results. ## Collaboration and Constraints - The user is a beginner and can invest about 7-8 hours per day in running Demos and giving visual feedback. - Codex is expected to handle environment setup, code, model selection, debugging, verification, and iteration. - The machine runs Windows and PowerShell with 64 GB RAM and an AMD RX 590 GME 8 GB GPU. There is no NVIDIA CUDA, so current Demos use CPU inference. - Use Python 3.12 for capability environments. The system also has Python 3.13, which must not replace or contaminate project environments. - `geoai-py` is MIT-licensed, but every dependency, dataset, and model weight needs a separate commercial-license check. - Current JPEG samples have no usable georeferencing. Their detections use pixel coordinates; accurate GeoJSON requires a georeferenced GeoTIFF. ## Environment Snapshot Dedicated object-detection environment: `E:\AllWorkProject\geoai-workbench\.venvs\01-object-detection` | Component | Version | | --- | --- | | Python | 3.12.10 | | geoai-py | 0.42.0 | | torch | 2.13.0+cpu | | torchvision | 0.28.0+cpu | | rasterio | 1.5.1 | | geopandas | 1.1.4 | | ultralytics | 8.4.118 | `pip check` passes in this environment. Dedicated anomaly-detection environment: `D:\lgh\code\geoai-workbench\.venvs\09-anomaly-detection` | Component | Version | | --- | --- | | Python | 3.12.10 | | geoai-py | 0.42.0 | | scikit-learn | 1.9.0 | | SciPy | 1.18.0 | | rasterio | 1.5.1 | | geopandas | 1.1.4 | | OpenCV | 4.14.0 | The environment is CPU-only, contains no model weights, and `pip check` passes. Dedicated semantic-mapping environment: `E:\AllWorkProject\geoai-workbench\.venvs\02-semantic-mapping` | Component | Version | | --- | --- | | Python | 3.12.10 | | geoai-py | 0.42.0 | | rasterio | 1.5.1 | | geopandas | 1.1.4 | | OpenCV | 5.0.0 | The environment reuses the compatible package set from the verified object-detection environment after the isolated setup exceeded the dependency-download timeout. It has its own Python 3.12 interpreter and `pip check` passes. Dedicated spatial-measurement environment: `E:\AllWorkProject\geoai-workbench\.venvs\04-spatial-measurement` | Component | Version | | --- | --- | | Python | 3.12.10 | | geoai-py | 0.42.0 | | rasterio | 1.5.1 | | geopandas | 1.1.4 | | OpenCV | 4.14.0 | The environment is CPU-only and `pip check` passes. Dedicated trajectory-analysis environment: `E:\AllWorkProject\geoai-workbench\.venvs\15-trajectory-analysis` | Component | Version | | --- | --- | | Python | 3.12.10 | | pandas | 2.3.3 | | geopandas | 1.1.4 | | shapely | 2.1.2 | | pyproj | 3.7.2 | | scikit-learn | 1.9.0 | | matplotlib | 3.11.1 | | openpyxl | 3.1.5 | `geoai-py` is intentionally not installed in this environment because version 0.42.0 has no trajectory, tracking, or behavior-recognition API. The capability consumes timestamped track results that may originate from an upstream GeoAI detection/export workflow. `pip check` passes. Dedicated change-detection environment: `E:\AllWorkProject\geoai-workbench\.venvs\00-change-detection` | Component | Version | | --- | --- | | Python | 3.12.10 | | geoai-py | 0.42.0 | | torchange | 0.0.4 | | ever-beta | 0.6.1 | | torch | 2.13.0+cpu | | rasterio | 1.5.1 | | geopandas | 1.1.4 | | OpenCV | 4.14.0 | The environment reuses the compatible 3.12 package set from the verified semantic-mapping environment through a local `.pth` file and adds ChangeStar dependencies. `pip check` passes. ## Local Experiment Console - Location: `apps/workbench-console/` - Frontend: Vue 3 + Vite + Ant Design Vue + Pinia. Trajectory maps use Cesium `1.126.0`, public ArcGIS World Imagery, and optional TianDiTu image/label layers configured by `apps/workbench-console/.env.local` `VITE_TIANDITU_TOKEN`. - Build: `Set-Location .\apps\workbench-console; npm install; npm run build` - Start command: `py -3.12 .\scripts\serve_workbench_console.py` - URL: `http://127.0.0.1:6173` (built console); Vite development is `http://127.0.0.1:6174/apps/workbench-console/`. Only `6xxx` ports are accepted. - Scope: independent local experiment workbench for this repository. It has no code, account, or product API link to the two drone-product repositories. The map client directly requests public ArcGIS tiles and, only when configured, TianDiTu tiles. - Current workflow: `00-change-detection`, `01-object-detection`, `02-semantic-mapping`, `04-spatial-measurement`, `09-anomaly-detection`, and `15-trajectory-analysis` support new local runs, searchable case libraries, and visual result workspaces. Anomaly detection accepts separate normal-reference and inspection groups through bounded binary uploads, runs asynchronously, and shows references, input/output comparison, heatmaps, candidates and downloads. Change detection shows two-date imagery, a ChangeStar raster overlay, pixel-coordinate GeoJSON, per-feature probability stats and downloads. Its scan workspace accepts new user-uploaded pairs with selectable threshold/minimum-area combinations, asynchronous CPU execution, per-combination overlays/statistics and GeoJSON, without treating scan inference as a formal model run. Spatial measurement shows raster/vector results, per-object metrics and downloads. Change detection and anomaly detection upload large raster/image files as raw binary streams and copy bytes into new run directories before fixed capability scripts run; source files are not rewritten. The server creates a new run ID for every submission, only accepts allowlisted input types and enabled tasks, and calls fixed virtual-environment scripts. - File exposure: the static handler permits only console assets, `shared/outputs`, and source images required for result comparison. Upload APIs write new raw and processed run directories but do not expose the rest of the repository. - Styling: `apps/workbench-console/src/styles.css` is organized into design variables, application shell, shared workbench components, capability workspaces, maps, and responsive rules. New capability pages must use a scoped workspace class and shared spacing variables instead of global override patches. ## Capability Status | Capability | Status | Current conclusion | | --- | --- | --- | | `00-change-detection` | Runnable CPU Demo verified; benchmark evaluator ready | A capability: `geoai.ChangeStarDetection`; ORB registration and JPG-to-GeoTIFF conversion are input preparation, while final cleaned-mask vector export uses Rasterio to preserve one feature per retained region. Auto/image mode handles ordinary imagery in pixel coordinates; GeoTIFF mode preserves spatial reference for inputs with matching CRS. When two GeoTIFF grids differ, the second image is reprojected to the first grid only in the processing copy; original files are unchanged. Real pair `07-16.jpg` -> `07-19.jpg` completed in about 41.6 seconds at 1024 px, with 755/769 registration inliers, 98.52% valid area, 674 changed pixels and one GeoJSON polygon. CLI/API/console runs accept per-run thresholds and processing modes/resolution options, all recorded in `run_metadata.json`. An independent evaluator now rejects misaligned truth grids and reports pixel TP/FP/FN/TN, Precision, Recall, F1, IoU and threshold comparisons, but no reviewed real truth set exists yet. | | `01-object-detection` | In progress; runnable people and vehicle experiments | Tiled YOLO helps people; GeoAI NWPU substantially improves top-down vehicles; tree detection is not implemented. | | `02-semantic-mapping` | Runnable CPU baseline verified | B capability: deterministic RGB/HSV segmentation plus `geoai.masks_to_vector`; raster and vector outputs are inspectable, but this is not a trained GeoAI model. | | `04-spatial-measurement` | Runnable CPU Demo verified | B capability: `geoai.masks_to_vector` plus ecosystem measurement; counts labelled raster objects and reports area/perimeter in projected or explicitly non-metric pixel/coordinate units. | | `07-risk-rule-engine` | Runnable CPU Demo verified | C capability: deterministic spatial zone-intersection and attribute-threshold scoring, not a built-in `geoai-py` function. It consumes CRS-aware GeoJSON inputs and produces an inspectable risk GeoTIFF, preview PNG, per-object scoring GeoJSON/CSV, summary and full run metadata. | | `09-anomaly-detection` | Runnable CPU CLI Demo verified | B capability: interpretable image features plus robust rules and Isolation Forest score visual outliers; `geoai-py` supplies `masks_to_vector`. Results are review candidates, not business-event conclusions. | | `15-trajectory-analysis` | Runnable CPU Demo verified | C capability consuming timestamped tracks: spatial metrics, DBSCAN and explicit behavior rules; not a built-in `geoai-py` function. | | `05-3d-pointcloud` | Runnable CPU Demo verified; semantic classification baseline added | B capability: pycolmap CPU SfM plus OpenMVS CPU MVS reconstructs dense point clouds, textured meshes and browser-viewable GLB from a coherent photo sequence; Open3D plus `geoai.masks_to_vector` produces DSM/elevated-surface GeoJSON. A separate explainable CPU RGB/local-geometry baseline produces semantic review candidates, not trained-model labels. | | `03`, `06`, `08`, `10` through `14`, `16` through `18` | Directory and initial README only | No verified local Demo yet. Start each one through `$geoai-capability-builder`. | ## Three-dimensional Reconstruction And Point-cloud Snapshot - Scripts: `capabilities/05-3d-pointcloud/run_pointcloud_understanding.py`, `run_photo_reconstruction.py`, read-only DJI RTK/LRF diagnostic `diagnose_photo_pose_alignment.py`, and `prepare_odx_reconstruction_inputs.py`; fixture generator: `generate_validation_inputs.py`. - Boundary: B. `geoai-py 0.42.0` has no point-cloud/SfM/MVS API in the installed package. pycolmap 4.1.1 performs CPU SIFT matching and incremental sparse SfM. Open3D 0.19.0 performs existing-point-cloud I/O, voxel filtering, RANSAC dominant-ground fitting and alpha-shape mesh construction. `geoai.masks_to_vector` receives the 0/255 elevated-surface raster; Rasterio is used as a documented completeness repair when GeoAI contour output does not cover every retained raster region. - Input/output contract: an existing PLY/PCD/XYZ/LAS/LAZ produces classified/mesh PLY, DSM and height GeoTIFFs, elevated-surface raster/preview, elevated-footprint GeoJSON, CSV and metadata. A coherent JPG/JPEG sequence produces a COLMAP sparse model, coloured PLY, PCA preview PNG, local camera poses CSV, EXIF GPS manifest and metadata with input SHA-256; the verified OpenMVS CPU branch additionally produces dense PLY, mesh PLY, texture PNGs, source GLB, a reliable-texture preview GLB, a complete-geometry neutral GLB, and a point-colour complete-geometry GLB. The reliable preview vertically flips atlas pixels for browser sampling and removes faces whose four interior samples hit black atlas background or OpenMVS's orange `RGB(255,127,39)` no-coverage colour; its JSON report records every kept/rejected count. The geometry preview retains all reconstructed mesh faces without inventing texture; the point-colour preview uses nearest fused RGB values and is not a per-face photo-texture claim. - Environment: `.venvs/05-3d-pointcloud` is a dedicated Python 3.12 environment that exposes the verified package directory from `04-spatial-measurement` through a local `.pth` file and adds Open3D 0.19.0, Laspy 2.7.0, Trimesh 4.12.2, pycolmap 4.1.1 and Matplotlib 3.11.1. It uses CPU only; `pip check` passes. - Validation: normal known-geometry PLY (9,600 source points) completed in 4.177 seconds, retained 7,644 downsampled points, 2,901 elevated points, 52 footprint regions and a 15,110-triangle mesh. Difficult sparse/slope/noise PLY completed in 3.831 seconds with 73 fragmented elevated footprints, explicitly demonstrating isolated-high-point false positives. Both PNG previews and GeoJSON outputs were inspected. - Real input: PCL tutorial `table_scene_lms400.pcd` is staged unchanged at `shared/data/raw/05-3d-pointcloud/pcl-table-scene-20260821/`, SHA-256 `E285D415641E0D9DE695B611DB874CC8FE995E8089B77A50D6056D24D8CBCC58`. Its 460,400 input points completed in 4.833 seconds with processing-copy `--ground-up-axis auto`: 41,143 downsampled points, 19,281 elevated points, 193 footprints and 7,090 mesh triangles. Its source-local vertical was not Z, so a 61.1666-degree dominant-plane rotation is recorded. This validates PCD handling and axis alignment, not drone reconstruction accuracy or semantic class accuracy. - Photo validation: the user-provided 18 DJI H30T side-view JPGs were staged unchanged under `shared/data/raw/05-3d-pointcloud/h30t-sideview-20260820-v2/`. The preserved original 18-photo high-resolution baseline has 3,379,097 dense points and 799,632 faces but failed the LRF diagnostic (13.3814 m median 3D error; 11.9794 m horizontal; -4.8131 m signed vertical). The current ODX-aligned local configuration uses COLMAP `OPENCV` intrinsics, RTK/GPS spatial matching (four neighbours), 2,000 px feature extraction, 18,000 features and a 0.05 m position prior. Normal and difficult six-photo validations each registered 6/6 images with 0.7581 px and 0.7596 px mean reprojection error. The full 18-photo sparse model registered 18/18 images, has 23,084 sparse points and 0.8410 px mean reprojection error. Its 2,400 px OpenMVS CPU run completed in 2,390.086 seconds, yielding 3,756,551 dense points and a 799,645-face mesh. The reliable-texture preview retains 293,614 faces (36.72%) after black/orange-atlas rejection; the point-colour and neutral complete-geometry previews retain all 799,645 faces. The LRF diagnostic now reports 0.4038 m median 3D nearest-point distance, 0.3073 m horizontal error and 0.0709 m signed vertical error. These target observations are diagnostic only, not independent surveyed check points. A two-photo low-baseline trial failed cleanly, documenting the need for sufficient baseline. - WebODM reference: `reference_project/WebODM-master` confirms that its task/UI service delegates reconstruction to NodeODX and that the engine supports ODX `geo.txt`, GCPs, and trusted `cameras.json`/fixed-camera-parameter workflows. The local NodeODX submodule is not populated, Docker is absent, and neither NodeODX nor NodeODM is installed, so WebODM was not executed. The new read-only preparation run `shared/outputs/05-3d-pointcloud/odx-input-h30t-sideview-20260822-v2/` validated all 18 DJI images and writes an `EPSG:4326` ODX `geo.txt`, camera-position GeoJSON, source-hash manifest, parameter advice, and compatibility report. It mirrors ODX's DJI orientation normalization and per-photo RTK accuracy inflation; global ODX `gps-accuracy` must remain unset because it would overwrite those per-photo values. The package intentionally does not treat LRF targets as GCPs or fabricate a `cameras.json` calibration. - Console: `GET/POST /api/3d-pointcloud/runs` remains enabled on the independent local console at `http://127.0.0.1:6188`. The top workflow tabs separate `照片三维重建` from `既有点云理解`: photos accept 3-30 JPG/JPEG files through bounded binary uploads, preserve raw bytes in a new run directory, use an asynchronous fixed-script CPU SfM/MVS job and poll queued/sparse/dense/completed/failed status; the GPS/RTK prior toggle selects the verified spatial-neighbour configuration only for photos with valid position metadata. Existing point-cloud uploads accept at most two allowlisted PLY/PCD/XYZ/LAS/LAZ files and use only the fixed Open3D script to produce raster/vector outputs. The case library discovers `ODX 对齐 CPU 高分重建(H30T 18 图)` from output metadata. Dense CPU-MVS results have reliable-texture, point-colour and complete-geometry modes, a wireframe toggle, local-`+Z` top-down button, filter report, dense PLY and raw mesh downloads. The geometry mode is deliberately neutral and retains every mesh face; point-colour uses fused-point RGB; texture remains evidence-only. The console only needs `npm run build` after Vue/TypeScript source changes, not after user uploads, reconstruction runs or automatic case discovery. - Limitations and next decision: this is a dense/textured local model that materially improves the DJI LRF diagnostic, but it is not a survey-grade result or independent check-point validation. pycolmap dense PatchMatch still requires CUDA; the verified dense route is OpenMVS CPU. It makes no DSM, orthomosaic, GIS-coordinate, semantic-class or engineering-measurement claim. Further accuracy work needs DJI/H30T intrinsics plus GNSS antenna-to-camera lever-arm/boresight calibration, or surveyed GCPs and separate check points. A CUDA/cloud ODX/WebODM workflow is a separate option only when it consumes the prepared `geo.txt`, trusted calibration/control, and reports independent checkpoint residuals. Existing-point-cloud ground/elevated is geometric rather than building/tree/equipment classification; its alpha-shape mesh is not watertight or accuracy-validated. OpenMVS and WebODM are AGPL-3.0-only, so commercial use needs a separate license assessment; NodeODX/ODX, DJI imagery, and all source data licenses remain separate. ### Point-cloud semantic classification update - The existing-point-cloud branch now writes a capped colour preview PLY, semantic LAS, class raster/PNG, candidate GeoJSON and CSV for ground, vegetation, building/structure, pole/tower, power-line and unknown. This is a transparent CPU local-geometry baseline, not a trained semantic model. It uses local shape rather than RGB vetoes for power facilities: horizontal linearity for conductors and vertical linearity for pole/tower members. - The unchanged `baseData/las/part_01.las` has 10,473,127 RGB/return points but every source classification value is `0`, so it is not truth data. `validation-las-part01-semantic-20260822-v11-original-rgb` completed in 73.586 CPU seconds after 0.20-unit voxel sampling: 356,170 ground, 714,122 vegetation, 1,031 structure, 3,183 pole/tower candidates, 8,162 power-line candidates and 288,316 unknown. Preview sampling retains all line/pole candidates before downsampling other categories. Candidate precision/recall require visual review and labelled truth before an asset, clearance, or inspection claim. - The local 6188 console has a semantic-classification tab with bounded binary PLY/PCD/XYZ/LAS/LAZ upload and a dense-MVS-case action that resolves only the selected fixed `dense.ply`. - The current H30T dense PLY route was checked as `validation-h30t-dense-semantic-20260822-v2`: 3,756,551 inputs became 1,205,115 sampled points in 38.673 CPU seconds, but its dominant plane was too steep and `ground_plane_available` is false. The local-low-point fallback produced 181,436 ground, 663,962 vegetation, 988 structure, 641 pole/tower candidates, zero power-line candidates and 358,088 unknown. This validates data-flow only, not semantic accuracy for the side-view reconstruction. ## Semantic Mapping Snapshot ## Anomaly Detection Snapshot - Script: `capabilities/09-anomaly-detection/run_anomaly_detection.py`; reproducible input generator: `generate_validation_inputs.py` in the same directory. - Boundary: B. Seventeen interpretable RGB/HSV/texture features feed a robust MAD rule baseline and a 200-tree Isolation Forest; fixed-view inputs additionally use class-agnostic corresponding-location Lab appearance and grayscale structure differences after image-wide normalization. `geoai-py 0.42.0` only supplies `masks_to_vector`. There are no model weights or colour/object-specific rules. - Contract: image or directory input; minimum 50 reference windows; outputs are two heatmaps, comparison overlay, encoded mask GeoTIFF, candidate GeoJSON, tile CSV and run metadata. Ordinary images use pixel coordinates; valid GeoTIFF CRS/transform is preserved. - Validation: controlled color, blur and dark anomalies were injected into a copy of `07-16.jpg`; `07-19.jpg` was used unchanged as a difficult real sample. Source-copy SHA256 values match the originals. - Measured result: 588 reference windows and three inputs completed in 41.051 seconds CPU. The rule method hit 3/3 controlled regions with precision 0.583, recall 0.672 and IoU 0.454; Isolation Forest hit 2/3 with precision 0.831, recall 0.500 and IoU 0.454. Normal-image coverage was 0.33% and 0.00%, respectively. Every image completed within 15 seconds. - Visual limitation: the normal image has a small rule false positive at a vegetation/rock transition. Difficult-image candidates occur around concrete structure, a dark opening and a top dark region, consistent with viewpoint/material/lighting shift; no real anomaly or business accuracy is claimed. - Console: `GET/POST /api/anomaly-detection/runs`, binary `PUT /api/anomaly-detection/uploads/` and asynchronous `GET /api/anomaly-detection/jobs/`. A real one-reference/one-input upload produced run `anomaly-20260818-102845-61f55b` with six review candidates. Desktop and 390 px layouts were visually checked; tables use internal horizontal scrolling and the collapsed menu trigger remains inside the viewport. - Synthetic fixed-view validation: five ImageGen normal references cover overcast, sunny, after-rain, morning-haze and late-afternoon conditions; one test image adds a localized branch/leaf/mud/rock blockage. The original pooled-feature run returned zero candidates and is retained as `ImageGen 五参考图堵塞复核(漏检案例)`. - Fixed-view optimization: `--spatial-mode auto` now selects same-position robust rules when 3+ references and all target images share dimensions, after normalizing each image's global feature profile; otherwise it falls back to the original global rule. At the unchanged 0.995 quantile, the synthetic blockage produced one correctly located rule candidate with 9.375% coverage. Five leave-one-normal-out checks produced 7.292%, 0%, 0%, 0%, and 0% coverage. The successful output is retained as `ImageGen 五参考图堵塞复核(同位置优化)`; Isolation Forest still missed this sample. - Generic local-change enhancement: same-position mode now also calibrates nearest-normal-reference Lab appearance and grayscale intensity/edge/contrast distances. A previously missed small added pattern became one 9,467-pixel rule candidate with 100% coverage of its 6,710 validation pixels and 0.602% full-image coverage; it is retained as `通用局部异常增强(小目标漏检修复)`. The blockage regression remains one candidate at 9.594% rule coverage. Five leave-one-normal-out combined coverages are 7.292%, 0%, 0%, 0.460%, and 1.209%. No sample colour, object class, or fixed coordinate is encoded. - Next decision: add image registration and/or a channel ROI or specialist blockage detector before accepting camera motion or claiming blockage semantics. Obtain real normal/labelled anomaly pairs; the synthetic result is only a pipeline check. ## Change Detection Snapshot - Script: `capabilities/00-change-detection/run_change_detection.py`. - Benchmark evaluator: `capabilities/00-change-detection/evaluate_change_detection.py`; manifest template: `benchmark_manifest.example.csv`. It requires before/after/truth GeoTIFFs on one exact CRS/grid and truth encoding `0=unchanged`, `1=changed`, `255=ignore`. Existing formal outputs can be scored without rerunning or changing inference. Synthetic unit fixtures verify exact metrics, explicit pixel-coordinate opt-in and rejection of a shifted truth grid; they do not establish real accuracy. - Boundary: A. Core inference calls `geoai.ChangeStarDetection`; OpenCV ORB homography is input registration for ordinary JPGs, and Rasterio exports one vector feature per region retained in the cleaned mask. - Inputs: user-provided `baseData/07-16.jpg` and `baseData/07-19.jpg`, both 3664 x 2748 RGB with no usable CRS. Staged copies are under `shared/data/raw/00-change-detection/validation-20260817/`. - Outputs: `shared/outputs/00-change-detection/validation-real-20260817-v4/`, `validation-self-20260817-v3/` and `resolution-2048-urban-validation/` contain registered GeoTIFFs, probability/mask rasters, overlays, GeoJSON, feature stats and `run_metadata.json`. - Visual evidence layer: formal runs now keep ChangeStar structural-change pixels in red and add a separate conservative RGB-difference candidate mask in cyan. This supplementary layer can reveal moved vehicles or people missed by the building-change weights, but may include shadows, edges and registration residuals; it is excluded from ChangeStar pixel/vector metrics and cannot be interpreted as a semantic alert. The console exposes the registered second-period processing image and uses it as the overlay/vector base, so displayed coordinates match model outputs. - 2026-08-20 road-pair validation: `shared/outputs/00-change-detection/runs/change-20260820-evidence-optimized/` completed at 2048 x 1152 in 68.643 seconds. ChangeStar retained 135,522 pixels and 34 polygons; the separate visual-difference layer retained 106,509 candidate pixels in 136 components. Visual inspection confirmed cyan coverage around the moved vehicle and some person-sized differences, with remaining edge/shadow/registration false positives. - Parameter-scan promotion now preserves the source inference's generic-difference raster, combined overlay and registered-image previews instead of reverting to the red-only scan overlay. Formal case `change-20260820-032014-615889` verifies cyan coverage at the disappeared vehicle and person locations for the `V_1` to `V_2` road pair. - Measured result: real pair at 1024 px / tile 512 / overlap 64 took 41.556 seconds on CPU, found 755 inliers from 769 ORB matches, 98.52% valid area, 674 changed pixels (0.0857%) and one polygon. Self-comparison at 512 px took 25.902 seconds and found zero changed pixels and zero polygons. On the urban parking sample, increasing from 1024 to 2048 produced 16 polygons instead of one and covered more vehicle/parking changes, but took about 84 seconds CPU and still had misses/false positives. - GeoTIFF grid-alignment validation: uploaded `1.tif` (6217 x 5525) and `2.tif` (6218 x 5497) share `EPSG:32650` but have slightly different origins and pixel sizes. The second image was reprojected bilinearly to the first grid in the processing copy, then completed at 1024 px in 80.882 seconds with georeferenced outputs. SHA256 checks confirmed the source staging files and their raw run copies are byte-identical. - Honest limitation: ChangeStar weights are trained for Changen2/S1 building change and the close-up rock/concrete scene is out of distribution. No manual truth exists, so no precision, recall, IoU, change type, or engineering alert is claimed. Pixel GeoJSON has no CRS; the downloaded model is CC BY-NC-SA 4.0 and not cleared for commercial use. - Console: `GET/POST /api/change-detection/runs`, `GET/POST /api/change-detection/scans`, `GET /api/change-detection/scan-jobs/`, `POST /api/change-detection/scans//promote` and binary upload endpoints on local `6xxx` ports. Real uploads at `6176` verified thresholds and selectable processing resolution; scan submissions are validated for at most 24 combinations and execute asynchronously through fixed capability scripts. Scan inference outputs remain in the scan workspace until a user promotes one selected combination; promotion creates a new formal run directory with raw-input references, makes the case discoverable, and uses rule rectangles as the primary case vector while retaining original polygons and masks. GeoTIFF candidates include source-CRS and EPSG:4326 vectors; ordinary images remain in px coordinates. Minimum connected area is a processed-pixel filter for both modes; an empty console scan selection defaults to `256 px`. Vector export now uses `rasterio.features.shapes` after the pixel-area filter, rather than GeoAI's morphological/NMS vector helper: a GeoTIFF validation changed from 42 exported vectors to all 308 retained mask regions, with 308 rectangles and 308 WGS84 features; every original polygon was covered by its matching rectangle. A non-overwriting corrected scan `scan-20260819-063712-744f45-vector-fixed` is available for review. Binary upload filenames are percent-encoded in the browser and decoded/sanitized by the server, so Chinese filenames no longer fail Request header validation. Auto/image and GeoTIFF mode handling is covered by unit tests. Separate raw before/after directories and a separate processed directory are used; unsafe basename sanitization plus invalid/oversized request rejection were verified. - Next decision: populate benchmark version `v1` with georeferenced same-GSD orthophotos and manually reviewed change masks for one intended business class. Include at least one no-change pair, one representative change pair and one difficult pseudo-change pair; then use the evaluator to compare registration error, false positives, misses, F1 and IoU before changing the model, selecting a production threshold, batch-running or integrating with a product. - Script: `capabilities/02-semantic-mapping/run_semantic_segmentation.py`. - Boundary: B. `geoai-py 0.42.0` supplies class-wise `masks_to_vector`; deterministic RGB/HSV rules supply the first offline segmentation mask because no general pretrained weight is bundled. - Classes: `other`, `vegetation`, `water`, and `impervious`. Outputs are mask PNG, overlay PNG, mask GeoTIFF, class GeoJSON, and `run_metadata.json`. - Validation input: two existing real 3840 x 2160 drone JPEGs copied to `shared/data/raw/02-semantic-mapping/validation-20260817/`. Both are ordinary non-georeferenced images, so their vector output is in pixel coordinates. - Measured result: two images completed on CPU in 15.738 seconds. The vegetation-heavy image produced 1,707,028 vegetation pixels; the difficult road image produced 8,167,327 impervious pixels. Both used `geoai.masks_to_vector`, and raster/vector artifacts plus both overlays were inspected. - Honest limitation: blue roofs and other blue objects can be false water, and lighting/material similarity can change all rule classes. There is no manual ground truth, so no accuracy, IoU, precision, or recall is claimed. - Task catalog: `capabilities/02-semantic-mapping/configs/task-catalog.json`. Only `color_baseline` is selectable; project classes such as drainage blockage are recorded but disabled until data, labels, weights, licenses, and acceptance thresholds are available. - Console: `GET /api/semantic-mapping/tasks` and `GET/POST /api/semantic-mapping/runs`, at most six allowlisted images per run. The server validates `taskId` before creating a run directory. Raw, processed, and output paths are separate. Run `semantic-20260817-063122-5f20ef` verified a real upload and persisted `color_baseline` / `通用颜色规则基线` in structured metadata. - Next decision: choose one business class, obtain normal and difficult georeferenced GeoTIFFs plus manual masks, then license and evaluate a lightweight pretrained model through `geoai.semantic_segmentation` before any batch or product use. ## 项目算法方案层 - 新增 `solutions/`:它是 C 类项目算法编排层,引用 `capabilities/` 中已验证的原子能力,不复制模型实现。 - `solutions/mining-inspection/requirements-map.json` 将需求文档中的 8 条记录归一化为 7 个方案域;“排洪沟巡查”和“排洪沟堵塞识别”合并,避免重复模型、标注和规则。 - 七个方案域为:人员与个体防护、爆破警戒热成像、排洪沟与箱涵堵塞、边坡变化、竖井巡查、索道巡查、尾矿库异常筛查。优先级、就绪度和 A/B/C 实现边界分别记录,不能相互替代。 - 当前两个专项目录 `01-person-safety` 和 `02-drainage-blockage` 仍为 `scaffold`,没有运行脚本、模型下载或产品告警接入;其余方案域保留在需求映射和方案索引中。 - 项目数据流必须区分模型观察、空间/测量分析、事件候选和平台动作。安全帽以人员与安全帽检测及实例关联为主,属性分类只作为可选辅助。 - 爆破区热成像人员识别是受数据条件限制的 P1,不等同于 RGB 人员检测的成熟度;当前颜色规则基线不是排洪沟模型,RGB 浑浊或颜色异常也不能证明矿浆渗漏。 - `shared/configs/solution-result.schema.json` 规定项目算法输出必须区分模型观察结果与供人工复核的事件候选。 ## geoai-py 能力目录 - `capabilities/GEOAI_PY_DIRECT_CAPABILITIES.md` 已按 `geoai-py 0.42.0` 实际导出接口整理能力边界。 - 算法人员交付模型时,必须同时提供权重/许可证、输入波段与 CRS、类别或掩膜规范、推理参数、输出样例和评估结果。 - 当前对象检测环境已具备 Transformers、timm、Lightning 和 OpenCV;`torchange`、`omniwatermask`、`rfdetr`、`terratorch`、`segment-geospatial`、`detectron2` 和 `onnxruntime` 尚未安装。 - 目标检测、分割、分类、变化检测、水体/树冠/深度/嵌入等是算法产出可被 GeoAI 工作流承接的方向;电子围栏、告警、无人机控制、工单和调度仍属于项目产品能力。 ## Spatial Measurement Snapshot ## Spatial Rule And Risk Scoring Snapshot - Script: `capabilities/07-risk-rule-engine/run_risk_rule_engine.py`; reproducible validation inputs: `generate_validation_inputs.py` in the same directory. - Boundary: C. `geoai-py 0.42.0` has no risk/rule/score API; the Demo does not invoke it. GeoAI detection, segmentation or measurement outputs may be supplied upstream as CRS-aware observation or zone GeoJSON, but the rule and score logic is GeoPandas/Shapely/Rasterio product-service code. - Contract: a projected-CRS observation GeoJSON with unique `object_id` and numeric `confidence`, a zone GeoJSON with `zone_type`, and a configured JSON rule set. Outputs are `risk_score.tif`, `risk_preview.png`, `risk_scores.geojson`, `risk_scores.csv`, `risk_summary.json`, and `run_metadata.json`; every object records matched rules, score contributions, score capping, risk level and suggestions. The pipeline rejects missing CRS, geographic observation CRS, invalid confidence, invalid rule schemas and non-empty output reuse. - Validation: synthetic EPSG:3857 normal and difficult cases completed on CPU. The normal case took 2.540 seconds and returned scores 0, 25 and 90. The difficult case took 0.371 seconds: a boundary object hit both zone rules for 90, a low-confidence restricted object was capped at 100, and a low-confidence outside object scored 20. The risk PNG previews and GeoTIFF/GeoJSON artifacts were inspected; this is a logic/output verification, not a real-risk accuracy result. - Environment: `.venvs/07-risk-rule-engine` is a dedicated Python 3.12 interpreter that reuses the verified compatible geospatial package directory from `04-spatial-measurement` through a local `.pth` file after package download exceeded the setup timeout. GeoPandas 1.1.4, Rasterio 1.5.1 and Shapely 2.1.2 load successfully; `pip check` passes. - Console: `GET/POST /api/risk-rule-engine/runs` uses fixed `07` interpreter/script and only accepts the three named, allowlisted files. A real local POST at port 6187 created `risk-20260820-083944-224155`; an unsafe-path submission created `risk-20260820-084008-10c884` with sanitized names and separate raw/processed/output roots. The Vue page follows new run -> bounded searchable case library -> result workspace, and shows the raster/GeoJSON result side-by-side, summary, object details and downloads. Browser screenshot validation was unavailable because no browser instance was exposed; the Vue production build and HTTP/API checks passed. - Limitations: scores are configurable rules for human prioritization, not verified events, enforcement conclusions or automatic actions. The synthetic data does not establish precision, recall, location tolerance, score calibration, zone authority or commercial readiness. Obtain authoritative dated zones, real georeferenced upstream outputs, reviewed labels and acceptance thresholds before operational or batch use. - Script: `capabilities/04-spatial-measurement/run_spatial_measurement.py`. - Boundary: B. `geoai-py 0.42.0` supplies `masks_to_vector`; Rasterio, GeoPandas and Shapely supply CRS handling and count/area/perimeter/centroid/bounds measurements. It consumes labelled rasters and does not infer classes from RGB imagery. - Inputs: single-band PNG/GeoTIFF labels (`0` background, positive integers as classes). Outputs are object GeoTIFF, PNG preview, measured GeoJSON, CSV and `run_metadata.json`. - Validation inputs: normal and difficult 3840 x 2160 label GeoTIFFs derived from the existing real drone-image semantic-mapping validation set, stored under `shared/data/raw/04-spatial-measurement/validation-20260817/`. - Measured result: the normal raster produced 1,210 objects in 25.190 seconds; the difficult road-dominant raster produced 89 objects in 9.474 seconds. Both call `geoai.masks_to_vector`, detect incomplete complex contours against a Rasterio reference, and apply a recorded completeness repair; raster/vector/table artifacts and both previews were inspected. - Unit boundary: both real validation rasters have no CRS, so results are explicitly `pixel^2` and `pixel`. A projected-CRS unit test confirms the map-unit branch. No metre or accuracy claim is made for the real samples. - Console: `GET/POST /api/spatial-measurement/runs`, at most four allowlisted PNG/TIF/TIFF label rasters. A valid upload, unsafe-name sanitization, invalid extension, oversized request, and script failure were verified at local port 6175; the default remains 6173. Browser screenshot verification was unavailable because no browser backend was exposed. - Next decision: obtain a georeferenced projected label GeoTIFF plus surveyed or manually measured truth, then evaluate count false positives/misses and area/perimeter error before product or batch use. ## Object Detection Snapshot Target classes: people, vehicles, and trees. Inputs: - Directory: `shared/data/raw/01-object-detection` - 20 files total: 19 ordinary JPEG images and one internal DJI MPO with a `.jpeg` extension. - Most images are 3840 x 2160. The MPO is skipped safely. Environment and scripts: - General tiled detector: `capabilities/01-object-detection/run_detection.py` - GeoAI aerial vehicle detector: `capabilities/01-object-detection/run_geoai_vehicle_detection.py` - General model: Ultralytics `yolo11n.pt`, CPU, 1024-pixel tiles, 20% overlap, confidence 0.20. - Aerial vehicle model: `giswqs/nwpu-vhr10-maskrcnn:best_model.pth`, called through `geoai-py`, 512-pixel windows, 128-pixel overlap, confidence 0.30. Measured results: - Whole-image YOLO baseline across 19 JPEGs: 13 detections, including 3 people and 10 cars; this misses many small targets. - `DJI_20260713102047_0001_V_19.jpeg`: tiled YOLO found five person candidates, including duplicates and a false positive; the visible red vehicle was still missed by both YOLO and NWPU. - `DJI_20260810092727_0001_V_10.jpeg`: general YOLO found only 2-3 cars. GeoAI NWPU produced 33 raw vehicle detections and 32 after containment deduplication, with about 90 seconds CPU inference. - NWPU is much better for top-down aerial vehicles but still misses vehicles and can produce partial-box duplicates or other aerial-class false positives. Current technical decisions: - Do not batch-run the final pipeline across all images yet. - Use separate model branches: tiled YOLO for people, aerial-specific detection for vehicles, and a future tree-crown detection or segmentation model for trees. - Do not claim that the current COCO or NWPU model detects trees. - Establish a fixed manually annotated validation set before tuning or training. - Product use of Ultralytics and NWPU weights remains blocked on license review and accuracy evaluation. ## Trajectory Analysis Snapshot Inputs and artifacts: - Generator: `capabilities/15-trajectory-analysis/generate_demo_inputs.py` - Analyzer: `capabilities/15-trajectory-analysis/run_trajectory_analysis.py` - Input contract: WGS84 timestamped CSV observations plus GeoJSON reference routes and zones, connected by a `*.case.json` manifest. - Generated representative inputs: `shared/data/raw/15-trajectory-analysis` - Inspectable outputs: `shared/outputs/15-trajectory-analysis` - User-provided real source data is staged, unchanged, in `shared/data/raw/15-trajectory-analysis/tian-dun-demo-20260814/`: no-fly GeoJSON, flyable-area Gzip binary source, DJI WPMZ KMZ, and an actual-flight XLSX log. `prepare_real_flight.py` produces a single WGS84 case from all four sources at `shared/data/processed/15-trajectory-analysis/tian-dun-flight-19578/`. The Gzip was verified as 46,518 closed `int32 / 1e7` coordinate rings and yields two local flyable polygons for display only; the zone rule still recognizes only `zone_type=restricted`. Measured validation: - The normal synthetic case has 2 tracks and 0 events. - The difficult synthetic case has 3 tracks, drops 1 duplicate timestamp, and finds exactly one stop, one route deviation, one restricted-zone event, and one gathering event. - Directory processing handled 5 tracks and 78 cleaned observations in about 2.8 seconds on CPU. - Missing required CSV columns fail cleanly with exit code 2. Both 1400 x 980 PNG results were visually inspected. - Real Tian Dun flight 19578: 233 observations became one WGS84 drone track; the 10-waypoint WPMZ route, one locally selected no-fly source area and two local flyable polygons were prepared and analyzed in 0.362 seconds. It produced two route-deviation runs (77 and 175 seconds) and one 464-second source-zone intersection, with no stop or gathering event. The static result map was visually inspected. Current decisions and limitations: - Keep the boundary explicit: the current Demo is C because it does not call `geoai-py`; using geospatial ecosystem libraries alone does not make it B. `geoai-py` is only a possible upstream source. - This is rule-based behavior detection, not learned video action recognition, and it assumes track IDs already exist. - Synthetic data verifies logic only. Do not claim real-world accuracy or batch-run operational data yet. - The Tian Dun zone intersection is a spatial result against an unverified third-party source, not a violation conclusion. The reference route does not encode takeoff, return-to-home or landing, so its two deviation runs require flight-phase-aware validation. - The flyable-area binary structure has been decoded, but its authority, publication time and operational semantics remain unverified; it is visual-only until that validation is complete. - Next decision: obtain manual truth labels for this real flight and another difficult real flight, then measure false positives, misses, GPS sensitivity and phase-aware thresholds. ## Starting a New Capability Open a new Codex task with the repository as the working directory and use: ```text 使用 $geoai-capability-builder,创建下一个能力:<能力名称>。 先读取 AGENTS.md 和 PROJECT_CONTEXT.md,再准备环境、Demo 输入输出和验收方式。 ``` When the capability needs direct user uploads, interactive execution, maps, image comparison, or an inspectable result workspace, add: ```text 同时使用 $geoai-workbench-console 接入独立本地实验控制台。 ``` `$geoai-capability-builder` owns the capability workflow. `$geoai-workbench-console` owns the independent local console workflow, including run discovery, safe uploads, output presentation, UI layout, and visual verification. After completing verified work, update this snapshot and the capability README. Change `AGENTS.md` only when a long-lived rule changes. ## 3D Point-cloud Annotation And Training - Boundary: B. `geoai-py` remains limited to elevated-raster vectorization; Open3D, NumPy, scikit-learn and PyTorch implement annotation/training. - Environment: `.venvs/05-3d-pointcloud` has Python 3.12, `torch 2.13.0+cpu` and `scikit-learn 1.9.0`; CUDA is unavailable locally. The shared-MLP model supports `auto`, `cpu`, and `cuda`, making a future GPU server an acceleration deployment rather than a different workflow. - Truth contract: generated annotation PLYs preserve observed RGB/XYZ. Rule colours are never labels. Separate revisions record source SHA-256, artifact, indices, class codes and class counts below `shared/outputs/05-3d-pointcloud/annotations/`. A mistaken revision can be deleted after confirmation; the deletion endpoint is constrained to that revision directory and never removes source clouds, semantic outputs or training outputs. - Training gate/output: at least two classes and 500 user-confirmed points per class; XY-block train/validation/test partition; `model.pt`, `metrics.json`, predicted PLY, per-class precision/recall/F1 and confusion matrix. Metrics apply only to labelled blocks. - Verification: CPU run `validation-las-part01-semantic-20260822-v11-original-rgb` processed unchanged `baseData/las/part_01.las` in 73.586 seconds and generated a 400,000 point RGB annotation source. Its 3,183 pole/tower and 8,162 power-line rule candidates are not truth. - Console: restarted at `http://127.0.0.1:6188`; root HTTP and annotation-source API checks passed. The annotation viewer now uses sRGB-correct anti-aliased circular points and separates browse left-drag rotation from brush/rectangle left-drag labels; right-drag rotates, middle-drag pans and the wheel zooms. Middle-button auto-scroll is suppressed and a rotate-centre tool places the orbit target at a clicked visible point without writing a label. A model-orientation popover provides independent local X/Y/Z display rotation from 0-360 degrees about the model centre; it leaves source coordinates and stored annotation indices unchanged while selection follows the display transform. Console/unit/type checks passed. Visual annotation review awaits a user screenshot under the no-browser-inspection rule. - Applied-model workflow: the supervised area now discovers only complete local `training-runs/*/{model.pt,metrics.json}` records. A user selects a model, uploads one RGB PLY/PCD/LAS/LAZ input, and the local-only server copies bytes to a new raw/processed inference run before launching the fixed CPU script. It exposes a polling job, in-page PLY prediction preview, classified LAS, class-count CSV, summary JSON, metadata, and weight download. Browser paths, arbitrary model paths, and XYZ-only inputs are rejected. Outputs are review candidates, not assets or inspection conclusions. - Verified 2026-08-24: the real model `semantic-model-20260824-023343-571983` applied to the 400,000-point RGB annotation PLY through the CLI in 1.608 seconds and through the HTTP upload / background-job route. The latter created `semantic-inference-20260824-024901-b60fda` and served a 10,800,209-byte PLY preview plus a 13,600,227-byte classified LAS. The model's labelled spatial test F1 is vegetation 0.979, power line 0.815, pole/tower 0.348; pole/tower predictions therefore have high false-positive risk. No browser visual check was performed by the agent under the project rule. - 3D workbench information architecture: the former mixed page is now four focused workspaces: photo 3D reconstruction; point-cloud geometry processing; point-cloud semantic classification; and annotation, training, and model application. Each has a separate filtered case library and result workspace. A point-cloud run can be opened in both geometry and semantic workspaces when it owns both output families, but no longer renders DSM, semantic review, annotation, training, and model application as one continuous page. Photo cases are isolated from LAS/PLY cases. This is a console UX change only; it does not alter any reconstruction, geometry, semantic-rule, annotation, or model-inference computation. ## 2026-08-14 工作台更新 - 本地控制台已从只读结果页升级为独立实验工作台:能力页包含新建运行入口、服务端自动发现的案例库和结果工作区,仍不连接任何无人机产品。 - `scripts/serve_workbench_console.py` 仅监听 `127.0.0.1` 等回环地址,支持轨迹与目标检测的受限 JSON/Base64 上传 API;每次生成唯一运行目录,不覆盖原始数据或既有输出。 - 轨迹上传入口接受 XLSX、KMZ、禁飞区 GeoJSON 和可选适飞区 Gzip,预处理器已支持缺少适飞区时继续生成可运行 case。 - 目标检测页面默认并列展示原图与标注图;案例数据从输出目录扫描,历史多模型检测结果可以在同一案例库中选择。 - 异常检测案例库支持把历史案例的原始参考图、待检测图和运行参数回填到新运行表单,供用户调整后创建新的检测运行;回填操作不自动运行,也不覆盖历史案例。 - 轨迹汇总的 `normal`、`stop`、`route_deviation`、`restricted_zone`、`gathering` 标签在 UI 显示中文,原始英文值保留在 CSV/GeoJSON。