Emissivity Explained
On this page
Problem statement
A thermal sensor does not measure temperature. It measures radiance, and turning radiance into temperature needs to know how efficiently the surface emits — its emissivity. A perfect emitter (a black body) has emissivity 1; real surfaces range from about 0.99 for water and dense vegetation down to 0.90 or less for bare metal roofs and some dry soils. Getting it wrong by a few hundredths moves the retrieved temperature by around a degree, and not uniformly: the error is largest on exactly the surfaces urban heat studies care about.
Landsat's Level-2 product handles emissivity for you, using the ASTER Global Emissivity Database. It also ships the layers it used, which makes it possible to see what emissivity does to the answer.
Quick answer
At-sensor radiance is a mix of surface emission, reflected sky radiance and atmospheric emission:
L_sensor = τ · [ ε · B(T_s) + (1 − ε) · L↓ ] + L↑
Solving for B(T_s) and inverting the Planck function gives the surface temperature; ε enters twice.
import numpy as np, rasterio, pystac_client, planetary_computer
from rasterio.warp import transform_bounds
AOI = (-3.75, 40.38, -3.63, 40.47)
cat = pystac_client.Client.open("https://planetarycomputer.microsoft.com/api/stac/v1")
it = min((i for i in cat.search(collections=["landsat-c2-l2"], bbox=list(AOI),
datetime="2023-07-01/2023-07-31").items()
if i.properties["platform"] == "landsat-8"), key=lambda i: i.properties["eo:cloud_cover"])
def read(asset, scale, offset=0.0, fill=-9999):
with rasterio.open(planetary_computer.sign(it.assets[asset].href)) as src:
win = rasterio.windows.from_bounds(*transform_bounds("EPSG:4326", src.crs, *AOI), src.transform)
a = src.read(1, window=win).astype("float64")
return np.where(a == fill, np.nan, a * scale + offset)
L = read("trad", 0.001) # thermal radiance at sensor, W/(m² sr µm)
up = read("urad", 0.001) # upwelling atmospheric radiance
down = read("drad", 0.001) # downwelling sky radiance
tau = read("atran", 0.0001) # atmospheric transmittance
emis = read("emis", 0.0001) # ASTER GED-based emissivity, band 10
st = read("lwir11", 0.00341802, 149.0, fill=0) - 273.15 # the official product, °C
K1, K2 = 774.8853, 1321.0789 # Landsat 8 band 10 constants
def lst_from(e):
B = (L - up - tau * (1 - e) * down) / (tau * e)
return K2 / np.log(K1 / B + 1) - 273.15
mine = lst_from(emis)
print(f"{it.id}: emissivity {np.nanpercentile(emis, 5):.3f}–{np.nanpercentile(emis, 95):.3f} (5th–95th)")
print(f"reconstructed LST vs product: median difference {np.nanmedian(mine - st):+.2f} °C")
for e in (1.0, 0.97, 0.95):
print(f"assuming ε = {e:.2f} everywhere: median error {np.nanmedian(lst_from(np.full_like(emis, e)) - st):+.2f} °C, "
f"95th pct |error| {np.nanpercentile(abs(lst_from(np.full_like(emis, e)) - st), 95):.2f} °C")
LC08_L2SP_201032_20230729_02_T1: emissivity 0.960–0.978 (5th–95th)
reconstructed LST vs product: median difference +0.13 °C
assuming ε = 1.00 everywhere: median error -2.07 °C, 95th pct |error| 2.70 °C
assuming ε = 0.97 everywhere: median error +0.05 °C, 95th pct |error| 0.84 °C
assuming ε = 0.95 everywhere: median error +1.51 °C, 95th pct |error| 2.19 °C
Rebuilding the product from its own inputs reproduces it to 0.13 °C. A constant of 0.97 happens to match the median emissivity here and stays within 0.84 °C on 95% of pixels; ε = 1 — the brightness-temperature assumption — makes the whole city about 2 °C too cold, and ε = 0.95 about 1.5 °C too hot.
Brightness versus surface temperature, and where emissivity is uncertain
1. Distinguish brightness and surface temperature
Brightness temperature assumes ε = 1 and ignores the atmosphere. Surface temperature corrects for both. Many older urban studies used brightness temperature, which runs cooler than the true surface.
2. Use a product that handles emissivity
Landsat Collection 2 Level-2, MODIS and ECOSTRESS LST products all include emissivity. Recomputing it yourself is rarely necessary.
3. Know where emissivity is uncertain
ASTER GED emissivity is a 100 m climatology from the early 2000s. Buildings constructed since, new roofs and seasonal vegetation changes are not in it. Uncertainty is higher over mixed urban pixels and bare soils.
4. Check the emissivity uncertainty layer
Landsat Level-2 includes emsd (emissivity standard deviation); high values flag pixels where the temperature is less reliable.
5. Do not correct twice
If a dataset is already surface temperature, applying an emissivity correction again introduces an error of the same size it was meant to remove.
Emissivity by land cover
Example 1 — emissivity by land cover
from rasterio.warp import reproject, Resampling
with rasterio.open(planetary_computer.sign(it.assets["emis"].href)) as src:
win = rasterio.windows.from_bounds(*transform_bounds("EPSG:4326", src.crs, *AOI), src.transform)
tf, crs, shape = src.window_transform(win), src.crs, (int(win.height), int(win.width))
wc = np.zeros(emis.shape, dtype="uint8")
wc_item = next(cat.search(collections=["esa-worldcover"], bbox=list(AOI), datetime="2021").items())
with rasterio.open(planetary_computer.sign(wc_item.assets["map"].href)) as src:
reproject(rasterio.band(src, 1), wc, dst_transform=tf, dst_crs=crs, resampling=Resampling.mode)
for code, name in ((10, "tree cover"), (30, "grassland"), (50, "built-up"), (60, "bare"), (80, "water")):
m = wc == code
if m.sum() > 50:
print(f"{name:<11} emissivity median {np.nanmedian(emis[m]):.3f}; "
f"error if ε = 1 assumed: {np.nanmedian(lst_from(np.ones_like(emis))[m] - st[m]):+.2f} °C")
tree cover emissivity median 0.972; error if ε = 1 assumed: -1.86 °C
grassland emissivity median 0.973; error if ε = 1 assumed: -1.80 °C
built-up emissivity median 0.968; error if ε = 1 assumed: -2.13 °C
bare emissivity median 0.969; error if ε = 1 assumed: -2.07 °C
water emissivity median 0.975; error if ε = 1 assumed: -1.54 °C
The class medians differ only in the third decimal. ASTER GED is a 100 m climatology, and in a dense city nearly every 100 m cell mixes roofs, trees and paving; even water comes out at 0.975, where open water is about 0.99. Built-up land is still the lowest, so a constant ε = 1 biases the classes by different amounts — 1.5 °C on water, 1.9 °C on trees, 2.1 °C on built-up land — and stretches the urban–vegetation contrast by a few tenths of a degree.
Example 2 — brightness temperature
bt = K2 / np.log(K1 / L + 1) - 273.15 # no atmosphere, no emissivity
print(f"top-of-atmosphere brightness temperature: median {np.nanmedian(bt):.1f} °C; "
f"surface temperature product: median {np.nanmedian(st):.1f} °C")
top-of-atmosphere brightness temperature: median 36.9 °C; surface temperature product: median 44.0 °C
Brightness temperature at the top of the atmosphere is several degrees below the surface temperature on a clear summer day: the atmosphere absorbs part of the surface signal and emits at a cooler temperature.
Example 3 — where emissivity is uncertain
emsd = read("emsd", 0.0001)
print(f"emissivity standard deviation: median {np.nanmedian(emsd):.4f}, "
f"99th percentile {np.nanpercentile(emsd, 99):.4f}")
hi = emsd > np.nanpercentile(emsd, 95)
print(f"land cover in the most uncertain 5%: "
f"{', '.join(f'{c}:{(wc[hi] == c).mean():.0%}' for c in (10, 30, 50, 60))}")
emissivity standard deviation: median 0.0066, 99th percentile 0.0144
land cover in the most uncertain 5%: 10:16%, 30:5%, 50:78%, 60:1%
Built-up land is 78% of the most uncertain twentieth of pixels, against 74% of the area as a whole, and tree cover 16% against 21%: the uncertainty leans towards built-up surfaces, where emissivity varies most between materials, but only slightly. In a city this dense, emissivity is uncertain almost everywhere.
Why the effect is not a constant offset
Why emissivity matters physically
A surface with emissivity below 1 emits less than a black body at the same temperature and reflects some of the sky's radiation. Without knowing ε, a lower radiance could mean a cooler surface or a less efficient emitter. The two are disentangled only by knowing ε.
Why the effect is not a constant offset
The error from a wrong emissivity scales with the difference between the assumed and true values and with the surface temperature. Surfaces with the lowest emissivity — bare soils, some roofs — get the largest errors, which are also the hottest surfaces.
Why ASTER GED is used
Estimating emissivity from each Landsat scene is not possible with one thermal band. The ASTER Global Emissivity Dataset, derived from a five-band thermal instrument, provides a consistent 100 m emissivity map worldwide, adjusted in the Landsat product for vegetation using NDVI.
Band constants, metal roofs and scale factors
- Band constants K1 and K2 differ between sensors and bands; read them from the scene metadata for other satellites.
- Seasonal vegetation changes emissivity slightly; the Landsat product adjusts using NDVI.
- Water emissivity is about 0.99 and stable.
- Metal roofs can have emissivity well below 0.9; they appear anomalously cool in products that assume higher values.
- Scale factors: the auxiliary layers have different scales from ST itself; read them from the product guide.
Internal links
- Land surface temperature explained — the quantity being retrieved
- Landsat thermal data explained — the sensor and product
- LST values on the wrong scale — scale factors and fill values
- How to read Landsat surface temperature — using the product directly
- How to relate LST to vegetation — where emissivity bias would distort a slope
- Units and scale factors in raster data — the general problem
FAQ
What is emissivity?
The efficiency with which a surface emits thermal radiation relative to a black body at the same temperature, from 0 to 1.
Why does emissivity matter for LST?
Radiance depends on both temperature and emissivity; without emissivity, temperature cannot be recovered correctly.
What emissivity should I assume?
None — use a surface temperature product that already includes a spatially varying emissivity.
What is brightness temperature?
Temperature computed from radiance assuming ε = 1 and no atmosphere; it is not surface temperature.
How large is the error from assuming ε = 1?
Around a degree on typical surfaces, more on low-emissivity materials.
Where does Landsat get emissivity from?
The ASTER Global Emissivity Dataset, adjusted with NDVI for vegetation.