Background Optimization Tool Examples
Here I would like to show some examples of background subtraction done with the background optimizer tool presented here. The background extraction is usually more challenging on widefield and/or star-crowded images, so I tried to pick up some more or less illustrative examples of these among my own data.
All images used were in linear state when I applied the tool to them. Here they are shown after delinearization, just for visualization purposes. In this case, the delinearization is just a histogram stretch based on the automatic SFT (Screen Transfer Function) of PixInsight.
Widefield landscape image
This example image comes from a stack of a non-tracked series shot under a relatively dark sky, threatened by light pollution at the horizon. It was taken at mid summer and there were considerable amounts of aerosol in the atmosphere, scattering the intrusive light even more. The individual frames were co-registered on the stars before stacking, resulting in a blurry foreground. Another stack of the same images, this time not registered, will conform the foreground of the final composite image, published in astrobin.
Input image for the background optimizer tool. Non-tracked frames, registered on the sky and then stacked.
In this case, the foreground is darker than the sky, except for the candle-lit areas. To avoid contamination of the background model by these lights, and focus only on the sky, we will use a mask. In this case, the mask is produced by applying a simple threshold to a delinearized copy a of the image, and then cloning out the candle-lit areas.
Mask image produced by thresholding and cloning out the highlights on the foreground.
Now we run the background optimization tool using this command:
python bgoptimizer.py -dq 0.95 -N 64 -m integration_cielo_h_LinearFit_mask_v2.xisf \
-N 64 -i grid -e 2000 integration_cielo_h_LinearFit_v2.xisf
__/ Arguments \__________
input_file : integration_cielo_h_LinearFit_v2.xisf
output_path : .
compress : False
downscaling_factor : 8
downscaling_func : median
delinearization_quantile: 0.95
preview : False
N : 64
O : 2
mask : integration_cielo_h_LinearFit_mask_v2.xisf
initializer : grid
epochs : 2000
alpha : 5
B : 1
lr : 0.001
threshold : (0.001, 1.0)
__/ Environment \__________
python: 3.8.0
tensorflow: 2.5.1
tensorflow_addons: 0.13.0
keras: 2.5.0
numpy: 1.21.2
skimage: 0.18.3
__/ Preprocessing \__________
[Original ] Min / Median / Max = [0.0001 0.0000 0.0000] / [0.0019 0.0019 0.0020] /
[0.2641 0.3061 0.6665]
[Delinearized] Min / Median / Max = [0.0000 0.0000 0.0000] / [0.2500 0.2500 0.2500] /
[1.0000 1.0000 1.0000]
[Downscaled ] Min / Median / Max = [0.0057 0.0051 0.0042] / [0.2477 0.2473 0.2497] /
[1.0000 1.0000 1.0000]
__/ Background modeling \__________
Fitting spline...
Epoch 00100 - loss: -4.357345
Epoch 00200 - loss: -4.390939
Epoch 00300 - loss: -4.336159
Epoch 00400 - loss: -4.425040
Epoch 00500 - loss: -4.433916
Epoch 00600 - loss: -4.441309
Epoch 00700 - loss: -4.440144
Epoch 00749: ReduceLROnPlateau reducing learning rate to 0.0005000000237487257.
Epoch 00800 - loss: -4.451993
Epoch 00900 - loss: -4.454562
Epoch 01000 - loss: -4.457142
Epoch 01100 - loss: -4.459919
Epoch 01200 - loss: -4.462820
Epoch 01300 - loss: -4.465984
Epoch 01400 - loss: -4.469417
Epoch 01500 - loss: -4.472053
Epoch 01600 - loss: -4.474144
Epoch 01700 - loss: -4.476099
Epoch 01800 - loss: -4.478065
Epoch 01900 - loss: -4.478837
Epoch 02000 - loss: -4.481518
Done in 46.49 seconds
Min loss: -4.481696
Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or
[0..255] for integers).
Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or
[0..255] for integers).
__/ Full-size background model & subtracted image \__________
0..1..3..4..6..7..9..10..12..14..15..17..18..20..21..23..25..26..28..29..31..32..34..35..
37..39..40..42..43..45..46..48..50..51..53..54..56..57..59..60..62..64..65..67..68..70..
71..73..75..76..78..79..81..82..84..85..87..89..90..92..93..95..96..98..100%
Elapsed 1.21 seconds
[Bg (linear) ] Min / Median / Max = [0.0012 0.0013 0.0013] / [0.0024 0.0024 0.0024] /
[0.0036 0.0038 0.0036]
[Subtracted ] Min / Median / Max = [-0.0034 -0.0035 -0.0035] / [0.0000 0.0000 0.0000] /
[0.2620 0.3039 0.6643] (!)
__/ Saving output files \__________
Writing ...\integration_cielo_h_LinearFit_v2_bgSubtracted.xisf... done.
Writing ...\integration_cielo_h_LinearFit_v2_bgModel.xisf... done.
Resulting in these background model and background-subtracted images:
Background model produced by the optimizer tool.
Background-subtracted image. Note that we are only interested in the sky;
the foreground will be overlaid when compositing the final image.
In general, we would want to force an aggressive stretch (lower the --delinearization-quantile
or -dq
parameter) but without blowing any sky background. The number of epochs is not critical provided you check that the loss curve flattens at the right end, as a sign of diminishing returns. Also have in mind that if the loss value stops improving, the tool will stop optimizing anyway, without reaching the provided number of epochs. Here I used a grid initializer, but in general it's not critical.
Widefield deep sky image
These images comes from stacks of narrowband data captured under polluted skies. As you can see, some light pollution leaks the filters, especially the [O III]. The frames were captured with a camera lens at f/4, and although these filters are rated to be used even at f/2.8, the [O III] filter seems to suffer from severe transmission differences across the image area.
On these images, we will apply simple threshold-based mask to ignore the bright nebulae. The commands (and their complete input argument reports) are shown below. Note that we would expect no trace of the nebulae in the background models, as we intend to subtract the light pollution contribution only.
python bgoptimizer.py -c -dq 0.98 -tM 0.6 -e 2000 \
masterLight_BIN-1_3358x2536_EXPOSURE-300.00s_FILTER-Ha_Mono_drizzle2x.xisf
__/ Arguments \__________
input_file : masterLight_BIN-1_3358x2536_EXPOSURE-300.00s_FILTER-Ha_Mono_drizzle2x.xisf
output_path : .
compress : True
downscaling_factor : 8
downscaling_func : median
delinearization_quantile: 0.98
preview : False
N : 32
O : 2
mask : None
initializer : random
epochs : 2000
alpha : 5
B : 1
lr : 0.001
threshold : (0.001, 0.6)
[...]
Hα image, original
Hα background-subtracted
Hα background model
python bgoptimizer.py -c -dq 0.995 -tM 0.8 -e 2000 \
masterLight_BIN-1_3358x2536_EXPOSURE-300.00s_FILTER-O3G_Mono_drizzle2x.xisf
__/ Arguments \__________
input_file : masterLight_BIN-1_3358x2536_EXPOSURE-300.00s_FILTER-O3G_Mono_drizzle2x.xisf
output_path : .
compress : True
downscaling_factor : 8
downscaling_func : median
delinearization_quantile: 0.995
preview : False
N : 32
O : 2
mask : None
initializer : random
epochs : 2000
alpha : 5
B : 1
lr : 0.001
threshold : (0.001, 0.8)
[...]
[O III] image, original
[O III] background-subtracted
[O III] background model
python bgoptimizer.py -c -dq 0.98 -tM 0.6 -e 2000 \
masterLight_BIN-1_3358x2536_EXPOSURE-300.00s_FILTER-S2R_Mono_drizzle2x.xisf
__/ Arguments \__________
input_file : masterLight_BIN-1_3358x2536_EXPOSURE-300.00s_FILTER-S2R_Mono_drizzle2x.xisf
output_path : .
compress : True
downscaling_factor : 8
downscaling_func : median
delinearization_quantile: 0.98
preview : False
N : 32
O : 2
mask : None
initializer : random
epochs : 2000
alpha : 5
B : 1
lr : 0.001
threshold : (0.001, 0.6)
[...]
[S II] image, original
[S II] background-subtracted
[S II] background model