从NASA DataPort到PyTorch:USGS光谱库.V7数据读取与预处理实战

张开发
2026/4/21 14:57:41 15 分钟阅读
从NASA DataPort到PyTorch:USGS光谱库.V7数据读取与预处理实战
1. USGS光谱库V7数据初探第一次接触USGS光谱库V7版本时我被它庞大的数据量震撼到了。这个由美国地质调查局维护的数据库就像是一个光谱数据的百科全书包含了从地面矿物到人造物体的各种光谱特征。特别是其中的AVIRIS传感器数据对做高光谱图像分析的研究者来说简直是宝藏。但很快我就发现这些数据并不像常见的图片数据集那样拿来就能用。每个文件都带着一堆扩展名奇怪的附属文件.img、.hdr、.spc、.geo等等。刚开始我完全摸不着头脑直到花了两周时间研究文档和源码才搞明白它们各自的作用。比如那个不起眼的.spc文件其实存储着至关重要的光谱校准参数直接影响到后续分析的准确性。2. 从NASA DataPort获取数据2.1 数据下载实战在NASA DataPort找数据就像在图书馆查资料得知道怎么用它的检索系统。我通常先进入Data Table页面用AVIRIS作为关键词筛选。找到感兴趣的数据集后重点看两个信息一是采集日期不同时期的数据质量可能有差异二是link_ftp字段提供的下载链接。这里有个小技巧下载前一定要检查文件大小。AVIRIS的原始数据动辄几个GB我曾经不小心下了一套80GB的数据集结果发现根本用不上。建议新手先从Kennedy Space Center这类经典小数据集入手练手。2.2 文件结构解析解压后的文件包就像一套完整的产品说明书组合.img文件是二进制格式的原始数据.hdr头文件记录着行列数、数据类型等元信息.spc文件保存波长、带宽等光谱参数.geo文件包含空间分辨率信息我刚开始总忽略这些附属文件直到有次分析结果出现系统性偏差才发现是没考虑.spc文件中的波长校准参数。现在我的原则是所有文件都要保留一个都不能少。3. 数据预处理全流程3.1 MATLAB初步处理虽然最终要用PyTorch但我建议先用MATLAB做初步检查。因为它内置的multibandread函数能直接读取.img文件配合.hdr文件可以快速验证数据完整性。这是我常用的检查脚本info envihdrread(scene.hdr); data multibandread(scene.img, [info.lines, info.samples, info.bands],... uint16, 0, bsq, ieee-le); imshow(data(:,:,50), []);这个步骤能帮你确认数据是否损坏以及基本的显示效果。我曾经遇到过下载的.img文件前512字节损坏的情况幸亏用MATLAB提前发现了。3.2 Python转换方案转到Python环境后我推荐使用rasterio库进行初步读取import rasterio with rasterio.open(scene.img) as src: data src.read() profile src.profile但要注意这样读取的数据可能需要进行维度调整HSI数据通常是bands last格式。我习惯用numpy的transpose处理data np.transpose(data, (1, 2, 0)) # 转为(height, width, bands)4. PyTorch数据集构建4.1 自定义Dataset类在PyTorch中处理HSI数据最关键的是实现高效的__getitem__方法。这是我的一个基础实现from torch.utils.data import Dataset import torch class HSIDataset(Dataset): def __init__(self, data, labelsNone, transformNone): self.data torch.from_numpy(data).float() self.labels torch.from_numpy(labels) if labels is not None else None self.transform transform def __len__(self): return len(self.data) def __getitem__(self, idx): sample self.data[idx] if self.transform: sample self.transform(sample) return (sample, self.labels[idx]) if self.labels is not None else sample4.2 内存优化技巧高光谱数据很容易撑爆内存我总结了几个实用技巧使用内存映射文件np.memmap可以避免一次性加载全部数据分块处理将大图像切割成小patch再输入网络波段选择根据.spc文件筛选关键波段减少数据量5. 实战中的常见问题5.1 波段对齐问题不同传感器的波段设置不同直接混合使用会导致问题。我的解决方案是提取.spc文件中的中心波长信息使用线性插值将数据重采样到统一波长范围特别注意水吸收波段104-108, 150-163等的处理5.2 辐射定标处理原始数据通常是DN值Digital Number需要转换为辐射亮度。这时.gain文件就派上用场了with open(scene.gain) as f: gains np.array([float(line) for line in f]) radiance data / gains[None, None, :] # 逐波段校正6. 完整代码示例下面是我在一个真实项目中的预处理流程import numpy as np import rasterio from torch.utils.data import DataLoader def load_aviris_data(img_path, hdr_path): # 读取头文件信息 with open(hdr_path) as f: lines [line.strip() for line in f.readlines()] # 解析关键参数 info {line.split()[0].strip(): line.split()[1].strip() for line in lines if in line} # 加载图像数据 with rasterio.open(img_path) as src: data src.read() # 转换为(height, width, bands)并归一化 data np.transpose(data, (1, 2, 0)) data data / np.iinfo(data.dtype).max return data # 使用示例 data load_aviris_data(scene.img, scene.hdr) dataset HSIDataset(data) dataloader DataLoader(dataset, batch_size32, shuffleTrue)这个流程我在Indian Pines和Salinas数据集上都测试过能够稳定运行。关键是要处理好数据类型的转换和归一化否则可能会遇到数值溢出问题。

更多文章