基於Python實現nc批量轉tif格式
由於做項目需要運用到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內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- 使用python進行nc轉tif的3種情況解決
- python多線程方法詳解
- Python讀取hdf文件並轉化為tiff格式輸出
- python如何將mat文件轉為png
- 圖片去摩爾紋簡述實現python代碼示例