def test_simple(self): cyxim = numpy.zeros((3, 512, 256), dtype=numpy.uint8) cyxim = model.DataArray(cyxim) orig_shape = cyxim.shape orig_md = cyxim.metadata.copy() for i in range(3): cyxim[i] = i yxcim = img.ensureYXC(cyxim) self.assertEqual(yxcim.shape, (512, 256, 3)) self.assertEqual(yxcim.metadata[model.MD_DIMS], "YXC") # check original da was not changed self.assertEqual(cyxim.shape, orig_shape) self.assertDictEqual(orig_md, cyxim.metadata) # try again with explicit metadata cyxim.metadata[model.MD_DIMS] = "CYX" orig_md = cyxim.metadata.copy() yxcim = img.ensureYXC(cyxim) self.assertEqual(yxcim.shape, (512, 256, 3)) self.assertEqual(yxcim.metadata[model.MD_DIMS], "YXC") # check no metadata was changed self.assertDictEqual(orig_md, cyxim.metadata) for i in range(3): self.assertEqual(yxcim[0, 0, i], i)
def _updateImage(self): """ Recomputes the image with all the raw data available """ # logging.debug("Updating image") if not self.raw: return try: if not isinstance(self.raw, list): raise AttributeError(".raw must be a list of DA/DAS") data = self.raw[0] bkg = self.background.value if bkg is not None: try: data = img.Subtract(data, bkg) except Exception as ex: logging.info("Failed to subtract background data: %s", ex) dims = data.metadata.get(model.MD_DIMS, "CTZYX"[-data.ndim::]) ci = dims.find("C") # -1 if not found # is RGB if dims in ("CYX", "YXC") and data.shape[ci] in (3, 4): rgbim = img.ensureYXC(data) rgbim.flags.writeable = False # merge and ensures all the needed metadata is there rgbim.metadata = self._find_metadata(rgbim.metadata) rgbim.metadata[model.MD_DIMS] = "YXC" # RGB format self.image.value = rgbim else: # is grayscale if data.ndim != 2: data = img.ensure2DImage(data) # Remove extra dimensions (of length 1) self.image.value = self._projectXY2RGB(data, self.tint.value) except Exception: logging.exception("Updating %s %s image", self.__class__.__name__, self.name.value)
def new_image(self, data): """ Update the window with the new image (the window is resize to have the image at ratio 1:1) data (numpy.ndarray): an 2D array containing the image (can be 3D if in RGB) """ if data.ndim == 3 and 3 in data.shape: # RGB rgb = img.ensureYXC(data) elif numpy.prod(data.shape) == data.shape[-1]: # 1D image => bar plot # TODO: add "(plot)" to the window title # Create a simple bar plot of X x 400 px lenx = data.shape[-1] leny = 400 maxy = data.max() logging.info("Plot data max = %s", maxy) rgb = numpy.zeros((leny, lenx, 3), dtype=numpy.uint8) for i, v in numpy.ndenumerate(data): h = leny - int((v * leny) / maxy) rgb[h:-1, i[-1], :] = 255 else: # Greyscale (hopefully) mn, mx, mnp, mxp = ndimage.extrema(data) logging.info("Image data from %s to %s", mn, mx) rgb = img.DataArray2RGB(data) # auto brightness/contrast self.app.img = NDImage2wxImage(rgb) wx.CallAfter(self.app.update_view)
def test_no_change(self): yxcim = numpy.zeros((512, 256, 3), dtype=numpy.uint8) yxcim = model.DataArray(yxcim) yxcim.metadata[model.MD_DIMS] = "YXC" newim = img.ensureYXC(yxcim) self.assertEqual(newim.shape, (512, 256, 3)) self.assertEqual(newim.metadata[model.MD_DIMS], "YXC")
def test_find_lens_center(self): """ Test FindRingCenter for lenses """ data = hdf5.read_data(os.path.join(TEST_IMAGE_PATH, "navcam-calib2.h5")) imgs = img.RGB2Greyscale(img.ensureYXC(data[0])) # lens_coordinates = delphi.FindCircleCenter(data[0][0], delphi.LENS_RADIUS, 5) # expected_coordinates = (-5.9703947e-05, 1.5257675e-04) # (451.5, 445.5) px lens_coordinates = delphi.FindRingCenter(imgs) expected_coordinates = (-1.6584835e-05, 1.3084411e-04) # 454.75, 446.1) px numpy.testing.assert_almost_equal(lens_coordinates, expected_coordinates)
def test_find_lens_center(self): """ Test FindRingCenter for lenses """ data = hdf5.read_data(os.path.join(TEST_IMAGE_PATH, "navcam-calib2.h5")) imgs = img.RGB2Greyscale(img.ensureYXC(data[0])) # lens_coordinates = delphi.FindCircleCenter(data[0][0], delphi.LENS_RADIUS, 5) # expected_coordinates = (-5.9703947e-05, 1.5257675e-04) # (451.5, 445.5) px lens_coordinates = delphi.FindRingCenter(imgs) expected_coordinates = (-1.6584835e-05, 1.3084411e-04 ) # 454.75, 446.1) px numpy.testing.assert_almost_equal(lens_coordinates, expected_coordinates)
def new_image(self, data): """ Update the window with the new image (the window is resize to have the image at ratio 1:1) data (numpy.ndarray): an 2D array containing the image (can be 3D if in RGB) """ if data.ndim == 3 and 3 in data.shape: # RGB rgb = img.ensureYXC(data) else: # Greyscale (hopefully) mn, mx, mnp, mxp = ndimage.extrema(data) logging.info("Image data from %s to %s", mn, mx) rgb = img.DataArray2RGB(data) # auto brightness/contrast self.app.img = NDImage2wxImage(rgb) wx.CallAfter(self.app.update_view)
def _updateImage(self): # Just pass the RGB data on if not self.raw: return try: data = self.raw[0] rgbim = img.ensureYXC(data) rgbim.flags.writeable = False # merge and ensures all the needed metadata is there rgbim.metadata = self._find_metadata(rgbim.metadata) rgbim.metadata[model.MD_DIMS] = "YXC" # RGB format self.image.value = rgbim except Exception: logging.exception("Updating %s image", self.__class__.__name__)
def _ensureGrayscale(self, data): ''' Ensures that the image is grayscale. If the image is an grayscale RGB, convert it to an 8bit grayscale image. data (DataArray or DataArrayShadow): The input image return (DataArray): The result 8bit grayscale image raises: ValueError if the image is RGB with different color channels ''' if len(data.shape) > 3: raise ValueError("Image format not supported") elif len(data.shape) == 3: if isinstance(data, model.DataArrayShadow): data = data.getData() data = img.ensureYXC(data) if (numpy.all(data[:, :, 0] == data[:, :, 1]) and numpy.all(data[:, :, 0] == data[:, :, 2])): data = data[:, :, 0] else: raise ValueError("Coloured RGB image not supported") return data
def _projectTile(self, tile): """ Project the tile tile (DataArray): Raw tile return (DataArray): Projected tile """ dims = tile.metadata.get(model.MD_DIMS, "CTZYX"[-tile.ndim::]) ci = dims.find("C") # -1 if not found # is RGB if dims in ("CYX", "YXC") and tile.shape[ci] in (3, 4): # Just pass the RGB data on tile = img.ensureYXC(tile) tile.flags.writeable = False # merge and ensures all the needed metadata is there tile.metadata = self.stream._find_metadata(tile.metadata) tile.metadata[model.MD_DIMS] = "YXC" # RGB format return tile else: if tile.ndim != 2: tile = img.ensure2DImage( tile) # Remove extra dimensions (of length 1) return self._projectXY2RGB(tile, self.stream.tint.value)
def new_image(self, data): """ Update the window with the new image (the window is resize to have the image at ratio 1:1) data (numpy.ndarray): an 2D array containing the image (can be 3D if in RGB) """ if data.ndim == 3 and 3 in data.shape: # RGB rgb = img.ensureYXC(data) elif numpy.prod(data.shape) == data.shape[-1]: # 1D image => bar plot # TODO: add "(plot)" to the window title # Create a simple bar plot of X x 400 px lenx = data.shape[-1] if lenx > MAX_WIDTH: binning = lenx // MAX_WIDTH data = data[..., 0::binning] logging.debug("Compressed data from %d to %d elements", lenx, data.shape[-1]) lenx = data.shape[-1] leny = 400 miny = min(0, data.min()) maxy = data.max() diffy = maxy - miny if diffy == 0: diffy = 1 logging.info("Plot data from %s to %s", miny, maxy) rgb = numpy.zeros((leny, lenx, 3), dtype=numpy.uint8) for i, v in numpy.ndenumerate(data): # TODO: have the base at 0, instead of miny, so that negative values are columns going down h = leny - int(((v - miny) * leny) / diffy) rgb[h:-1, i[-1], :] = 255 else: # Greyscale (hopefully) mn, mx, mnp, mxp = ndimage.extrema(data) logging.info("Image data from %s to %s", mn, mx) rgb = img.DataArray2RGB(data) # auto brightness/contrast self.app.spots, self.app.translation, self.app.scaling, self.app.rotation = FindGridSpots( data, self.gridsize) self.app.img = NDImage2wxImage(rgb) wx.CallAfter(self.app.update_view)
def _updateImage(self): """ Recomputes the image with all the raw data available """ # logging.debug("Updating image") if not self.raw: return try: if not isinstance(self.raw, list): raise AttributeError(".raw must be a list of DA/DAS") data = self.raw[0] bkg = self.background.value if bkg is not None: try: data = img.Subtract(data, bkg) except Exception as ex: logging.info("Failed to subtract background data: %s", ex) dims = data.metadata.get(model.MD_DIMS, "CTZYX"[-data.ndim::]) ci = dims.find("C") # -1 if not found # is RGB if dims in ("CYX", "YXC") and data.shape[ci] in (3, 4): rgbim = img.ensureYXC(data) rgbim.flags.writeable = False # merge and ensures all the needed metadata is there rgbim.metadata = self._find_metadata(rgbim.metadata) rgbim.metadata[model.MD_DIMS] = "YXC" # RGB format self.image.value = rgbim else: # is grayscale if data.ndim != 2: data = img.ensure2DImage( data) # Remove extra dimensions (of length 1) self.image.value = self._projectXY2RGB(data, self.tint.value) except Exception: logging.exception("Updating %s %s image", self.__class__.__name__, self.name.value)
def _projectTile(self, tile): """ Project the tile tile (DataArray): Raw tile return (DataArray): Projected tile """ dims = tile.metadata.get(model.MD_DIMS, "CTZYX"[-tile.ndim::]) ci = dims.find("C") # -1 if not found # is RGB if dims in ("CYX", "YXC") and tile.shape[ci] in (3, 4): # Just pass the RGB data on tile = img.ensureYXC(tile) tile.flags.writeable = False # merge and ensures all the needed metadata is there tile.metadata = self.stream._find_metadata(tile.metadata) tile.metadata[model.MD_DIMS] = "YXC" # RGB format return tile elif dims in ("ZYX",) and model.hasVA(self.stream, "zIndex"): tile = img.getYXFromZYX(tile, self.stream.zIndex.value) tile.metadata[model.MD_DIMS] = "ZYX" else: tile = img.ensure2DImage(tile) return self._projectXY2RGB(tile, self.stream.tint.value)
def new_image(self, data): """ Update the window with the new image (the window is resize to have the image at ratio 1:1) data (numpy.ndarray): an 2D array containing the image (can be 3D if in RGB) """ if data.ndim == 3 and 3 in data.shape: # RGB rgb = img.ensureYXC(data) elif numpy.prod(data.shape) == data.shape[-1]: # 1D image => bar plot # TODO: add "(plot)" to the window title # Create a simple bar plot of X x 400 px lenx = data.shape[-1] if lenx > MAX_WIDTH: binning = lenx // MAX_WIDTH data = data[..., 0::binning] logging.debug("Compressed data from %d to %d elements", lenx, data.shape[-1]) lenx = data.shape[-1] leny = 400 miny = min(0, data.min()) maxy = data.max() diffy = maxy - miny if diffy == 0: diffy = 1 logging.info("Plot data from %s to %s", miny, maxy) rgb = numpy.zeros((leny, lenx, 3), dtype=numpy.uint8) for i, v in numpy.ndenumerate(data): # TODO: have the base at 0, instead of miny, so that negative values are columns going down h = leny - int(((v - miny) * leny) / diffy) rgb[h:-1, i[-1], :] = 255 else: # Greyscale (hopefully) mn, mx, mnp, mxp = ndimage.extrema(data) logging.info("Image data from %s to %s", mn, mx) rgb = img.DataArray2RGB(data) # auto brightness/contrast self.app.spots, self.app.translation, self.app.scaling, self.app.rotation = FindGridSpots(data, self.gridsize) self.app.img = NDImage2wxImage(rgb) wx.CallAfter(self.app.update_view)
def new_image(self, data): """ Update the window with the new image (the window is resize to have the image at ratio 1:1) data (numpy.ndarray): an 2D array containing the image (can be 3D if in RGB) """ if data.ndim == 3 and 3 in data.shape: # RGB rgb = img.ensureYXC(data) elif numpy.prod(data.shape) == 1: # single point => show text text = "%g" % (data.flat[0], ) logging.info("Data value is: %s", text) # Create a big enough white space (30x200 px) of BGRA format rgb = numpy.empty((30, 200, 4), dtype=numpy.uint8) rgb.fill(255) # Get a Cairo context for that image surface = cairo.ImageSurface.create_for_data( rgb, cairo.FORMAT_ARGB32, rgb.shape[1], rgb.shape[0]) ctx = cairo.Context(surface) # Draw a black text of 20 px high ctx.set_source_rgb(0, 0, 0) ctx.select_font_face("Sans", cairo.FONT_SLANT_NORMAL) ctx.set_font_size(20) ctx.move_to(5, 20) ctx.show_text(text) del ctx # ensure the context is flushed elif numpy.prod(data.shape) == data.shape[-1]: # 1D image => bar plot # TODO: add "(plot)" to the window title # Create a simple bar plot of X x 400 px lenx = data.shape[-1] if lenx > MAX_WIDTH: binning = lenx // MAX_WIDTH data = data[..., 0::binning] logging.debug("Compressed data from %d to %d elements", lenx, data.shape[-1]) lenx = data.shape[-1] leny = 400 miny = min(0, data.min()) maxy = data.max() diffy = maxy - miny if diffy == 0: diffy = 1 logging.info("Plot data from %s to %s", miny, maxy) rgb = numpy.zeros((leny, lenx, 3), dtype=numpy.uint8) for i, v in numpy.ndenumerate(data): # TODO: have the base at 0, instead of miny, so that negative values are columns going down h = leny - int(((v - miny) * leny) / diffy) rgb[h:-1, i[-1], :] = 255 else: # Greyscale (hopefully) mn, mx, mnp, mxp = ndimage.extrema(data) logging.info("Image data from %s to %s", mn, mx) rgb = img.DataArray2RGB(data) # auto brightness/contrast self.app.img = NDImage2wxImage(rgb) disp_size = wx.Display(0).GetGeometry().GetSize() if disp_size[0] < rgb.shape[1] or disp_size[1] < rgb.shape[0]: asp_ratio = rgb.shape[1] / rgb.shape[0] if disp_size[0] / disp_size[1] < asp_ratio: self.app.magn = disp_size[0] / rgb.shape[1] else: self.app.magn = disp_size[1] / rgb.shape[0] self.app.img.Rescale(rgb.shape[1] * self.app.magn, rgb.shape[0] * self.app.magn, rgb.shape[2]) else: self.app.magn = 1 wx.CallAfter(self.app.update_view)