系列文章目录: MODIS数据处理系列专栏
本文基于Arcmap10.2对MCD12Q2植被物候生长数据集进行处理,并在每个步骤中提供批量处理的python代码。
一、MCD12Q2介绍
MCD12Q2以MODISEVI为数据源,先对 EVI 时间序列数据进行预处理,消减云、气溶胶、雪和观测角度等影响,然后用滑动窗口(连续 5 个时相 EVI 值)来判断持续升高和降低区间,当所在区间的极大值和振幅满足给定阈值条件后,判断该升高和降低区间为一个生长周期过程。对于每一个生长周期,采用分段 Logistic 函数拟合,并利用其曲率值变化的极值点,确定生长始期、EVI 持续增加的中点、成熟期、峰值、末期、 EVI 持续降低中点和生长末期。一年当中最多记录两个生长周期。详情介绍可参考:MCD12Q2数据集说明文档
MCD12Q2数据集中各子数据集对应的变量如下图所示,其中各物候节点的值为距1970年1月1日的天数:
- Greenup:生长季始期
- MidGreenup:EVI持续增加的中点
- Peak:峰值
- Maturity:成熟期
- MidGreendown:EVI持续降低的中点
- Senescence:衰老
- Dormancy:生长季末期
二、问题描述
本文演示使用的是MCD12Q2数据集,空间分辨率为500m,时间分辨率为yearly。为了分析中国区域植被物候空间分布特征,需要提取生长季始期SOS(start of the growing season)、生长季末期EOS(end of the growing season),这两个变量分别对应MCD12Q2的Greenup、Dormancy,并利用生长季末期SOS减生长季始期EOS得到生长季长度LOS(length of the growing season)
三、预处理
预处理涉及到的操作均可在Arcmap中完成,演示的版本为10.2,每步均提供有批量处理的方法。
1、提取子数据集
利用提取子数据集工具从.hdf文件中提取Greenup、Dormancy子数据集并转为栅格文件。
批量处理的方法见:【ArcGIS自定义脚本工具】批量提取子数据集
经过此步我们得到了Greenup、Dormancy子数据集的栅格(.tif)文件。
2、波段提取
MCD12Q2一年当中最多记录两个生长周期,中国部分区域存在两个生长周期,且大都分布在华东地区,这在EVI的全年变化曲线中也有体现,如下:
这导致提取后的子数据集波段数为2,为了方便分析及之后的操作,我们需要将栅格文件的两个波段分别提取出来。
利用创建栅格图层工具将Greenup、Dormancy子数据集中的两个波段分别存储为栅格,并以后缀“_b1”与“_b2”区别所在波段,参数设置可参考下图。
其他提取波段的方法可以参考这篇:利用ArcGIS10.2波段合并及提取。基于ArcGIS的自定义脚本,可以批量提取栅格某个波段,代码如下:
#!/usr/local/bin/python2.7
# -*- coding: utf-8 -*-
"""
@File : Batch_extractband.py
@Author : salierib
@Time : 2020/12/15 22:19
"""
import arcpy
import os
import time
raster_path = arcpy.GetParameterAsText(0)
band_index = arcpy.GetParameterAsText(1)
out_path = arcpy.GetParameterAsText(2)
arcpy.env.workspace = raster_path
rasters = arcpy.ListRasters("*", "tif")
nums = len(rasters) # number of hdf files
num = 1 # current serial number
if not os.path.exists(out_path):
os.makedirs(out_path)
for raster in rasters:
s = time.time()
new_name = "{0}_b{1}.tif".format(raster, band_index)
try:
arcpy.MakeRasterLayer_management(raster, new_name, "#", "#", band_index)
arcpy.CopyRaster_management(new_name, os.path.join(out_path, new_name), "", "", "", "NONE", "NONE", "")
e = time.time()
arcpy.AddMessage("{0}/{1} | {2} Completed, time used {3}s".format(num, nums, new_name, e-s))
except:
arcpy.AddMessage("{0}/{1} | {2} Errored".format(num, nums, new_name))
num += 1
该代码可以将raster_path中的所有栅格(.tif)中波段索引为band_index的波段提取出来,并存储到out_path路径下,提取后的文件名为“原文件名+_波段索引”,工具参数设置及脚本运行截图如下所示:
还可以利用QGIS右键重排波段工具,以批处理的方式运行,具体步骤如下:
利用表达式对转换后的文件进行命名,表达式为:
format('%1\\%2_band1.tif',file_path(@INPUT),base_file_name(@INPUT))
3、拼接
利用镶嵌至新栅格工具,将同一波段、同时刻不同区块的多个栅格拼接为一个栅格,参数设置可参考:
批量镶嵌不同MODIS区块栅格的方法可以参考:【ArcGIS自定义脚本工具】按区块批量镶嵌MODIS影像
4、栅格投影
栅格目标坐标系采用Albers等面积割圆锥投影方法(第1、第2纬线、中央经线分别采用27,45,105),地理坐标系选择WGS_1984,可在ArcGIS自定义投影坐标界面新建该坐标系。
新建适合中国地区的自定义投影坐标系后,利用栅格投影工具将拼接好的包含中国地区的栅格文件投影到目标坐标系,参数设置可参考:
批量投影栅格到指定坐标系的方法可以参考:【ArcGIS自定义脚本工具】批量重投影栅格脚本
5、裁剪
经过上述1-4步骤,我们得到了包含中国区域的Greenup、Dormancy不同波段的栅格文件,如下所示:
利用裁剪工具,仅保留中国区域范围的栅格,参数设置可参考:
批量裁剪栅格的方法可以参考:【ArcGIS自定义脚本工具】批量裁剪栅格脚本
四、获取生长季长度
利用数学分析工具箱的减工具用同波段索引的生长季末期Dormancy栅格减去生长季初期Greenup栅格,可以得到反映生长季长度的栅格影像,参数设置如下:
批量执行该步骤的代码可以参考:
import sys
arcpy_path = [r'C:\Program Files (x86)\ArcGIS\Desktop10.2\arcpy',
r'C:\Program Files (x86)\ArcGIS\Desktop10.2\bin',
r'C:\Program Files (x86)\ArcGIS\Desktop10.2\ArcToolbox\Scripts']#修改成Arcgis安装对应路径
sys.path.extend(arcpy_path)
import arcpy
from arcpy import env
from arcpy.sa import *
import os
import datetime
import time
# Check out the ArcGIS Spatial Analyst extension license
arcpy.CheckOutExtension("Spatial")
# Set environment settings
path1 = r"F:\MCD12Q2v006\start" # 输入,Greenup所在的文件夹
path2 = r"F:\MCD12Q2v006\end" # 输入,Dormancy所在的文件夹
out_path = r"F:\MCD12Q2v006\LOS" # 输出
env.workspace = path1
rasters = arcpy.ListRasters('*', 'tif')
if not os.path.exists(out_path):
os.makedirs(out_path)
nums = len(rasters)
num = 1
for raster in rasters:
# start stopwatch
s = time.time()
inRaster1 = raster # china_greenup_a2004001_b1.tif
inRaster2 = os.path.join(path2, raster.replace("greenup", "dormancy")) # china_dormancy_a2004001_b1.tif
# Execute Minus
outMinus = Minus(inRaster2, inRaster1)
# Save the output
newtif = "LOS" + "_" + raster.split("_")[2]
newraster = os.path.join(out_path, newtif)
outMinus.save(newraster)
# stop stopwatch
e = time.time()
arcpy.AddMessage("{0}/{1} | {2} Completed, time used {3}s".format(num, nums, newtif, e-s))
num += 1
五、获取生长季始、末所在日期
通过上述的预处理操作我们得到了中国区域逐年Greenup(生长期初期)、Dormancy(生长季末期)的栅格,但此时栅格的值代表的是距1970年1月1日的天数。例如值为12518时,对应的日期为2004年4月10日。
为了方便分析,将栅格的值转换为日期在所在年的日序,2004年4月10日是2004年的第100天,故需将像元值从12518转为100。
此步可以利用数学分析工具箱的减工具完成
批量执行该步骤的代码如下:
#!/usr/local/bin/python2.7
# -*- coding: utf-8 -*-
"""
@File : arcpy_minus.py
@Author : salierib
@Time : 2020/12/16 20:02
"""
"""
本脚本可以通过在pycharm中直接调用Arcpy的方式运行
作用:将MCD12Q2中各物候阶段对应的原始值(距1970-1-1的天数),转为在当前年的日序,即生长季开始的日子位于当前年的日序
"""
import sys
arcpy_path = [r'C:\Program Files (x86)\ArcGIS\Desktop10.2\arcpy',
r'C:\Program Files (x86)\ArcGIS\Desktop10.2\bin',
r'C:\Program Files (x86)\ArcGIS\Desktop10.2\ArcToolbox\Scripts']#修改成Arcgis安装对应路径
sys.path.extend(arcpy_path)
import arcpy
from arcpy import env
from arcpy.sa import *
import os
import datetime
import time
# Set environment settings
in_path = r"F:\MCD12Q2v006\6_China" # 输入,待转换后栅格所在的文件夹
out_path = r"F:\MCD12Q2v006\7_days" # 输入,存储转换后栅格的文件夹,若无,会自动创建
env.workspace = in_path
rasters = arcpy.ListRasters('*', 'tif')
if not os.path.exists(out_path):
os.makedirs(out_path)
nums = len(rasters)
num = 1
# Check out the ArcGIS Spatial Analyst extension license
arcpy.CheckOutExtension("Spatial")
for raster in rasters:
# start stopwatch
s = time.time()
# Set local variables
inRaster1 = raster
year = '{0}-01-01'.format(int(raster.split("_")[-2][1:5])) # 输入栅格的原始命名需满足类似"xxx_a2004001_xx.tif"
d1 = datetime.datetime.strptime(year, '%Y-%m-%d')
d2 = datetime.datetime.strptime('1970-01-01', '%Y-%m-%d')
t = d1 - d2
inRaster2 = t.days
# Execute Minus
outMinus = Minus(inRaster1, inRaster2)
# Save the output
newraster = os.path.join(out_path, "days" + "_" + "_".join(raster.split("_")[3:]))
outMinus.save(newraster)
# stop stopwatch
e = time.time()
arcpy.AddMessage("{0}/{1} | {2} Completed, time used {3}s".format(num, nums, raster, e-s))
num += 1
可将上述代码保存为.py文件后在Arcmap中的python窗口加载该文件运行,具体操作步骤如下:
处理后的栅格文件如下图所示: