matlab:如何将ERA5(.nc)批量输出为Geotiff文件?

发布于:2025-04-21 ⋅ 阅读:(28) ⋅ 点赞:(0)

01 文件格式要求

文件样式形如2m_dewpoint_temperature_2000_01.nc

文件样式截屏

02 源码

clc
clear
%% 准备
in_dir = 'G:/ERA5/2m_temperature';  % 存储待处理nc文件的路径
out_dir='E:\MyTEMP\ERA5';  % 输出路径
start_year = 2000;  % 起始年份
end_year = 2000;  % 终止年份
var_wildcard_name = '2m_temperature';
var_name = 't2m';  % 变量名称
[status, msg] = mkdir(out_dir);  % 创建目录(存在则不创建)
srs=georefcells([-90 90],[-180 180],[1801 3600],'ColumnsStartFrom','north','RowsStartFrom','west');  % 坐标系信息
%{
georefcells函数用于针对一个规则栅格矩阵(确定的经纬度范围, 具体的行列数),创建一个
地理参考对象.
'ColumnsStartFrom','north' ==> 默认列方向是自北向南
'RowsStartFrom','west'  ==> 默认行方向是自西向东
%}
%% 迭代获取变量的栅格矩阵并输出未Geotiff文件
% 检索nc文件
nc_paths = dir(fullfile(in_dir, '*.nc'));
for cur_year = start_year:end_year
    for cur_month = 1:1
        mdays = eomday(cur_year, cur_month);  % 获取当前年当前月份的天数
        % 读取当前循环nc文件的变量数组和基本信息
        cur_nc_path = fullfile(in_dir, sprintf('%s_%d_%02d.nc', var_wildcard_name, cur_year, cur_month));
        vinfo = ncinfo(cur_nc_path, var_name);
        [col, row, time] = deal(vinfo.Size(1), vinfo.Size(2), vinfo.Size(3));
        time_step = 0;  % 用于时间步计数
        for cur_day = 1:mdays
            for cur_hour = 1:24
                time_step = time_step + 1;
                var = ncread(cur_nc_path, var_name, [1, 1, time_step], [col, row, 1]);
                %{
                ncread(nc文件路径, 变量名称, 开始位置, 读取元素数)
                [1, 1, time_step], 第一个维度(col)1开始, 第二个维度(row)也是,
                第三个维度(time)从第time_step开始
                [col, row, 1], 第一个维度读取的元素数为col, 第二个为row, 第三个说明只读取一个时间点
                %}
                var = var';  % 转置-行列互换
                var = [var(:, 1801:3600), var(:, 1:1800)];
                %{
                由于经度是0~360,这对应于地理坐标系就是0~180,-180~0
                为了保证这与srs的地理参数设置一致(左上角点为-180°W,90°N)
                %}
                % 输出
                cur_out_filename = sprintf('era5_%s_%d%02d%02d_%02d.tif', var_wildcard_name, cur_year, cur_month, cur_day, cur_hour);
                cur_out_path = fullfile(out_dir, cur_out_filename);
                geotiffwrite(cur_out_path, var, srs);
                fprintf('当前处理: %s\n', cur_out_filename);
            end
        end
    end
end

03 部分函数说明

3.1 georefcells函数

georefcells函数会返回一个针对地理坐标中规则像元栅格的默认参考对象。一般与geotiffwrite函数搭配使用(返回值可作为其函数的R参数传入)。

有三种传参方式:

  • srs = georefcells(latlim,lonlim,rasterSize)

latlim: 表示纬度范围,例如[-90, 90]表示从90°S~90°N;

lonlim: 表示经度范围,例如[0, 180]表示从0°~180°E;

rasterSize: 表示栅格大小,这里指代栅格图像的行列数,例如[1800, 3600]表示1800行3600列;

  • srs = georefcells(latlim,lonlim,latcellextent,loncellextent)

这里的传参前面latlim,lonlim是一样,但是后面传入参数不一样。

latcellextent: 表示纬度方向(y方向)上单个像元/栅格/单元的表示的范围,实际上就是纬度方向上的像元分辨率;

loncellextent: 表示经度方向(x方向)上单个像元/栅格/单元的表示的范围,实际上就是纬度方向上的像元分辨率;譬如GPM IMERG降水影像的空间分辨率为0.1°×0.1°(经纬度方向上分辨率一致,范围全球),那么这里的就可以传入:

srs = georefcells([-90, 90], [-180, 180],0.1,0.1)

  • srs = georefcells(latlim,lonlim,___,Name,Value)

除了传入上述必要参数外,还有一些可选参数通过关键字传参,这里包括:

R = georefcells([-90, 90], [-180, 180], 0.1, 0.1,'ColumnsStartFrom','north')
R = georefcells([-90, 90], [-180, 180], 0.1, 0.1,'RowsStartFrom','east')

ColumnsStartFrom表示列方向上是从哪里开始,默认是从北开始,即从北到南,如果栅格矩阵默认最上方是北边那么此处可以不进行关键字传参因为默认上方就是北(north);

RowsStartFrom表示行方向上是从哪里开始,默认是从西开始,即从西到东,如果栅格矩阵默认最左侧是东边那么此处可以不进行关键字传参因为默认左侧就是东(east);

一般情况下,对于目前我所遇到的卫星遥感影像,大部分都是上北下南,左西右东,所以对于RowsStartFrom是需要指定为west.但是也有例外,对于MODIS的部分产品例如OMI/SWATH等产品部分存在南北颠倒即栅格矩阵上方是南极区域下方是北极区域.不过对于这种我一般还是不去更改这个ColumnsStartFrom参数,而是将读取的栅格矩阵进行南北极调换颠倒过来再进行后续操作.

3.2 eomday函数

很简单的一个函数,就是依据传入的年和月计算得到当前年份当前月份下总共有多少天,官方说明即是:返回年份 Y 中指定月份 M 的最后一天(End of month day, eomday);

eomday传参如下:

E = eomday(Y,M)

Y: 表示年份;

M: 表示月份;

3.3 ncinfo函数

获取当前nc文件或者当前nc文件下指定变量/group的基本信息.

有如下三种传参方式:

finfo = ncinfo(source)
vinfo = ncinfo(source,varname)
ginfo = ncinfo(source,groupname)

source:表示nc文件的路径,不指定varnamegroup参数即返回该nc文件的基本信息;

varname: 表示待查询的变量名称,注意此处变量的名称其实应当是变量在nc文件内的路径,例如t2m变量在group1/group2/t2m下,那么应该传入该路径而不是仅仅传入t2m这个变量名称;

group_name: 表示待查询的group名称,说明与varname基本相似;

3.4 ncread函数

获取当前nc文件指定变量名称的数组.

传参方式主要有下面两种:

vardata = ncread(source,varname)
vardata = ncread(source,varname,start,count)

区别在于:如果你只是单纯想提取出整个变量数组,直接使用第一个传参方式即可;如果你需要提取变量数组中指定区域的部分数组出来,可以使用第二个传参方式(一般是在整个变量数组无法全部加载进电脑内存中,或者你需要针对变量数组中不同部分的小数组进行不同操作例如对于一个shape=(行,列,时间)的数组,或许对于不同时间的栅格矩阵需要单独处理亦或者只需要某一个时间步的栅格矩阵)

source: 表示nc文件的路径;

varname: 表示待读取变量的名称,实际是变量在nc文件中的路径;

start: 表示各个维度上的起始索引,例如对于shape=(行=100,列=200,波段数=3)的三维数组, 我们想要读取第二个波段的栅格矩阵可以设置[1, 1, 2],再配合count参数(下面马上提及)设置为[100, 200, 1]即可;

count: 表示沿每个维度读取的元素数;例如上述例子中需要提取第二个波段的栅格矩阵即从start中第一个维度(行)的索引1(matlab索引从1开始而非0)开始往后读取100个元素,类似地从列维度的索引1开始往后读取200个元素,从波段维度的索引2开始读取一个元素(即只读取一个元素就是第二个波段);

3.5 geotiffwrite函数

传参方式: geotiffwrite(filename,A,R)

filename: 输出Geotiff文件的输出路径;

A: 输出的栅格矩阵,对于灰度图像或者单波段影像要求shape=(行,列);而对于RGB、多波段或者高光谱影像,要求shape=(行,列,波段);

R: 地理参考对象,可以通过前面的georefcells函数构建得到;


网站公告

今日签到

点亮在社区的每一天
去签到