How to Perform Land Use Classification Using Sentinel-2 Imagery (And Why Analysts Trust It Most)

Land use classification is one of the most common tasks in GIS and remote sensing. It answers a simple question: what is on the ground, and where?

To answer that question reliably, you need imagery you can trust. And for most analysts working today, that imagery comes from Sentinel-2.

This article walks through the full process of performing land use classification using Sentinel-2 data. It covers the data, the bands, the classification approaches, and the validation steps that make your output worth trusting.


Why Sentinel-2 Is the Trusted Standard for Land Classification

Sentinel-2 is part of the European Space Agency’s Copernicus programme. It is a twin-satellite mission, with Sentinel-2A and Sentinel-2B together providing a 5-day revisit cycle over the same location.

Here is why analysts trust it for land use work:

  • 10-meter spatial resolution for visible and near-infrared bands
  • 13 spectral bands covering visible, red edge, near-infrared, and shortwave infrared
  • Free and open access with no licensing restrictions
  • Consistent, well-documented radiometric calibration
  • Global coverage with regular updates

No other freely available sensor offers this combination of resolution, spectral depth, and revisit frequency. That is why Sentinel-2 has become the trusted foundation for land cover mapping at local, regional, and national scales.


Step 1: Understand the Sentinel-2 Band Structure

Before you classify anything, you need to trust your inputs. That starts with understanding what each band captures and which bands matter for land use work.

BandNameCentral WavelengthResolution
B02Blue490 nm10 m
B03Green560 nm10 m
B04Red665 nm10 m
B08NIR842 nm10 m
B05Red Edge 1705 nm20 m
B06Red Edge 2740 nm20 m
B07Red Edge 3783 nm20 m
B8ANarrow NIR865 nm20 m
B11SWIR 11610 nm20 m
B12SWIR 22190 nm20 m

For land use classification, the bands you will rely on most are B02, B03, B04, B08 (the core 10-meter bands), and B11 and B12 (SWIR bands at 20 meters, which are excellent for distinguishing built-up areas, bare soil, and moisture content).

The red edge bands (B05, B06, B07) are particularly trusted for separating vegetation types, which is useful when distinguishing cropland from forest or grassland.


Step 2: Access and Download the Right Data

Choose Level-2A (Surface Reflectance)

Sentinel-2 data comes in two processing levels:

  • Level-1C: Top-of-atmosphere reflectance. Raw, unprocessed.
  • Level-2A: Bottom-of-atmosphere (surface) reflectance. Atmospherically corrected.

Always use Level-2A for classification. Atmospheric correction removes the distortion caused by gases, aerosols, and water vapour in the atmosphere. Without it, the spectral values you classify cannot be trusted.

Where to download

  • Copernicus Data Space Ecosystem: dataspace.copernicus.eu
  • Google Earth Engine (for cloud-based workflows)
  • Microsoft Planetary Computer (STAC API access)

Selecting a scene

When selecting an image, pay attention to:

  • Cloud cover: Keep it below 10 percent for reliable classification. Clouds and cloud shadows will be misclassified if not masked.
  • Acquisition date: Match the season to your classification goal. Summer imagery captures full vegetation cover. Winter imagery may be better for distinguishing evergreen from deciduous.
  • Tile coverage: Sentinel-2 uses a Military Grid Reference System (MGRS) tiling scheme. Identify which tile or tiles cover your area of interest.

Step 3: Preprocess the Imagery

Even with Level-2A data, preprocessing is needed before classification. Skipping this step means your classification results cannot be fully trusted.

Cloud masking

Use the Scene Classification Layer (SCL) that comes with Level-2A data. It classifies each pixel into categories including cloud, cloud shadow, vegetation, bare soil, water, and snow. Use it to mask out clouds and shadows before classification.

In Python using rasterio and numpy:

import rasterio
import numpy as np

# Load the SCL band
with rasterio.open("T43PGM_20240601_SCL_20m.jp2") as src:
    scl = src.read(1)

# Create a cloud mask: keep pixels where SCL is vegetation (4),
# bare soil (5), water (6), or unclassified (7)
valid_pixels = np.isin(scl, [4, 5, 6, 7])

Band stacking

Stack your chosen bands into a single multi-band raster. This simplifies the input to your classifier and keeps your file structure clean.

In Python:

import rasterio
import numpy as np
from rasterio.enums import Resampling

band_paths = {
    "B02": "T43PGM_20240601_B02_10m.jp2",
    "B03": "T43PGM_20240601_B03_10m.jp2",
    "B04": "T43PGM_20240601_B04_10m.jp2",
    "B08": "T43PGM_20240601_B08_10m.jp2",
    "B11": "T43PGM_20240601_B11_20m.jp2",
    "B12": "T43PGM_20240601_B12_20m.jp2",
}

# Read and stack bands (resample 20m bands to 10m)
arrays = []
profile = None

for name, path in band_paths.items():
    with rasterio.open(path) as src:
        if src.res[0] == 20:
            data = src.read(
                1,
                out_shape=(src.count, src.height * 2, src.width * 2),
                resampling=Resampling.bilinear
            )
        else:
            data = src.read(1)
        arrays.append(data)
        if profile is None:
            profile = src.profile

stacked = np.stack(arrays, axis=0)

Calculate spectral indices

Spectral indices improve classification accuracy. They compress multi-band information into a single value that highlights specific surface characteristics.

The most trusted indices for land use classification:

  • NDVI (Normalized Difference Vegetation Index): Separates vegetated from non-vegetated surfaces. NDVI = (B08 - B04) / (B08 + B04)
  • NDWI (Normalized Difference Water Index): Highlights water bodies. NDWI = (B03 - B08) / (B03 + B08)
  • NDBI (Normalized Difference Built-up Index): Highlights built-up and urban areas. NDBI = (B11 - B08) / (B11 + B08)
  • BSI (Bare Soil Index): Separates bare soil from vegetation and built-up areas. BSI = ((B11 + B04) - (B08 + B02)) / ((B11 + B04) + (B08 + B02))

Adding these as additional input layers gives your classifier more to work with and makes the output significantly more trustworthy.


Step 4: Define Your Land Use Classes

Before collecting training data or running any algorithm, define exactly what classes you want to map. Vague class definitions produce results you cannot trust.

A typical classification scheme for general land use mapping might include:

  1. Vegetation (forest, scrub, grassland)
  2. Agriculture (cropland, fallow)
  3. Urban and built-up
  4. Bare soil and exposed rock
  5. Water bodies
  6. Wetlands

Refine this based on your project goals. A flood risk study may need to separate water bodies and wetlands in detail. An urban growth study may need multiple urban density classes.

Each class must be clearly distinguishable in spectral terms. If two classes look nearly identical in the bands you are using, your classifier will not be able to separate them reliably.


Step 5: Collect Training Samples

Training samples are the foundation your classifier learns from. Their quality determines whether your results can be trusted.

Best practices for training data collection:

  • Collect samples from areas you know with certainty. Ground truth is most trusted.
  • Use high-resolution imagery (Google Earth, OpenAerialMap) to verify land cover at sample locations.
  • Collect at least 50 to 100 samples per class. More complex classes need more samples.
  • Distribute samples across the entire study area. Do not cluster them in one region.
  • Avoid edge pixels where two land cover types meet. These introduce spectral mixing and reduce classifier trust.

In QGIS, you can collect training polygons using the Semi-Automatic Classification Plugin (SCP). In ArcGIS Pro, use the Training Samples Manager in the Image Classification toolbar. In Python, samples can be collected as GeoJSON or Shapefile and then overlaid on the stacked imagery to extract pixel values.


Step 6: Choose a Classification Algorithm

There are two broad approaches to classification: supervised and unsupervised.

Unsupervised classification

The algorithm groups pixels into clusters based on spectral similarity without any prior labeling. You define the number of clusters. You interpret the result afterward.

K-Means is the most commonly used unsupervised method. It is a good starting point when you have little prior knowledge of the area. But the output is harder to validate and generally less trusted for final deliverables.

Supervised classification

You provide labeled training samples. The algorithm learns the spectral signature of each class and applies that learning across the image.

The most trusted supervised classifiers for Sentinel-2 land use work are:

  • Random Forest: An ensemble method that builds multiple decision trees and votes on the final class label. It handles noisy training data well, works with high-dimensional inputs, and produces probability outputs that help you assess confidence.
  • Support Vector Machine (SVM): Effective in high-dimensional spectral space. Trusted for separating classes with subtle spectral differences.
  • Gradient Boosting (XGBoost, LightGBM): Increasingly used for large-scale classification tasks. High accuracy but requires more careful tuning.

Random Forest is the most widely trusted choice for Sentinel-2 classification because of its robustness and interpretability.

Running a Random Forest classifier in Python:

from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report
import numpy as np

# X = array of pixel values (n_samples, n_bands+indices)
# y = array of class labels (n_samples,)

X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.3, random_state=42, stratify=y
)

clf = RandomForestClassifier(n_estimators=200, random_state=42, n_jobs=-1)
clf.fit(X_train, y_train)

y_pred = clf.predict(X_test)
print(classification_report(y_test, y_pred))

Step 7: Apply the Classifier and Export the Result

Once trained, apply the classifier to your full stacked imagery array to produce the classified map.

# Reshape image for prediction
height, width = stacked.shape[1], stacked.shape[2]
image_2d = stacked.reshape(stacked.shape[0], -1).T  # (n_pixels, n_bands)

# Predict
predicted = clf.predict(image_2d)
classified_map = predicted.reshape(height, width)

# Export as GeoTIFF
output_profile = profile.copy()
output_profile.update(count=1, dtype="uint8")

with rasterio.open("land_use_classification.tif", "w", **output_profile) as dst:
    dst.write(classified_map.astype("uint8"), 1)

Step 8: Validate and Assess Accuracy

A classified map without validation is a map you should not trust.

Accuracy assessment compares your classified output against reference data collected independently from your training samples. It produces an error matrix (also called a confusion matrix) that tells you how often each class was correctly or incorrectly classified.

Key accuracy metrics:

  • Overall Accuracy: Percentage of correctly classified pixels across all classes.
  • Producer’s Accuracy: How often a real-world class is correctly mapped. Measures errors of omission.
  • User’s Accuracy: How often a mapped class is correct on the ground. Measures errors of commission.
  • Kappa Coefficient: Measures agreement between the classified map and reference data, accounting for chance agreement. A Kappa above 0.80 is generally trusted as strong agreement.

Best practices for validation:

  • Use a separate validation dataset, not the same samples used for training.
  • Collect at least 50 validation points per class.
  • Use stratified random sampling to ensure all classes are represented.
  • Document your validation process clearly so others can assess how much to trust your results.

In Python, sklearn.metrics.confusion_matrix and classification_report handle this. In ArcGIS Pro, the Accuracy Assessment tools in the Image Classification workflow automate the process.


Step 9: Post-Classification Refinement

Raw classification output often contains isolated pixels misclassified due to spectral noise. A few refinement steps improve the visual quality and analytical trustworthiness of the result.

Majority filter (sieve filter)

Removes small isolated pixel clusters by replacing them with the majority class of surrounding pixels. Apply this as a raster analysis step in QGIS, ArcGIS Pro, or using GDAL.

gdal_sieve.py -st 10 -4 land_use_classification.tif land_use_refined.tif

The -st 10 flag removes patches smaller than 10 pixels and reassigns them to adjacent classes.

Boundary smoothing

Classification outputs often have jagged, pixel-level boundaries. Converting rasters to vector polygons and applying a simplification function (such as Simplify Polygon in ArcGIS Pro or v.generalize in QGIS) produces cleaner, more presentable outputs.


Step 10: Symbolize and Communicate the Result

A land use map is only useful if it communicates clearly. Apply a consistent, trusted color scheme that matches widely recognized classification conventions:

  • Green shades for vegetation and forest
  • Yellow and light brown for agriculture
  • Red and grey for urban and built-up
  • Tan for bare soil
  • Blue for water
  • Teal or olive for wetlands

Add a legend, scale bar, north arrow, and data source information. If sharing the output beyond your immediate team, include a methods summary describing the imagery date, classification approach, and accuracy metrics. This gives your audience a reason to trust what they are looking at.


Working with Sentinel-2 in ArcGIS and Google Earth Engine

ArcGIS Pro

ArcGIS Pro’s Image Classification wizard supports the full supervised classification workflow. It handles training sample collection, Random Forest and SVM classification, and accuracy assessment in a single guided interface. The Living Atlas also includes pre-processed Sentinel-2 imagery layers for direct use without downloading.

Google Earth Engine

Earth Engine hosts the full Sentinel-2 archive and supports cloud-based classification using its JavaScript and Python APIs. The ee.Classifier.smileRandomForest() function runs a Random Forest classifier directly in the cloud, which is trusted for large study areas where local processing would be impractical.

// Google Earth Engine example (JavaScript)
var classifier = ee.Classifier.smileRandomForest(200)
  .train({
    features: trainingData,
    classProperty: 'landuse',
    inputProperties: bands
  });

var classified = image.classify(classifier);
Map.addLayer(classified, {min: 1, max: 6, palette: palette}, 'Land Use');

Final Thoughts

Land use classification with Sentinel-2 is a well-established, trusted workflow. The data is reliable. The methods are documented. The tools are accessible.

What separates a classification result worth trusting from one that is not comes down to the decisions made at each step: using atmospherically corrected imagery, collecting clean training samples, validating independently, and documenting the process clearly.

Follow the steps in this article and you will produce a land use map that you can stand behind, and that your audience can trust.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *