资讯动态

MODIS地表温度MOD11A2数据处理全解析:从HDF读取到温度换算与质量控制

发布时间:2026/10/2 9:19:04 来源:尧图企业网站定制
先说一下这篇东西是写给哪种人的你手里已经拿到或者准备下载NASA发布的MODIS/Terra地表温度与发射率8天合成数据MOD11A2但对着HDF文件不知道从哪里下手或者下载完只会在GIS里拉伸成一张彩色图之后就没下文了。不管是做气候趋势、城市热岛还是生态干旱监测、农业区划这套数据都值得认真对待但它也有不少“年深日久”的老坑我今天就把自己实际用过的流程和踩过的坑一次性讲清楚。1. 先说清楚这个数据产品到底是什么1.1 几个关键指标拆开看标题里的“MODIS/Terra全球地表温度与发射率8天合成数据1km2000–2026”拆开来看信息量非常大。MODIS是搭载在Terra卫星上的中分辨率成像光谱仪Terra是NASA对地观测系统中的一颗上午星当地太阳时大约是上午10:30过境所以它采集的是白天的地表温度状态与之对应的Aqua卫星是下午星采集的是一天中下午时段的状态。所谓“地表温度LST”指的是地表物理温度一般用开尔文K表示换算成摄氏度要减273.15。很多人会把它跟气温混在一起实际上在晴朗天气下正午的地表温度可以比气温高出十几度甚至更多这是生态、气候、农业研究里非常关键的差异。“发射率”是指地表在热红外波段发射电磁波的能力MOD11A2里面主要给出两个热红外波段31和32波段的发射率。这个参数和地表温度经常是一起反演出来的所以产品把LST与发射率打包发布数据格式上也能看到Emis_31、Emis_32这两个科学数据集。“8天合成”是时间维度上的处理方式官方把一年划分成大约46个8天周期对每个周期内的晴空观测做统计合成这样既保留了时间连续性又比逐日数据能更有效地规避云污染的影响。分辨率1km指的是像元空间分辨率每个像元对应地面一公里乘一公里的范围在全球尺度研究中属于“偏宏观但够用”的级别。2000–2026这组年份的意义在于Terra卫星自2000年2月正式获取数据以来已经积累了超过二十年连续观测记录。这个跨度在卫星遥感地表温度产品中非常珍贵做长期趋势研究时数据时间越长气候信号越能从年际波动中分离出来。标题里写2026一般对应的是数据产品的时间覆盖范围与档案计划目前官方产品会持续滚动更新所以说这套数据是当前全球地表温度研究里少有的“超长连续序列”一点都不过分。1.2 它与MOD11A1、MYD11A2的区别很多新手在LP DAAC和Earthdata搜索里一看到同类产品就懵了MOD11A1、MOD11A2、MYD11A2、MOD11B2……名字长得几乎一样。我建议你在下载之前先把这几者的关系理清否则很容易下错数据浪费时间。MOD11A1是Terra卫星的逐日全球1km地表温度和发射率产品每天一景时间分辨率高但云污染严重MOD11A2就是本篇文章的主角Terra的8天合成产品对MOD11A1在8天窗口内做晴空条件下的统计合成能明显减少云的影响MYD11A2是Aqua卫星对应的8天合成产品过境时间在下午反映的热状态和Terra不一样MOD11B2是Terra的3分钟切片合成产品分辨率5km左右主要用于全球尺度能量平衡研究颗粒度太粗城市尺度的研究一般不推荐。实际研究中经常有人Terra和Aqua数据一块用然后直接把两者平均这是要谨慎的。上午星和下午星反演的是不同时刻的地表热状态直接平均会得到一个介于两者之间的“不伦不类”的温度序列。如果你做长期趋势或物候分析最好是固定使用同一颗卫星的产品保持序列一致性。1.3 这套数据能做什么适合谁这套数据最典型的使用场景集中在三个方向第一是气候研究。比如城市热岛强度分析、地表温度对极端高温事件的响应、全球陆地表面温度变化趋势等。1km分辨率在城市群尺度上可以将城市建成区与郊区明显区分开8天合成又能较好滤除掉单日天气波动的影响。第二是生态与农业应用。干旱监测中经常用温度状态与植被状况的比值比如温度植被干旱指数TVDI来判断土壤水分胁迫农业上则用来评估霜冻灾害范围、作物热胁迫风险甚至辅助灌溉调度。因为这些场景强调“热状态是否异常”对准确度的要求反而不如“相对变化趋势”那么苛刻MOD11A2的精度基本够用。第三是作为陆面过程模型、全球气候模型的地表状态输入参数。模型的初始化、验证、同化都需要一张大范围、时间连续的LST背景场MOD11A2的全球覆盖和时间连续性在这些场景里非常受欢迎。一句话总结适合的用户是遥感专业的研究生、从事气候环境研究的科研人员、农业气象服务相关从业者以及为数不少的地理信息系统开发工程师。只要你有“长时间序列、大范围、一致性好”的地表温度需求这个产品基本就是首选。2. 上手之前必须先搞懂的6个细节这一部分是我认为全文最重要的部分。我知道很多教程上来就教你怎么下载怎么在ArcGIS里打开但实际操作中95%的“结果不对”都来自细节没搞懂。我按自己在项目中处理MOD11A2的顺序把这些细节一层层拆开。2.1 分块瓦片与正弦投影MODIS地表温度产品并不是“全球一张大图”直接下载的它是按MODIS正弦投影的瓦片系统分块存储的也就是大家常说的tile。全球陆地被划分成很多个网格块每个瓦片大约覆盖1200公里乘1200公里文件名里的h和v表示横向和纵向的索引。第一次下载的人最容易犯的错是研究区跨两个瓦片却只下载了其中一个最后出图发现有半块区域是空的。你在Earthdata Search或LP DAAC选择数据时系统通常会按边界框匹配瓦片但建议你还是确认一下选中的瓦片是否完整覆盖研究区尤其是东西跨度大的区域经常需要另外补下载一两个瓦片。投影方面MOD11A2用的是MODIS正弦投影Sinusoidal坐标系是整型坐标单位是米。很多人下载后直接在WGS84经纬度坐标系里叠加显示看起来没问题但一旦要计算面积、做距离分析误差就出来了。正确做法是用专门的MODIS重投影工具MRT或者GDAL、R中的相关函数把数据重投影到你项目统一使用的坐标系中。2.2 波段结构别拿LST的原始值直接用一个MOD11A2 HDF文件里面包含十几个科学数据集SDS但最常用的大概就这么几个科学数据集名称含义单位Scale FactorLST_Day_1km8天合成白天地表温度开尔文0.02LST_Night_1km8天合成夜间地表温度开尔文0.02QC_Day白天像元质量控制标记无无QC_Night夜间像元质量控制标记无无Emis_3131波段发射率无量纲0.002Emis_3232波段发射率无量纲0.002Clear_day_cov白天晴空覆盖次数无无Clear_night_cov夜间晴空覆盖次数无无最核心的一句提醒HDF文件里存储的原始值是16位整型DN值要得到物理量必须乘以对应的Scale Factor。比如LST原始值如果是13000乘以0.02得到260K再减273.15才是-13.15摄氏度。你如果不乘scale直接用温度数值直接差了几十倍如果乘了scale但忘了减273.15则会把开尔文错当摄氏度用。发射率的Scale Factor是0.002比如原始值8500乘以0.002得到0.85。这个参数在研究地表材质异质性、干旱监测时也会用到不要以为它没用。2.3 Scale factor与单位换算单位换算是另一个特别容易出事故的地方。官方明确说明LST_Day_1km和LST_Night_1km的Scale是0.02单位是开尔文。但有些旧版数据或者经过某些工具预处理过的数据可能已经自动应用了Scale因子直接以浮点K值存储。所以你拿到数据的第一步不是埋头处理而是先检查这个数据集的DN值范围。如果最小值在几百到几千大概率没乘Scale要做换算如果已经接近250~320之间说明可能已经转成了物理量就不用再乘了。稳妥的做法是用支持读取元数据的工具确认一下HDF里面通常有scale_factor属性字段。提示在GEE等云平台里MOD11A2影像已经帮你做了尺度换算直接拿到的是K值浮点数据但底层算法不会自动减掉273.15所以做摄氏度时仍然要自己减。2.4 质量控制QC是数据生命线如果说有一件事新手最容易忽视那一定是QC也就是质量控制波段。MOD11A2的QC_Day和QC_Night每个像元都存了质量标记用二进制位字段记录该像元反演时的置信度、云污染情况、误差范围等。我见过不少项目直接拿LST波段做全图统计没做任何质量控制结果出来一大堆离谱的极值和虚假的温度突变。实际上云覆盖区域、高反射地表、敏感地形区域的反演值质量很差必须在处理之前用QC把这些像元筛掉。QC的使用逻辑是用位掩码bitmask做按位与运算。比如你想保留“LST误差小于等于1K”的像元就找到对应位的掩码值将QC数值与掩码做逻辑与保留满足条件的像元。不同C版本Collection 5、C6、C6.1的QC位定义略有差别具体规则请以LP DAAC提供的产品用户手册为准我建议把对应的PDF下载下来放项目文件夹里随时查。另外Clear_day_cov和Clear_night_cov这两个数据集也很值得关注它们记录8天合成窗口内有多少次晴空观测。值越大代表该像元的合成结果越稳定如果晴空次数只有1次那这个像元的温度代表性就很弱做研究的时候最好标记出来。2.5 8天合成的时间标签MOD11A2的8天合成起止日和中心日期在文件名里有标记但也有人看了还是搞错。文件名中的DOY年中日并不一定是第8天通常对应的是合成周期的开始日或中心日。官方推荐用HDF全局属性中的“RANGEBEGINNINGDATE”和“RANGEENDINGDATE”来确认实际覆盖周期。这里再强调一句8天合成并不是每个像元都会覆盖完整8天。因为云的存在有些像元可能只在一个晴空时刻被成功反演合成结果就是这一个时次的值。所以你看到时间序列里某个像元突然出现一个明显的温度跳跃不一定是真实的气候信号可能是合成窗口内晴空观测次数变化造成的取样差异。2.6 版本与数据来源渠道数据版本目前主流是Collection 6.1简称C6.1比老版本C6做了不少算法修正尤其是在冰雪覆盖、干旱半干旱地区的反演质量上有改善。做新项目我建议一律用C6.1旧版本的C5已经不建议再用。获取渠道主要有三个方向NASA Earthdata Search/LP DAAC官方标准平台支持按时间范围和瓦片检索HDF原始文件适合做本地处理的人和需要原始归档数据的研究AppEEARSNASA提供的在线抽取工具可以直接选点或选区域输出CSV或GeoTIFF非常适合不想折腾HDF格式的生态学研究者GEEGoogle Earth Engine云平台影像集ID是“MODIS/061/MOD11A2”全球范围内可直接调用做区域统计和趋势分析非常方便能省去下载、存储、重投影一大串工序。如果你是新手并且研究区范围不大我建议直接从AppEEARS或GEE入手省去环境配置的麻烦如果你后续要做多波段时间序列或需要原始质量控制标记做深度分析那下载HDF文件到本地处理更合适。3. 实操从下载到出结果的全流程理论说太多容易飘我直接把一个典型任务走一遍提取某区域2015年至2020年每年夏季6月到8月的白天地表温度平均值并判断该区域温度变化趋势。3.1 第一步框定研究区和时间范围先明确研究区边界。如果是城市热岛研究建议把城市及周边30公里缓冲区都纳入如果是生态区研究可以直接用流域或保护区边界。然后把边界范围的矢量文件准备好最好统一坐标参考系统。时间范围也要提前想清楚夏季还是全年白天还是夜晚每天、每月、还是每年不同选择决定了你要处理的数据量和合成粒度。以MOD11A2为例8天合成产品每年46期5年的夏季三个月大约是60期影像这在本地下载和处理都还能接受但如果拉长到20年全部年份数据量就非常可观适合直接上云平台。3.2 第二步在Earthdata搜索或直接调用GEE如果你选择本地处理去Earthdata Search检索“MOD11A2”然后在时间过滤器和空间过滤器里设置好参数下载对应的HDF文件。下载时比较推荐用批量下载的方式一个地区多时间序列文件加起来有几百MB到几个GB手工一个个点会崩溃。如果你选择GEE那就简单很多。代码如下var dataset ee.ImageCollection(MODIS/061/MOD11A2) .filterDate(2015-06-01, 2015-08-31) .filterBounds(roi) .map(function(img) { var lstDay img.select(LST_Day_1km).multiply(0.02).subtract(273.15); return lstDay.clip(roi).copyProperties(img, [system:time_start]); }); var meanLST dataset.mean(); Map.centerObject(roi, 8); Map.addLayer(meanLST, {palette: [blue, cyan, green, yellow, red], min: 15, max: 40}, Summer LST Mean);这段代码的意思是先是筛选出2015年夏季的MOD11A2影像时间范围和空间范围都过滤了然后把每张影像的LST_Day_1km乘以0.02并减去273.15换算成摄氏度最后求整个时段的空间平均。注意这里没有做QC过滤正式研究里应该在map回调函数里加上QC掩膜逻辑。3.3 第三步GEE提取区域LST并计算均值接着上面的代码如果你要提取区域平均温度可以写成var trendList ee.List([]); var years ee.List.sequence(2015, 2020); years.evaluate(function(yrList) { yrList.forEach(function(y) { var summer ee.ImageCollection(MODIS/061/MOD11A2) .filter(ee.Filter.calendarRange({start: 6, field: month})) .filter(ee.Filter.calendarRange({start: 8, field: month})) .filterDate(ee.Date.fromYMD(y, 1, 1), ee.Date.fromYMD(y, 12, 31)) .mean(); var meanVal summer.reduceRegion({ reducer: ee.Reducer.mean(), geometry: roi, scale: 1000, maxPixels: 1e13 }).get(LST_Day_1km); trendList trendList.add(meanVal); }); });这一步容易遇到的问题reduceRegion的scale参数如果是1000GEE会按MOD11A2原始分辨率提取如果传的是别的值GEE会自动重采样这会改变统计结果。做时间序列统计时不同年份的scale必须保持一致。3.4 第四步Python本地读取HDF本地读取HDF文件时推荐用Python的xarray搭配h5netcdf或pyhdf读取。MOD11A2是HDF4格式直接用rasterio打开不太方便建议先用pyhdf读到科学数据集再转换成xarray或numpy数组。一个简单示例from pyhdf.SD import SD, SDC import numpy as np file_path MOD11A2.A2020193.h25v05.061.2021201130849.hdf hdf SD(file_path, SDC.READ) lst_day hdf.select(LST_Day_1km) lst_data lst_day.get() scale lst_day.attributes()[scale_factor] lst_kelvin lst_data * scale lst_celsius lst_kelvin - 273.15这部分代码把LST从原始DN值变成摄氏度然后你就可以继续做裁剪、重投影、统计等操作。需要说明的是不同处理工具对HDF属性的读取方式稍有差异拿不到scale因子时也可以直接从官方文档里找到固定数值先用上再说。3.5 第五步重投影、清洗与趋势计算注意事项到了这一步你已经有了数值正确的LST数据但距离发文章还差两步。第一步是重投影。MODIS正弦投影的瓦片边界是斜的叠加到行政边界上非常别扭。推荐用GDAL的gdalwarp将数据重投影到UTM或Albers等面积投影。重投影时要特别注意重采样方法。温度是连续变量用双线性内插问题不大如果你同时还导出了QC或者分类数据那就该用最近邻法否则质量控制标记会被插值污染。第二步是清洗。先用QC把云、边缘、低质量像元剔除。通常做法是把QC按位掩码过滤后将不合格像元赋为NaN再做后续统计。这一步必须在重投影之前还是之后做我个人的习惯是在原始投影下做因为原始网格和QC是对应的重投影会破坏像元对应关系。4. 常见问题与排查实录这部分是从各个项目里翻出来的“现场事故”每一条都是我亲眼见过、甚至亲手解决过的按实用频率排个序。4.1 为什么LST图上有大片空洞这是最常见的现象尤其在多雨地区。空洞背后的原因通常是云污染。虽然有8天合成但如果一个周期内天天阴天像元就永远没有晴空观测合成结果就会缺失或QC标记为低质量。遇到这种情况处理办法有三种拉长合成窗口比如从8天合成延伸到月合成用时间和空间插值补洞比如用前后时相的温度做线性内插或者干脆避开雨季选择气候上相对干燥的时段再分析。注意补洞操作在论文里要做敏感性分析因为插值会人为压低温度变化的方差。我个人写论文时一般先展示原始有洞的LST图再放插值后的图并且把插值区域用阴影标出来这样审稿人不会觉得你在刻意掩盖数据缺陷。4.2 为什么异常值要么是-273.15要么是几千如果你打印数据发现最小温度是-273.15那说明那个像元是填充值fill value把原始值0或特殊编码值直接当成物理量参与计算了。数据里出现的-273.15其实就是0K是无效像元的标志而几千的值多半是没乘scaleDN值直接参与了统计。处理方法是加载数据后先做一次“有效值检查”看看像元值分布是否在合理范围内白天LST一般在220K到330K之间。如果出现极端值就要检查科学数据集的fill_value属性把这些无效像元先置为NaN后再做统计。4.3 重投影后边缘拉伸如何处理MODIS瓦片本身是1200公里宽的方形网格但研究区往往在瓦片边缘重投影时边缘容易出现拉伸变形或空洞。这在南方低纬度地区尤其明显因为瓦片边缘的像元在正弦投影下本身就是梯形的。处理建议是在重投影前先把研究区外扩一两个像元裁剪时再裁回原来的范围边缘的重采样误差会被裁剪掉。4.4 不同时间、不同瓦片数据拼接错位如果你下载了多个瓦片直接拼接时发现相邻瓦片之间出现温度错位常见原因有三个一是用了不同版本的产品一个C6一个C6.1二是影像日期不一致这个在存档数据里很少见但需要注意三是拼接时没有先在原始投影下对齐网格重投影到WGS84后才拼接导致边缘错位。正确做法是先把所有瓦片保持在同一个正弦投影网格下执行“先拼接、后重投影”而不是“先重投影、后拼接”。用GDAL做VRT拼接再一次性重投影能有效避免边缘错位问题。4.5 常见问题速查表问题现象可能原因排查与解决方向温度值整体偏高几十倍未乘以Scale Factor按0.02换算并检查单位是否为开尔文温度出现-273.15或0K填充值未过滤设置有效值范围或读取fill_value属性研究区部分区域无数据只下载了部分瓦片检查边界框是否覆盖多个tile补下载空间边缘呈锯齿状原投影是MODIS正弦投影使用MRT或GDAL重投影并裁剪时间序列里出现剧烈跳跃云污染或合成窗口晴空次数不同用QC筛选参考Clear_day_cov判断相邻瓦片拼接有温度断裂投影或日期不一致保持原始投影拼接后再重投影5. 我用下来的几点真实体会数据用了几年我最大的感受就是MOD11A2这个产品反演精度不是所有区域都一样的。它在植被覆盖好、地表均匀的地方误差小在高海拔冰雪区、干旱裸露区、复杂地形区域误差会明显增大。所以你如果研究区在青藏高原或西北荒漠最好不要拿单期影像直接说事至少做三到五期的平均值或者用质量标记严格筛选。另外我很少单独依赖LST_Day_1km。做生态研究时发射率、晴空观测次数、夜间温度这几个配套数据集最好一起下载下来。夜间LST对于研究霜冻灾害、城市夜间热岛、反演地表发射率变化都非常有价值而且夜间云的影响相对白天更小时间序列质量往往更干净。动手前花几分钟检查数据的Scale Factor和QC定义很多时候能帮你避免后面好几天的返工。这个习惯是我踩坑踩出来的现在每个新项目开始第一件事都是先写一小段代码扫一遍全部文件的最小值、最大值、有效像元占比确认数据健康再进入正式处理流程。如果你打算把这套数据做成长时间序列研究我最后的建议是别贪多先选一个典型年份手工完整跑通整个流程再扩展到全部年份。一次跑二十年数据一旦中间参数错了回头排查的成本会成倍增加。先小后大稳扎稳打这套数据才能成为你研究里最可靠的一块基石。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑