从零开始:如何用Python快速上手处理Ottawa和Bern这两个经典SAR变化检测数据集?
实战指南:Python处理Ottawa与Bern SAR变化检测数据集全流程
SAR(合成孔径雷达)变化检测是遥感领域的重要研究方向,而Ottawa和Bern数据集作为该领域的经典基准数据,常被用于算法验证和性能评估。本文将手把手带你用Python完成从数据获取到预处理的全流程,并构建可用于深度学习的数据加载器。
1. 环境准备与数据获取
在开始处理SAR数据前,需要确保Python环境已安装必要的科学计算库。推荐使用conda创建虚拟环境:
conda create -n sar_cd python=3.8 conda activate sar_cd pip install numpy scipy matplotlib rasterio scikit-image torchOttawa和Bern数据集可以从以下渠道获取:
- Ottawa数据集:包含1997年5月和8月两期RADARSAT图像,覆盖加拿大渥太华地区
- Bern数据集:包含1999年4月和5月两期ERS-2图像,覆盖瑞士伯尔尼地区
提示:部分数据集可能需要学术用途申请,建议提前准备.edu邮箱
2. 数据读取与格式转换
SAR数据通常以.mat(MATLAB)或.tif格式存储。我们使用scipy.io和rasterio分别处理这两种格式:
import numpy as np import rasterio from scipy.io import loadmat # 读取.mat格式的Bern数据集 def load_mat_data(path): data = loadmat(path) img1 = data['t1'] # 时相1 img2 = data['t2'] # 时相2 gt = data['gt'] # 变化标签 return img1, img2, gt # 读取.tif格式的Ottawa数据集 def load_tif_data(t1_path, t2_path): with rasterio.open(t1_path) as src: img1 = src.read(1) with rasterio.open(t2_path) as src: img2 = src.read(1) return img1, img2常见问题处理:
- 数据类型不匹配:SAR数据可能存储为uint16但实际值范围在0-1之间
- 坐标系差异:不同时相图像可能存在轻微偏移
- 缺失值处理:部分像素可能为NaN或异常值
3. 数据可视化与分析
使用matplotlib实现三图并排显示(时相1、时相2、变化图):
import matplotlib.pyplot as plt def plot_sar_comparison(img1, img2, gt=None): fig, ax = plt.subplots(1, 3, figsize=(15,5)) ax[0].imshow(img1, cmap='gray') ax[0].set_title('Time 1') ax[0].axis('off') ax[1].imshow(img2, cmap='gray') ax[1].set_title('Time 2') ax[1].axis('off') if gt is not None: ax[2].imshow(gt, cmap='jet') ax[2].set_title('Change Map') else: diff = np.abs(img1 - img2) ax[2].imshow(diff, cmap='hot') ax[2].set_title('Difference') ax[2].axis('off') plt.tight_layout() plt.show()SAR图像可视化要点:
- 使用对数变换增强对比度:
np.log1p(img) - 考虑添加颜色条显示强度范围
- 对于多时相数据,保持相同的色彩范围
4. 数据预处理流程
SAR数据预处理是变化检测的关键步骤,主要包括:
辐射校正:消除传感器增益和地形影响
def radiometric_correction(img, sigma=1.0): return img / sigma斑点噪声抑制:使用Refined Lee滤波
from skimage.filters import median def lee_filter(img, window_size=3): return median(img, np.ones((window_size, window_size)))数据归一化:将像素值缩放到固定范围
def normalize(img): return (img - img.min()) / (img.max() - img.min())配准对齐:确保两时相图像空间一致
from skimage.transform import SimilarityTransform, warp def register_images(img1, img2): # 这里需要实际的特征匹配和变换估计 tform = SimilarityTransform(scale=1, rotation=0, translation=(2, 1)) img2_reg = warp(img2, tform.inverse) return img2_reg
注意:实际配准需要特征点检测和匹配,上述代码仅为示例框架
5. 构建PyTorch数据加载器
为方便深度学习模型训练,我们创建自定义Dataset类:
import torch from torch.utils.data import Dataset, DataLoader class SARDataset(Dataset): def __init__(self, img1, img2, gt=None, transform=None): self.img1 = img1 self.img2 = img2 self.gt = gt self.transform = transform def __len__(self): return self.img1.shape[0] def __getitem__(self, idx): x1 = self.img1[idx] x2 = self.img2[idx] if self.transform: x1 = self.transform(x1) x2 = self.transform(x2) if self.gt is not None: y = self.gt[idx] return x1, x2, y return x1, x2 # 创建滑动窗口样本 def create_patches(img, patch_size=64, stride=32): patches = [] for i in range(0, img.shape[0]-patch_size, stride): for j in range(0, img.shape[1]-patch_size, stride): patch = img[i:i+patch_size, j:j+patch_size] patches.append(patch) return np.array(patches)数据增强技巧:
- 随机旋转和翻转
- 添加轻微噪声增强鲁棒性
- 调整亮度和对比度
6. 无监督变化检测实践
对于无监督变化检测,常用的方法是基于差异图分割:
from skimage.filters import threshold_otsu from skimage.segmentation import mark_boundaries def unsupervised_cd(img1, img2): # 计算差异图 diff = np.abs(img1 - img2) # Otsu自动阈值分割 thresh = threshold_otsu(diff) binary = diff > thresh # 后处理 from skimage.morphology import remove_small_objects cleaned = remove_small_objects(binary, min_size=50) # 可视化结果 plt.imshow(mark_boundaries(img1, cleaned)) plt.title('Unsupervised Change Detection') plt.axis('off') plt.show() return cleaned进阶方法可以尝试:
- PCA变换后差异分析
- 基于聚类的方法(如K-means)
- 深度学习自编码器特征差异
7. 实战技巧与常见问题
在处理Ottawa和Bern数据集时,有几个实用技巧:
坐标系统统一
import pyproj def reproject_to_utm(img, transform, crs): with rasterio.open('temp.tif', 'w', driver='GTiff', height=img.shape[0], width=img.shape[1], count=1, dtype=img.dtype, crs=crs, transform=transform) as dst: dst.write(img, 1) # 重新读取确保投影正确 with rasterio.open('temp.tif') as src: return src.read(1)处理大型SAR文件的技巧
- 使用分块处理:
rasterio.windows.Window - 内存映射:
np.memmap - 多进程处理
性能优化对比
| 操作 | 原始方法 | 优化方法 | 速度提升 |
|---|---|---|---|
| 读取 | 直接加载 | 分块读取 | 3-5x |
| 滤波 | 逐像素 | 向量化 | 10x |
| 配准 | 全图匹配 | 特征点+ROI | 8x |
实际项目中遇到的典型问题:
- 两时相图像亮度差异显著
- 季节性变化被误检为真实变化
- 云层覆盖导致光学数据不可用
- 城市区域的高反射率影响
