288 lines
12 KiB
Markdown
288 lines
12 KiB
Markdown
## `StripStitch.py` 说明文档(遥感航带批量配准)
|
||
|
||
`StripStitch.py` 用于 **批量将文件夹内的 `.bip` 航带影像配准到一张参考 GeoTIFF(`.tif`)底图**。脚本默认启动 **GUI(Tkinter)**,也支持通过 `--cli` 走“无界面批处理”(但当前版本 **没有 argparse 参数**,CLI 模式仍使用脚本内的默认配置/或你手动改常量)。
|
||
|
||
---
|
||
|
||
## 1. 功能概览
|
||
|
||
- **批量处理**:遍历 `BIP_DIR` 下的 `*.bip`,逐个配准到参考底图。
|
||
- **自动裁剪参考 ROI**:根据源图有效像素掩膜推算与底图的重叠范围,并在底图上取 ROI(可额外 padding)。
|
||
- **特征匹配**:通过 `vismatch.get_matcher()` 调用多种 matcher(可选 GPU/CPU)。
|
||
- **质量控制**:
|
||
- 掩膜羽化(降低硬边界导致的假匹配)
|
||
- 掩膜边缘带剔除(减少“掩膜边界”上的伪匹配点)
|
||
- 纹理过滤(低梯度/低纹理区域的匹配点剔除)
|
||
- 最少内点数/最少内点比例阈值
|
||
- **多模型变换尝试并自动选最优**:按你设置的优先级尝试 `similarity/affine/homography/piecewise_affine/polynomial/tps...`,以重投影误差(p95)选择最优。
|
||
- **输出**:
|
||
- 配准后的 `.bip`(ENVI driver)
|
||
- 匹配可视化图(匹配线、关键点)
|
||
- 统计 CSV(每个航带一行:内点数、内点比例、选用模型、误差等)
|
||
- **可选底图掩膜**:先用另一个 mask GeoTIFF 对参考底图做掩膜生成新底图,再用新底图进行配准(依赖 `tif_caijain.py`)。
|
||
|
||
---
|
||
|
||
## 2. 运行方式
|
||
|
||
### 2.1 GUI(默认)
|
||
|
||
在脚本所在目录执行:
|
||
|
||
```bash
|
||
python StripStitch.py
|
||
```
|
||
|
||
GUI 会打开“遥感影像批量配准工具”,在界面里选择:
|
||
|
||
- 参考底图(GeoTIFF)
|
||
- BIP 文件夹
|
||
- 输出文件夹
|
||
- matcher、设备(CUDA/CPU)
|
||
- 变换模型优先级
|
||
- 一系列阈值/过滤参数
|
||
|
||
点击“开始”后批处理运行,日志会实时显示;可点击“停止”中断。
|
||
|
||
### 2.2 CLI(无界面批处理)
|
||
|
||
```bash
|
||
python StripStitch.py --cli
|
||
```
|
||
|
||
注意:
|
||
|
||
- 当前脚本仅通过 `if "--cli" in sys.argv` 切换模式,**没有命令行参数解析**。
|
||
- CLI 模式使用脚本顶部的默认常量(如 `REF_TIF / BIP_DIR / OUT_DIR / MATCHER_NAME ...`)构造配置。
|
||
- 如果你希望 CLI 可配置参数,需要额外改造(例如用 `argparse`)。
|
||
|
||
---
|
||
|
||
## 3. 输入数据要求
|
||
|
||
- **参考底图**:GeoTIFF(`.tif`),必须有 **有效 CRS/transform**(脚本会报错或无法正确投影/裁剪)。
|
||
- **待配准航带**:ENVI BIP(扩展名 `.bip`,内部 profile 由 `rasterio` 读取)。
|
||
- **坐标系**:
|
||
- 源 `.bip` 若缺少 CRS,脚本会尝试使用参考底图 CRS 继续(可能导致错误配准,建议为源数据补齐 CRS)。
|
||
- ROI 的推算使用 `rasterio.warp.transform_bounds` 从源 CRS 转到参考 CRS。
|
||
|
||
---
|
||
|
||
## 4. 输出结构与文件命名
|
||
|
||
假设输出目录为 `OUT_DIR`,运行一次批处理会生成:
|
||
|
||
- **配准结果**:`OUT_DIR/<bip_stem>_registered.bip`
|
||
- 写入使用 `rasterio.open(..., driver="ENVI", interleave="bip")`
|
||
- 旁边通常会伴随 ENVI 的头文件(如 `.hdr` 等,取决于 `rasterio/GDAL` 行为)
|
||
- **可视化**:`OUT_DIR/visualizations/`
|
||
- `<bip_stem>_matches.png`:匹配线可视化
|
||
- `<bip_stem>_keypoints_src.png`:源图关键点
|
||
- `<bip_stem>_keypoints_ref.png`:参考 ROI 关键点
|
||
- **统计**:`OUT_DIR/stats/registration_stats_<YYYYMMDD_HHMMSS>.csv`
|
||
- 列:`timestamp, filename, num_inliers, num_matches, inlier_ratio, selected_method, median_error, p95_error, success`
|
||
- **(可选)掩膜后的参考底图**:`OUT_DIR/masked_refs/<ref_stem>_masked_<ts>.tif`
|
||
- 仅当 GUI 勾选“启用底图掩膜”且 `tif_caijain.py` 可用时生成
|
||
|
||
---
|
||
|
||
## 5. 参数说明(GUI 与脚本配置一致)
|
||
|
||
### 5.1 基础路径
|
||
|
||
- **参考 TIF 文件**:配准目标底图(匹配在底图 ROI 上进行)。
|
||
- **BIP 文件夹**:批量遍历 `*.bip`。
|
||
- **输出文件夹**:结果、可视化、统计都写入这里。
|
||
|
||
### 5.2 底图掩膜(可选)
|
||
|
||
GUI 勾选“启用底图掩膜”后:
|
||
|
||
- 需要提供 **掩膜 TIF**,并要求与底图 **严格对齐**(同 CRS、分辨率、范围、尺寸)。
|
||
- 掩膜值为 `remove_value` 的区域会被设置为 NoData(由 `tif_caijain.mask_data_by_binary_mask` 实现)。
|
||
- 脚本会先生成“掩膜后的底图”,后续配准基于该底图进行。
|
||
|
||
### 5.3 matcher 与设备
|
||
|
||
- **匹配算法(matcher_name)**:由 `vismatch.get_matcher(name, device=...)` 创建。
|
||
- GUI 下拉框内内置了一长串候选(如 `matchanything-roma`, `loftr`, `sift-lightglue`, `roma`, `xfeat-star` 等)。
|
||
- 不同 matcher 在速度/鲁棒性/显存占用方面差异很大。
|
||
- **设备(device)**:
|
||
- `cuda`:更快,但需要 GPU + CUDA 环境
|
||
- `cpu`:更通用,但会慢
|
||
|
||
### 5.4 变换模型(按优先级)
|
||
|
||
可多选并排序;脚本会按优先级逐一估计并评估误差,最终选 p95 重投影误差最小者。
|
||
|
||
常用含义(对应 GUI 列表):
|
||
|
||
- **`similarity`**:相似变换(平移 + 旋转 + 等比缩放)
|
||
- **`affine`**:仿射变换(含非等比缩放/切变)
|
||
- **`homography`**:单应(透视)变换,最灵活但更易受离群点影响
|
||
- **`piecewise_affine` / `polynomial` / `polynomial_order3` / `tps`**:非刚性/高阶模型(依赖可选库,见“依赖”)
|
||
|
||
### 5.5 匹配与 ROI 参数
|
||
|
||
- **匹配最大边长(match_max_side)**:匹配前会等比缩小到最大边不超过该值。越大越慢、细节更多。
|
||
- **ROI 填充像素(roi_pad_px)**:从源有效区域推算出的底图 ROI,会再向外扩展该像素数(底图像素尺度)。
|
||
- **掩膜膨胀像素(mask_pad_px)**:仅用于匹配阶段,对源有效掩膜重投影到参考 ROI 后进行膨胀,扩大可匹配区域。
|
||
|
||
### 5.6 质量控制(建议从默认值起调)
|
||
|
||
- **最少内点数(min_inliers)**:过滤后 RANSAC 内点数低于该值直接判失败。
|
||
- **最少内点比例(min_inlier_ratio)**:\(\text{inliers} / \text{matches}\) 低于阈值判失败。
|
||
- **掩膜羽化宽度(feather_px)**:在掩膜边界做平滑过渡,减少硬边界假匹配。
|
||
- **边缘带剔除宽度(edge_band_px)**:剔除距离掩膜边界过近的匹配点(小图尺度会按缩放比例换算)。
|
||
- **纹理过滤分位阈值(min_grad_quantile)**:在匹配尺寸上计算梯度幅值分位数,低纹理区域的点会被剔除。值越大,保留的区域越“高纹理”。
|
||
|
||
---
|
||
|
||
## 6. 内部处理流程(高层)
|
||
|
||
单个 `.bip` 的核心流程(简化版):
|
||
|
||
- 读取源图与源有效掩膜(`read_masks`),在源 CRS 下取有效像素包围盒
|
||
- 包围盒 bounds 投影到参考 CRS,在参考底图上构建 ROI window,并额外 `roi_pad_px`
|
||
- 读取源图全图、参考底图 ROI
|
||
- 将源有效掩膜重投影到参考 ROI,并按 `mask_pad_px` 膨胀
|
||
- 对源/参考做掩膜羽化(`feather_px`)后进入匹配
|
||
- 下采样到 `match_max_side`,运行 matcher 得到匹配点/内点
|
||
- 用“边缘带剔除 + 纹理过滤”对匹配点/内点二次过滤,得到最终内点与质量指标
|
||
- 在你选定的多个变换模型中估计并评估,选 p95 误差最小者
|
||
- 根据模型类型执行重采样并写出 ENVI BIP
|
||
- 写统计 CSV,保存可视化图片
|
||
|
||
---
|
||
|
||
## 7. 依赖与可选依赖(缺失时的行为)
|
||
|
||
### 7.1 必需依赖(脚本直接 import)
|
||
|
||
- `numpy`
|
||
- `opencv-python`(`cv2`)
|
||
- `rasterio`
|
||
- `affine`
|
||
- `tkinter`(Windows 自带 Python 通常包含)
|
||
- `vismatch`(脚本依赖它来创建 matcher,并用 `vismatch.viz` 保存可视化图)
|
||
|
||
### 7.2 可选依赖(缺失会降级/跳过)
|
||
|
||
- **`tif_caijain.py`**:用于“底图掩膜”功能;缺失则 GUI 勾选会报错。
|
||
- **`scikit-image`**:用于 `piecewise_affine` / `polynomial` 等变换;缺失会跳过这些方法或走回退逻辑。
|
||
- **`matplotlib` + `scipy`(ConvexHull)**:用于点集凸包的“内点判定”,缺失时会退化为矩形内判断(更可能外推导致异常区域)。
|
||
- **`SimpleITK` / `pirt` / `scipy.interpolate.Rbf`**:用于 TPS 等更复杂的非线性变换与回退路径;缺失时可能回退到更简单的仿射。
|
||
|
||
---
|
||
|
||
## 8. 常见问题排查
|
||
|
||
- **报错:参考文件缺少 CRS 信息**
|
||
- 参考 GeoTIFF 必须有 CRS。用 GIS 软件或 `gdalinfo` 检查并修复投影信息。
|
||
|
||
- **源 `.bip` 缺少 CRS**
|
||
- 脚本会“尝试用参考 CRS”,但这通常不可靠;建议为源数据补齐正确 CRS。
|
||
|
||
- **内点很少 / 内点比例很低**
|
||
- 优先检查:
|
||
- 参考底图与航带是否确实有重叠区域
|
||
- ROI padding 是否过小(`roi_pad_px`)
|
||
- 边缘带剔除是否过强(`edge_band_px`)
|
||
- 纹理过滤是否过强(`min_grad_quantile`)
|
||
- 其次尝试更鲁棒的 matcher(或改用 GPU)。
|
||
|
||
- **输出范围不对 / 被裁得太小**
|
||
- 输出范围由匹配点映射到参考像素后的外接矩形决定;匹配点集中在局部会导致 bbox 偏小。
|
||
- 可尝试增大 `roi_pad_px`、降低过滤强度、或换更稳定的 matcher。
|
||
|
||
- **非线性方法(piecewise/polynomial/tps)经常失败**
|
||
- 先确保 `scikit-image`、`scipy` 等可用。
|
||
- 非线性方法更依赖匹配点覆盖范围与质量;当点分布很局部时更容易外推/数值不稳。
|
||
- 生产环境通常建议把 `affine` 作为兜底并放在较高优先级。
|
||
|
||
---
|
||
|
||
## 9. 推荐使用习惯(实操)
|
||
|
||
- **先用少量样本跑通**:把 `BIP_DIR` 里先放 1–3 条航带验证匹配与输出,再批量跑全量。
|
||
- **先看 `visualizations/`**:匹配线与关键点能最快判断“是没重叠、还是过滤过强、还是 matcher 不适配”。
|
||
- **保留 `stats/`**:后续筛选失败样本、做参数回归/对比很有用。
|
||
|
||
flowchart TD
|
||
A[开始处理单个BIP文件] --> B[读取源文件和参考文件]
|
||
B --> C{检查CRS坐标系统}
|
||
C -->|源文件无CRS| D[使用参考文件CRS]
|
||
C -->|源文件有CRS| E[使用源文件CRS]
|
||
D --> F[计算有效区域ROI]
|
||
E --> F
|
||
|
||
F --> F1[基于有效掩膜计算包围盒]
|
||
F1 --> F2[将包围盒转换到参考坐标系]
|
||
F2 --> F3[扩展窗口ROI_PAD_PX]
|
||
|
||
F3 --> G[读取图像数据]
|
||
G --> H[将源图掩膜重投影到参考空间]
|
||
H --> H1[可选: 膨胀掩膜MASK_PAD_PX]
|
||
|
||
H1 --> I[图像预处理]
|
||
I --> I1[转3通道_float01格式]
|
||
I1 --> I2[百分位数拉伸归一化]
|
||
|
||
I2 --> J[生成软掩膜]
|
||
J --> J1[距离变换生成羽化边缘]
|
||
J1 --> J2[应用掩膜到图像]
|
||
|
||
J2 --> K[降采样用于匹配]
|
||
K --> K1[等比缩放到MATCH_MAX_SIDE]
|
||
|
||
K1 --> L[特征匹配]
|
||
L --> L1[调用Matcher获取匹配点]
|
||
|
||
L1 --> M[匹配点过滤]
|
||
M --> M1[边缘带剔除 EDGE_BAND_PX]
|
||
M --> M2[纹理过滤 MIN_GRAD_QUANTILE]
|
||
M1 --> M3[组合掩膜过滤]
|
||
M2 --> M3
|
||
|
||
M3 --> N{质量控制检查}
|
||
N -->|内点数<MIN_INLIERS| O[配准失败]
|
||
N -->|内点比例<MIN_RATIO| O
|
||
N -->|通过检查| P[计算全分辨率坐标]
|
||
|
||
P --> Q[估计多种变换模型]
|
||
Q --> Q1[similarity]
|
||
Q --> Q2[affine]
|
||
Q --> Q3[homography]
|
||
Q --> Q4[piecewise_affine]
|
||
Q --> Q5[polynomial]
|
||
|
||
Q1 --> R[评估变换质量]
|
||
Q2 --> R
|
||
Q3 --> R
|
||
Q4 --> R
|
||
Q5 --> R
|
||
|
||
R --> S[选择最优变换模型]
|
||
S --> T{变换类型判断}
|
||
|
||
T -->|Affine| U[仿射变换处理]
|
||
T -->|Homography| V[单应变换处理]
|
||
T -->|Piecewise/Polynomial| W[非线性变换处理]
|
||
|
||
U --> X[计算最小外接矩形]
|
||
V --> X
|
||
W --> X
|
||
|
||
X --> Y[创建输出文件]
|
||
Y --> Z[逐波段几何重采样]
|
||
Z --> AA[保存配准结果]
|
||
AA --> AB[记录统计信息]
|
||
AB --> AC[结束]
|
||
|
||
O --> AD[记录失败信息]
|
||
AD --> AC
|
||
|
||
T -->|所有变换失败| AE[仿射回退处理]
|
||
AE -->|回退成功| AA
|
||
AE -->|回退失败| O
|