基于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实现的tab文件操作类分享
Nov 20 Python
Python常用内置函数总结
Feb 08 Python
Python的collections模块中的OrderedDict有序字典
Jul 07 Python
Python二叉树的定义及常用遍历算法分析
Nov 24 Python
Python Json序列化与反序列化的示例
Jan 31 Python
Python 实现中值滤波、均值滤波的方法
Jan 09 Python
如何利用Python分析出微信朋友男女统计图
Jan 25 Python
python实现kmp算法的实例代码
Apr 03 Python
Pandas时间序列基础详解(转换,索引,切片)
Feb 26 Python
Python实现排序方法常见的四种
Jul 15 Python
Python实现滑雪小游戏
Sep 25 Python
Python如何使用循环结构和分支结构
Apr 13 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
如何选购合适的收音机
2021/03/01 无线电
用Apache反向代理设置对外的WWW和文件服务器
2006/10/09 PHP
用PHP实现读取和编写XML DOM代码
2010/04/07 PHP
PHP MVC框架skymvc支持多文件上传
2016/05/26 PHP
Json2Template.js 基于jquery的插件 绑定JavaScript对象到Html模板中
2011/10/29 Javascript
js定时器怎么写?就是在特定时间执行某段程序
2013/10/11 Javascript
jQuery修改li下的样式以及li下的img的src的值的方法
2014/11/02 Javascript
深入理解关于javascript中apply()和call()方法的区别
2016/04/12 Javascript
node.js缺少mysql模块运行报错的解决方法
2016/11/13 Javascript
jQuery点击弹出层弹出模态框点击模态框消失代码分享
2017/01/21 Javascript
Vue实现表格中对数据进行转换、处理的方法
2018/09/06 Javascript
JS实现盒子跟着鼠标移动及键盘方向键控制盒子移动效果示例
2019/01/29 Javascript
node学习笔记之读写文件与开启第一个web服务器操作示例
2019/05/29 Javascript
leaflet加载geojson叠加显示功能代码
2020/02/21 Javascript
Vue+Bootstrap实现简易学生管理系统
2021/02/09 Vue.js
使用Python脚本将绝对url替换为相对url的教程
2015/04/24 Python
举例讲解Python中metaclass元类的创建与使用
2016/06/30 Python
使用Python3 编写简单信用卡管理程序
2016/12/21 Python
解决Pycharm下面出现No R interpreter defined的问题
2018/10/29 Python
python基于Selenium的web自动化框架
2019/07/14 Python
使用python实现滑动验证码功能
2019/08/05 Python
python的常见矩阵运算(小结)
2019/08/07 Python
PyTorch中topk函数的用法详解
2020/01/02 Python
django创建超级用户时指定添加其它字段方式
2020/05/14 Python
Python调用jar包方法实现过程解析
2020/08/11 Python
使用HTML5 Canvas API控制字体的显示与渲染的方法
2016/03/24 HTML / CSS
在校生党员自我评价
2013/09/25 职场文书
大学生活学习的自我评价
2013/12/03 职场文书
晨会主持词
2014/03/17 职场文书
公司办公室岗位职责
2014/03/19 职场文书
无传销社区工作方案
2014/05/13 职场文书
介绍信样本
2015/01/31 职场文书
2015年检验科工作总结
2015/04/27 职场文书
护士业务学习心得体会
2016/01/25 职场文书
手把手教你导入Go语言第三方库
2021/08/04 Golang
mysql中int(3)和int(10)的数值范围是否相同
2021/10/16 MySQL