本文介紹基於Python語言,結合已知研究區域中所覆蓋的全部遙感影像的分幅條帶號,從大量的遙感影像檔案中篩選落在這一研究區域中的遙感影像檔案的方法。
首先,先來明確一下本文所需實現的需求。現已知一個研究區域(四川省),且已知覆蓋這一研究區域所需的全部遙感影像的分幅條帶號(這裡就以Sentinel-2資料所採用的分幅規則為例來介紹),如下圖所示。
其中,向量圖層上的標籤(Label)就是所需的遙感影像的分幅條帶號;且這一向量要素的屬性表中,有具體每一個分幅條帶號的具體欄位(如上圖紅色方框所示的那一列)。
同時,我們還下載好了大量的遙感影像——這些遙感影像數量眾多,既有位於這一研究區域內的遙感影像,同時還有位於研究區域外的。其中,這裡所有的遙感影像都儲存在一個大資料夾下,而這一大資料夾下還有多個子資料夾,具體遙感影像就存在於子資料夾中;如下圖所示。
其中,紅色框內的資料夾即為前述“大資料夾”,紫色框內的每一個資料夾即為前述“子資料夾”。此外,每一個子資料夾的命名也是和遙感影像的分幅條帶號對應的,比如43LCC
這一個子資料夾就是儲存了UTM編號為43
的網格內的全部遙感影像。這裡關於Sentinel-2遙感影像分幅條帶號的介紹,如果大家有需要,可以參考哨兵2號Sentinel-2分幅條帶介紹與MGRS網格向量檔案獲取這篇文章。
同時,在每一個遙感影像檔案的檔名中,都有分幅條帶號這一欄位;例如,開啟43LCC
這一子資料夾,如下圖所示。
我們希望實現的,就是基於上圖所示的研究區域內遙感影像的分幅條帶號資訊,在大量的遙感影像中篩選出這些分幅對應的遙感影像檔案,並將其透過複製的方式放入到一個新的結果資料夾中。
瞭解了具體需求,我們就可以開始程式碼的撰寫。首先,本文所需的完整程式碼如下所示。
# -*- coding: utf-8 -*-
"""
Created on Fri Feb 3 18:33:11 2023
@author: fkxxgis
"""
import os
import xlrd
import shutil
xls_file = r"E:\02_Project\Sentinel.xls"
tif_path = r"G:\S2_CSI_LCC_product\LCC_10days_2020"
result_path = r"G:\Select"
book = xlrd.open_workbook(xls_file)
sh = book.sheet_by_index(0)
row_num = sh.nrows
for row in range(1, row_num):
mgrs = sh.cell(row,6).value
utm = mgrs[0:2]
for root, dirs, files in os.walk(tif_path):
for name in dirs:
if name[0:2] == utm:
for root_1, dirs_1, files_1 in os.walk(os.path.join(root, name)):
for name_1 in files_1:
if name_1.find(mgrs) != -1:
if not os.path.exists(os.path.join(result_path, mgrs)):
os.makedirs(os.path.join(result_path, mgrs))
print("Make " + mgrs + " path.")
shutil.copy(os.path.join(root, name, name_1), os.path.join(result_path, mgrs, name_1))
其中,我們需要匯入os
、xlrd
與shutil
等3
個Python庫,分別實現系統檔案遍歷、Excel資料讀取與研究區域內遙感影像資料的複製。其中,關於xlrd
庫的配置,如果大家是用的Anaconda環境,可以參考Python表格處理模組xlrd在Anaconda中的安裝這篇文章。此外,我們首先需要將本文開頭提及的表示遙感影像資料分幅條帶號的向量檔案的屬性表匯出(透過“System Toolboxes”→“Conversion Tools.tbx”→“Excel”→“Table To Excel”選項,如下圖所示),儲存為.xls
格式的表格檔案,從而方便我們後期程式碼對資料的讀取。
在程式碼中,xls_file
表示我們將屬性表匯出後得到的.xls
格式的表格檔案,tif_path
表示存放所有遙感影像的大資料夾,result_path
則表示找到我們所需的結果遙感影像檔案後,希望將其複製到的路徑。
隨後,我們透過xlrd.open_workbook()
函式開啟.xls
格式的表格檔案,讀取其中的資料並獲取其行數row_num
;接下來,我們即可對這一表格檔案的單元格資料加以遍歷,也就是程式碼中的第1
個for
迴圈——我們從第2
行開始(因為第1
行是表頭),讀取每一行第7
列的資料(也就是存放有遙感影像分幅條帶號的那一列),從而依次獲取所需的遙感影像條帶號。
接下來,由於遙感影像的分幅條帶號的前兩位,以及前述子資料夾名稱的前兩位,都是表示UTM編號的兩位數字,因此我們透過utm = mgrs[0:2]
這句程式碼,擷取當前遙感影像分幅條帶號的前兩位,並透過os.walk()
函式進行遍歷,透過一個if
判斷語句找到大資料夾下對應的子資料夾;隨後,在這一子資料夾中同樣透過os.walk()
函式,進行遙感影像檔案的遍歷——也就是程式碼中第2
個、第3
個、第4
個for
迴圈所做的事情。
接下來,針對遍歷得到的子資料夾中每一個遙感影像檔案,我們透過.find()
函式找到所有滿足這一分幅條帶號的遙感影像檔案,也就是程式碼中第5
個for
迴圈與第2
個if
判斷語句的工作。找到符合當前分幅條帶號的遙感影像檔案後,我們即可開始將其複製到目標資料夾中。
這裡還有一個需求,因為我們這裡儲存的是多時相遙感影像資料(即每一個分幅條帶號對應著多個不同時相的遙感影像檔案),因此我們希望在目標資料夾中,同樣用各個分幅條帶號作為名稱,建立多個子資料夾;然後將當前分幅條帶號對應的全部遙感影像資料放入這一資料夾中。基於此,我們透過os.path.exists()
函式判斷是否存在指定的子資料夾,如果不存在的話就新建這一資料夾;隨後,透過shutil.copy()
函式複製這些遙感影像檔案。
執行上述程式碼,最終我們得到的結果如下圖所示;其中,每一個子資料夾都表示一個分幅條帶號,子資料夾內即為這一分幅條帶號所對應的全部時相的遙感影像檔案。
至此,大功告成。