ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

R语言高光谱数据处理全流程实战:从读取到建模分析

R语言高光谱数据处理全流程实战:从读取到建模分析 简介这是一份面向遥感、地学与农业等领域研究者的R语言高光谱数据分析开源资源围绕hsdar包提供从数据导入、预处理、特征提取到分类建模的完整处理思路适合具备基础R使用经验、希望快速上手高光谱数据管理与分析的读者。资源压缩包共224个文件约3.73MB以R脚本.r、Rd文档.rd、Fortran源代码.f90/.f、示例数据与PDF说明为主还包含C、RData、图表及编译配置文件等便于学习源码实现、查阅函数用法并复现分析流程。内容涵盖ENVI、HDF、GeoTIFF等格式数据读取光谱平滑与大气校正PCA/ICA/PLSR降维SVM与随机森林分类以及回归建模和可视化等关键环节。目前已有740人学习浏览能够帮助用户快速构建从原始数据到解释结果的高光谱分析路径对科研与工程应用均有较强参考价值。 做高光谱数据分析这几年我先后折腾过ENVI、Python、Matlab最后还是把R当成了主力。原因很简单R在光谱数据统计分析上的生态太成熟了而且整套工具链完全开源配上一个hsdar包就能覆盖从数据读取、预处理到建模分析的大部分流程。今天不聊那些虚的直接把我用R处理高光谱数据的完整思路和踩过的坑分享出来适合刚接触高光谱数据、又不想在商业软件上花冤枉钱的研究生和科研人员参考。1. 高光谱数据的特点与R选型逻辑1.1 高光谱数据到底长什么样高光谱数据和普通图像最大的区别在于它有几十到几百个连续波段。以我常用的机载高光谱数据为例通常覆盖400到2500纳米范围光谱分辨率在5到10纳米之间单景数据就是几百个波段的“三维立方体”。很多刚上手的朋友容易懵是因为不知道这个三维结构怎么在R里面表示、怎么索引。其实高光谱数据在R里就是两个东西的组合一个是像元的空间位置信息另一个是每个像元对应的光谱曲线。如果你把数据展平本质上就是一个大矩阵行是每个像元列是波段。R处理这种矩阵结构天然有优势尤其是后续做PCA、聚类、回归这些统计分析时R的统计建模能力比ENVI自带的工具强太多。1.2 为什么选择R而不是Python或商业软件我知道Python也有spectral库但如果你做的是科学研究需要交代统计方法的细节R的文档和论文支持明显更友好。举个实际例子我早期用Python提取光谱特征到了做PLSR回归那一步Python需要自己拼装各种库而R里一个pls包就全搞定了还自带交叉验证和可视化。商业软件当然好用像ENVI的一键式操作确实省心但问题在于贵而且闭源你没法知道每个处理步骤的数学原理。R的好处是每个函数的源代码都是开放的出了问题可以直接翻源码看实现逻辑这个对科研工作的可复现性来说太重要了。另外R的社区包更新速度很快很多最新发表的算法隔几个月就有对应的R包实现这在ENVI里是等不到的。2. 环境搭建与R包选型实战2.1 核心R包安装清单和用途R处理高光谱数据的核心包其实就那几个按处理流程排列如下hyperSpec读取和操作高光谱数据的基础包支持ENVI、FIA等常见格式也可以把光谱数据存成hyperSpec对象方便后续切片、分组、绘图。hsdar高光谱遥感专用包能够计算各种植被指数、实现包络线去除continuum removal、光谱特征提取等功能是我们做光谱分析的主力。prospectr做光谱预处理特别好用包括Savitzky-Golay平滑、标准正态变换SNV、多元散射校正MSC、一阶二阶导数计算等。pls偏最小二乘回归的经典R包做光谱定量分析必备。caret统一模型训练和调参框架搞分类和回归模型时方便做交叉验证。安装时直接用install.packages就行如果提示缺少系统依赖一般是gdal或者proj库的问题Windows用户建议直接装RToolsLinux用户可以用apt安装libgdal-dev解决。2.2 数据准备阶段的注意事项读数据之前有一件事特别重要确认你的数据是怎么来的。我接手过很多数据有的是别人导出的文本表格一列是一个波段一行是一个样点有的是成熟的ENVI标准格式.hdr文件加.dat文件还有的是从成像光谱仪直接导出的原始cube文件。不同来源的数据在R里的读取方式完全不同。如果是ENVI格式hyperSpec包里的read.ENVI函数可以直接读但其要求很严格必须保证hdr文件的波段信息正确。我一开始不知道这个坑用别人处理过的数据经常读不进去后来学会先打开hdr文件检查确保里面有波段数量、波长范围和数据类型这几项问题就解决了一大半。如果是文本格式read.csv直接读进来自己构建光谱矩阵就行。3. 高光谱数据的预处理流程拆解3.1 辐射校正与反射率转换很多朋友拿到手的数据第一反应就是直接开始分析这是个大坑。从仪器上导出的原始数据保存的是数字量化值即DN值它受到暗电流、光照条件、仪器响应等因素的影响不能直接用来做光谱间的比较。正确的做法是先做反射率转换。如果数据供应商已经帮你做了这一步数据里存的就是反射率值那就可以跳过如果拿到的还是DN值你可以用暗校正板或白板数据进行计算。在R里面实现很简单直接用每个波段的DN值除以对应波段白板的DN值再乘上白板的标准反射率就行。说白了就是逐波段的除法运算用hyperSpec对象一行代码就能搞定# 假设dat是待校正数据white是白板光谱数据 reflectance - dat / white这个过程我建议一定要做很多光谱指标的计算对反射率的绝对值很敏感跳过这一步会让后续分析精度大打折扣。3.2 光谱平滑与噪声去除的窗口选择高光谱数据在个别波段区域信噪比特别差比如大气吸收带附近的波段在1400纳米、1900纳米附近会有明显的噪声谷。这时候就需要做光谱平滑。我常用的方法是Savitzky-Golay平滑它的好处是在去除噪声的同时能保留光谱的峰谷形状。prospectr包里的savitzkyGolay函数参数不多关键是选对窗口大小和多项式阶数。这里我踩过坑窗口太小噪声滤不掉窗口太大会把有用的光谱特征磨平。以波段间隔为5纳米到10纳米的数据为例我一般选窗口尺寸为11到15个波段点多项式阶数设为2。如果你的数据光谱分辨率低波段间隔大可以适当减小窗口。做完平滑后强烈建议把处理前后的光谱曲线叠在一起对比看确认特征峰没有明显变形。3.3 波段筛选与数据降维的实操细节高光谱数据波段多但波段之间的冗余也大。很多人在完成预处理后直接丢进模型结果过拟合得一塌糊涂。我在实际工作中通常会先用方差过滤掉那些几乎恒定的波段再用连续投影算法或者随机森林变量重要性排序做进一步筛选。hsdar包里的波段选择函数和一些特征提取方法可以配合使用。另外PCA也是我常用的降维手段。R里用prcomp函数做PCA之后可以画出碎石图看前几个主成分的贡献率。做高光谱分类时我一般取累计贡献率超过95%的前若干个主成分作为输入特征效果比直接用全部波段稳定很多。4. 光谱指数计算与包络线去除分析4.1 常用遥感指数的R实现光谱指数是高光谱分析中最常用的工具像NDVI、EVI这些植被指数大家都很熟了但高光谱数据的能力远不止于此。因为波段足够多我们可以精确提取红边位置、计算各种窄带指数这些指数对作物生化参数的反演比宽波段指数敏感得多。在hsdar包里计算植被指数非常方便。包内自带的spectralIndices函数一次可以计算几十个常见指数你只需要指定光谱数据对象和波段范围。举个实际例子我计算归一化植被指数时需要同时知道红光波段和近红外波段的位置# 用hsdar包计算NDVI library(hsdar) # 假设spec是hyperSpec对象需要先转换为Speclib对象 spc - as.speclib(spectra, wavelength) ndvi - spectralIndices(spc, NDVI)这里有个小提示如果你的数据波段范围不够覆盖660纳米和800纳米附近算出来的NDVI就不靠谱这类指数在计算前一定要先检查波段覆盖范围。4.2 包络线去除的原理与实操包络线去除也叫连续统去除是高光谱特征分析的经典方法。它的作用是把光谱曲线归一化到一个共同的基准线上消除光照、地形等因素的影响同时突出光谱的吸收特征。原理其实不复杂先拟合出光谱曲线的包络线然后用原始光谱除以包络线得到的数值范围在0到1之间波谷就是吸收特征的位置。hsdar包中包络线去除有现成函数但我建议你去翻一下源码理解它的插值算法是怎么实现的这样后面调参数时就不容易出错。操作上先对光谱对象做包络线去除再针对特定吸收特征比如叶绿素在680纳米附近的吸收峰提取特征参数包括吸收深度、吸收宽度、吸收面积等这些参数是后续分类或回归建模的关键输入。我在做植被病害检测时就是用包络线去除后的吸收深度来量化叶绿素降解程度效果比直接用原始反射率好很多因为去除了背景信号的干扰。4.3 光谱角度制图与分类实战分类是高光谱数据应用的重要方向。使用R做分类时我比较推荐光谱角度制图方法它把每个像元的光谱视为多维空间中的一个向量用向量间的夹角来衡量光谱相似度对光照变化不敏感。R中实现光谱角度制图并不复杂可以自己写一个函数先计算参考光谱与目标光谱之间的夹角余弦再设置阈值分类。参考光谱可以从样地实测数据或纯像元平均获得。实测下来这种方法在植被类型分类时表现稳定尤其是类间差异较小的情况下比单纯用欧氏距离要好。如果你的数据量大、类别多也可以考虑SVM或随机森林模型。caret包提供了统一的接口配合doParallel进行并行计算处理几百万像元的数据也不会慢得离谱。分类完成后记得做精度评价用混淆矩阵和Kappa系数评估结果这步在写论文时是必须的。5. 高光谱可视化的几个常用套路高光谱数据可视化是很多人的痛点。普通RGB图像只能显示三个波段而高光谱数据动辄上百个波段怎么把信息有效地展示出来直接影响你对数据的理解和最终成果的表达。我常用的几个可视化方案如下单波段灰度图用来快速查看某个特定波长下的空间分布比如查看红色波段下的植被区域直接plot就能出图。RGB真彩色或假彩色合成从数据中挑选三个波段分别赋给红绿蓝通道比如用近红外、红光、绿光波段做假彩色合成植被在图上就会显示为亮红色视觉上非常直观。光谱曲线图展示单个像元或区域平均光谱时用ggplot2绘制x轴为波长、y轴为反射率的折线图多组光谱可以用不同颜色区分。分类结果专题图用raster包将分类结果输出为栅格结合tmap包做交互式制图效果非常好。这里分享一个技巧如果想把光谱曲线的多个波段特征同时展示在一张图上可以先把光谱数据缩放归一化到0到1再按波段位置错位绘制形成“光谱堆叠图”这种图在开组会时展示特别直观。6. 常见报错与排查经验实录R处理高光谱数据的坑是真的不少很多问题不是代码写错了而是数据本身或者R包的使用方式不对。我把这两年遇到的典型问题整理成表格方便大家排查。问题现象可能原因解决方法读取ENVI数据提示“data format not supported”hdr文件里的数据类型设置不对比如真实数据是浮点型hdr文件却写成整型打开hdr文件检查data type字段用文本编辑器修改成正确的数值类型计算光谱指数时报错提示波长范围不对数据的波长单位不统一有的是纳米有的是微米统一波长单位到纳米用wavelength()函数查看并乘以1000转换绘图时出现大量噪音和尖刺没有做光谱平滑或者平滑窗口太小用savitzkyGolay函数重新处理窗口适当加大PCA结果内存不足程序崩溃数据矩阵太大一次加载了整个影像立方体分块读取用raster包处理大影像或者抽样部分像元进行探索性分析SVM分类训练时间过长样本量太大或特征维度太高没有降维先做PCA或波段筛选再训练模型可并行加速6.1 一个典型的波段单位坑这个我单独拿出来说因为它太隐蔽了。某次我从一台成像光谱仪导出数据波长信息在hdr文件里显示是400到1000我以为是纳米结果跑光谱指数计算时hsdar包提示波段超出可见光范围。排查了半天才发现这台仪器的波长单位其实是微米也就是说400到1000是0.4到1.0微米。换算成纳米后一切正常。所以拿到任何数据第一件事就是打印出波长信息再用plot函数画出几条光谱曲线肉眼确认一下形状是否符合预期。花两分钟做这个检查能省下后面排查问题的一整天。6.2 内存管理心得高光谱影像的像元数量和波段数量乘起来数据量非常可观。一个1000乘1000像元、200个波段的影像浮点型存储大概是1.6GB在R里处理时内存占用还会翻倍。我的做法是能不加载全图就不加载全图。做统计分析时先从影像中均匀抽取一定比例的像元作为样本来建模把模型训练好之后再用predict函数逐块预测整个影像最后拼接起来。这样做内存压力小而且因为模型已经固定结果和全量计算几乎一致。raster包里的blockSize函数和writeRaster函数配合使用可以很优雅地实现分块读写。7. 从数据到成果的完整实操流程最后把我近期一个完整项目的流程捋一遍大家可以当作模板参考。这个项目是对一组小麦田的高光谱影像做叶绿素含量反演数据是机载高光谱空间分辨率0.5米波段范围400到1000纳米共128个波段。实际操作中我的步骤如下先读入ENVI格式数据打印波长信息确认波段范围。用暗电流白板数据做反射率转换并用savitzkyGolay平滑光谱。剔除1400纳米前后的噪声波段区域保留400到1300纳米的波段参与分析。按感兴趣区域提取一定数量的样点光谱和实测SPAD值一一对应。做MSC预处理再计算光谱植被指数和包络线去除吸收特征参数。把指数和特征参数整合成建模矩阵使用caret包随机划分训练集和验证集。用pls包做偏最小二乘回归建模用交叉验证选择潜变量个数。最终模型在验证集上的决定系数是0.82均方根误差2.3 SPAD单位效果可以接受。用最终模型对整个影像逐块预测输出叶绿素含量空间分布图。从开始分析到出图整个过程完全在R里完成没有使用任何商业软件数据和脚本打包后可以在任何一台装了R的机器上复现这种可复现性在论文投稿时是个很好的加分项。整个流程跑顺之后再遇到类似的高光谱数据处理任务基本上半天就能完成从数据到结果的闭环。最后再分享一个小技巧R里的hsdar包和hyperSpec包有非常详细的文档和论文引用要求如果你在论文里用了这些包记得引用相应的文献。很多审稿人会关注这一点引用规范既能体现专业性也是对这些开源包开发者的一种尊重和支持。本文还有配套的精品资源点击获取
返回列表