基于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实现倒计时的示例
Feb 14 Python
python数据结构链表之单向链表(实例讲解)
Jul 25 Python
Python实现破解12306图片验证码的方法分析
Dec 29 Python
Python3基于sax解析xml操作示例
May 22 Python
基于anaconda下强大的conda命令介绍
Jun 11 Python
对python中Json与object转化的方法详解
Dec 31 Python
Python Flask 搭建微信小程序后台详解
May 06 Python
Python面向对象封装操作案例详解
Dec 31 Python
Python基础之列表常见操作经典实例详解
Feb 26 Python
OpenCV 使用imread()函数读取图片的六种正确姿势
Jul 09 Python
Python+OpenCV图像处理——图像二值化的实现
Oct 24 Python
教你用Python+selenium搭建自动化测试环境
Jun 18 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操作SVN版本服务器类代码
2011/11/27 PHP
php include和require的区别深入解析
2013/06/17 PHP
Thinkphp5结合layer弹窗定制操作结果页面
2017/07/07 PHP
Laravel框架Request、Response及Session操作示例
2019/05/06 PHP
Thinkphp5.0 框架Model模型简单用法分析
2019/10/11 PHP
TNC vs BOOM BO3 第一场2.13
2021/03/10 DOTA
jQuery的实现原理的模拟代码 -2 数据部分
2010/08/01 Javascript
javascript代码加载优化方法
2011/01/30 Javascript
JavaScript更改字符串的大小写
2015/05/07 Javascript
js实现鼠标划过给div加透明度的方法
2015/05/25 Javascript
jQuery的each循环用法简单示例
2016/06/12 Javascript
Bootstrap源码解读导航条(7)
2016/12/23 Javascript
canvas实现图片根据滑块放大缩小效果
2017/02/24 Javascript
ES6中Symbol类型用法实例详解
2017/04/06 Javascript
JavaScript定义及输出螺旋矩阵的方法详解
2017/12/01 Javascript
Vue2.0点击切换类名改变样式的方法
2018/08/22 Javascript
对vue v-if v-else-if v-else 的简单使用详解
2018/09/29 Javascript
微信小程序与后台PHP交互的方法实例分析
2018/12/10 Javascript
JavaScript从原型到原型链深入理解
2019/06/03 Javascript
React中使用UMEditor的方法示例
2019/12/27 Javascript
JS Thunk 函数的含义和用法实例总结
2020/04/08 Javascript
python中wx将图标显示在右下角的脚本代码
2013/03/08 Python
python查询sqlite数据表的方法
2015/05/08 Python
python引入导入自定义模块和外部文件的实例
2017/07/24 Python
python中数组和矩阵乘法及使用总结(推荐)
2019/05/18 Python
通过cmd进入python的实例操作
2019/06/26 Python
Django结合ajax进行页面实时更新的例子
2019/08/12 Python
django之自定义软删除Model的方法
2019/08/14 Python
基于HTML5 WebGL的3D机房的示例
2018/03/16 HTML / CSS
音乐教学随笔感言
2014/02/19 职场文书
文化活动实施方案
2014/03/28 职场文书
银行奉献演讲稿
2014/09/16 职场文书
党课主持词大全
2015/06/30 职场文书
浅谈Python 中的复数问题
2021/05/19 Python
Redis 持久化 RDB 与 AOF的执行过程
2021/11/07 Redis
SpringBoot集成MongoDB实现文件上传的步骤
2022/04/18 MongoDB