shuishen
2026-08-19 2ae460fc4a4c2419cf44329783d49a739e2a04ea
capabilities/09-anomaly-detection/README.md
@@ -1,6 +1,161 @@
# Anomaly Detection
# 09 Anomaly Detection
- 输入:影像特征、轨迹特征或业务指标。
- 输出:异常分数、异常清单和原因特征。
- 首个 Demo:规则基线与 Isolation Forest 对比。
## 状态与能力边界
- 状态:可运行 CPU CLI Demo,已于 2026-08-18 完成受控样本和困难真实样本验证。
- 分类:B 类能力。RGB/HSV 等可解释影像特征、稳健规则评分和 Isolation Forest 来自生态库;`geoai-py 0.42.x` 仅用于调用 `masks_to_vector` 将异常掩膜转成候选多边形。
- 目标:寻找与正常参考影像分布明显不同的视觉区域,供人工复核。
- 非目标:不能把候选直接解释成堵塞、损坏、渗漏或生产告警,也不代表真实矿山场景精度。
首版没有引入深度嵌入权重。`geoai-py` 当前的 Embeddings API 主要服务于预计算地球嵌入数据集,不是本 Demo 的本地通用异常模型。
## 输入约束
- 参考和待检测输入可以是单张影像或目录,支持 JPG、JPEG、PNG、TIF、TIFF。
- JPG/PNG 转为 RGB 并使用像素坐标;GeoTIFF 默认读取前三个波段,只有有效 CRS 和仿射变换才会写入空间参考。
- 默认窗口 `256 x 256`、步长 `128`,边缘窗口锚定到影像边界。
- 参考集至少需要 50 个窗口,影像尺寸不能小于窗口,输出目录必须不存在或为空。
## 方法
每个窗口提取 17 个特征:RGB/HSV 均值与标准差、灰度熵、边缘密度、Laplacian 清晰度以及暗/亮像素比例。
- 规则基线:`auto` 模式下,3 张以上同尺寸固定机位参考图会先消除每张图的整体亮度/色彩漂移,再将测试窗口只与参考图的相同位置比较;条件不满足时回退到全局中位数/MAD。两种模式都记录贡献最大的原因特征。
- 通用局部变化:同位置模式额外学习正常参考图的 Lab 局部外观,以及灰度、边缘和局部对比度结构分布,用参考图之间的差异自动校准阈值。该通道没有颜色、物品类别或固定坐标规则,用于补充被大窗口平均掉的小而连贯的外观/结构变化。
- Isolation Forest:先对参考特征拟合 `StandardScaler`,再训练 `IsolationForest(n_estimators=200, random_state=42)`。
- 两种方法分别用参考分数的默认 `99.5%` 分位数定阈值,不通过固定污染率强制标记正常窗口。
- 重叠窗口分数平均回像素网格,掩膜编码为 `0=正常、1=仅规则、2=仅 Isolation Forest、3=两者一致`。
## 环境与运行
环境固定在仓库内的 `.venvs/09-anomaly-detection`,使用 Python 3.12,不安装到系统 Python:
```powershell
.\scripts\setup.ps1 -Capability 09-anomaly-detection
.\.venvs\09-anomaly-detection\Scripts\python.exe -m pip check
```
运行 CLI:
```powershell
.\.venvs\09-anomaly-detection\Scripts\python.exe `
  .\capabilities\09-anomaly-detection\run_anomaly_detection.py `
  --reference <正常参考影像或目录> `
  --input <待检测影像或目录> `
  --output <新的空目录> `
  --tile-size 256 `
  --stride 128 `
  --threshold-quantile 0.995 `
  --random-state 42 `
  --spatial-mode auto `
  --truth-manifest <可选验证真值JSON>
```
生成可重复的验证输入(复制源图时校验 SHA256,绝不覆盖 `baseData` 原图):
```powershell
.\.venvs\09-anomaly-detection\Scripts\python.exe `
  .\capabilities\09-anomaly-detection\generate_validation_inputs.py `
  --source-dir .\baseData `
  --raw-output .\shared\data\raw\09-anomaly-detection\validation-20260818-v2 `
  --processed-output .\shared\data\processed\09-anomaly-detection\validation-20260818-v2
```
## 输出接口
每张输入影像生成:
- `*.rule.heatmap.png` 和 `*.isolation.heatmap.png`
- `*.comparison.overlay.png`
- `*.anomaly-mask.tif`
- `*.anomalies.geojson`
- `*.tiles.csv`
运行目录还会生成 `run_metadata.json`,记录环境版本、阈值、特征、参考/输入数量、耗时、空间参考、逐图统计、真值指标、矢量化路径和限制。GeoJSON 包含方法标记、最大分数、主要原因特征和像素面积。
## 验证结果
验证输出位于 `shared/outputs/09-anomaly-detection/validation-20260818-v3/`。参考图产生 588 个窗口,共处理 3 张目标图,CPU 总耗时 41.051 秒。
| 样本 | 规则覆盖率 | Isolation Forest 覆盖率 | 单图耗时 |
| --- | ---: | ---: | ---: |
| 注入异常 `07-16-injected.png` | 7.16% | 3.74% | 14.741 秒 |
| 未修改正常图 `07-16-normal.jpg` | 0.33% | 0.00% | 9.211 秒 |
| 困难真实图 `07-19-difficult.jpg` | 1.46% | 0.56% | 10.341 秒 |
受控注入包含颜色块、局部模糊和暗色遮挡。规则方法命中 3/3,precision 0.583、recall 0.672、IoU 0.454;Isolation Forest 命中 2/3,precision 0.831、recall 0.500、IoU 0.454。这些指标只验证受控链路,不代表真实业务准确率。
人工查看结果图后确认:颜色块和暗色遮挡与候选明显对齐;模糊区域主要由规则方法检出。正常图在左上植被/岩体过渡处有少量规则误报;困难图的候选集中在混凝土结构、门洞和顶部暗区,可能来自视角、材质和光照差异,不能称为真实异常。
## 测试
```powershell
.\.venvs\09-anomaly-detection\Scripts\python.exe -m unittest discover `
  -s .\capabilities\09-anomaly-detection\tests -v
```
测试覆盖边缘切片、特征响应、随机种子复现、完整 CLI 输出、非空输出拒绝、参考窗口下限、目录输入、无支持格式,以及带投影三波段 GeoTIFF 的 CRS/仿射变换保留。
## 许可证与限制
| 项目 | 许可证/状态 |
| --- | --- |
| `geoai-py` | MIT |
| scikit-learn、SciPy、Rasterio、GeoPandas | BSD 系列;Rasterio 依赖的 GDAL 需独立核查 |
| OpenCV | Apache-2.0 |
| Pillow | HPND |
| 模型权重 | 无 |
| 验证影像 | 用户已有样本;本 Demo 不扩展其授权范围 |
当前只处理 RGB 可视影像,不支持热红外、SAR 或任意多光谱组合。下一步应先取得多场景正常参考图、真实异常人工标注和地理配准影像,测量跨视角/光照的误报与漏报,再决定是否接入控制台或产品告警。
## 本地实验控制台
控制台已接入输入、后台运行、案例库和结果工作区:
```text
http://127.0.0.1:6173/apps/workbench-console/#/capability/09-anomaly-detection
```
- 输入:分别多选 1~6 张正常参考影像和 1~6 张待检测影像,可调整窗口、步长、阈值分位数和随机种子。
- 上传:JPG/PNG/GeoTIFF 都通过受限二进制流传输,保存原始字节、大小和 SHA256;每次创建新的 raw、processed 和 output 运行目录。
- 运行:提交后进入本机后台任务,页面轮询状态,不维持长时间上传请求。
- 输出:展示参考输入、待检测原图、对比叠加、两张热力图、覆盖率、候选表格,并下载掩膜 GeoTIFF、GeoJSON、窗口 CSV 和元数据。
- API:`GET/POST /api/anomaly-detection/runs`、`PUT /api/anomaly-detection/uploads/<upload-id>`、`GET /api/anomaly-detection/jobs/<job-id>`。
2026-08-18 使用一张 3664 × 2748 参考图和一张困难影像完成控制台真实上传验证,后台任务成功产生 6 个候选区;原图与结果工件均通过本地 HTTP 读取。控制台仍只用于实验复核,不连接产品告警。
## 五参考图合成场景复核(2026-08-19)
使用内置 ImageGen 生成同一固定机位的排水沟场景:5 张正常参考图分别覆盖阴天、晴天、雨后、晨雾和傍晚,异常图仅在沟内加入树枝、落叶、泥土和石块形成的堵塞。生成信息位于 `shared/data/raw/09-anomaly-detection/validation-20260819-imagegen-v1/generation_metadata.json`。
- 5 张参考图产生 385 个参考窗口;默认参数运行耗时 5.861 秒。
- 多参考图结果为 0 个候选,规则法和 Isolation Forest 均漏掉堵塞。
- 只使用最接近的阴天基准图时产生 4 个候选;两方法一致区域覆盖堵塞位置,但规则覆盖率达到 41.67%,画面两侧和远端出现大面积误报。
- 原因:当前特征模型汇总所有位置的窗口分布,不理解“岩石在坡面正常、类似材质进入排水沟才异常”的空间语义;天气参考和生成编辑的全局纹理变化又扩大了正常范围。
该运行已登记到控制台案例库,名称为 `ImageGen 五参考图堵塞复核(漏检案例)`,保留 0 候选的真实输出以及五张参考图、测试原图、热力图和下载工件。
该结果否定了“多放几张正常图就能可靠识别排水沟堵塞”的假设。为此新增了固定机位同位置规则:`--spatial-mode auto` 在至少 3 张参考图且所有图像尺寸一致时自动启用,否则保留原全局规则;也可显式选择 `aligned` 或 `global`。Isolation Forest 仍作为全局外观基线保留。
优化后的新运行位于 `shared/outputs/09-anomaly-detection/validation-20260819-imagegen-aligned-v2/`,没有覆盖原漏检结果:
- 默认 `99.5%` 参考分位阈值为 13.6367,没有为命中样本降低阈值。
- 堵塞图产生 1 个规则候选,覆盖率 9.375%;人工查看确认候选覆盖沟内树枝、落叶、泥石,没有扩散到两侧山坡和道路。Isolation Forest 在该样本仍为 0 个候选。
- 将 5 张正常图逐张留出、其余 4 张作参考时,规则覆盖率依次为 7.292%、0%、0%、0%、0%,均不高于 10%。
- 新结果已登记为 `ImageGen 五参考图堵塞复核(同位置优化)`,与 `漏检案例` 并列用于前后对照。
同位置模式解决的是固定机位、相同构图中的局部画面变化,不具备“堵塞”语义。明显机位偏移仍会造成误报;真实部署还应增加图像配准、排水沟 ROI 或专门的检测/分割模型,并取得真实标注数据。
## 通用局部异常增强验证(2026-08-19)
针对运行 `anomaly-20260819-061029-583672` 中面积较小的显著新增图案漏检,新增通用局部外观/结构通道。红色图案只作为漏检验证样本,算法没有红色阈值、物品类别或样本坐标规则。
- 原方法在该区域的规则最高分 3.007(阈值 18.931),Isolation Forest 最高分 0.559(阈值 0.583),均未过线。
- 增强后形成一个 9,467 像素的 `local_appearance_change` 候选,覆盖验证区域全部 6,710 个高饱和红色像素;整图局部变化覆盖率 0.602%。原有 Isolation Forest 建筑区域候选保持不变。
- 排水沟堵塞回归仍产生 1 个候选,规则覆盖率由此前 9.375% 变为 9.594%,候选仍覆盖沟内堵塞物;细长配准噪声经通用连通性过滤清除。
- 五张排水沟正常图逐张留出验证的总规则覆盖率为 7.292%、0%、0%、0.460%、1.209%,均不高于 10%。
- 结果分别位于 `validation-20260819-small-local-v5/` 和 `validation-20260819-imagegen-local-v5/`;小目标修复结果登记为控制台案例 `通用局部异常增强(小目标漏检修复)`。
当前局部通道要求固定机位和相同尺寸,最小保留 512 像素且过滤细长稀疏连通区。它仍可能把移动阴影、树叶变化或生成式影像细节漂移标为异常,不代表理解了物体类别或业务原因。