Skip to content

Switch from per-band mean/std normalization of Sentinel-2 values to surface reflectance conversion instead #94

@weiji14

Description

@weiji14

Using mean and standard deviation normalization is a common procedure in standard Computer Vision, and can be applied e.g. by using torchvision's Normalize function. But this normalization can lead to incorrect band ratios when applied to optical remote sensing images.

E.g. let's take the formula for Normalized Difference Vegetation Index (NDVI):

$$ \text{NDVI} = \frac{\text{NIR} - \text{Red}}{\text{NIR} + \text{Red}} $$

If say, we have a un-normalized Sentinel-2 pixel with Band 8 (NIR): 3327, and Band 4 (Red): 426, then the NDVI value would be:

$$ \text{NDVI} = \frac{3327-426}{3327+426} = 0.77 $$

However, if we apply a per-band mean/std normalization scheme, the value becomes:

$$\text{NIR} = \frac{3327-2238}{1414} = 0.77$$ $$\text{Red} = \frac{426-583}{981} = -0.16$$ $$\text{NDVI} = \frac{0.77-(-0.16)}{0.77+(-0.16)} = 1.52$$

Clearly this is wrong, since we've removed the NDVI signal! A model trained on these mean/std normalized pixel values would have a harder time capturing the semantics of band indices such as NDVI.

One possible solution, is that instead of applying a per-band normalization, we can convert the Sentinel-2 Digital Number (DN) values to surface reflectance by dividing with the dynamic range of the band to a value between 0-1. Sentinel-2's MSI sensor is 12-bit, but the data is stored as 16-bit. Usually people use 10000, but this doesn't work for very bright white areas, so I'll use $2^{14} = 16384$ below:

$$\text{NIR} = \frac{3327}{16384} = 0.20$$ $$\text{Red} = \frac{426}{16384} = 0.026$$ $$\text{NDVI} = \frac{0.20-0.026}{0.20+0.026} = 0.77$$

which matches with the actual NDVI value.

Notes:


Side note: Using a single mean and standard deviation value for all Sentinel-2 bands won't preserve the band ratios either. E.g. if we use a mean value of 1351 and standard deviation of 1071, and apply it to the NIR/Red bands

$$\text{NIR} = \frac{3327-1351}{1071} = 1.845$$ $$\text{Red} = \frac{426-1351}{1071} = -0.8637$$ $$\text{NDVI} = \frac{1.845-(-0.8637)}{1.845+(-0.8637)} = 2.76$$

The 2.76 result is still not the correct NDVI value of 0.77.

References:

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingdata-pipelinePull Requests about the data pipeline

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions