Sentinel-2 End-to-End Python Workflow: 47 Indices & 8-Class Land Classification
This article presents a complete Python workflow for Sentinel-2 L2A imagery, covering automated download, preprocessing, 47 remote sensing indices calculation, index applications, and GB/T 21010-2017 compliant 8-class land cover classification with a PySide6 visualization interface.
Introduction
This project builds an end-to-end automated workflow for Sentinel-2 L2A imagery, using Haikou City as a case study. The pipeline covers data acquisition, preprocessing, 47 remote sensing indices calculation, index applications, visualization, and 8-class land classification compliant with GB/T 21010-2017.
Data and Environment
Imagery source: Sentinel-2 L2A (surface reflectance, atmospherically corrected)
Data portal: Copernicus Data Space (OData/OAuth2.0)
Study area: Haikou City, spanning UTM tiles T49QDB and T49QDC
Bands: 12 bands (B1–B12) resampled to 10 m resolution
Classification standard: GB/T 21010-2017 "Current Land Use Classification" three-level system
Runtime: Python 3.10+, Windows/Linux
UI framework: PySide6 (Qt 6) for visualization script
Module Overview
Preprocessing and Indices (9 scripts)
1_sentinel_download.py– Automated Sentinel-2 query and download (OData filtering, OAuth2.0, streaming download, Excel manifest) 2_resampling_stacking.py – Resample multi-resolution bands to 10 m and stack into 12-band TIFF; process SCL layer 3_cloud_shadow_masking.py – Mask clouds, cloud shadows, cirrus using SCL scene classification (block processing, default mask codes 3/8/9/10) 4_cloud_free_image_mosaicking.py – Multi-temporal cloud-free filling: tile grouping, adaptive base selection, rule-based/adaptive dual strategy, fill quality report 5_tiff_merge.py – Cross-tile mosaicking: automatic boundary calculation, four overlap strategies (nodata_first/first/last/mean), distance-weighted feathering 6_tiff_shp_cut.py – Clip by Shapefile administrative boundary: geopandas filtering, CRS auto-conversion, rasterio.mask 7_remote_sensing_index.py – Batch index calculation entry: calls remote_sensing_index.py to compute 47 indices and output TIFFs 8_remote_sensing_index_application.py – Index applications: single-index classification, multi-index weighted evaluation, national-standard land classification (modules 1/2/3/all) 9_remote_sensing_index_ui.py – PySide6 interactive viewer: three-level tree menu, pyramid zoom, continuous/discrete dual-mode rendering, dynamic legend
Land Classification (4 scripts)
13_water_extract.py– Water prior extraction: multi-index voting + KMeans clustering + river neighborhood growth + roof suppression 14_road_extract.py – Road prior extraction: directional contrast line detection + trunk/village road morphological growth + building exclusion 15_building_extract.py – Building prior extraction: roof seeds + density threshold + expansion to impervious surfaces + red roof identification 16_land_classification.py – Land classification CLI: reads indices from result/ and priors from application/, outputs three-level classification
Core Libraries
remote_sensing_index.py– RemoteSensingIndex class: unified engine for 47 indices, reflective invocation (getattr), safe division, nodata masking land_classification.py – LandClassificationApplication / WeightedIndexLandClassifier: candidate rules, Up/Down/Tri physical response scoring, P2–P98 robust standardization, area quotas, mutually exclusive allocation, sub-class subdivision
Installation and Usage
Environment Setup
git clone https://gitee.com/baoqiangwang/remote-sensing-index-application.git
cd remote-sensing-index-application
python -m venv .venv
# Windows: .venv\Scripts\activate
# Linux: source .venv/bin/activate
pip install -r requirements.txtNote: requirements.txt locks only direct imports (rasterio, numpy, geopandas, pandas, requests, openpyxl, tqdm, scipy, opencv-python, scikit-learn, PySide6); transitive dependencies resolved by pip.
Full Pipeline Commands
# Stage 1: Data acquisition & preprocessing
# 1. Download Sentinel-2 (edit user config at top of script)
python 1_sentinel_download.py
# 2. Resample & stack (modify RAW_DATA_ROOT / OUTPUT_ROOT)
python 2_resampling_stacking.py
# 3. Cloud/shadow masking (modify INPUT_ROOT / OUTPUT_ROOT)
python 3_cloud_shadow_masking.py
# 4. Cloud-free mosaicking (modify MASKED_ROOT / OUTPUT_ROOT / FILL_MAPPING)
python 4_cloud_free_image_mosaicking.py
# 5. Tile merging (optional feathering -f)
python 5_tiff_merge.py T49QDB_202605_masked.tif T49QDC_202605_masked.tif -o T49QDB_QDC_202605.tif -m nodata_first -f
# 6. Shapefile clipping (-x admin code 460100 for Haikou)
python 6_tiff_shp_cut.py -t T49QDB_QDC_202605.tif -s haikou.shp -o T49QDB_QDC_202605_haikou.tif -x 460100
# Stage 2: Indices & applications
# 7. Compute 47 indices (omit -i for all)
python 7_remote_sensing_index.py -t result/T49QDB_QDC_202605_haikou.tif -o result -i NDVI NDWI EVI NDBI MNDWI
# 8. Index applications (module 1=classification 2=evaluation 3=standard all=all)
python 8_remote_sensing_index_application.py -t result/T49QDB_QDC_202605_haikou.tif -o application -i result -m all
# 9. Launch visualization UI
python 9_remote_sensing_index_ui.py
# Stage 3: 8-class land classification
# 13/14/15. Extract water, road, building priors (output to application/ subdirs)
python 13_water_extract.py -t result/T49QDB_QDC_202605_haikou.tif
python 14_road_extract.py -t result/T49QDB_QDC_202605_haikou.tif
python 15_building_extract.py -t result/T49QDB_QDC_202605_haikou.tif
# 16. Land classification: reads indices from result/ + priors from application/, outputs three-level classification
python 16_land_classification.py -t result/T49QDB_QDC_202605_haikou.tif -i result -o applicationRemote Sensing Indices and Classification Results
47 Indices Overview
The RemoteSensingIndex class computes 47 indices grouped into six categories:
Basic vegetation ratio (1): SR – quick vegetation/bare soil discrimination
General normalized vegetation (17): NDVI, EVI, NDRE, GNDVI, WDRVI, CIgreen, ARI… – vegetation vigor, chlorophyll, nitrogen
Soil-adjusted vegetation (7): SAVI, MSAVI, OSAVI, PVI, MCARI, TCARI/OSAVI… – low cover/early-stage monitoring
Atmospheric/aerosol corrected (4): ARVI, SARVI, AFRI, VARI – cloudy/hazy conditions
Water/drought/salinity stress (7): MSI, NDMI, LSWI, AWEIsh, AWEInsh, SMMI… – water, drought, salinity assessment
Bare soil/water/built-up classification (11): NDBI, BSI, BI, MNDWI, NDWI, IBI, NBR, MVI… – land cover classification, feature extraction
Formulas are implemented in remote_sensing_index.py; reflectance values are divided by 10000 before calculation, with _safe_divide handling division by zero and _apply_mask flagging invalid pixels.
Eight-Class Land Classification System
Classification follows GB/T 21010-2017 three-level hierarchy: Level 1 (3 classes) → Level 2 (12 classes) → Level 3 (35 valid codes). Allocation order: Transportation → Water → Built-up (priors locked first), then the remaining pixels compete among Cropland, Orchard, Forest, Grassland, Wetland , finally subdivided by official area quotas.
Cropland (3 sub-classes): indices NDVI, EVI, NDRE, LSWI, NDMI; five-class competition, suppresses urban high-density misclassification
Orchard (4 sub-classes): NDVI, EVI, NDRE, NBR, LSWI; high vegetation threshold, emphasizes perennial vegetation
Forest (4 sub-classes): NDVI, EVI, NDRE, NBR; prefers high cover, suppresses bare soil and built-up
Grassland (2 sub-classes): NDVI, EVI, NDRE, BSI, NDMI; peak-shaped vegetation response, avoids confusion with dense forest
Wetland (4 sub-classes): MNDWI, LSWI, NDMI, MVI, NDWI; dual candidate channels for vegetated and open wetland
Water (5 sub-classes): NDWI, MNDWI, AWEIsh, AWEInsh; water prior + multi-index voting + 320 m hydrological neighborhood + roof suppression
Built-up (5 sub-classes): BI, NDBI, BSI, low NDVI; building prior bonus, road penalty, converted at 40% cover ratio
Transportation (6 sub-classes): NDBI, BSI, medium BI, low water indices; road prior bonus, building penalty, water hard exclusion
Known limitations: Single-date imagery lacks phenological information; 10 m mixed pixels hinder narrow feature separation; LSWI duplicates NBR , IBI duplicates BSI (identical formulas); area quotas control quantity but not spatial accuracy; empirical thresholds calibrated for Haikou's tropical coastal scene, requiring recalibration for transfer.
Directory Structure
remote-sensing-index-application/
├── README.md
├── requirements.txt
├── assets/
│ ├── qrcode_mp.png # WeChat official account QR code
│ └── qrcode_wechat.png # WeChat QR code
├── 1_sentinel_download.py
├── 2_resampling_stacking.py
├── 3_cloud_shadow_masking.py
├── 4_cloud_free_image_mosaicking.py
├── 5_tiff_merge.py
├── 6_tiff_shp_cut.py
├── 7_remote_sensing_index.py
├── 8_remote_sensing_index_application.py
├── 9_remote_sensing_index_ui.py
├── 13_water_extract.py
├── 14_road_extract.py
├── 15_building_extract.py
├── 16_land_classification.py
├── remote_sensing_index.py
└── land_classification.pyAll scripts remain flat in the root directory to ensure cross-script import and importlib loading work correctly.
License
Apache License 2.0.
Contact
The project accompanies two WeChat article series: 【Remote Sensing Image Analysis】 (9 articles) covering the full workflow from download to visualization, and 【One Scene, Eight Classes】 (9 articles) explaining how a single satellite image is split into the eight major land categories. The complete open-source repository, sample data, and debug versions are maintained via the WeChat official account "Python and Big Data Analysis" (reply keyword remotesensingindexapplication).
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
ITPUB
Official ITPUB account sharing technical insights, community news, and exciting events.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
