如何在 Python 中将高光谱 .HDR 文件转换为栅格数组并生成镜像图像
本文介绍使用 rasterio 和 spectral 库读取 ENVI 格式高光谱数据(.hdr + 对应原始数据文件),解决 EOFError: read() didn't return enough bytes 错误,并高效生成逐波段镜像图像的完整流程。
本文介绍使用 rasterio 和 spectral 库读取 envi 格式高光谱数据(.hdr + 对应原始数据文件),解决 `eoferror: read() didn't return enough bytes` 错误,并高效生成逐波段镜像图像的完整流程。
高光谱数据常以 ENVI 格式存储,包含一个头文件(.hdr)和一个二进制原始数据文件(如 .raw、.hsi 或无扩展名)。初学者常误用 spectral.io.envi.open() 直接传入 .hdr 路径而忽略关联的原始数据文件,导致 read_band() 报 EOFError——这是因为 spectral 库需同时定位头文件与对应的数据体文件,且对文件路径、字节对齐和数据类型高度敏感。
推荐优先采用 rasterio 读取:它原生支持 ENVI 格式,自动解析 .hdr 元信息,稳定加载为 (bands, height, width) 形状的 NumPy 数组,避免 I/O 错误。而 spectral 加载结果为 (height, width, bands),虽语义更贴近图像思维,但在批量处理或与地理空间工具链(如 rasterio、xarray)协同时,rasterio 的轴序更统一、兼容性更强。
以下为完整可运行示例(请根据实际路径调整):
import rasterio
import numpy as np
import matplotlib.pyplot as plt
# ✅ 正确路径配置:指向原始数据文件(非 .hdr!),rasterio 自动读取同名 .hdr
data_file = r"C:/Users/Desktop/HyperspectralData/raw_rd_rf" # 注意:不带 .hdr 或 .raw 扩展名(rasterio 会自动查找)
# 若原始文件有明确后缀(如 raw_rd_rf.raw),则写全路径:.../raw_rd_rf.raw
with rasterio.open(data_file) as src:
# 读取全部波段 → 形状为 (bands, rows, cols)
cube = src.read() # e.g., (150, 1024, 1344)
profile = src.profile # 保留原始元数据(坐标系、分辨率等)
print(f"数据形状: {cube.shape} → (波段数, 行数, 列数)")
print(f"波段数量: {src.count}")
若需获取波长信息,再用 spectral 加载头文件(仅解析元数据,不读取像素):
Kaiber
Kaiber是一个视频生成引擎,用户可以根据自己的图片或文字描述创建视频
下载
import spectral
hdr_file = r"C:/Users/Desktop/HyperspectralData/raw_rd_rf.hdr"
img = spectral.io.envi.open(hdr_file, image=data_file) # 第二个参数必须是原始数据路径!
wavelengths = np.array(img.bands.centers) # 单位通常为 nm
print(f"波长范围: {wavelengths[0]:.1f}–{wavelengths[-1]:.1f} nm")
生成镜像图像(水平翻转,即沿垂直轴左右镜像):
# 对第 0 波段做镜像(使用 np.fliplr,高效且内存友好)
band_0_mirror = np.fliplr(cube[0]) # shape: (rows, cols)
# 可视化对比
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(10, 4))
ax1.imshow(cube[0], cmap='viridis')
ax1.set_title("原始波段 0")
ax1.axis('off')
ax2.imshow(band_0_mirror, cmap='viridis')
ax2.set_title("镜像波段 0(左右翻转)")
ax2.axis('off')
plt.tight_layout()
plt.show()
⚠️ 关键注意事项:
- rasterio.open() 的参数必须是原始数据文件路径(如 raw_rd_rf 或 raw_rd_rf.raw),不是 .hdr 文件;它会自动匹配同目录下的 .hdr。
- spectral.io.envi.open(hdr_path, image=raw_path) 中两个路径必须严格对应,且 raw_path 需指向真实存在的二进制文件。
- np.fliplr() 适用于 (rows, cols) 二维图像;若处理整立方体,可用 cube[:, ::-1, :] 实现所有波段同步水平翻转。
- 如需保存镜像结果为 GeoTIFF,可复用 profile 并更新 transform(若含地理参考),调用 rasterio.open(..., 'w', **profile) 写入。
通过此方法,您可稳定加载高光谱数据、规避 EOF 错误,并灵活实现单波段或全波段镜像操作,为后续辐射定标、特征提取或数据增强奠定可靠基础。