本文介紹基於Python中的gdal
模組,對大量長時間序列的柵格遙感影像檔案,繪製其每一個波段中、若干隨機指定的像元的時間序列曲線圖的方法。
在之前的文章中,我們就已經介紹過基於gdal
模組,對大量多時相柵格影像,批次繪製像元時間序列折線圖的方法。不過當時文章中的需求,每1
個時相都對應著3
個不同的遙感影像檔案,而每1
個遙感影像檔案則都僅僅只有1
個波段;而在本文中,我們每1
景遙感影像都對應著2
個波段,我們最終繪製的多條曲線圖,也都來自於這每1
景遙感影像的不同波段。
我們再來明確一下本文的需求。現在有一個資料夾,其中放置了大量的遙感影像檔案,如下圖所示。其中,所有遙感影像都是同一地區、不同成像時間的影像,其各自的空間參考資訊、像元行數與列數等都是一致的,檔名中有表示成像日期的具體欄位;且每1
景遙感影像都具有2
個波段。現在我們希望,在遙感影像覆蓋的區域內,隨機選取若干的像元,基於這些像元,我們繪製其隨時間變化的曲線圖。因為我們的每個遙感影像都有2
個波段,且都希望繪製出曲線圖,因此最終的曲線圖一共就有2
條曲線。
明確了需求,我們就可以開始程式碼的撰寫。本文用到的程式碼如下。
# -*- coding: utf-8 -*-
"""
Created on Tue Jul 25 23:04:41 2023
@author: fkxxgis
"""
import os
import random
import matplotlib.pyplot as plt
from osgeo import gdal
def load_image(image_path):
dataset = gdal.Open(image_path)
band1 = dataset.GetRasterBand(1).ReadAsArray()
band2 = dataset.GetRasterBand(2).ReadAsArray()
del dataset
return band1, band2
def plot_time_series(image_folder, pic_folder, num_pixels):
image_files = [file for file in os.listdir(image_folder) if file.endswith(".tif")]
band1_merge, band2_merge = [], []
i = 0
for image_file in image_files:
image_path = os.path.join(image_folder, image_file)
band1, band2 = load_image(image_path)
band1_merge.append(band1)
band2_merge.append(band2)
i += 1
x_size, y_size = band1.shape
pixel_indices = random.sample(range(x_size * y_size), num_pixels)
for pixel_index in pixel_indices:
x, y = divmod(pixel_index, y_size)
band_list_1, band_list_2 = [], []
for i in range(len(band1_merge)):
band_data_1 = band1_merge[i]
band_list_1.append(band_data_1[x, y])
band_data_2 = band2_merge[i]
band_list_2.append(band_data_2[x, y])
plt.figure()
plt.plot(range(len(band1_merge)), band_list_1, label="Band 1")
plt.plot(range(len(band1_merge)), band_list_2, label="Band 2")
plt.xlabel("Time")
plt.ylabel("NDVI")
plt.ylim(0, 1000)
plt.title(f"Time Series for Pixel at ({x}, {y})")
plt.legend()
plt.savefig(os.path.join(pic_folder, str(x) + "_" + str(y)))
plt.show()
image_folder_path = "E:/02_Project/Result/test"
pic_folder_path = "E:/02_Project/TIFF/Plot"
num_pixels = 50
plot_time_series(image_folder_path, pic_folder_path, num_pixels)
上述程式碼的具體含義如下。
首先,我們匯入了需要使用的庫;其中,os
用於處理檔案路徑和目錄操作,random
用於隨機選擇畫素,matplotlib.pyplot
則用於繪製影像。
隨後,我們定義函式load_image(image_path)
;這個函式接收一個影像檔案路徑image_path
作為輸入引數。隨後,在函式內使用gdal
庫開啟該影像檔案,然後提取其第一個和第二個波段的資料,並分別儲存在band1
和band2
中。最後,函式返回這兩個波段的資料。
接下來,我們定義函式plot_time_series(image_folder, pic_folder, num_pixels)
;這個函式接收三個輸入引數,分別為image_folder
、pic_folder
和num_pixels
。其中,image_folder
為包含多個.tif
格式的影像檔案的資料夾路徑,pic_folder
是儲存生成的時間序列影像的資料夾路徑,而num_pixels
則指定了隨機選擇的畫素數量,用於繪製時間序列圖——這個引數設定為幾,我們最後就會得到幾張結果影像。
在這個函式的內部,我們透過os.listdir
函式獲取image_folder
中所有以.tif
結尾的影像檔案,並將這些檔名儲存在image_files
列表中。然後,我們建立兩個空列表band1_merge
和band2_merge
,用於儲存所有影像檔案的2
個波段資料。接下來,我們遍歷所有影像檔案,逐個載入每個影像檔案的全部波段資料,並將它們新增到對應的列表中。其次,使用random.sample
函式從畫素索引的範圍中隨機選擇num_pixels
個畫素的索引,並儲存在pixel_indices
列表中。接下來,我們遍歷並恢復pixel_indices
中的每個畫素索引,計算該畫素在每個影像中的每個波段的時間序列資料,並儲存在band_list_1
、band_list_2
列表中。
隨後,我們即可繪製兩個時間序列圖,分別表示2
個波段在不同影像日期上的數值。最後,我們將影像儲存到指定的資料夾pic_folder
中,命名規則為x_y
,其中x
與y
分別代表畫素的橫、縱座標。
執行上述程式碼,我們即可在指定的資料夾路徑下看到我們生成的多張曲線圖;如下圖所示。
其中,每1
張影像都表示了我們2
個波段在這段時間內的數值走勢;如下圖所示。
至此,大功告成。