SAR imagery explained: what radar measures and why it sees through cloud
On this page
Problem statement
An optical satellite photographs sunlight reflected off the ground, so it sees nothing at night and nothing under cloud — which is exactly when floods, storms and winter crops need watching. Synthetic aperture radar carries its own illumination: it sends microwave pulses and records what comes back. Clouds are transparent at those wavelengths, and the sensor does not care whether it is day or night.
The price is that a radar image is not a picture in any familiar sense. Its brightness is a measure of how rough and how wet a surface is and how it faces the sensor, not of its colour. Water is black, cities are white, fields are grey and change with the weather, and every pixel is covered in a grain called speckle. Reading SAR well starts with knowing what the numbers are.
Quick answer
A Sentinel-1 radiometrically terrain-corrected (RTC) pixel is backscatter: the fraction of transmitted power returned towards the sensor, per unit area, in linear units. Convert to decibels to look at it:
import numpy as np
from sar_io import search, passes, grid, read_pass, to_db
bbox = [-0.46, 39.25, -0.33, 39.45] # south of Valencia, Spain
g = grid(bbox, "EPSG:25830")
p = passes(search(bbox, "2024-10-20/2024-10-20", orbit=110))
vv = read_pass(next(iter(p.values())), "vv", g)
db = to_db(vv)
print(f"{np.isfinite(vv).mean():.1%} valid; linear median {np.nanmedian(vv):.3f}; "
f"dB median {np.nanmedian(db):.1f}; 1st–99th percentile "
f"{np.nanpercentile(db, 1):.1f} to {np.nanpercentile(db, 99):.1f} dB")
100.0% valid; linear median 0.110; dB median -9.6; 1st–99th percentile -22.7 to 5.9 dB
sar_io is the small module from the reading guide. Linear values are what physics adds and averages; decibels are what eyes and thresholds work with.
What the sensor sends, what returns, and when to use it
1. Know what the sensor sends
Sentinel-1 is a C-band radar: a wavelength of 5.55 cm. It looks sideways, not down, at incidence angles between about 30° and 46° across its 250 km swath, and it transmits in one polarisation and receives in two — VV and VH over land.
2. Know what comes back
Calm water acts as a mirror and reflects the pulse away from the sensor: very little returns, so water is dark. Rough surfaces scatter in all directions and send some back. Vegetation scatters from leaves and stems, depolarising the signal. Buildings form corners with the ground that reflect the pulse straight back, so cities are the brightest thing in the scene.
3. Know the units
Backscatter coefficients — sigma0, or gamma0 for terrain-corrected products — are ratios, usually between 0.001 and 1 over land. Decibels are 10·log₁₀ of that, so most land lies between −25 and 0 dB. Bright targets can exceed 1 (positive dB); that is a corner reflector, not an error.
4. Expect grain
Each pixel sums returns from many scatterers whose phases interfere randomly. The result, speckle, makes neighbouring pixels of the same field differ by several decibels. It is a property of coherent imaging, not noise to be cleaned away completely — see the speckle guide.
5. Expect geometry to matter
Because the sensor looks sideways, slopes facing it are bright and compressed and slopes facing away are dark or hidden. The same field looks different from an ascending and a descending pass.
6. Use it when optics cannot
Flood mapping, ship detection, soil moisture, crop monitoring through the cloudy season, and ground motion from InSAR are where SAR earns its complexity.
Radar passes against the optical record in a cloudy fortnight
The data used on this page
Sentinel-1 radiometrically terrain-corrected backscatter (sentinel-1-rtc) from the Microsoft Planetary Computer, read through sar_io.py — the small module from the reading guide that searches, groups frames into passes and mosaics each pass onto a fixed grid.
%%writefile sar_io.py
"""Find, read and mosaic Sentinel-1 RTC scenes from Microsoft Planetary Computer."""
from collections import defaultdict
import numpy as np
import planetary_computer
import pystac_client
import rasterio
from rasterio.enums import Resampling
from rasterio.transform import from_origin
from rasterio.vrt import WarpedVRT
from rasterio.warp import transform_bounds
STAC = "https://planetarycomputer.microsoft.com/api/stac/v1"
def search(bbox, dates, orbit=None, direction=None, collection="sentinel-1-rtc"):
"""Items over bbox (lon/lat) in a date range, filtered by relative orbit and pass direction."""
cat = pystac_client.Client.open(STAC, modifier=planetary_computer.sign_inplace)
items = cat.search(collections=[collection], bbox=bbox, datetime=dates).item_collection()
keep = [i for i in items
if (orbit is None or i.properties["sat:relative_orbit"] == orbit)
and (direction is None or i.properties["sat:orbit_state"] == direction)]
return sorted(keep, key=lambda i: i.datetime)
def passes(items):
"""Group frames into passes: same day, same relative orbit."""
groups = defaultdict(list)
for i in items:
groups[(i.datetime.date(), i.properties["sat:relative_orbit"])].append(i)
return dict(sorted(groups.items()))
def grid(bbox, crs, res=10):
"""A fixed target grid: every pass is read onto this, so arrays line up."""
left, bottom, right, top = transform_bounds(4326, crs, *bbox)
width, height = int((right - left) // res), int((top - bottom) // res)
return {"crs": crs, "transform": from_origin(left, top, res, res),
"width": width, "height": height}
def read_pass(frames, band, g):
"""Mosaic one pass's frames for one band onto grid g. Linear power; NaN where no data."""
out = np.full((g["height"], g["width"]), np.nan, dtype="float32")
for item in frames:
with rasterio.open(item.assets[band].href) as src, WarpedVRT(
src, crs=g["crs"], transform=g["transform"], width=g["width"],
height=g["height"], resampling=Resampling.bilinear, nodata=np.nan) as vrt:
a = vrt.read(1)
a[a <= 0] = np.nan # -32768 nodata and zero-padding
fill = np.isnan(out) & np.isfinite(a)
out[fill] = a[fill]
return out
def to_db(linear):
return 10 * np.log10(linear)
Overwriting sar_io.py
Example 1 — the optical record over the same fortnight
import pystac_client
es = pystac_client.Client.open("https://earth-search.aws.element84.com/v1")
s2 = es.search(collections=["sentinel-2-c1-l2a"], bbox=bbox,
datetime="2024-10-25/2024-11-06").item_collection()
for it in sorted(s2, key=lambda i: i.datetime):
print(it.datetime.date(), f"cloud {it.properties['eo:cloud_cover']:5.1f}%")
2024-10-26 cloud 29.5%
2024-10-26 cloud 20.9%
2024-10-31 cloud 61.2%
2024-10-31 cloud 56.4%
2024-11-05 cloud 59.5%
2024-11-05 cloud 51.4%
2024-11-05 cloud 61.1%
2024-11-05 cloud 52.9%
Three Sentinel-2 passes, 21–61% cloud over the tile, and nothing at all between 26 and 31 October — the flood came on the 29th.
Example 2 — the radar passes in the same window
s1 = passes(search(bbox, "2024-10-25/2024-11-06"))
for (day, orbit), frames in s1.items():
print(day, f"orbit {orbit:3d}", frames[0].properties["sat:orbit_state"], len(frames), "frame(s)")
2024-10-25 orbit 8 descending 1 frame(s)
2024-10-26 orbit 30 ascending 2 frame(s)
2024-11-01 orbit 110 descending 2 frame(s)
2024-11-06 orbit 8 descending 2 frame(s)
Example 3 — what the brightness means
post_frames = next(iter(passes(search(bbox, "2024-11-01/2024-11-01", orbit=110)).values()))
post = to_db(read_pass(post_frames, "vv", g))
for label, lo, hi in [("very dark (< -20 dB)", -99, -20), ("dark (-20 to -15)", -20, -15),
("grey (-15 to -5)", -15, -5), ("bright (> -5 dB)", -5, 99)]:
share_pre = np.nanmean((db >= lo) & (db < hi))
share_post = np.nanmean((post >= lo) & (post < hi))
print(f"{label:22} 20 Oct {share_pre:6.1%} 1 Nov {share_post:6.1%}")
very dark (< -20 dB) 20 Oct 6.2% 1 Nov 14.4%
dark (-20 to -15) 20 Oct 6.1% 1 Nov 11.8%
grey (-15 to -5) 20 Oct 75.0% 1 Nov 57.8%
bright (> -5 dB) 20 Oct 12.6% 1 Nov 16.1%
The very dark class — open water — grows between the two dates as the rice fields around the Albufera lagoon fill with water.
Why microwaves pass through cloud
Why microwaves pass through cloud
Cloud droplets are a few micrometres across. Visible light, at half a micrometre, is scattered strongly by them; a 5.55 cm microwave is thousands of times longer than the droplets and passes almost untouched. Heavy rain does attenuate and scatter C-band a little, but ordinary cloud cover is invisible to it.
Why radar looks sideways
A radar measures distance by timing echoes. Looking straight down, points either side of the track would return at the same time and be indistinguishable. Looking to one side makes range increase across the swath, so time of return maps to position on the ground. The same side-looking geometry is what causes layover and shadow in mountains.
Why "synthetic aperture"
Resolution along track would need an antenna kilometres long. Instead, the satellite records echoes over a stretch of its orbit and combines them as if they came from one long antenna — the synthetic aperture. That processing is done by the agency; users receive images at about 10 m pixel spacing.
Rain cells, wind on water and frozen ground
- Heavy rain cells can darken or brighten C-band slightly; they are rare in a scene.
- Wind roughens water, which then returns more and can look like land.
- Frozen ground changes backscatter sharply without any change in cover.
- Sentinel-1B failed in December 2021, so revisit fell to 12 days until Sentinel-1C began operations in 2025.
- L-band sensors such as ALOS-2 and NISAR penetrate vegetation further than C-band.
- Radar is not thermal. It measures reflected microwaves, not emitted heat.
Internal links
- SAR polarisation explained — what VV and VH each respond to
- Speckle explained — the grain in every radar image
- SAR geometry explained — layover, foreshortening and shadow
- How to read Sentinel-1 RTC data in Python — the reader used here
- How to map floods from Sentinel-1 in Python — the classic use
- Spectral bands explained — the optical side
FAQ
What is SAR imagery?
Images made by a side-looking radar that sends its own microwave pulses and records the backscatter, so it works day and night through cloud.
What do bright and dark mean in a SAR image?
Bright is rough, wet or facing the sensor, like buildings and some vegetation. Dark is smooth, like calm water and tarmac.
What units are Sentinel-1 values in?
Backscatter coefficients in linear power ratios; convert to decibels with 10·log₁₀ for display and thresholds.
Does SAR see through cloud?
Yes. C-band microwaves pass through cloud almost unaffected.
Why are SAR images grainy?
Speckle: interference between many scatterers within each pixel.