python处理nc数据转换为tif格式

应用背景

最近在做蒸散发的相关数据处理,上一篇用ArcPy进行处理,发现太慢了,于是继续寻找简便方法。此篇文章为可运行代码。
参考文献:《使用Python语言将.nc格式影像转换成TIF格式,.nc文件涉及到多个参数变量、12个月均的数据(多图层提取))_Jack_33学习之路的博客-程序员宅基地》

使用数据:E_2006_GLEAM_v3.6a.nc(数据放在百度网盘了)
链接:https://pan.baidu.com/s/1jb1f2lYyoP-gZlY07LPQvA?pwd=1111
提取码:1111

1. 原始代码

# -*- coding: utf-8 -*-
# 模块导入
import numpy as np
import netCDF4 as nc
from osgeo import gdal,osr,ogr
import os
import glob
import datetime
def NC_to_tiffs(data,Output_folder):
    nc_data_obj = nc.Dataset(data)
    # print(nc_data_obj,type(nc_data_obj)) # 了解NC_DS的数据类型,
    # print(nc_data_obj.variables) # 了解变量的基本信息
    # print(nc_data_obj)
    Lon = nc_data_obj.variables['longitude'][:]
    Lat = nc_data_obj.variables['latitude'][:]
    u_arr = np.asarray(nc_data_obj.variables['v10'])  # 这里根据需求输入想要转换的波段名称
    #影像的左上角和右下角坐标
    LonMin,LatMax,LonMax,LatMin = [Lon.min(),Lat.max(),Lon.max(),Lat.min()]
    #分辨率计算
    N_Lat = len(Lat)
    N_Lon = len(Lon)
    Lon_Res = (LonMax - LonMin) /(float(N_Lon)-1)
    Lat_Res = (LatMax - LatMin) / (float(N_Lat)-1)
    for i in range(len(u_arr[:])):
        #创建.tif文件
        driver = gdal.GetDriverByName('GTiff')
        out_tif_name = Output_folder + '/' + 'v10_' + data.split('\\')[-1].split('.')[0] + '_' + str(i+1) + '.tif'
        out_tif = driver.Create(out_tif_name,N_Lon,N_Lat,1,gdal.GDT_Float32)
        # 设置影像的显示范围
        #-Lat_Res一定要是-的
        geotransform = (LonMin,Lon_Res, 0, LatMax, 0, -Lat_Res)
        out_tif.SetGeoTransform(geotransform)
        #获取地理坐标系统信息,用于选取需要的地理坐标系统
        srs = osr.SpatialReference()
        srs.ImportFromEPSG(4326) # 定义输出的坐标系为"WGS 84",AUTHORITY["EPSG","4326"]
        out_tif.SetProjection(srs.ExportToWkt()) # 给新建图层赋予投影信息

        # 去除异常值
        u_arr[u_arr[:, :] == -32768] = -99

        #数据写出
        out_tif.GetRasterBand(1).WriteArray(u_arr[i][::-1])
        # 将数据写入内存,此时没有写入硬盘 此处[::-1]用于图像的垂直镜像对称,避免图像颠倒
        out_tif.FlushCache() # 将数据写入硬盘
    del out_tif # 注意必须关闭tif文件
def main():
    Input_folder = 'H:/LAB/LABDATA/ECMWF/3/NC'
    Output_folder = 'H:/LAB/LABDATA/ECMWF/3/TIF/v10'
    # 读取所有nc数据
    data_list = glob.glob(Input_folder + '/*.nc')
    for i in range(len(data_list)):
        data = data_list[i]
        NC_to_tiffs(data, Output_folder)
        print(data + '-----转tif成功')
    print('----转换结束----')
if __name__ == '__main__':
    main()

2. 修改代码

2.1 修改属性

我的nc图层里有下图这些属性,需要的是“E”,而源代码所需要的是“v10”,因此进行修改
python处理nc数据转换为tif格式_第1张图片
原来:

 u_arr = np.asarray(nc_data_obj.variables['v10'])  

现在:

u_arr = np.asarray(nc_data_obj.variables['E'])  

输入和输出文件夹也修改成自己的。

2.2 检验图像

修改完成之后,打一个断点,运行出第一个图像看看效果
python处理nc数据转换为tif格式_第2张图片

结果发现得到的图像跟正常图像相比进行了倒转,原因在这里:

out_tif.GetRasterBand(1).WriteArray(u_arr[i][::-1])
        # 将数据写入内存,此时没有写入硬盘 此处[::-1]用于图像的垂直镜像对称,避免图像颠倒

删掉[ : : -1],改成:

out_tif.GetRasterBand(1).WriteArray(u_arr[i])
        # 将数据写入内存,此时没有写入硬盘 此处[::-1]用于图像的垂直镜像对称,避免图像颠倒

再看看结果:
python处理nc数据转换为tif格式_第3张图片
成功啦!

这是修改后的所有代码:

import numpy as np
import netCDF4 as nc
from osgeo import gdal,osr,ogr
import os
import glob
import datetime
def NC_to_tiffs(data,Output_folder):
    nc_data_obj = nc.Dataset(data)
    # print(nc_data_obj,type(nc_data_obj)) # 了解NC_DS的数据类型,
    # print(nc_data_obj.variables) # 了解变量的基本信息
    # print(nc_data_obj)
    Lon = nc_data_obj.variables['lon'][:]
    Lat = nc_data_obj.variables['lat'][:]
    u_arr = np.asarray(nc_data_obj.variables['E'])  # 这里根据需求输入想要转换的波段名称
    #影像的左上角和右下角坐标
    LonMin,LatMax,LonMax,LatMin = [Lon.min(),Lat.max(),Lon.max(),Lat.min()]
    #分辨率计算
    N_Lat = len(Lat)
    N_Lon = len(Lon)
    Lon_Res = (LonMax - LonMin) /(float(N_Lon)-1)
    Lat_Res = (LatMax - LatMin) / (float(N_Lat)-1)
    for i in range(len(u_arr[:])):
        #创建.tif文件
        driver = gdal.GetDriverByName('GTiff')
        out_tif_name = Output_folder + '/' + '2006' + data.split('\\')[-1].split('.')[0] + '_' + str(i+1) + '.tif'
        out_tif = driver.Create(out_tif_name,N_Lon,N_Lat,1,gdal.GDT_Float32)
        # 设置影像的显示范围
        #-Lat_Res一定要是-的
        geotransform = (LonMin,Lon_Res, 0, LatMax, 0, -Lat_Res)
        out_tif.SetGeoTransform(geotransform)
        #获取地理坐标系统信息,用于选取需要的地理坐标系统
        srs = osr.SpatialReference()
        srs.ImportFromEPSG(4326) # 定义输出的坐标系为"WGS 84",AUTHORITY["EPSG","4326"]
        out_tif.SetProjection(srs.ExportToWkt()) # 给新建图层赋予投影信息

        # 去除异常值
        u_arr[u_arr[:, :] == -32768] = -99

        #数据写出
        out_tif.GetRasterBand(1).WriteArray(u_arr[i])
        # 将数据写入内存,此时没有写入硬盘 此处[::-1]用于图像的垂直镜像对称,避免图像颠倒
        out_tif.FlushCache() # 将数据写入硬盘
    del out_tif # 注意必须关闭tif文件
def main():
    Input_folder = r'D:\DATA\nc\GLEAM\2006'
    Output_folder = r'D:\DATA\nc\GLEAM\2006\2006'
    # 读取所有nc数据
    data_list = glob.glob(Input_folder + '/*.nc')
    for i in range(len(data_list)):
        data = data_list[i]
        NC_to_tiffs(data, Output_folder)
        print(data + '-----转tif成功')
    print('----转换结束----')
if __name__ == '__main__':
    main()

365天的数据转换成功大致是1分半,相比较昨天ArcPy做的,确实速度很快

3.后续

后面就要学习一下按掩膜提取了

你可能感兴趣的:(遥感数据学习,python,开发语言)