def _process(self, img, key=None): if self.p.fast: return self._fast_process(img, key) proj = self.p.projection x0, x1 = img.range(0) y0, y1 = img.range(1) xn, yn = img.interface.shape(img, gridded=True)[:2] px0, py0, px1, py1 = project_extents((x0, y0, x1, y1), img.crs, proj) src_ext, trgt_ext = (x0, x1, y0, y1), (px0, px1, py0, py1) if img.crs == proj and np.isclose(src_ext, trgt_ext).all(): return img arrays = [] for vd in img.vdims: arr = img.dimension_values(vd, flat=False) if arr.size: projected, extents = warp_array(arr, proj, img.crs, (xn, yn), src_ext, trgt_ext) else: projected, extents = arr, trgt_ext arrays.append(projected) if xn == 0 or yn == 0: return img.clone([], bounds=extents, crs=proj) xunit = ((extents[1]-extents[0])/float(xn))/2. yunit = ((extents[3]-extents[2])/float(yn))/2. xs = np.linspace(extents[0]+xunit, extents[1]-xunit, xn) ys = np.linspace(extents[2]+yunit, extents[3]-yunit, yn) return img.clone((xs, ys)+tuple(arrays), bounds=None, kdims=img.kdims, vdims=img.vdims, crs=proj, xdensity=None, ydensity=None)
def project_cartopy(self): """ Reproject the satellite image on an equirectangular map using the cartopy library """ import cartopy.crs as ccrs from cartopy.img_transform import warp_array img = Image.open(self.filename).convert("L") self.data = self.cut_borders(img) width = self.outwidth height = self.outheight buf, _extent = \ warp_array(self.data, source_proj=ccrs.Geostationary( central_longitude=self.longitude, satellite_height=35785831.0 ), target_proj=ccrs.PlateCarree(), target_res=(width, height)) dataResampledImage = self.rescale(buf.data) # dataResampledImage = self.polar_clouds(dataResampledImage) weight = self.get_weight() result = np.array([dataResampledImage, weight]) return result
def test_warpimage(self): img = np.asanyarray(self.img) img = img[::-1] regrid_shape = 1.2 * min(img.shape) regrid_shape = mkin.regrid_shape_aspect(regrid_shape, self.oextent) imgout, ext = cimg.warp_array(np.asanyarray(self.img), source_proj=self.iproj, source_extent=self.iextent, target_proj=self.oproj, target_res=regrid_shape, target_extent=self.oextent, mask_extrapolated=True) imgout = np.ma.filled(imgout[::-1], fill_value=0) imgoutmkin = mkin.WarpImage(img, self.iproj, self.iextent, self.oproj, self.oextent, origin="upper", rgcoeff=1.2) imgoutmkin = np.ma.filled(imgoutmkin, fill_value=0) self.assertTrue( np.all( np.isclose(imgout.ravel(), imgoutmkin.ravel(), rtol=1e-6, atol=1e-10)))
def project_cartopy(self): """ Reproject the satellite image on an equirectangular map using the cartopy library """ import cartopy.crs as ccrs from cartopy.img_transform import warp_array self.load_image() width = self.outwidth height = self.outheight buf, _extent = \ warp_array(self.data, source_proj=ccrs.Geostationary( central_longitude=self.longitude, satellite_height=35785831.0 ), target_proj=ccrs.PlateCarree(), target_res=(width, height)) dataResampledImage = self.rescale(buf.data) dataResampledImage = self.polar_clouds(dataResampledImage) weight = self.get_weight() result = np.array([dataResampledImage, weight]) return result
def _process(self, img, key=None): if self.p.fast: return self._fast_process(img, key) proj = self.p.projection if proj == img.crs: return img x0, x1 = img.range(0) y0, y1 = img.range(1) xn, yn = img.interface.shape(img, gridded=True)[:2] px0, py0, px1, py1 = project_extents((x0, y0, x1, y1), img.crs, proj) src_ext, trgt_ext = (x0, x1, y0, y1), (px0, px1, py0, py1) arrays = [] for vd in img.vdims: arr = img.dimension_values(vd, flat=False) projected, extents = warp_array(arr, proj, img.crs, (xn, yn), src_ext, trgt_ext) arrays.append(projected) projected = np.dstack(arrays) if len(arrays) > 1 else arrays[0] data = np.flipud(projected) bounds = (extents[0], extents[2], extents[1], extents[3]) return img.clone(data, bounds=bounds, kdims=img.kdims, vdims=img.vdims, crs=proj, xdensity=None, ydensity=None)
def img_projection(img_fname, source_proj, target_proj, target_res, res_fname): from cartopy.img_transform import warp_array import numpy as np import PIL.Image img = PIL.Image.open(img_fname) result_array, extent = warp_array(np.array(img), source_proj, target_proj, target_res) result = PIL.Image.fromarray(result_array) result.save(res_fname) return ()
def _warped_located_image(image, source_projection, source_extent, output_projection, output_extent, target_resolution): """ Reproject an Image from one source-projection and extent to another. Returns ------- LocatedImage A reprojected LocatedImage, the extent of which is >= the requested 'output_extent'. """ if source_projection == output_projection: extent = output_extent else: # Convert Image to numpy array (flipping so that origin # is 'lower'). img, extent = warp_array(np.asanyarray(image)[::-1], source_proj=source_projection, source_extent=source_extent, target_proj=output_projection, target_res=np.asarray(target_resolution, dtype=int), target_extent=output_extent, mask_extrapolated=True) # Convert arrays with masked RGB(A) values to non-masked RGBA # arrays, setting the alpha channel to zero for masked values. # This avoids unsightly grey boundaries appearing when the # extent is limited (i.e. not global). if np.ma.is_masked(img): if img.shape[2:3] == (3,): # RGB old_img = img img = np.zeros(img.shape[:2] + (4,), dtype=img.dtype) img[:, :, 0:3] = old_img img[:, :, 3] = ~ np.any(old_img.mask, axis=2) if img.dtype.kind == 'u': img[:, :, 3] *= 255 elif img.shape[2:3] == (4,): # RGBA img[:, :, 3] = np.where(np.any(img.mask, axis=2), 0, img[:, :, 3]) img = img.data # Convert warped image array back to an Image, undoing the # earlier flip. image = Image.fromarray(img[::-1]) return LocatedImage(image, extent)
def WarpImage(img, iproj, iextent, oproj, oextent, origin="upper", rgcoeff=1.2): """ Warps images with cartopy.img_transform.warp_array, then plots them with imshow. Based on cartopy.mpl.geoaxes.imshow. Parameter descriptions are identical to those in WarpImagePad. """ if iproj == oproj: raise Warning("WARNING: input and output transforms are identical!" "Returing input!") return img else: if origin == 'upper': # Regridding operation implicitly assumes origin of # image is 'lower', so adjust for that here. img = img[::-1] # The 1.2 is padding when we rescale the image with imshow regrid_shape = rgcoeff * min(img.shape) regrid_shape = regrid_shape_aspect(regrid_shape, oextent) # cimg.warp_array uses cimg.mesh_projection, which # cannot handle any zeros being used in iextent. Create # iextent_nz to fix iextent_nz = np.array(iextent) iextent_nz[iextent_nz == 0] = 1e-8 iextent_nz = list(iextent_nz) imgout, extent = cimg.warp_array(img, source_proj=iproj, source_extent=iextent_nz, target_proj=oproj, target_res=regrid_shape, target_extent=oextent, mask_extrapolated=True) if origin == 'upper': # Transform back imgout = imgout[::-1] return imgout
def draw(self, ax, vmin, vmax, target_projection, target_resolution=(1000, 1000), c=0.5, s=1, cmap='RdBu'): """ Draws the projected data set in a given Axes instance. Parameters ---------- ax : matplotlib.axes.Axes axes instance vmin : float lower data limit vmax : float upper data limit target_projection : cartopy.crs.Projection projection applied to the lon/lat data target_resolution : tuple resolution of the output grid c : float offset parameter for alpha computation s : float slope parameter for alpha computation cmap : str matplotlib colormap """ if isinstance(cmap, str): cmap = plt.get_cmap(cmap) data, extent = warp_array(self.__data, target_projection, ccrs.PlateCarree(), target_res=target_resolution) values_normalized = (data - vmin) / (vmax - vmin) magnitude = np.abs(data / vmax) magnitude[magnitude > 1] = 1 magnitude[data.mask] = 0 alpha = Image.fromarray(np.uint8(alpha_scaling(magnitude, c, s) * 255)) bitmap = Image.fromarray(np.uint8(cmap(values_normalized) * 255)) bitmap.putalpha(alpha) return ax.imshow(bitmap, extent=extent)
def _image_and_extent(self, wms_proj, wms_srs, wms_extent, output_proj, output_extent, target_resolution): min_x, max_x, min_y, max_y = wms_extent wms_image = self.service.getmap(layers=self.layers, srs=wms_srs, bbox=(min_x, min_y, max_x, max_y), size=target_resolution, format='image/png', **self.getmap_extra_kwargs) wms_image = Image.open(io.BytesIO(wms_image.read())) if wms_proj == output_proj: extent = output_extent else: # Convert Image to numpy array (flipping so that origin # is 'lower'). img, extent = warp_array(np.asanyarray(wms_image)[::-1], source_proj=wms_proj, source_extent=wms_extent, target_proj=output_proj, target_res=target_resolution, target_extent=output_extent, mask_extrapolated=True) # Convert arrays with masked RGB(A) values to non-masked RGBA # arrays, setting the alpha channel to zero for masked values. # This avoids unsightly grey boundaries appearing when the # extent is limited (i.e. not global). if np.ma.is_masked(img): if img.shape[2:3] == (3, ): # RGB old_img = img img = np.zeros(img.shape[:2] + (4, ), dtype=img.dtype) img[:, :, 0:3] = old_img img[:, :, 3] = ~np.any(old_img.mask, axis=2) if img.dtype.kind == 'u': img[:, :, 3] *= 255 elif img.shape[2:3] == (4, ): # RGBA img[:, :, 3] = np.where(np.any(img.mask, axis=2), 0, img[:, :, 3]) img = img.data # Convert warped image array back to an Image, undoing the # earlier flip. wms_image = Image.fromarray(img[::-1]) return LocatedImage(wms_image, extent)
def _image_and_extent(self, wms_proj, wms_srs, wms_extent, output_proj, output_extent, target_resolution): min_x, max_x, min_y, max_y = wms_extent wms_image = self.service.getmap(layers=self.layers, srs=wms_srs, bbox=(min_x, min_y, max_x, max_y), size=target_resolution, format='image/png', **self.getmap_extra_kwargs) wms_image = Image.open(io.BytesIO(wms_image.read())) if wms_proj == output_proj: extent = output_extent else: # Convert Image to numpy array (flipping so that origin # is 'lower'). img, extent = warp_array(np.asanyarray(wms_image)[::-1], source_proj=wms_proj, source_extent=wms_extent, target_proj=output_proj, target_res=target_resolution, target_extent=output_extent, mask_extrapolated=True) # Convert arrays with masked RGB(A) values to non-masked RGBA # arrays, setting the alpha channel to zero for masked values. # This avoids unsightly grey boundaries appearing when the # extent is limited (i.e. not global). if np.ma.is_masked(img): if img.shape[2:3] == (3,): # RGB old_img = img img = np.zeros(img.shape[:2] + (4,), dtype=img.dtype) img[:, :, 0:3] = old_img img[:, :, 3] = ~ np.any(old_img.mask, axis=2) if img.dtype.kind == 'u': img[:, :, 3] *= 255 elif img.shape[2:3] == (4,): # RGBA img[:, :, 3] = np.where(np.any(img.mask, axis=2), 0, img[:, :, 3]) img = img.data # Convert warped image array back to an Image, undoing the # earlier flip. wms_image = Image.fromarray(img[::-1]) return LocatedImage(wms_image, extent)
def img_proj_merc(fname, res_name, resolution, height): import cartopy.crs as ccrs from cartopy.img_transform import warp_array import numpy as np import PIL.Image img = PIL.Image.open(fname) result_array, extent = warp_array( np.array(img), source_proj=ccrs.Geostationary(satellite_height=height), target_proj=ccrs.Mercator(), target_res=resolution) result = PIL.Image.fromarray(result_array) result.save(res_name) return ()
def _process(self, img, key=None): if self.p.fast: return self._fast_process(img, key) proj = self.p.projection x0, x1 = img.range(0, dimension_range=False) y0, y1 = img.range(1, dimension_range=False) yn, xn = img.interface.shape(img, gridded=True)[:2] (px0, py0, px1, py1) = project_extents((x0, y0, x1, y1), img.crs, proj) # Some bug in cartopy is causing zero values eps = sys.float_info.epsilon src_extent = tuple( e + v if e == 0 else e for e, v in zip((x0, x1, y0, y1), (eps, -eps, eps, -eps))) tgt_extent = (px0, px1, py0, py1) if img.crs == proj and np.isclose(src_extent, tgt_extent).all(): return img arrays = [] for vd in img.vdims: arr = img.dimension_values(vd, flat=False) if arr.size: projected, _ = warp_array(arr, proj, img.crs, (xn, yn), src_extent, tgt_extent) else: projected = arr arrays.append(projected) if xn == 0 or yn == 0: return img.clone([], bounds=tgt_extent, crs=proj) xunit = ((tgt_extent[1] - tgt_extent[0]) / float(xn)) / 2. yunit = ((tgt_extent[3] - tgt_extent[2]) / float(yn)) / 2. xs = np.linspace(tgt_extent[0] + xunit, tgt_extent[1] - xunit, xn) ys = np.linspace(tgt_extent[2] + yunit, tgt_extent[3] - yunit, yn) return img.clone((xs, ys) + tuple(arrays), bounds=None, kdims=img.kdims, vdims=img.vdims, crs=proj, xdensity=None, ydensity=None)
def _process(self, img, key=None): proj = self.p.projection if proj == img.crs: return img arr = img.dimension_values(2, flat=False) x0, x1 = img.range(0) y0, y1 = img.range(1) xn, yn = arr.shape px0, py0, px1, py1 = project_extents((x0, y0, x1, y1), img.crs, proj) src_ext, trgt_ext = (x0, x1, y0, y1), (px0, px1, py0, py1) projected, extents = warp_array(arr, proj, img.crs, (xn, yn), src_ext, trgt_ext) bounds = (extents[0], extents[2], extents[1], extents[3]) data = np.flipud(projected) return Image(data, bounds=bounds, kdims=img.kdims, vdims=img.vdims, crs=proj)
def _warped_located_image(image, source_projection, source_extent, output_projection, output_extent, target_resolution): """ Reproject an Image from one source-projection and extent to another. Returns ------- LocatedImage A reprojected LocatedImage, the extent of which is >= the requested 'output_extent'. """ if source_projection == output_projection: extent = output_extent else: # Convert Image to numpy array (flipping so that origin # is 'lower'). # Convert to RGBA to keep the color palette in the regrid process # if any img, extent = warp_array(np.asanyarray(image.convert('RGBA'))[::-1], source_proj=source_projection, source_extent=source_extent, target_proj=output_projection, target_res=np.asarray(target_resolution, dtype=int), target_extent=output_extent, mask_extrapolated=True) # Convert arrays with masked RGB(A) values to non-masked RGBA # arrays, setting the alpha channel to zero for masked values. # This avoids unsightly grey boundaries appearing when the # extent is limited (i.e. not global). if np.ma.is_masked(img): img[:, :, 3] = np.where(np.any(img.mask, axis=2), 0, img[:, :, 3]) img = img.data # Convert warped image array back to an Image, undoing the # earlier flip. image = Image.fromarray(img[::-1]) return LocatedImage(image, extent)
def Warp_image(img,iso,iex,ortho,ox): if iproj == oproj: raise Warning("Input and output transforms are identical!" "Returing input!") return img origin=upper img=img[::-1] regrid_shape = 1.2 * min(img.shape) regrid_shape = regrid_shape_aspect(regrid_shape, oextent) iextent_nozeros = np.array(iextent) iextent_nozeros[iextent_nozeros == 0] = 1e-8 iextent_nozeros = list(iextent_nozeros) imgout, extent = cimg.warp_array(img,source_proj=iproj, source_extent=iextent_nozeros, target_proj=oproj, target_res=regrid_shape, target_extent=oextent, mask_extrapolated=True) imgout = imgout[::-1] return(imgout)
def _process(self, img, key=None): if self.p.fast: return self._fast_process(img, key) proj = self.p.projection x0, x1 = img.range(0) y0, y1 = img.range(1) xn, yn = img.interface.shape(img, gridded=True)[:2] px0, py0, px1, py1 = project_extents((x0, y0, x1, y1), img.crs, proj) src_ext, trgt_ext = (x0, x1, y0, y1), (px0, px1, py0, py1) if img.crs == proj and np.isclose(src_ext, trgt_ext).all(): return img arrays = [] for vd in img.vdims: arr = img.dimension_values(vd, flat=False) if arr.size: projected, extents = warp_array(arr, proj, img.crs, (xn, yn), src_ext, trgt_ext) else: projected, extents = arr, trgt_ext arrays.append(projected) if xn == 0 or yn == 0: return img.clone([], bounds=extents, crs=proj) xunit = ((extents[1] - extents[0]) / float(xn)) / 2. yunit = ((extents[3] - extents[2]) / float(yn)) / 2. xs = np.linspace(extents[0] + xunit, extents[1] - xunit, xn) ys = np.linspace(extents[2] + yunit, extents[3] - yunit, yn) return img.clone((xs, ys) + tuple(arrays), bounds=None, kdims=img.kdims, vdims=img.vdims, crs=proj, xdensity=None, ydensity=None)
def draw(self, ax, target_projection, target_resolution=(1000, 1000)): """ Draws the projected image in a given Axes instance. Parameters ---------- ax : matplotlib.axes.Axes axes instance target_projection : cartopy.crs.Projection projection applied to the lon/lat data target_resolution : tuple resolution of the output grid """ data, extent = warp_array(self.__data, target_projection, ccrs.PlateCarree(), target_res=target_resolution) img = Image.fromarray(data) alpha = Image.fromarray(np.uint8(~data.mask[:, :, 0] * 255)) img.putalpha(alpha) return ax.imshow(img, extent=extent)
def WarpImage(img, iproj, iextent, oproj, oextent, origin="upper", rgcoeff=1.2): """Warps images with cartopy.img_transform.warp_array, then plots them with imshow. Based on cartopy.mpl.geoaxes.imshow. Parameters ---------- img : numpy.ndarray Image as a 2D array. iproj : cartopy.crs.Projection instance Input coordinate system. iextent : list-like Coordinate limits (x_min, x_max, y_min, y_max) of input. oproj : cartopy.crs.Projection instance Output coordinate system. oextent : list-like Coordinate limits (x_min, x_max, y_min, y_max) of output. origin : "lower" or "upper", optional Based on imshow convention for displaying image y-axis. "upper" means [0,0] is in the upper-left corner of the image; "lower" means it's in the bottom-left. rgcoeff : float, optional Fractional size increase of transformed image height. Generically set to 1.2 to prevent loss of fidelity during transform (though some of it is inevitably lost due to warping). """ if iproj == oproj: raise Warning("Input and output transforms are identical!" "Returing input!") return img if origin == 'upper': # Regridding operation implicitly assumes origin of image is # 'lower', so adjust for that here. img = img[::-1] # rgcoeff is padding when we rescale the image later. regrid_shape = rgcoeff * min(img.shape) regrid_shape = regrid_shape_aspect(regrid_shape, oextent) # cimg.warp_array uses cimg.mesh_projection, which cannot handle any # zeros being used in iextent. Create iextent_nozeros to fix. iextent_nozeros = np.array(iextent) iextent_nozeros[iextent_nozeros == 0] = 1e-8 iextent_nozeros = list(iextent_nozeros) imgout, extent = cimg.warp_array(img, source_proj=iproj, source_extent=iextent_nozeros, target_proj=oproj, target_res=regrid_shape, target_extent=oextent, mask_extrapolated=True) if origin == 'upper': # Transform back. imgout = imgout[::-1] return imgout
def test_warpimage(self, box): """Test image warping and padding. Output of this function was tested by visual inspection. """ box = np.array(box, dtype='int32') # Crop image. img = np.asanyarray(self.img.crop(box)) # Determine long/lat and output projection. llbd = self.get_llbd(box) oproj = ccrs.Orthographic(central_longitude=np.mean(llbd[:2]), central_latitude=np.mean(llbd[2:]), globe=self.iglobe) # Determine coordinates of image limits in input and output projection # coordinates. iextent, oextent, ores = self.get_extents(llbd, self.geoproj, self.iproj, oproj) regrid_shape = 1.2 * min(img.shape) regrid_shape = igen.regrid_shape_aspect(regrid_shape, oextent) imgout, ext = cimg.warp_array(img[::-1], source_proj=self.iproj, source_extent=iextent, target_proj=oproj, target_res=regrid_shape, target_extent=oextent, mask_extrapolated=True) imgout = np.ma.filled(imgout[::-1], fill_value=0) # Obtain image from igen.WarpImage. imgout_WarpImage = igen.WarpImage(img, self.iproj, iextent, oproj, oextent, origin="upper", rgcoeff=1.2) imgout_WarpImage = np.ma.filled(imgout_WarpImage, fill_value=0) # Test that WarpImage gives the same result as this function. assert np.all(imgout == imgout_WarpImage) # Pad image. imgw = Image.fromarray(imgout, mode="L") imgw_loh = imgw.size[0] / imgw.size[1] if imgw_loh > (img.shape[1] / img.shape[0]): imgw = imgw.resize([img.shape[0], int(np.round(img.shape[0] / imgw_loh))], resample=Image.NEAREST) else: imgw = imgw.resize([int(np.round(imgw_loh * img.shape[0])), img.shape[0]], resample=Image.NEAREST) imgpad = Image.new('L', (img.shape[1], img.shape[0]), (0)) offset = ((imgpad.size[0] - imgw.size[0]) // 2, (imgpad.size[1] - imgw.size[1]) // 2) imgpad.paste(imgw, offset) # Obtain image from igen.WarpImagePad. imgout_WarpImagePad, WIPsize, WIPoffset = igen.WarpImagePad( img, self.iproj, iextent, oproj, oextent, origin="upper", rgcoeff=1.2, fillbg="black") # Test that WarpImagePad gives the same result as this function. assert np.all(np.asanyarray(imgpad) == np.asanyarray(imgout_WarpImagePad)) assert WIPsize == imgw.size assert offset == WIPoffset