Stage 00
The frame as downlinked
Twelve-bit digital numbers, displayed across their true range. The column
striping is the sensor's own: each image column reads through its own
amplifier chain, and the offsets differ. The mottling is photon shot noise
plus 28 e− of read noise. Somewhere under it is a crater floor.
Stage 01
Radiometric correction
Bias and dark current are added to every pixel whether or not a photon
arrived, so they come off first. The offset is estimated from the mode of
the frame's own low tail rather than a calibration table, which keeps the
method usable on data whose ancillary files you do not have.
Why first: every later estimator assumes zero-mean noise about a physical signal.
Stage 02
Column fixed-pattern removal
The stripes are constant down each column; real terrain is not. Taking the
column-wise median of the residual against a horizontally smoothed copy
isolates the electronic offset and leaves vertical geology intact. Watch the
vertical banding leave without the ridges going with it.
Why here: striping is structured noise. A denoiser tuned for white noise treats it as signal and preserves it.
Stage 03
Edge-preserving denoise
A guided filter fits a local linear model of the image against itself. Where
the local variance is pure noise the model collapses to the local mean; where
it is a crater rim, the edge passes through untouched. Linear time in pixel
count, and no gradient reversal at the boulder edges this whole exercise
exists to protect.
Why before deblurring: Richardson–Lucy amplifies whatever noise you hand it, without bound.
Stage 04
Illumination correction
Inside a PSR the light comes from whatever patch of sunlit wall a spot can
see, so irradiance falls by more than a decade across one frame. Multi-scale
retinex divides out the illumination field at three scales at once and leaves
reflectance — the property of the rock rather than of the geometry.
This is the step that makes a single global stretch work at all.
Stage 05
Deconvolution
The blur is not anyone's mistake. It is the optical point spread function
convolved with 2.4 pixels of along-track smear, because a TDI line rate never
exactly matches ground speed. Richardson–Lucy is the maximum-likelihood
inverse for Poisson data — which is what a photon-starved frame is — and it
cannot return negative radiance, so rims sharpen instead of ringing into
ghost pairs.
Iterations are capped at 24. Past that it stops recovering structure and starts inventing it.
Stage 06
Local contrast, clipped
CLAHE equalises tile by tile so a bright patch of wall-lit floor cannot crush
the shadowed half of the frame. The clip limit caps the transfer slope, which
is the honesty parameter of the entire pipeline: without it, a tile of flat
noise gets stretched into convincing texture.
Clip limit 2.6. Raise it and the picture gets prettier and less true.
Stage 07
The trained network
Everything above is the deterministic chain — operators anyone can audit,
each one doing a thing you can name. This stage is PSR-Net: 714 000
parameters trained on synthetic frames whose sensor was re-randomised on
every single sample, so it never saw the same noise, blur, gain or column
pattern twice.
Running here, in your browser, on the same array the chain got.
—
On 24 held-out scenes it scores 20.28 dB against the chain's
17.47. Held out means scenes and noise seeds it never trained on —
but from the same generator, so it proves the network inverts this
calibrated degradation better than a fixed operator chain, not that it
works on real OHRC frames.
Stage 08
Detection, with a hallucination test
Laplacian-of-Gaussian blobs across a scale octave, scored on the
block-and-shadow pair rather than on brightness — a noise spike has no
shadow. Then the part that matters: every candidate is re-tested against
independent noise realisations of the same scene. Real blocks survive
resampling because they are in the signal. Hallucinations do not.
— detections retained, — rejected as unstable.
Ring size is scale; opacity is confidence.
Stage 09 · Result
Against the target
The right-hand half is the paired target: the same scene under the same
light, rendered with a noiseless, smear-free sensor. Nothing in the pipeline
has ever seen it. It exists so the numbers underneath the viewport can be
measured rather than asserted.
Drag the divider, or focus the frame and use the arrow keys.