Python地學分析 — GDAL讀取HDF數據並保存爲TIF圖像

歡迎關注博主的微信公衆號:“智能遙感”。

該公衆號將爲您奉上Python地學分析、爬蟲、數據分析、Web開發、機器學習、深度學習等熱門源代碼。

本人的GitHub代碼資料主頁(持續更新中,多給Star,多Fork):

https://github.com/xbr2017

CSDN也在同步更新:

https://blog.csdn.net/XBR_2014

 

 本節通過Python + GDAL讀取MODIS HDF格式的數據集。

作爲一名遙感仁,在接觸Python之前,一直使用IDL語言(遙感專業的一門語言)處理遙感數據,從幾何校正、輻射定標、圖像拼接、矢量裁剪柵格以及幾乎所有的遙感圖像運算、數據讀取與常見格式的存儲,無一不是通過IDL來實現的。在讀研期間,甚至一度迷上用IDL製作讀取與展示遙感數據的小軟件界面,在畢業論文裏竟然專門有一小節介紹該軟件,現在想想,是多麼的蒼白無力

IDL是一門小衆語言,冷了不能再冷的語言。牆裂推薦:不管你是否搞科研,還是做開發,對於沒有計算機編程基礎(C、C++、Java等)的小夥伴們,包括軟妹子吆,Python是性價比最高的語言,沒有之一,簡單易懂,上手快。來吧,讓我們一起高喊:“人生苦短,我用Python”!

順便多說一句,既然我們使用了Python來處理遙感數據,那就準備拋棄ArcGis、MeteoInfo之類的二次開發環境,所以在今後的遙感數據處理介紹中,爭取不使用arcpy包。因爲要使用該模塊,自己的本本上需要安裝ArcGis軟件,所以還是儘量不使用arcpy。

GDAL讀取HDF

今天以較爲經典的衛星數據MODIS爲例,講解如何使用Python+GDAL讀取HDF文件,以及輸出指定投影的tif文件,這裏的tif是指Geotiff文件,其中包含地理信息。

HDF爲分層數據格式的文件,可以使用GetSubDatasets函數獲取它們的列表,然後使用該信息打開你想要的那個數據集。

例如,讓我們打開MODIS文件中包含的子數據集。請注意,默認情況下,HDAL驅動程序不包含在GDAL中,因此如果你的GDAL版本不包含HDF支持,此示例將不適用於你。假設你可以使用HDF文件,第一步是將HDF文件作爲數據集打開:

from osgeo import gdal

ds = gdal.Open('MYD13Q1.A2014313.h20v11.005.2014330092746.hdf')

現在,你可以獲取此開放數據集中包含的子數據集列表。GetSubDatasets方法返回元組列表,每個子數據集有一個元組。每個元組按順序包含子數據集的名稱和描述。以下代碼段獲取此列表,然後打印出每個子數據集的名稱和描述:

subdatasets = ds.GetSubDatasets()
print 'Number of subdatasets: {}'.format(len(subdatasets))

for sd in subdatasets:
    print 'Name: {0}\nDescription:{1}\n'.format(*sd)

前幾行輸出看起來像這樣,並顯示第一個子數據集的信息,即NDVI(歸一化差異植被指數),這裏只展示第一個,剩餘11個就不放在這顯示了:

Number of subdatasets: 12

Name: HDF4_EOS:EOS_GRID:"D:/osgeopy-data/Modis/MYD13Q1.A2014313.h20v11.005.2014330092746.hdf":MODIS_Grid_16DAY_250m_500m_VI:250m 16 days NDVI
Description:[4800x4800] 250m 16 days NDVI MODIS_Grid_16DAY_250m_500m_VI (16-bit integer)

要打開子數據集,請將其名稱傳遞給gdalOpen。例如,這將獲取與第一個子數據集對應的元組,從元組中獲取第一個項(名稱),然後使用它來打開子數據集:

ndvi_ds = gdal.Open(subdatasets[0][0])

同樣,使用subdatasets[4] [0]表示打開第五個子數據集。一旦打開了這樣的子數據集,它就可以像任何其他數據集一樣處理。例如,你可以使用ndvi_ds.GetRasterBand(1)獲取NDVI子數據集中的第一個波段。

如果沒有特殊說明,HDF一般指hdf4,現在很多衛星數據開始使用hdf5格式存儲,對於GDAL都可以去讀取操作。當然,也有專門讀取hdf4與hdf5的包,感興趣的可以pip install安裝一下相關的包就可以直接使用啦。這裏給大家稍微展示一下具體代碼使用:

# _*_ coding: utf-8 _*_
__author__ = 'xbr'
__date__ = '2018/11/28 22:47'

import h5py
import numpy as np

# HDF5的讀取:
in_ds = h5py.File('FY4A-_AGRI--_N_DISK_1047E_L1-_FDI-_MULT_NOM_20180101024500_20180101025959_4000M_V0001.HDF','r')   
# 讀取FY4A靜止衛星第一波段數據
array = in_ds['NOMChannel01'][:]  
in_ds.close()

GDAL將數據保存爲tif格式

遙感圖像需要包含經緯度、空間分辨率、投影座標等地理信息,這是普通圖像所不具備的,一般彩色圖像只有RGB三個波段,而遙感圖像可以包含很多波段。下面的程序是讀取MODIS歸一化植被指數(NDVI),並將數據保存爲帶有地理信息的tif文件,必要的解釋在代碼中已給出。

# _*_ coding: utf-8 _*_
__author__ = 'xbr'
__date__ = '2018/11/26 17:48'

import gdal, osr


def array2raster(newRasterfn, rasterOrigin, xsize, ysize, array):
    """
     newRasterfn: 輸出tif路徑
     rasterOrigin: 原始柵格數據路徑
     xsize: x方向像元大小
     ysize: y方向像元大小
     array: 計算後的柵格數據
    """
    cols = array.shape[1]  # 矩陣列數
    rows = array.shape[0]  # 矩陣行數
    originX = rasterOrigin[0]  # 起始像元經度
    originY = rasterOrigin[1]  # 起始像元緯度
    driver = gdal.GetDriverByName('GTiff')
    outRaster = driver.Create(newRasterfn, cols, rows, 1, gdal.GDT_Float32)
    # 括號中兩個0表示起始像元的行列號從(0,0)開始
    outRaster.SetGeoTransform((originX, xsize, 0, originY, 0, ysize))
    # 獲取數據集第一個波段,是從1開始,不是從0開始
    outband = outRaster.GetRasterBand(1)
    outband.WriteArray(array)
    outRasterSRS = osr.SpatialReference()
    # 代碼4326表示WGS84座標
    outRasterSRS.ImportFromEPSG(4326)
    outRaster.SetProjection(outRasterSRS.ExportToWkt())
    outband.FlushCache()


ds = gdal.Open('D:/osgeopy-data/Modis/MYD13Q1.A2014313.h20v11.005.2014330092746.hdf')

subdatasets = ds.GetSubDatasets()
print('Number of subdatasets: {}'.format(len(subdatasets)))
for sd in subdatasets:
    print('Name: {0}\nDescription:{1}\n'.format(*sd))

ndvi_ds = gdal.Open(subdatasets[0][0]).ReadAsArray()
dst_filename = "D:/nc/try.tif"
xsize = 0.0025
ysize = 0.0025

array2raster(dst_filename, [90, 75], xsize, ysize, ndvi_ds)

 

NDVI第一波段的灰色圖像展示

NDVI第一波段的彩色圖像展示

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章