def load_file(self, filespec, dstobj=None, **kwargs): info = iohelper.get_fileinfo(filespec) if not info.ondisk: raise ValueError("File does not appear to be on disk: %s" % (info.url)) filepath = info.filepath if dstobj is None: # Put here to avoid circular import from ginga.RGBImage import RGBImage dstobj = RGBImage(logger=self.logger) header = Header() metadata = {'header': header, 'path': filepath} data_np = self.imload(filepath, header) # TODO: set up the channel order correctly dstobj.set_data(data_np, metadata=metadata) if dstobj.name is not None: dstobj.set(name=dstobj.name) else: name = iohelper.name_image_from_path(filepath, idx=None) dstobj.set(name=name) dstobj.set(path=filepath, idx=None, image_loader=self.load_file) return dstobj
def load_idx(self, idx, **kwargs): if self.rgb_f is None: raise ValueError("Please call open_file() first!") self.rgb_f.seek(0) self.rgb_f.seek(idx) image = self.rgb_f kwds = {} try: self._get_header(image, kwds) except Exception as e: self.logger.warning("Failed to get image metadata: %s" % (str(e))) metadata = dict(header=kwds) # convert to working color profile, if can if self.clr_mgr.can_profile(): image = self.clr_mgr.profile_to_working_pil(image, kwds) # convert from PIL to numpy data_np = np.array(image) from ginga.RGBImage import RGBImage data_obj = RGBImage(data_np=data_np, logger=self.logger) data_obj.io = self name = self.fileinfo.name + '[{}]'.format(idx) data_obj.set(name=name, path=self.fileinfo.filepath, idx=idx, header=kwds) return data_obj
def load_idx(self, idx, **kwargs): if self.rgb_f is None: raise ValueError("Please call open_file() first!") if idx is None: idx = 0 self.rgb_f.set(cv2.CAP_PROP_POS_FRAMES, idx) okay, data_np = self.rgb_f.read() if not okay: raise ValueError("Error reading index {}".format(idx)) metadata = {} data_np = self._process_opencv_array(data_np, metadata, self.fileinfo.filepath) from ginga.RGBImage import RGBImage data_obj = RGBImage(data_np=data_np, logger=self.logger, order=metadata['order'], metadata=metadata) data_obj.io = self name = self.fileinfo.name + '[{}]'.format(idx) data_obj.set(name=name, path=self.fileinfo.filepath, idx=idx) return data_obj
def png_to_colormap(png_file): from ginga.RGBImage import RGBImage img = RGBImage() img.load_file(png_file) data = img.get_data() return rgbarr_to_colormap(data)
def load_file(self, filespec, dstobj=None, **kwargs): info = iohelper.get_fileinfo(filespec) if not info.ondisk: raise ValueError("File does not appear to be on disk: %s" % ( info.url)) filepath = info.filepath if dstobj is None: # Put here to avoid circular import from ginga.RGBImage import RGBImage dstobj = RGBImage(logger=self.logger) header = Header() metadata = {'header': header, 'path': filepath} data_np = self._imload(filepath, header) # TODO: set up the channel order correctly dstobj.set_data(data_np, metadata=metadata) if dstobj.name is not None: dstobj.set(name=dstobj.name) else: name = iohelper.name_image_from_path(filepath, idx=None) dstobj.set(name=name) dstobj.set(path=filepath, idx=None, image_loader=self.load_file) return dstobj
def snap_cb(self, w): format = self.tosave_type # snap image self.fv.error_wrap(self.fitsimage.save_rgb_image_as_file, self.tmpname, format=format) self.saved_type = format img = RGBImage(logger=self.logger) img.load_file(self.tmpname) self.scrnimage.set_image(img)
def masktorgb(mask, color='lightgreen', alpha=1.0): """Convert boolean mask to RGB image object for canvas overlay. Parameters ---------- mask : ndarray Boolean mask to overlay. 2D image only. color : str Color name accepted by Ginga. alpha : float Opacity. Unmasked data are always transparent. Returns ------- rgbobj : RGBImage RGB image for canvas Image object. Raises ------ ValueError Invalid mask dimension. """ mask = np.asarray(mask) if mask.ndim != 2: raise ValueError('ndim={0} is not supported'.format(mask.ndim)) ht, wd = mask.shape r, g, b = colors.lookup_color(color) rgbobj = RGBImage(data_np=np.zeros((ht, wd, 4), dtype=np.uint8)) rc = rgbobj.get_slice('R') gc = rgbobj.get_slice('G') bc = rgbobj.get_slice('B') ac = rgbobj.get_slice('A') ac[:] = 0 # Transparent background rc[mask] = int(r * 255) gc[mask] = int(g * 255) bc[mask] = int(b * 255) ac[mask] = int(alpha * 255) # For debugging #rgbobj.save_as_file('ztmp_rgbobj.png') return rgbobj
def masktorgb(mask, color='lightgreen', alpha=1.0): """Convert boolean mask to RGB image object for canvas overlay. Parameters ---------- mask : ndarray Boolean mask to overlay. 2D image only. color : str Color name accepted by Ginga. alpha : float Opacity. Unmasked data are always transparent. Returns ------- rgbobj : RGBImage RGB image for canvas Image object. Raises ------ ValueError Invalid mask dimension. """ mask = numpy.asarray(mask) if mask.ndim != 2: raise ValueError('ndim={0} is not supported'.format(mask.ndim)) ht, wd = mask.shape r, g, b = colors.lookup_color(color) rgbobj = RGBImage(data_np = numpy.zeros((ht, wd, 4), dtype=numpy.uint8)) rc = rgbobj.get_slice('R') gc = rgbobj.get_slice('G') bc = rgbobj.get_slice('B') ac = rgbobj.get_slice('A') ac[:] = 0 # Transparent background rc[mask] = int(r * 255) gc[mask] = int(g * 255) bc[mask] = int(b * 255) ac[mask] = int(alpha * 255) # For debugging #rgbobj.save_as_file('ztmp_rgbobj.png') return rgbobj
def load_idx(self, idx, **kwargs): if self.rgb_f is None: raise ValueError("Please call open_file() first!") # TODO: idx ignored for now for RGB images! #self.rgb_f.seek(0) #print(dir(self.rgb_f)) okay, data_np = self.rgb_f.read() if not okay: raise ValueError("Error reading index {}".format(idx)) # funky indexing because opencv returns BGR images, # whereas PIL and others return RGB if len(data_np.shape) >= 3 and data_np.shape[2] >= 3: data_np = data_np[..., ::-1] # OpenCv doesn't "do" image metadata, so we punt to piexif # library (if installed) kwds = {} self.piexif_getexif(self._path, kwds) # OpenCv added a feature to do auto-orientation when loading # (see https://github.com/opencv/opencv/issues/4344) # So reset these values to prevent auto-orientation from # happening later kwds['Orientation'] = 1 kwds['Image Orientation'] = 1 # convert to working color profile, if can if self.clr_mgr.can_profile(): data_np = self.clr_mgr.profile_to_working_numpy(data_np, kwds) from ginga.RGBImage import RGBImage data_obj = RGBImage(data_np=data_np, logger=self.logger) data_obj.io = self name = self.fileinfo.name + '[{}]'.format(idx) data_obj.set(name=name, path=self.fileinfo.filepath, idx=idx, header=kwds) return data_obj
def overlay_mask(self, maskImage, maskDict, maskAlpha): import numpy as np from ginga.RGBImage import RGBImage from ginga import colors maskArray = maskImage.getArray() height, width = maskArray.shape maskRGBA = np.zeros((height, width, 4), dtype=np.uint8) nSet = np.zeros_like(maskArray, dtype=np.uint8) for maskValue, maskColor in maskDict.items(): r, g, b = colors.lookup_color(maskColor) isSet = (maskArray & maskValue) != 0 if (isSet == 0).all(): continue maskRGBA[:, :, 0][isSet] = 255 * r maskRGBA[:, :, 1][isSet] = 255 * g maskRGBA[:, :, 2][isSet] = 255 * b nSet[isSet] += 1 maskRGBA[:, :, 3][nSet == 0] = 0 maskRGBA[:, :, 3][nSet != 0] = 255 * maskAlpha nSet[nSet == 0] = 1 for C in (0, 1, 2): maskRGBA[:, :, C] //= nSet rgb_img = RGBImage(data_np=maskRGBA) Image = self._viewer.canvas.get_draw_class('image') maskImageRGBA = Image(0, 0, rgb_img) if "mask_overlay" in self._gingaViewer.canvas.get_tags(): self._gingaViewer.canvas.delete_object_by_tag("mask_overlay") self._gingaViewer.canvas.add(maskImageRGBA, tag="mask_overlay")
def _snap_cb(self, w): """This function is called when the user clicks the 'Snap' button. """ # Clear the snap image viewer self.scrnimage.clear() self.scrnimage.redraw_now(whence=0) self.fv.update_pending() format = self.tosave_type if self._screen_size: # snap image using actual viewer self.fv.error_wrap(self.fitsimage.save_rgb_image_as_file, self.tmpname, format=format) else: # we will be using shot generator, not actual viewer. # check that shot generator size matches UI params self.check_and_adjust_dimensions() # copy background color of viewer to shot generator bg = self.fitsimage.get_bg() self.shot_generator.set_bg(*bg) # add the main canvas from channel viewer to shot generator c1 = self.fitsimage.get_canvas() c2 = self.shot_generator.get_canvas() c2.delete_all_objects(redraw=False) c2.add(c1, redraw=False) # hack to fix a few problem graphics self.shot_generator._imgobj = self.fitsimage._imgobj # scale of the shot generator should be the scale of channel # viewer multiplied by the ratio of window sizes scale_x, scale_y = self.fitsimage.get_scale_xy() c1_wd, c1_ht = self.fitsimage.get_window_size() c2_wd, c2_ht = self.shot_generator.get_window_size() scale_wd = float(c2_wd) / float(c1_wd) scale_ht = float(c2_ht) / float(c1_ht) scale = max(scale_wd, scale_ht) scale_x *= scale scale_y *= scale self.shot_generator.scale_to(scale_x, scale_y) self.fitsimage.copy_attributes(self.shot_generator, self.transfer_attrs) # snap image self.fv.error_wrap(self.shot_generator.save_rgb_image_as_file, self.tmpname, format=format) c2.delete_all_objects(redraw=False) self.shot_generator._imgobj = None self.saved_type = format img = RGBImage(logger=self.logger) img.load_file(self.tmpname) # load the snapped image into the screenshot viewer self.scrnimage.set_image(img)
def _mtv(self, image, mask=None, wcs=None, title=""): """Display an Image and/or Mask on a ginga display""" self._erase() self._canvas.delete_all_objects() if image: # We'd call # self._viewer.load_data(image.getArray()) # except that we want to include the wcs # # Still need to handle the title # from ginga import AstroImage astroImage = AstroImage.AstroImage(logger=self._viewer.logger, data_np=image.getArray()) if wcs is not None: astroImage.set_wcs(WcsAdaptorForGinga(wcs)) self._viewer.set_image(astroImage) if mask: import numpy as np from matplotlib.colors import colorConverter from ginga.RGBImage import RGBImage # 8 bpp RGB[A] images # create a 3-channel RGB image + alpha maskRGB = np.zeros((mask.getHeight(), mask.getWidth(), 4), dtype=np.uint8) maska = mask.getArray() nSet = np.zeros_like(maska, dtype='uint8') R, G, B, A = 0, 1, 2, 3 # names for colours and alpha plane colorGenerator = self.display.maskColorGenerator(omitBW=True) for maskPlaneName, maskPlaneNum in mask.getMaskPlaneDict().items(): isSet = maska & (1 << maskPlaneNum) != 0 if (isSet == 0).all(): # no bits set; nowt to do continue color = self.display.getMaskPlaneColor(maskPlaneName) if not color: # none was specified color = next(colorGenerator) elif color.lower() == "ignore": continue r, g, b = colorConverter.to_rgb(color) maskRGB[:, :, R][isSet] = 255 * r maskRGB[:, :, G][isSet] = 255 * g maskRGB[:, :, B][isSet] = 255 * b nSet[isSet] += 1 alpha = self.display.getMaskTransparency( ) # Bug! Fails to return a value if alpha is None: alpha = self._getMaskTransparency() maskRGB[:, :, A] = 255 * (1 - alpha) maskRGB[:, :, A][nSet == 0] = 0 nSet[nSet == 0] = 1 # avoid division by 0 for C in (R, G, B): maskRGB[:, :, C] //= nSet rgb_img = RGBImage(data_np=maskRGB) Image = self._canvas.get_draw_class( 'image') # the appropriate class maskImageRGBA = Image(0, 0, rgb_img) self._canvas.add(maskImageRGBA)