## `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
