文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

基于Python实现nc批量转tif格式

2024-04-02 19:55

关注

由于做项目需要运用到netCDF格式的气象数据,而ArcGIS中需要用栅格影像进行处理,对于较多的文件,ArcGIS一个个手动转换过于繁琐,因此我们采用Python进行转换,当然也可以采用matlab进行转换。

首先需要安装下面几个库:

import os
import netCDF4 as nc
import numpy as np
from osgeo import gdal, osr, ogr
import glob

我们可以在下面网址中寻找对应python安装版本的安装包,下载后,在pycharm控制台中直接安装即可。例如pip install netCDF4-1.5.8-cp39-cp39-

win_amd64.whl

https://www.lfd.uci.edu/~gohlke/pythonlibs/

安装之后即可进行转换:

def nc2tif(data, Output_folder):
    tmp_data = nc.Dataset(data)  # 利用.Dataset()方法读取nc数据
    print('tmp_data', tmp_data)
 
    Lat_data = tmp_data.variables['lat'][:]
    Lon_data = tmp_data.variables['lon'][:]
    # print(Lat_data)
    # print(Lon_data)
 
    tmp_arr = np.asarray(tmp_data.variables['temp'])
 
    # 影像的左上角&右下角坐标
    Lonmin, Latmax, Lonmax, Latmin = [Lon_data.min(), Lat_data.max(), Lon_data.max(), Lat_data.min()]
    # print(Lonmin, Latmax, Lonmax, Latmin)
 
    # 分辨率计算
    Num_lat = len(Lat_data)  # 5146
    Num_lon = len(Lon_data)  # 7849
    Lat_res = (Latmax - Latmin) / (float(Num_lat) - 1)
    Lon_res = (Lonmax - Lonmin) / (float(Num_lon) - 1)
    # print(Num_lat, Num_lon)
    # print(Lat_res, Lon_res)
 
    for i in range(len(tmp_arr[:])):
        # i=0,1,2,3,4,5,6,7,8,9,...
        # 创建tif文件
        driver = gdal.GetDriverByName('GTiff')
        out_tif_name = Output_folder + '\\' + data.split('\\')[-1].split('.')[0] + '_' + str(i + 1) + '.tif'
        out_tif = driver.Create(out_tif_name, Num_lon, Num_lat, 1, gdal.GDT_Int16)
 
        # 设置影像的显示范围
        # Lat_re前需要添加负号
        geotransform = (Lonmin, Lon_res, 0.0, Latmax, 0.0, -Lat_res)
        out_tif.SetGeoTransform(geotransform)
 
        # 定义投影
        prj = osr.SpatialReference()
        prj.ImportFromEPSG(4326)  # WGS84
        out_tif.SetProjection(prj.ExportToWkt())
 
        # 数据导出
        out_tif.GetRasterBand(1).WriteArray(tmp_arr[i])  # 将数据写入内存,此时没有写入到硬盘
        out_tif.FlushCache()  # 将数据写入到硬盘
        out_tif = None  # 关闭tif文件
 
def main():
    Input_folder = r"E:\competition\航天宏图\2-meter air temperature_CMFD\Data_forcing_01yr_010deg\\"
    # Input_folder = r"E:\competition\航天宏图\2-meter air temperature_CMFD\Data_forcing_01mo_010deg\\"
    Output_folder = r"E:\competition\航天宏图\2-meter air temperature_CMFD\tif\\"
 
    # 读取所有数据
    data_list = glob.glob(os.path.join(Input_folder + '*.nc'))
    print(data_list)
 
    for i in range(len(data_list)):
        data = data_list[i]
        nc2tif(data, Output_folder)
        print(data + '转tif成功')

值得注意的是,tmp_arr = np.asarray(tmp_data.variables['temp'])中的temp可以根据需要转换的波段进行选择,我们可以在读取数据之后print一下,找到对应的波段进行替换即可。如下图中我们应该选择的就是temp。

完成上述步骤即可得到所需的tif图像:

在上述代码中,经过处理的影像是倒置的,可能是处理过程中仿射矩阵读写错误导致的。因此我们可以在写入影像的时候,进行影像的垂直镜像操作即可:WriteArray(ndvi_arr_float[i][::-1]) 

def NC_to_tiffs(data, Output_folder):
    nc_data_obj = nc.Dataset(data)
    Lon = nc_data_obj.variables['lon'][:]
    Lat = nc_data_obj.variables['lat'][:]
    ndvi_arr = np.asarray(nc_data_obj.variables['temp'])  
    ndvi_arr_float = ndvi_arr.astype(float) / 10000  之间
    # 影像的左上角和右下角坐标
    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(ndvi_arr[:])):
        driver = gdal.GetDriverByName('GTiff')
        out_tif_name = Output_folder + '\\' + data.split('\\')[-1].split('.')[0] + '_' + str(i + 1) + '.tif'
        out_tif = driver.Create(out_tif_name, N_Lon, N_Lat, 1, gdal.GDT_Float32)
       
        geotransform = (LonMin, Lon_Res, 0, LatMax, 0, -Lat_Res)
        out_tif.SetGeoTransform(geotransform)
      
        srs = osr.SpatialReference()
        srs.ImportFromEPSG(4326) 
        out_tif.SetProjection(srs.ExportToWkt()) 
        # 数据写出
        out_tif.GetRasterBand(1).WriteArray(ndvi_arr_float[i][::-1])  # 将数据写入内存,此时没有写入硬盘 此处[::-1]用于图像的垂直镜像对称,避免图像颠倒
        out_tif.FlushCache()  # 将数据写入硬盘
        out_tif = None  # 注意必须关闭tif文件

这样便可以得到正确输出的影像:

当然,我们除了在写入时做垂直镜像操作之外,还可以利用python对图像进行几何变换来实现翻转。具体代码如下:

图像水平翻转:

#  图像水平翻转
    im_data_hor = np.flip(im_data, axis=2)
    hor_path = train_image_path + "\\" + str(tran_num) + imageList[i][-4:]
    writeTiff(im_data_hor, im_geotrans, im_proj, hor_path)

标签水平翻转: 

 #  标签水平翻转
    Hor = cv2.flip(label, 1)
    hor_path = train_label_path + "\\" + str(tran_num) + labelList[i][-4:]
    cv2.imwrite(hor_path, Hor)
    tran_num += 1

图像垂直翻转:

 #  图像垂直翻转
    im_data_vec = np.flip(im_data, axis=1)
    vec_path = train_image_path + "\\" + str(tran_num) + imageList[i][-4:]
    writeTiff(im_data_vec, im_geotrans, im_proj, vec_path)

标签垂直翻转:

 #  标签垂直翻转
    Vec = cv2.flip(label, 0)
    vec_path = train_label_path + "\\" + str(tran_num) + labelList[i][-4:]
    cv2.imwrite(vec_path, Vec)
    tran_num += 1

图像镜像翻转:

 #  图像对角镜像
    im_data_dia = np.flip(im_data_vec, axis=2)
    dia_path = train_image_path + "\\" + str(tran_num) + imageList[i][-4:]
    writeTiff(im_data_dia, im_geotrans, im_proj, dia_path)

标签镜像翻转:

 #  标签对角镜像
    Dia = cv2.flip(label, -1)
    dia_path = train_label_path + "\\" + str(tran_num) + labelList[i][-4:]
    cv2.imwrite(dia_path, Dia)
    tran_num += 1

若是输出路径的文件夹没有建立好,则会报如下错误。当然,为了减少工作量,也可以定义一个函数,如果路径不存在则自动创建,就可以解决这个问题。

到此这篇关于基于Python实现nc批量转tif格式的文章就介绍到这了,更多相关Python nc转tif内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯