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


Posted in Python onAugust 14, 2022

由于做项目需要运用到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。

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

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

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

基于Python实现nc批量转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实现nc批量转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格式的文章就介绍到这了,更多相关Python nc转tif内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
python网络编程学习笔记(六):Web客户端访问
Jun 09 Python
Python的Bottle框架中获取制定cookie的教程
Apr 24 Python
Python Queue模块详细介绍及实例
Dec 27 Python
用python找出那些被“标记”的照片
Apr 20 Python
python实现生命游戏的示例代码(Game of Life)
Jan 24 Python
numpy中矩阵合并的实例
Jun 15 Python
Python正则表达式指南 推荐
Oct 09 Python
Python字典中的键映射多个值的方法(列表或者集合)
Oct 17 Python
python获取指定日期范围内的每一天,每个月,每季度的方法
Aug 08 Python
python pillow模块使用方法详解
Aug 30 Python
python用线性回归预测股票价格的实现代码
Sep 04 Python
Python实现滑雪小游戏
Sep 25 Python
LyScript实现绕过反调试保护的示例详解
Aug 14 #Python
LeetCode189轮转数组python示例
Aug 05 #Python
python语言中pandas字符串分割str.split()函数
Aug 05 #Python
python绘制云雨图raincloud plot
Aug 05 #Python
python计算列表元素与乘积详情
Aug 05 #Python
Pygame游戏开发之太空射击实战敌人精灵篇
Aug 05 #Python
python playwrigh框架入门安装使用
Jul 23 #Python
You might like
PHP 高手之路(二)
2006/10/09 PHP
PHP+shell实现多线程的方法
2015/07/01 PHP
js setattribute批量设置css样式
2009/11/26 Javascript
javascript两段代码,两个小技巧
2010/02/04 Javascript
javascript获取当前日期时间及其它操作函数
2011/01/11 Javascript
JavaScript回调(callback)函数概念自我理解及示例
2013/07/04 Javascript
当鼠标滑过文本框自动选中输入框内容的JS代码分享
2013/11/26 Javascript
javascript限制文本框输入值类型的方法
2015/05/07 Javascript
微信jssdk在iframe页面失效问题的解决措施
2016/03/03 Javascript
vue2.0结合DataTable插件实现表格动态刷新的方法详解
2017/03/17 Javascript
Vue官网todoMVC示例代码
2018/01/29 Javascript
Angular5中调用第三方js插件的方法
2018/02/26 Javascript
重新认识vue之事件阻止冒泡的实现
2018/08/02 Javascript
JavaScript中join()、splice()、slice()和split()函数用法示例
2018/08/24 Javascript
JavaScript使用递归和循环实现阶乘的实例代码
2018/08/28 Javascript
vue中的面包屑导航组件实例代码
2019/07/01 Javascript
[56:47]Ti4 循环赛第三日 iG vs Liquid
2014/07/12 DOTA
Python实现将DOC文档转换为PDF的方法
2015/07/25 Python
利用python获取某年中每个月的第一天和最后一天
2016/12/15 Python
Python 实现数据库(SQL)更新脚本的生成方法
2017/07/09 Python
Python PyQt4实现QQ抽屉效果
2018/04/20 Python
Python创建普通菜单示例【基于win32ui模块】
2018/05/09 Python
Python合并同一个文件夹下所有PDF文件的方法
2019/03/11 Python
Python2与Python3的区别点整理
2019/12/12 Python
python GUI库图形界面开发之PyQt5信号与槽多窗口数据传递详细使用方法与实例
2020/03/08 Python
Python类中的装饰器在当前类中的声明与调用详解
2020/04/15 Python
python爬虫用mongodb的理由
2020/07/28 Python
彻底搞懂python 迭代器和生成器
2020/09/07 Python
Pycharm Available Package无法显示/安装包的问题Error Loading Package List解决
2020/09/18 Python
Python 实现键盘鼠标按键模拟
2020/11/18 Python
AutoShack.com加拿大:北美主要的汽车零部件零售商
2019/07/24 全球购物
关于教师节的广播稿
2014/09/10 职场文书
销售会议开幕词
2015/01/28 职场文书
2015年学校办公室工作总结
2015/05/26 职场文书
公司庆典主持词
2015/07/04 职场文书
JS数组方法some、every和find的使用详情
2021/10/05 Javascript