24 from deprecated.sphinx
import deprecated
28 from .rgb
import replaceSaturatedPixels, getZScale
32 """Return a naive total intensity from the red, blue, and green intensities 36 imageR : `lsst.afw.image.MaskedImage`, `lsst.afw.image.Image`, or `numpy.ndarray`, (Nx, Ny) 37 intensity of image that'll be mapped to red; or intensity if imageG and imageB are None 38 imageG : `lsst.afw.image.MaskedImage`, `lsst.afw.image.Image`, or `numpy.ndarray`, (Nx, Ny) 39 intensity of image that'll be mapped to green; or None 40 imageB : `lsst.afw.image.MaskedImage`, `lsst.afw.image.Image`, or `numpy.ndarray`, (Nx, Ny) 41 intensity of image that'll be mapped to blue; or None 45 image : type of ``imageR``, ``imageG``, and `imageB`` 47 if imageG
is None or imageB
is None:
48 assert imageG
is None and imageB
is None, \
49 "Please specify either a single image or red, green, and blue images" 52 imageRGB = [imageR, imageG, imageB]
54 for i, c
in enumerate(imageRGB):
55 if hasattr(c,
"getImage"):
56 c = imageRGB[i] = c.getImage()
57 if hasattr(c,
"getArray"):
58 imageRGB[i] = c.getArray()
60 intensity = (imageRGB[0] + imageRGB[1] + imageRGB[2])/float(3)
64 Image = afwImage.ImageU
if intensity.dtype ==
'uint16' else afwImage.ImageF
66 if hasattr(imageR,
"getImage"):
68 elif hasattr(imageR,
"getArray"):
69 intensity = Image(intensity)
75 """Base class to map red, blue, green intensities into uint8 values 79 minimum : `float` or sequence of `float` 80 Intensity that should be mapped to black. If an array, has three 83 The image to be used to calculate the mapping. 84 If provided, also the default for makeRgbImage() 88 self.
_uint8Max = float(np.iinfo(np.uint8).max)
94 assert len(minimum) == 3,
"Please provide 1 or 3 values for minimum" 99 def makeRgbImage(self, imageR=None, imageG=None, imageB=None,
100 xSize=None, ySize=None, rescaleFactor=None):
101 """Convert 3 arrays, imageR, imageG, and imageB into a numpy RGB image 103 imageR : `lsst.afw.image.Image` or `numpy.ndarray`, (Nx, Ny) 104 Image to map to red (if `None`, use the image passed to the ctor) 105 imageG : `lsst.afw.image.Image` or `numpy.ndarray`, (Nx, Ny), optional 106 Image to map to green (if `None`, use imageR) 107 imageB : `lsst.afw.image.Image` or `numpy.ndarray`, (Nx, Ny), optional 108 Image to map to blue (if `None`, use imageR) 109 xSize : `int`, optional 110 Desired width of RGB image. If ``ySize`` is `None`, preserve aspect ratio 111 ySize : `int`, optional 112 Desired height of RGB image 113 rescaleFactor : `float`, optional 114 Make size of output image ``rescaleFactor*size`` of the input image 119 "You must provide an image (or pass one to the constructor)")
127 imageRGB = [imageR, imageG, imageB]
128 for i, c
in enumerate(imageRGB):
129 if hasattr(c,
"getImage"):
130 c = imageRGB[i] = c.getImage()
131 if hasattr(c,
"getArray"):
132 imageRGB[i] = c.getArray()
134 if xSize
is not None or ySize
is not None:
135 assert rescaleFactor
is None,
"You may not specify a size and rescaleFactor" 136 h, w = imageRGB[0].shape
138 ySize = int(xSize*h/float(w) + 0.5)
140 xSize = int(ySize*w/float(h) + 0.5)
142 size = (ySize, xSize)
143 elif rescaleFactor
is not None:
144 size = float(rescaleFactor)
151 except ImportError
as e:
153 "Unable to rescale as scipy.misc is unavailable: %s" % e)
155 for i, im
in enumerate(imageRGB):
156 imageRGB[i] = scipy.misc.imresize(
157 im, size, interp=
'bilinear', mode=
'F')
162 """Return the total intensity from the red, blue, and green intensities 166 This is a naive computation, and may be overridden by subclasses 171 """Map an intensity into the range of a uint8, [0, 255] (but not converted to uint8) 173 with np.errstate(invalid=
'ignore', divide=
'ignore'):
174 return np.where(intensity <= 0, 0,
177 def _convertImagesToUint8(self, imageR, imageG, imageB):
178 """Use the mapping to convert images imageR, imageG, and imageB to a triplet of uint8 images 180 imageR = imageR - self.
minimum[0]
181 imageG = imageG - self.
minimum[1]
182 imageB = imageB - self.
minimum[2]
186 imageRGB = [imageR, imageG, imageB]
187 with np.errstate(invalid=
"ignore"):
195 r0, g0, b0 = imageRGB
198 with np.errstate(invalid=
'ignore', divide=
'ignore'):
199 for i, c
in enumerate(imageRGB):
200 c = np.where(r0 > g0,
202 np.where(r0 >= pixmax, c*pixmax/r0, c),
203 np.where(b0 >= pixmax, c*pixmax/b0, c)),
205 np.where(g0 >= pixmax, c*pixmax/g0, c),
206 np.where(b0 >= pixmax, c*pixmax/b0, c))).astype(np.uint8)
207 c[c > pixmax] = pixmax
215 """A linear map of red, blue, green intensities into uint8 values 219 minimum : `float` or sequence of `float` 220 Intensity that should be mapped to black. If an array, has three 221 elements for R, G, B. 223 Intensity that should be mapped to white 225 Image to estimate minimum/maximum if not explicitly set 228 def __init__(self, minimum=None, maximum=None, image=None):
229 if minimum
is None or maximum
is None:
230 assert image
is not None,
"You must provide an image if you don't set both minimum and maximum" 234 minimum = stats.getValue(afwMath.MIN)
236 maximum = stats.getValue(afwMath.MAX)
238 Mapping.__init__(self, minimum, image)
244 assert maximum - minimum != 0,
"minimum and maximum values must not be equal" 245 self.
_range = float(maximum - minimum)
248 """Return an array which, when multiplied by an image, returns that 249 image mapped to the range of a uint8, [0, 255] (but not converted to uint8) 251 The intensity is assumed to have had ``minimum`` subtracted (as that 252 can be done per-band) 254 with np.errstate(invalid=
'ignore', divide=
'ignore'):
255 return np.where(intensity <= 0, 0,
256 np.where(intensity >= self.
_range,
261 """A mapping for a linear stretch chosen by the zscale algorithm 262 (preserving colours independent of brightness) 264 x = (I - minimum)/range 269 Image whose parameters are desired 271 The number of samples to use to estimate the zscale parameters 275 def __init__(self, image, nSamples=1000, contrast=0.25):
276 if not hasattr(image,
"getArray"):
277 image = afwImage.ImageF(image)
278 z1, z2 =
getZScale(image, nSamples, contrast)
280 LinearMapping.__init__(self, z1, z2, image)
284 """A mapping for an asinh stretch (preserving colours independent of brightness) 286 x = asinh(Q (I - minimum)/range)/Q 290 This reduces to a linear stretch if Q == 0 292 See http://adsabs.harvard.edu/abs/2004PASP..116..133L 296 Mapping.__init__(self, minimum)
313 self.
_soften = Q/float(dataRange)
316 """Return an array which, when multiplied by an image, returns that image mapped to the range of a 317 uint8, [0, 255] (but not converted to uint8) 319 The intensity is assumed to have had minimum subtracted (as that can be done per-band) 321 with np.errstate(invalid=
'ignore', divide=
'ignore'):
322 return np.where(intensity <= 0, 0, np.arcsinh(intensity*self.
_soften)*self.
_slope/intensity)
326 """A mapping for an asinh stretch, estimating the linear stretch by zscale 328 x = asinh(Q (I - z1)/(z2 - z1))/Q 333 The image to analyse, or a list of 3 images to be converted to an intensity image 335 The asinh softening parameter 336 pedestal : `float` or sequence of `float`, optional 337 The value, or array of 3 values, to subtract from the images 339 N.b. pedestal, if not None, is removed from the images when calculating the zscale 340 stretch, and added back into Mapping.minimum[] 349 assert len(image)
in (1, 3,),
"Please provide 1 or 3 images" 353 if pedestal
is not None:
355 assert len(pedestal)
in (
356 1, 3,),
"Please provide 1 or 3 pedestals" 358 pedestal = 3*[pedestal]
361 for i, im
in enumerate(image):
362 if pedestal[i] != 0.0:
363 if hasattr(im,
"getImage"):
365 if hasattr(im,
"getArray"):
368 image[i] = im - pedestal[i]
370 pedestal = len(image)*[0.0]
376 dataRange = zscale.maximum - zscale.minimum[0]
377 minimum = zscale.minimum
379 for i, level
in enumerate(pedestal):
382 AsinhMapping.__init__(self, minimum, dataRange, Q)
386 def makeRGB(imageR, imageG=None, imageB=None, minimum=0, dataRange=5, Q=8, fileName=None,
387 saturatedBorderWidth=0, saturatedPixelValue=None,
388 xSize=None, ySize=None, rescaleFactor=None):
389 """Make a set of three images into an RGB image using an asinh stretch and 390 optionally write it to disk 397 minimum : `float` or sequence of `float` 401 The output file. The suffix defines the format, and must be supported by matplotlib 403 If saturatedBorderWidth is non-zero, replace saturated pixels with 404 ``saturatedPixelValue``. Note that replacing saturated pixels requires 405 that the input images be `lsst.afw.image.MaskedImage`. 416 if saturatedBorderWidth:
417 if saturatedPixelValue
is None:
419 "saturatedPixelValue must be set if saturatedBorderWidth is set")
421 saturatedBorderWidth, saturatedPixelValue)
424 rgb = asinhMap.makeRgbImage(imageR, imageG, imageB,
425 xSize=xSize, ySize=ySize, rescaleFactor=rescaleFactor)
434 """Display an rgb image using matplotlib 439 The RGB image in question 441 If `True`, call `matplotlib.pyplot.show()` 443 import matplotlib.pyplot
as plt
444 plt.imshow(rgb, interpolation=
'nearest', origin=
"lower")
451 """Write an RGB image to disk 456 The output file. The suffix defines the format, and must be supported by matplotlib 458 Most versions of matplotlib support png and pdf (although the eps/pdf/svg writers may be buggy, 459 possibly due an interaction with useTeX=True in the matplotlib settings). 461 If your matplotlib bundles pil/pillow you should also be able to write jpeg and tiff files. 463 The image, as made by e.g. makeRGB 465 import matplotlib.image
466 matplotlib.image.imsave(fileName, rgbImage)
473 @deprecated(reason=
"Use `AsinhMapping` instead. To be removed after 20.0.0.",
474 category=FutureWarning)
476 """Deprecated object used to support legacy API 486 """Deprecated object used to support legacy API 489 def __init__(self, imageR, imageG, imageB, mapping):
490 asinh =
AsinhMapping(mapping.minimum, mapping.dataRange, mapping.Q)
491 self.
rgb = asinh.makeRgbImage(imageR, imageG, imageB)
498 reason=
"Use `Mapping.makeRgbImage` instead. To be removed after 20.0.0.",
499 category=FutureWarning)
501 """Deprecated legacy API 503 return _RgbImageF(imageR, imageG, imageB, mapping)
Angle abs(Angle const &a)
std::pair< double, double > getZScale(image::Image< T > const &image, int const nSamples=1000, double const contrast=0.25)
Calculate an IRAF/ds9-style zscaling.
def __init__(self, imageR, imageG, imageB, mapping)
def mapIntensityToUint8(self, intensity)
def displayRGB(rgb, show=True)
def __init__(self, minimum, dataRange, Q)
def makeRGB(imageR, imageG=None, imageB=None, minimum=0, dataRange=5, Q=8, fileName=None, saturatedBorderWidth=0, saturatedPixelValue=None, xSize=None, ySize=None, rescaleFactor=None)
def __init__(self, minimum=None, image=None)
def makeRgbImage(self, imageR=None, imageG=None, imageB=None, xSize=None, ySize=None, rescaleFactor=None)
def RgbImageF(imageR, imageG, imageB, mapping)
def _convertImagesToUint8(self, imageR, imageG, imageB)
void replaceSaturatedPixels(ImageT &rim, ImageT &gim, ImageT &bim, int borderWidth=2, float saturatedPixelValue=65535)
MaskedImage< ImagePixelT, MaskPixelT, VariancePixelT > * makeMaskedImage(typename std::shared_ptr< Image< ImagePixelT >> image, typename std::shared_ptr< Mask< MaskPixelT >> mask=Mask< MaskPixelT >(), typename std::shared_ptr< Image< VariancePixelT >> variance=Image< VariancePixelT >())
A function to return a MaskedImage of the correct type (cf.
Statistics makeStatistics(lsst::afw::math::MaskedVector< EntryT > const &mv, std::vector< WeightPixel > const &vweights, int const flags, StatisticsControl const &sctrl=StatisticsControl())
The makeStatistics() overload to handle lsst::afw::math::MaskedVector<>
def mapIntensityToUint8(self, intensity)
def writeRGB(fileName, rgbImage)
def __init__(self, minimum, dataRange, Q=8)
def mapIntensityToUint8(self, intensity)
def write(self, fileName)
def intensity(self, imageR, imageG, imageB)
def __init__(self, image, Q=8, pedestal=None)
def __init__(self, image, nSamples=1000, contrast=0.25)
Backwards-compatibility support for depersisting the old Calib (FluxMag0/FluxMag0Err) objects...
def computeIntensity(imageR, imageG=None, imageB=None)
daf::base::PropertyList * list
def __init__(self, minimum=None, maximum=None, image=None)