|
26 | 26 |
|
27 | 27 | from contextlib import contextmanager
|
28 | 28 | import numpy
|
| 29 | +from scipy.ndimage import median_filter |
29 | 30 |
|
30 | 31 | from lsstDebug import getDebugFrame
|
31 | 32 | from lsst.utils import suppress_deprecations
|
@@ -177,6 +178,16 @@ class SubtractBackgroundConfig(pexConfig.Config):
|
177 | 178 | dtype=bool,
|
178 | 179 | default=False,
|
179 | 180 | )
|
| 181 | + doFilterSuperPixels = pexConfig.Field( |
| 182 | + doc="Remove outliers from the binned image.", |
| 183 | + dtype=bool, |
| 184 | + default=False, |
| 185 | + ) |
| 186 | + superPixelFilterSize = pexConfig.Field( |
| 187 | + doc="Size of the median filter to use to remove outliers from the binned image.", |
| 188 | + dtype=int, |
| 189 | + default=3, |
| 190 | + ) |
180 | 191 |
|
181 | 192 |
|
182 | 193 | class SubtractBackgroundTask(pipeBase.Task):
|
@@ -224,6 +235,10 @@ def run(self, exposure, background=None, stats=True, statsKeys=None, backgroundT
|
224 | 235 | backgroundToPhotometricRatio=backgroundToPhotometricRatio,
|
225 | 236 | ):
|
226 | 237 | fitBg = self.fitBackground(maskedImage)
|
| 238 | + if self.config.doFilterSuperPixels: |
| 239 | + filterSuperPixels(maskedImage.getBBox(), fitBg, |
| 240 | + superPixelFilterSize=self.config.superPixelFilterSize) |
| 241 | + |
227 | 242 | maskedImage -= fitBg.getImageF(self.config.algorithm, self.config.undersampleStyle)
|
228 | 243 |
|
229 | 244 | actrl = fitBg.getBackgroundControl().getApproximateControl()
|
@@ -392,3 +407,20 @@ def fitBackground(self, maskedImage, nx=0, ny=0, algorithm=None):
|
392 | 407 | if bg is None:
|
393 | 408 | raise RuntimeError("lsst.afw.math.makeBackground failed to fit a background model")
|
394 | 409 | return bg
|
| 410 | + |
| 411 | + |
| 412 | +def filterSuperPixels(bbox, background, superPixelFilterSize=3): |
| 413 | + """Remove outliers from the binned background model. |
| 414 | +
|
| 415 | + Parameters |
| 416 | + ---------- |
| 417 | + bbox : `lsst.geom.Box2I` |
| 418 | + Bounding box of the original image. |
| 419 | + background : `lsst.afw.math.BackgroundMI` |
| 420 | + Fit and binned background image, which will be modified in place. |
| 421 | + superPixelFilterSize : `int`, optional |
| 422 | + Size of the median filter to use, in pixels. |
| 423 | + """ |
| 424 | + statsImg = background.getStatsImage() |
| 425 | + statsImg.image.array = median_filter(statsImg.image.array, mode='reflect', size=superPixelFilterSize) |
| 426 | + background = afwMath.BackgroundMI(bbox, statsImg) |
0 commit comments