基于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获取命令行输入参数列表的实例代码
Jun 23 Python
Python动态语言与鸭子类型详解
Jul 01 Python
Python read函数按字节(字符)读取文件的实现
Jul 03 Python
Python异常处理例题整理
Jul 07 Python
如何通过50行Python代码获取公众号全部文章
Jul 12 Python
python中的subprocess.Popen()使用详解
Dec 25 Python
解决django无法访问本地static文件(js,css,img)网页里js,cs都加载不了
Apr 07 Python
python 常用日期处理-- datetime 模块的使用
Sep 02 Python
flask项目集成swagger的方法
Dec 09 Python
详解解决jupyter不能使用pytorch的问题
Feb 18 Python
pytorch 中nn.Dropout的使用说明
May 20 Python
Python+Selenium实现抖音、快手、B站、小红书、微视、百度好看视频、西瓜视频、微信视频号、搜狐视频、一点号、大风号、趣头条等短视频自动发布
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
PHP远程连接MYSQL数据库非常慢的解决方法
2008/07/05 PHP
php pki加密技术(openssl)详解
2013/07/01 PHP
php写一个函数,实现扫描并打印出自定目录下(含子目录)所有jpg文件名
2017/05/26 PHP
LaravelS通过Swoole加速Laravel/Lumen详解
2018/03/02 PHP
jquery 元素相对定位代码
2010/10/15 Javascript
javascript通过元素id和name直接取得元素的方法
2015/04/28 Javascript
javascript中DOM复选框选择用法实例
2015/05/14 Javascript
JS+CSS实现TreeMenu二级树形菜单完整实例
2015/09/18 Javascript
Javascript中匿名函数的调用与写法实例详解(多种)
2016/01/26 Javascript
使用jquery如何获取时间
2016/10/13 Javascript
jQuery中animate的几种用法与注意事项
2016/12/12 Javascript
NodeJS处理Express中异步错误
2017/03/26 NodeJs
EasyUI Datebox 日期验证之开始日期小于结束时间
2017/05/19 Javascript
基于node.js express mvc轻量级框架实践
2017/09/14 Javascript
Bootstrap 实现表格样式、表单布局的实例代码
2018/12/09 Javascript
详解Node.js amqplib 连接 Rabbit MQ最佳实践
2019/01/24 Javascript
使用jquery实现轮播图效果
2021/01/02 jQuery
Python的Flask框架中的Jinja2模板引擎学习教程
2016/06/30 Python
python 出现SyntaxError: non-keyword arg after keyword arg错误解决办法
2017/02/14 Python
python实现NB-IoT模块远程控制
2018/06/20 Python
Python爬取数据并写入MySQL数据库的实例
2018/06/21 Python
python中的字符串内部换行方法
2018/07/19 Python
python实现整数的二进制循环移位
2019/03/08 Python
python实现简单五子棋游戏
2019/06/18 Python
浅谈优化Django ORM中的性能问题
2020/07/09 Python
HTML5+lufylegend实现游戏中的卷轴
2016/02/29 HTML / CSS
卡西欧G-SHOCK英国官网: 防水防震手表
2018/01/08 全球购物
卡骆驰德国官方网站:Crocs德国
2019/03/29 全球购物
电子商务专业个人的自我评价分享
2013/10/29 职场文书
教师的实习鉴定
2013/12/15 职场文书
小学生自我评价范文
2014/01/25 职场文书
文秘人员工作职责
2014/01/31 职场文书
技术经济专业求职信
2014/09/03 职场文书
2016年小学圣诞节活动总结
2016/03/31 职场文书
告诉你一个秘密:富人致富的五大优点
2019/07/11 职场文书
Golang 链表的学习和使用
2022/04/19 Golang