示例#1
0
文件: image.py 项目: 3Geo/mpop
    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
示例#2
0
文件: image.py 项目: 3Geo/mpop
    def crude_stretch(self, ch_nb, min_stretch = None, max_stretch = None):
        """Perform simple linear stretching (without any cutoff) on the channel
        *ch_nb* of the current image and normalize to the [0,1] range."""

        if(min_stretch is None):
            min_stretch = self.channels[ch_nb].min()
        if(max_stretch is None):
            max_stretch = self.channels[ch_nb].max()

        if((not self.channels[ch_nb].mask.all()) and
            max_stretch - min_stretch > 0):    
            stretched = ((self.channels[ch_nb].data - min_stretch) * 1.0 /
                                    (max_stretch - min_stretch))
            self.channels[ch_nb] = np.ma.array(stretched, 
                                               mask=self.channels[ch_nb].mask)
        else:
            LOG.warning("Nothing to stretch !")
示例#3
0
文件: image.py 项目: 3Geo/mpop
    def stretch_logarithmic(self, ch_nb, factor=100.):
        """Move data into range [1:factor] and do a normalized logarithmic
        enhancement.
        """
        LOG.debug("Perform a logarithmic contrast stretch.")
        if ((self.channels[ch_nb].size ==
             np.ma.count_masked(self.channels[ch_nb])) or
            (self.channels[ch_nb].min() == self.channels[ch_nb].max())):
            LOG.warning("Nothing to stretch !")
            return

        crange=(0., 1.0)

        arr = self.channels[ch_nb]
        b = float(crange[1] - crange[0])/np.log(factor)
        c = float(crange[0])
        slope = (factor-1.)/float(arr.max() - arr.min())
        arr = 1. + (arr - arr.min())*slope
        arr = c + b*np.log(arr)
        self.channels[ch_nb] = arr
示例#4
0
文件: image.py 项目: 3Geo/mpop
    def stretch_linear(self, ch_nb, cutoffs=(0.005, 0.005)):
        """Stretch linearly the contrast of the current image on channel
        *ch_nb*, using *cutoffs* for left and right trimming.
        """
        LOG.debug("Perform a linear contrast stretch.")

        if((self.channels[ch_nb].size ==
            np.ma.count_masked(self.channels[ch_nb])) or
           self.channels[ch_nb].min() == self.channels[ch_nb].max()):
            LOG.warning("Nothing to stretch !")
            return
        
        nwidth = 2048.0


        arr = self.channels[ch_nb]

        carr = arr.compressed()
        hist, bins = np.histogram(carr, nwidth)

        ndim = carr.size

        left = 0
        hist_sum = 0.0
        i = 0
        while i < nwidth and hist_sum < cutoffs[0]*ndim:
            hist_sum = hist_sum + hist[i]
            i = i + 1

        left = bins[i-1]

        right = 0
        hist_sum = 0.0
        i = nwidth - 1
        while i >= 0 and hist_sum < cutoffs[1]*ndim:
            hist_sum = hist_sum + hist[i]
            i = i - 1

        right = bins[i+1]
        delta_x = (right - left)
        LOG.debug("Interval: left=%f,right=%f width=%f"
                  %(left,right,delta_x))

        if delta_x > 0.0:
            self.channels[ch_nb] = np.ma.array((arr - left) / delta_x, 
                                               mask = arr.mask)
        else:
            self.channels[ch_nb] = np.ma.zeros(arr.shape)
            LOG.warning("Unable to make a contrast stretch!")
示例#5
0
文件: geo_image.py 项目: Pelgrum/mpop
    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)
示例#6
0
文件: geo_image.py 项目: Pelgrum/mpop
    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)
示例#7
0
文件: geo_image.py 项目: Pelgrum/mpop
    def geotiff_save(self, filename, compression=6,
                     tags=None, gdal_options=None,
                     blocksize=0, geotransform=None,
                     spatialref=None, floating_point=False):
        """Save the image to the given *filename* in geotiff_ format, with the
        *compression* level in [0, 9]. 0 means not compressed. The *tags*
        argument is a dict of tags to include in the image (as metadata).  By
        default it uses the 'area' instance to generate geotransform and
        spatialref information, this can be overwritten by the arguments
        *geotransform* and *spatialref*. *floating_point* allows the saving of
        'L' mode images in floating point format if set to True.
        
        .. _geotiff: http://trac.osgeo.org/geotiff/
        """
        from osgeo import gdal, osr
        
        raster = gdal.GetDriverByName("GTiff")

        if floating_point:
            if self.mode != "L":
                raise ValueError("Image must be in 'L' mode for floating point"
                                 " geotif saving")
            channels = [self.channels[0].astype(np.float64)]
            fill_value = self.fill_value or 0
            gformat = gdal.GDT_Float64
        else:
            channels, fill_value = self._finalize()
            gformat = gdal.GDT_Byte

        LOG.debug("Saving to GeoTiff.")

        if tags is not None:
            self.tags.update(tags)
        if gdal_options is not None:
            self.gdal_options.update(gdal_options)

        g_opts = ["=".join(i) for i in self.gdal_options.items()]

        if compression != 0:
            g_opts.append("COMPRESS=DEFLATE")
            g_opts.append("ZLEVEL=" + str(compression))

        if blocksize != 0:
            g_opts.append("TILED=YES")
            g_opts.append("BLOCKXSIZE=" + str(blocksize))
            g_opts.append("BLOCKYSIZE=" + str(blocksize))
            

        if(self.mode == "L"):
            ensure_dir(filename)
            if fill_value is not None:
                dst_ds = raster.Create(filename, 
                                       self.width,
                                       self.height, 
                                       1, 
                                       gformat,
                                       g_opts)
            else:
                g_opts.append("ALPHA=YES")
                dst_ds = raster.Create(filename, 
                                       self.width, 
                                       self.height, 
                                       2, 
                                       gformat,
                                       g_opts)
            self._gdal_write_channels(dst_ds, channels, 255, fill_value)
        elif(self.mode == "LA"):
            ensure_dir(filename)
            g_opts.append("ALPHA=YES")
            dst_ds = raster.Create(filename, 
                                   self.width, 
                                   self.height, 
                                   2, 
                                   gformat,
                                   g_opts)
            self._gdal_write_channels(dst_ds,
                                      channels[:-1], channels[1],
                                      fill_value)
        elif(self.mode == "RGB"):
            ensure_dir(filename)
            if fill_value is not None:
                dst_ds = raster.Create(filename, 
                                       self.width, 
                                       self.height, 
                                       3, 
                                       gformat,
                                       g_opts)
            else:
                g_opts.append("ALPHA=YES")
                dst_ds = raster.Create(filename, 
                                       self.width, 
                                       self.height, 
                                       4, 
                                       gformat,
                                       g_opts)

            self._gdal_write_channels(dst_ds, channels, 255, fill_value)

        elif(self.mode == "RGBA"):
            ensure_dir(filename)
            g_opts.append("ALPHA=YES")
            dst_ds = raster.Create(filename, 
                                   self.width, 
                                   self.height, 
                                   4, 
                                   gformat,
                                   g_opts)

            self._gdal_write_channels(dst_ds, channels[:-1], channels[3], fill_value)
        else:
            raise NotImplementedError("Saving to GeoTIFF using image mode"
                                      " %s is not implemented."%self.mode)


                
        # Create raster GeoTransform based on upper left corner and pixel
        # resolution ... if not overwritten by argument geotranform.

        if geotransform:
            dst_ds.SetGeoTransform(geotransform)
            if spatialref:
                if not isinstance(spatialref, str):
                    spatialref = spatialref.ExportToWkt()
                dst_ds.SetProjection(spatialref)
        else:
            try:
                from pyresample import utils
                from mpop.projector import get_area_def
            
                area = get_area_def(self.area)
            except (utils.AreaNotFound, AttributeError):
                area = self.area


            try:
                adfgeotransform = [area.area_extent[0], area.pixel_size_x, 0,
                                   area.area_extent[3], 0, -area.pixel_size_y]
                dst_ds.SetGeoTransform(adfgeotransform)
                srs = osr.SpatialReference()
                srs.ImportFromProj4(area.proj4_string)
                srs.SetProjCS(area.proj_id)
                try:
                    srs.SetWellKnownGeogCS(area.proj_dict['ellps'])
                except KeyError:
                    pass
                try:
                    # Check for epsg code.
                    srs.SetAuthority('PROJCS', 'EPSG',
                                     int(area.proj_dict['init'].
                                         split('epsg:')[1]))
                except (KeyError, IndexError):
                    pass
                srs = srs.ExportToWkt()
                dst_ds.SetProjection(srs)
            except AttributeError:
                LOG.exception("Could not load geographic data, invalid area")

        self.tags.update({'TIFFTAG_DATETIME':
                          self.time_slot.strftime("%Y:%m:%d %H:%M:%S")})

        dst_ds.SetMetadata(self.tags, '')
        
        # Close the dataset
        
        dst_ds = None
示例#8
0
    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]))
示例#9
0
    def geotiff_save(
        self, filename, compression=6, tags=None, gdal_options=None, blocksize=0, geotransform=None, spatialref=None
    ):
        """Save the image to the given *filename* in geotiff_ format, with the
        *compression* level in [0, 9]. 0 means not compressed. The *tags*
        argument is a dict of tags to include in the image (as metadata).
        By default it uses the 'area' instance to generate geotransform and spatialref
        information, this can be overwritte by the arguments *geotransform* and
        *spatialref*.
        
        .. _geotiff: http://trac.osgeo.org/geotiff/
        """
        from osgeo import gdal, osr

        raster = gdal.GetDriverByName("GTiff")

        channels, fill_value = self._finalize()

        LOG.debug("Saving to GeoTiff.")

        if tags is not None:
            self.tags.update(tags)
        if gdal_options is not None:
            self.gdal_options.update(gdal_options)

        g_opts = ["=".join(i) for i in self.gdal_options.items()]

        if compression != 0:
            g_opts.append("COMPRESS=DEFLATE")
            g_opts.append("ZLEVEL=" + str(compression))

        if blocksize != 0:
            g_opts.append("TILED=YES")
            g_opts.append("BLOCKXSIZE=" + str(blocksize))
            g_opts.append("BLOCKYSIZE=" + str(blocksize))

        if self.mode == "L":
            ensure_dir(filename)
            if fill_value is not None:
                dst_ds = raster.Create(filename, self.width, self.height, 1, gdal.GDT_Byte, g_opts)
            else:
                dst_ds = raster.Create(filename, self.width, self.height, 2, gdal.GDT_Byte, g_opts)
            self._gdal_write_channels(dst_ds, channels, 255, fill_value)
        elif self.mode == "RGB":
            ensure_dir(filename)
            if fill_value is not None:
                dst_ds = raster.Create(filename, self.width, self.height, 3, gdal.GDT_Byte, g_opts)
            else:
                dst_ds = raster.Create(filename, self.width, self.height, 4, gdal.GDT_Byte, g_opts)

            self._gdal_write_channels(dst_ds, channels, 255, fill_value)

        elif self.mode == "RGBA":
            ensure_dir(filename)
            dst_ds = raster.Create(filename, self.width, self.height, 4, gdal.GDT_Byte, g_opts)

            self._gdal_write_channels(dst_ds, channels, channels[3], fill_value)
        else:
            raise NotImplementedError("Saving to GeoTIFF using image mode" " %s is not implemented." % self.mode)

        # Create raster GeoTransform based on upper left corner and pixel
        # resolution ... if not overwritten by argument geotranform.

        if geotransform:
            dst_ds.SetGeoTransform(geotransform)
            if spatialref:
                if not isinstance(spatialref, str):
                    spatialref = spatialref.ExportToWkt()
                dst_ds.SetProjection(spatialref)
        else:
            try:
                from pyresample import utils
                from mpop.projector import get_area_def

                area = get_area_def(self.area_id)
            except (utils.AreaNotFound, AttributeError):
                area = self.area_id

            try:
                adfgeotransform = [
                    area.area_extent[0],
                    area.pixel_size_x,
                    0,
                    area.area_extent[3],
                    0,
                    -area.pixel_size_y,
                ]
                dst_ds.SetGeoTransform(adfgeotransform)
                srs = osr.SpatialReference()
                srs.SetProjCS(area.proj_id)
                srs.ImportFromProj4(area.proj4_string)
                srs = srs.ExportToWkt()
                dst_ds.SetProjection(srs)
            except AttributeError:
                LOG.exception("Could not load geographic data, invalid area")

        self.tags.update({"TIFFTAG_DATETIME": self.time_slot.strftime("%Y:%m:%d %H:%M:%S")})

        dst_ds.SetMetadata(self.tags, "")

        # Close the dataset

        dst_ds = None