def stretch_hist_equalize(self, ch_nb): """Stretch the current image's colors by performing histogram equalization on channel *ch_nb*. """ LOG.info("Perform a histogram equalized contrast stretch.") if(self.channels[ch_nb].size == np.ma.count_masked(self.channels[ch_nb])): LOG.warning("Nothing to stretch !") return arr = self.channels[ch_nb] nwidth = 2048.0 carr = arr.compressed() imhist, bins = np.histogram(carr, nwidth, normed=True) cdf = imhist.cumsum() - imhist[0] cdf = cdf / cdf[-1] res = np.ma.empty_like(arr) res.mask = np.ma.getmaskarray(arr) res[~res.mask] = np.interp(carr, bins[:-1], cdf) self.channels[ch_nb] = res
def add_overlay(self, color=(0, 0, 0)): """Add coastline and political borders to image, using *color*. """ import acpgimage import _acpgpilext import pps_array2image self.convert("RGB") import ConfigParser conf = ConfigParser.ConfigParser() conf.read(os.path.join(CONFIG_PATH, "geo_image.cfg")) coast_dir = CONFIG_PATH coast_file = os.path.join(coast_dir, conf.get("coasts", "coast_file")) arr = np.zeros(self.channels[0].shape, np.uint8) LOG.debug("Adding overlay: " + str(self.area_id)) if not isinstance(self.area_id, str): area_id = self.area_id.area_id else: area_id = self.area_id LOG.info("Add coastlines and political borders to image. " "Area = %s" % (area_id)) rimg = acpgimage.image(area_id) rimg.info["nodata"] = 255 rimg.data = arr area_overlayfile = "%s/coastlines_%s.asc" % (coast_dir, area_id) LOG.info("Read overlay. Try find something prepared on the area...") try: overlay = _acpgpilext.read_overlay(area_overlayfile) LOG.info("Got overlay for area: %s." % area_overlayfile) except IOError: LOG.info("Didn't find an area specific overlay." " Have to read world-map...") overlay = _acpgpilext.read_overlay(coast_file) LOG.info("Add overlay.") overlay_image = pps_array2image.add_overlay(rimg, overlay, pil.fromarray(arr), color=1) val = np.ma.asarray(overlay_image) self.channels[0] = np.ma.where(val == 1, color[0], self.channels[0]) self.channels[0].mask = np.where(val == 1, False, np.ma.getmaskarray(self.channels[0])) self.channels[1] = np.ma.where(val == 1, color[1], self.channels[1]) self.channels[1].mask = np.where(val == 1, False, np.ma.getmaskarray(self.channels[1])) self.channels[2] = np.ma.where(val == 1, color[2], self.channels[2]) self.channels[2].mask = np.where(val == 1, False, np.ma.getmaskarray(self.channels[2]))
def save(self, filename, compression=6, tags=None, gdal_options=None, fformat=None, blocksize=256, **kwargs): """Save the image to the given *filename*. If the extension is "tif", the image is saved to geotiff_ format, in which case the *compression* level can be given ([0, 9], 0 meaning off). See also :meth:`image.Image.save`, :meth:`image.Image.double_save`, and :meth:`image.Image.secure_save`. The *tags* argument is a dict of tags to include in the image (as metadata), and the *gdal_options* holds options for the gdal saving driver. A *blocksize* other than 0 will result in a tiled image (if possible), with tiles of size equal to *blocksize*. If the specified format *fformat* is not know to MPOP (and PIL), we will try to import module *fformat* and call the method `fformat.save`. .. _geotiff: http://trac.osgeo.org/geotiff/ """ file_tuple = os.path.splitext(filename) fformat = fformat or file_tuple[1][1:] if fformat.lower() in ('tif', 'tiff'): return self.geotiff_save(filename, compression, tags, gdal_options, blocksize, **kwargs) try: # Let image.pil_save it ? super(GeoImage, self).save(filename, compression, fformat=fformat) except mpop.imageo.image.UnknownImageFormat: # No ... last resort, try to import an external module. LOG.info("Importing image saver module '%s'" % fformat) try: saver = __import__(fformat, globals(), locals(), ['save']) except ImportError: raise mpop.imageo.image.UnknownImageFormat( "Unknown image format '%s'" % fformat) saver.save(self, filename, **kwargs)
def add_overlay(self, color=(0, 0, 0), width=0.5, resolution=None): """Add coastline and political borders to image, using *color* (tuple of integers between 0 and 255). Warning: Loses the masks ! *resolution* is chosen automatically if None (default), otherwise it should be one of: +-----+-------------------------+---------+ | 'f' | Full resolution | 0.04 km | | 'h' | High resolution | 0.2 km | | 'i' | Intermediate resolution | 1.0 km | | 'l' | Low resolution | 5.0 km | | 'c' | Crude resolution | 25 km | +-----+-------------------------+---------+ """ img = self.pil_image() import ConfigParser conf = ConfigParser.ConfigParser() conf.read(os.path.join(CONFIG_PATH, "mpop.cfg")) coast_dir = conf.get('shapes', 'dir') LOG.debug("Getting area for overlay: " + str(self.area)) if self.area is None: raise ValueError("Area of image is None, can't add overlay.") from mpop.projector import get_area_def if isinstance(self.area, str): self.area = get_area_def(self.area) LOG.info("Add coastlines and political borders to image.") LOG.debug("Area = " + str(self.area)) if resolution is None: x_resolution = ((self.area.area_extent[2] - self.area.area_extent[0]) / self.area.x_size) y_resolution = ((self.area.area_extent[3] - self.area.area_extent[1]) / self.area.y_size) res = min(x_resolution, y_resolution) if res > 25000: resolution = "c" elif res > 5000: resolution = "l" elif res > 1000: resolution = "i" elif res > 200: resolution = "h" else: resolution = "f" LOG.debug("Automagically choose resolution " + resolution) from pycoast import ContourWriterAGG cw_ = ContourWriterAGG(coast_dir) cw_.add_coastlines(img, self.area, outline=color, resolution=resolution, width=width) cw_.add_borders(img, self.area, outline=color, resolution=resolution, width=width) arr = np.array(img) if len(self.channels) == 1: self.channels[0] = np.ma.array(arr[:, :] / 255.0) else: for idx in range(len(self.channels)): self.channels[idx] = np.ma.array(arr[:, :, idx] / 255.0)