Background Neutralization
Equalize the per-channel background so the sky is neutral grey,
using the medians inside a sample box. Shadows are lifted onto a common
background level while bright highlights (stars, bright nebulosity) are left
untouched — so colour balance in the signal survives.
1. Using the tool
Pick a patch of empty sky — manually or automatically — and click
Apply Neutralization. SASpro computes the per-channel medians inside the
box, picks the mean as the common target, and rebalances the channels so the
background reaches it.
Choosing the sample box
- Draw a box — left-click-drag on the preview; a green dashed
rectangle follows the mouse, and release leaves a solid red box. The
selection must be at least 10×10 px.
- Find Background — auto-selects a 50×50 px patch of
the darkest usable sky (§2.2) and marks its centre with a gold
crosshair that stays the same size as you zoom.
- Pick a region that's pure sky — no nebulosity, no stars, no
gradient hot spot. The further off the sample is, the more it'll push
colour balance.
Preview & apply
- Enable Auto-Stretch toggles a non-destructive preview stretch so you
can see faint background structure while picking a patch; the data processed
on Apply is always the linear source.
- Zoom In / Out / Fit to View navigate the preview; the wheel also
zooms (anchored under the cursor). While the user hasn't manually zoomed,
resizes refit automatically.
- Apply Neutralization commits a “Background Neutralization”
step (and records the sample box so the operation is replayable);
Cancel closes without changes. The dialog follows the active image
window, so clicking a different view loads it in place.
- Grip (bottom-left) drags to the canvas to mint a shortcut —
with a box, as a
rect preset; without one, as auto
so each drop re-finds its own patch.
2. Technical details
RGB only. The sample box fixes a per-channel baseline; the
rebalance pins highlights at 1.0 so bright signal doesn't drift.
2.1 The neutralization
Optionally, a per-channel pedestal is removed from the whole image first
— each channel's minimum is subtracted so the darkest pixel per channel sits
at zero:
I_c\;\to\;I_c-\min(I_c)\quad(\mathrm{per\ channel,\ whole\ image})
Then the per-channel medians inside the sample box, and the common grey target
as their mean, are computed:
m_c=\mathrm{median}\!\left(I_{\mathrm{sample}}[\cdot,c]\right)\,,\qquad t=\frac{1}{3}\!\left(m_R+m_G+m_B\right)
The default rebalance is a per-channel gain pivoted around 1.0, which
keeps bright pixels fixed and only lifts the shadows:
g_c=\frac{1-t}{1-m_c}\,,\qquad \mathrm{out}_c=1-(1-I_c)\,g_c
By construction this maps I_c = m_c → t (every channel's
background lands on the shared grey) and I_c = 1 → 1 (pure white
is left alone), so star cores and highlights don't drift colour:
\mathrm{at}\ I_c=1:\ \mathrm{out}_c=1\,;\qquad \mathrm{at}\ I_c=m_c:\ \mathrm{out}_c=t
An alternative offset mode adds a flat per-channel shift sized to not
clip:
\mathrm{out}_c=I_c+(t-m_c)\quad(\mathrm{capped\ to\ avoid\ clipping})
Offset is simplest and leaves relative colours untouched, but can't
protect highlights the way the pivot-at-1 gain does — which is why the
pivot form is the default.
2.2 The automatic background finder
With no box drawn, Find Background locates a dark patch of sky in three
stages:
- Split the luminance plane into a 10×10 grid and keep the two tiles
with the lowest median.
- Inside each dark tile, drop ~200 random seeds and walk each one downhill
through its 8-neighbourhood until it reaches a local minimum — so the
final points cluster on the dimmest sky, not on arbitrary pixels.
- Score the candidates by the median of a 50×50 window around each, then
refine with a small step grid, keeping the box at least ~100 px from
every edge.
The result is a 50×50 background patch; the preview marks its centre with
a crosshair rather than a filled rectangle, so you can see exactly which point
drives the medians.
2.3 Masking
With an active mask on the destination document, the neutralized image is
blended back against the original over the mask, so only masked regions change
(out = src·(1−m) + out·m).
2.4 Notes
- The algorithm requires an RGB image; mono doesn't have a colour balance to
neutralize.
- Headless and grip-dropped runs follow the same preset schema:
mode:
"rect" with normalised rect_norm = [x, y, w, h] in
[0,1], or mode: "auto" to re-find a patch on each run.