Esempio n. 1
0
def main():
    usage = '''
Usage:
------------------------------------------------

RX anomaly detection for multi- and hyperspectral images

python %s [OPTIONS]  filename

Options:
  
  -h         this help
  
-------------------------------------------------''' % sys.argv[0]
    options, args = getopt.getopt(sys.argv[1:], 'h')
    for option, value in options:
        if option == '-h':
            print usage
            return
    gdal.AllRegister()
    infile = args[0]
    path = os.path.dirname(infile)
    basename = os.path.basename(infile)
    root, ext = os.path.splitext(basename)
    outfile = path + '/' + root + '_rx' + ext
    print '------------ RX ---------------'
    print time.asctime()
    print 'Input %s' % infile
    start = time.time()
    #  input image, convert to ENVI format
    inDataset = gdal.Open(infile, GA_ReadOnly)
    cols = inDataset.RasterXSize
    rows = inDataset.RasterYSize
    projection = inDataset.GetProjection()
    geotransform = inDataset.GetGeoTransform()
    driver = gdal.GetDriverByName('ENVI')
    enviDataset = driver.CreateCopy('imagery/entmp', inDataset)
    inDataset = None
    enviDataset = None
    #  RX-algorithm
    img = envi.open('imagery/entmp.hdr')
    arr = img.load()
    rx = RX(background=calc_stats(arr))
    res = rx(arr)
    #  output
    driver = gdal.GetDriverByName('GTiff')
    outDataset = driver.Create(outfile,cols,rows,1,\
                                    GDT_Float32)
    if geotransform is not None:
        outDataset.SetGeoTransform(geotransform)
    if projection is not None:
        outDataset.SetProjection(projection)
    outBand = outDataset.GetRasterBand(1)
    outBand.WriteArray(np.asarray(res, np.float32), 0, 0)
    outBand.FlushCache()
    outDataset = None
    os.remove('imagery/entmp')
    os.remove('imagery/entmp.hdr')
    print 'Result written to %s' % outfile
    print 'elapsed time: %s' % str(time.time() - start)
Esempio n. 2
0
    def __call__(self, X):
        '''Compute ACE detector scores for X.

        Arguments:

            `X` (numpy.ndarray):

                For an image with shape (R, C, B), `X` can be a vector of
                length B (single pixel) or an ndarray of shape (R, C, B) or
                (R * C, B).

        Returns numpy.ndarray or float:

            The return value will be the RX detector score (squared Mahalanobis
            distance) for each pixel given.  If `X` is a single pixel, a float
            will be returned; otherwise, the return value will be an ndarray
            of floats with one less dimension than the input.
        '''
        from spectral.algorithms.algorithms import calc_stats
        if not isinstance(X, np.ndarray):
           raise TypeError('Expected a numpy.ndarray.')

        shape = X.shape

        if X.ndim == 1:
            # Compute ACE score for single pixel
            if self._background.mean is not None:
                X = X - self._background.mean
            z = self._background.sqrt_inv_cov.dot(X)
            return z.dot(self._P).dot(z) / (z.dot(z))

        if self._background is None:
            self.set_background(calc_stats(X))

        if self.vectorize:
            # Compute all scores at once
            
            if self._background.mean is not None:
                X = X - self._background.mean

            if X.ndim == 3:
                X = X.reshape((-1, X.shape[-1]))

            z = self._background.sqrt_inv_cov.dot(X.T).T
            zP = np.dot(z, self._P)
            zPz = np.einsum('ij,ij->i', zP, z)
            zz = np.einsum('ij,ij->i', z, z)

            return (zPz / zz).reshape(shape[:-1])

        else:
            # Call recursively for each pixel
            return np.apply_along_axis(self, -1, X)
Esempio n. 3
0
    def __call__(self, X):
        '''Compute ACE detector scores for X.

        Arguments:

            `X` (numpy.ndarray):

                For an image with shape (R, C, B), `X` can be a vector of
                length B (single pixel) or an ndarray of shape (R, C, B) or
                (R * C, B).

        Returns numpy.ndarray or float:

            The return value will be the RX detector score (squared Mahalanobis
            distance) for each pixel given.  If `X` is a single pixel, a float
            will be returned; otherwise, the return value will be an ndarray
            of floats with one less dimension than the input.
        '''
        from spectral.algorithms.algorithms import calc_stats
        if not isinstance(X, np.ndarray):
            raise TypeError('Expected a numpy.ndarray.')

        shape = X.shape

        if X.ndim == 1:
            # Compute ACE score for single pixel
            if self._background.mean is not None:
                X = X - self._background.mean
            z = self._background.sqrt_inv_cov.dot(X)
            return z.dot(self._P).dot(z) / (z.dot(z))

        if self._background is None:
            self.set_background(calc_stats(X))

        if self.vectorize:
            # Compute all scores at once

            if self._background.mean is not None:
                X = X - self._background.mean

            if X.ndim == 3:
                X = X.reshape((-1, X.shape[-1]))

            z = self._background.sqrt_inv_cov.dot(X.T).T
            zP = np.dot(z, self._P)
            zPz = np.einsum('ij,ij->i', zP, z)
            zz = np.einsum('ij,ij->i', z, z)

            return (zPz / zz).reshape(shape[:-1])

        else:
            # Call recursively for each pixel
            return np.apply_along_axis(self, -1, X)
Esempio n. 4
0
def main():
    gdal.AllRegister()
    path = auxil.select_directory('Input directory')
    if path:
        os.chdir(path)


#  input image, convert to ENVI format
    infile = auxil.select_infile(title='Image file')
    if infile:
        inDataset = gdal.Open(infile, GA_ReadOnly)
        cols = inDataset.RasterXSize
        rows = inDataset.RasterYSize
        projection = inDataset.GetProjection()
        geotransform = inDataset.GetGeoTransform()
        driver = gdal.GetDriverByName('ENVI')
        enviDataset=driver\
           .CreateCopy('entmp',inDataset)
        inDataset = None
        enviDataset = None
    else:
        return
    outfile, outfmt= \
           auxil.select_outfilefmt(title='Output file')
    #  RX-algorithm
    img = envi.open('entmp.hdr')
    arr = img.load()
    rx = RX(background=calc_stats(arr))
    res = rx(arr)
    #  output
    driver = gdal.GetDriverByName(outfmt)
    outDataset = driver.Create(outfile,cols,rows,1,\
                                    GDT_Float32)
    if geotransform is not None:
        outDataset.SetGeoTransform(geotransform)
    if projection is not None:
        outDataset.SetProjection(projection)
    outBand = outDataset.GetRasterBand(1)
    outBand.WriteArray(np.asarray(res, np.float32), 0, 0)
    outBand.FlushCache()
    outDataset = None
    print 'Result written to %s' % outfile
Esempio n. 5
0
    def __call__(self, X):
        '''Applies the RX anomaly detector to X.

        Arguments:

            `X` (numpy.ndarray):

                For an image with shape (R, C, B), `X` can be a vector of
                length B (single pixel) or an ndarray of shape (R, C, B) or
                (R * C, B).

        Returns numpy.ndarray or float:

            The return value will be the RX detector score (squared Mahalanobis
            distance) for each pixel given.  If `X` is a single pixel, a float
            will be returned; otherwise, the return value will be an ndarray
            of floats with one less dimension than the input.
        '''
        from spectral.algorithms.algorithms import calc_stats
        if not isinstance(X, np.ndarray):
            raise TypeError('Expected a numpy.ndarray.')

        if self.background is None:
            self.set_background(calc_stats(X))

        X = (X - self.background.mean)
        C_1 = self.background.inv_cov

        ndim = X.ndim
        shape = X.shape

        if ndim == 1:
            return X.dot(C_1).dot(X)

        if ndim == 3:
            X = X.reshape((-1, X.shape[-1]))

        A = X.dot(C_1)
        r = np.einsum('ij,ij->i', A, X)
        return r.reshape(shape[:-1])
Esempio n. 6
0
    def __call__(self, X):
        '''Applies the RX anomaly detector to X.

        Arguments:

            `X` (numpy.ndarray):

                For an image with shape (R, C, B), `X` can be a vector of
                length B (single pixel) or an ndarray of shape (R, C, B) or
                (R * C, B).

        Returns numpy.ndarray or float:

            The return value will be the RX detector score (squared Mahalanobis
            distance) for each pixel given.  If `X` is a single pixel, a float
            will be returned; otherwise, the return value will be an ndarray
            of floats with one less dimension than the input.
        '''
        from spectral.algorithms.algorithms import calc_stats
        if not isinstance(X, np.ndarray):
            raise TypeError('Expected a numpy.ndarray.')

        if self.background is None:
            self.set_background(calc_stats(X))

        X = (X - self.background.mean)
        C_1 = self.background.inv_cov

        ndim = X.ndim
        shape = X.shape

        if ndim == 1:
            return X.dot(C_1).dot(X)

        if ndim == 3:
            X = X.reshape((-1, X.shape[-1]))

        A = X.dot(C_1)
        r = np.einsum('ij,ij->i', A, X)
        return r.reshape(shape[:-1])
Esempio n. 7
0
def main():
    gdal.AllRegister()
    path = auxil.select_directory("Input directory")
    if path:
        os.chdir(path)
    #  input image, convert to ENVI format
    infile = auxil.select_infile(title="Image file")
    if infile:
        inDataset = gdal.Open(infile, GA_ReadOnly)
        cols = inDataset.RasterXSize
        rows = inDataset.RasterYSize
        projection = inDataset.GetProjection()
        geotransform = inDataset.GetGeoTransform()
        driver = gdal.GetDriverByName("ENVI")
        enviDataset = driver.CreateCopy("entmp", inDataset)
        inDataset = None
        enviDataset = None
    else:
        return
    outfile, outfmt = auxil.select_outfilefmt(title="Output file")
    #  RX-algorithm
    img = envi.open("entmp.hdr")
    arr = img.load()
    rx = RX(background=calc_stats(arr))
    res = rx(arr)
    #  output
    driver = gdal.GetDriverByName(outfmt)
    outDataset = driver.Create(outfile, cols, rows, 1, GDT_Float32)
    if geotransform is not None:
        outDataset.SetGeoTransform(geotransform)
    if projection is not None:
        outDataset.SetProjection(projection)
    outBand = outDataset.GetRasterBand(1)
    outBand.WriteArray(np.asarray(res, np.float32), 0, 0)
    outBand.FlushCache()
    outDataset = None
    print "Result written to %s" % outfile
Esempio n. 8
0
def matched_filter(X, target, background=None, window=None, cov=None):
    r'''Computes a linear matched filter target detector score.

    Usage:

        y = matched_filter(X, target, background)

        y = matched_filter(X, target, window=<win> [, cov=<cov>])
        
    Given target/background means and a common covariance matrix, the matched
    filter response is given by:

    .. math::

        y=\frac{(\mu_t-\mu_b)^T\Sigma^{-1}(x-\mu_b)}{(\mu_t-\mu_b)^T\Sigma^{-1}(\mu_t-\mu_b)}

    where :math:`\mu_t` is the target mean, :math:`\mu_b` is the background
    mean, and :math:`\Sigma` is the covariance.

    Arguments:

        `X` (numpy.ndarray):

            For the first calling method shown, `X` can be an image with
            shape (R, C, B) or an ndarray of shape (R * C, B). If the
            `background` keyword is given, it will be used for the image
            background statistics; otherwise, background statistics will be
            computed from `X`.

            If the `window` keyword is given, `X` must be a 3-dimensional
            array and background statistics will be computed for each point
            in the image using a local window defined by the keyword.

        `target` (ndarray):

            Length-K vector specifying the target to be detected.

        `background` (`GaussianStats`):

            The Gaussian statistics for the background (e.g., the result
            of calling :func:`calc_stats` for an image). This argument is not
            required if `window` is given.

        `window` (2-tuple of odd integers):

            Must have the form (`inner`, `outer`), where the two values
            specify the widths (in pixels) of inner and outer windows centered
            about the pixel being evaulated. Both values must be odd integers.
            The background mean and covariance will be estimated from pixels
            in the outer window, excluding pixels within the inner window. For
            example, if (`inner`, `outer`) = (5, 21), then the number of
            pixels used to estimate background statistics will be
            :math:`21^2 - 5^2 = 416`. If this argument is given, `background`
            is not required (and will be ignored, if given).

            The window is modified near image borders, where full, centered
            windows cannot be created. The outer window will be shifted, as
            needed, to ensure that the outer window still has height and width
            `outer` (in this situation, the pixel being evaluated will not be
            at the center of the outer window). The inner window will be
            clipped, as needed, near image borders. For example, assume an
            image with 145 rows and columns. If the window used is
            (5, 21), then for the image pixel at (0, 0) (upper left corner),
            the the inner window will cover `image[:3, :3]` and the outer
            window will cover `image[:21, :21]`. For the pixel at (50, 1), the
            inner window will cover `image[48:53, :4]` and the outer window
            will cover `image[40:51, :21]`.
            
        `cov` (ndarray):

            An optional covariance to use. If this parameter is given, `cov`
            will be used for all matched filter calculations (background
            covariance will not be recomputed in each window) and only the
            background mean will be recomputed in each window. If the
            `window` argument is specified, providing `cov` will allow the
            result to be computed *much* faster.

    Returns numpy.ndarray:

        The return value will be the matched filter scores distance) for each
        pixel given.  If `X` has shape (R, C, K), the returned ndarray will
        have shape (R, C).
    '''
    if background is not None and window is not None:
        raise ValueError('`background` and `window` are mutually ' \
                         'exclusive arguments.')
    if window is not None:
        from .spatial import map_outer_window_stats
        def mf_wrapper(bg, x):
            return MatchedFilter(bg, target)(x)
        return map_outer_window_stats(mf_wrapper, X, window[0], window[1],
                                      dim_out=1, cov=cov)
    else:
        from spectral.algorithms.algorithms import calc_stats
        if background is None:
            background = calc_stats(X)
        return MatchedFilter(background, target)(X)
Esempio n. 9
0
def matched_filter(X, target, background=None, window=None, cov=None):
    r'''Computes a linear matched filter target detector score.

    Usage:

        y = matched_filter(X, target, background)

        y = matched_filter(X, target, window=<win> [, cov=<cov>])
        
    Given target/background means and a common covariance matrix, the matched
    filter response is given by:

    .. math::

        y=\frac{(\mu_t-\mu_b)^T\Sigma^{-1}(x-\mu_b)}{(\mu_t-\mu_b)^T\Sigma^{-1}(\mu_t-\mu_b)}

    where :math:`\mu_t` is the target mean, :math:`\mu_b` is the background
    mean, and :math:`\Sigma` is the covariance.

    Arguments:

        `X` (numpy.ndarray):

            For the first calling method shown, `X` can be an image with
            shape (R, C, B) or an ndarray of shape (R * C, B). If the
            `background` keyword is given, it will be used for the image
            background statistics; otherwise, background statistics will be
            computed from `X`.

            If the `window` keyword is given, `X` must be a 3-dimensional
            array and background statistics will be computed for each point
            in the image using a local window defined by the keyword.

        `target` (ndarray):

            Length-K vector specifying the target to be detected.

        `background` (`GaussianStats`):

            The Gaussian statistics for the background (e.g., the result
            of calling :func:`calc_stats` for an image). This argument is not
            required if `window` is given.

        `window` (2-tuple of odd integers):

            Must have the form (`inner`, `outer`), where the two values
            specify the widths (in pixels) of inner and outer windows centered
            about the pixel being evaulated. Both values must be odd integers.
            The background mean and covariance will be estimated from pixels
            in the outer window, excluding pixels within the inner window. For
            example, if (`inner`, `outer`) = (5, 21), then the number of
            pixels used to estimate background statistics will be
            :math:`21^2 - 5^2 = 416`. If this argument is given, `background`
            is not required (and will be ignored, if given).

            The window is modified near image borders, where full, centered
            windows cannot be created. The outer window will be shifted, as
            needed, to ensure that the outer window still has height and width
            `outer` (in this situation, the pixel being evaluated will not be
            at the center of the outer window). The inner window will be
            clipped, as needed, near image borders. For example, assume an
            image with 145 rows and columns. If the window used is
            (5, 21), then for the image pixel at (0, 0) (upper left corner),
            the the inner window will cover `image[:3, :3]` and the outer
            window will cover `image[:21, :21]`. For the pixel at (50, 1), the
            inner window will cover `image[48:53, :4]` and the outer window
            will cover `image[40:51, :21]`.
            
        `cov` (ndarray):

            An optional covariance to use. If this parameter is given, `cov`
            will be used for all matched filter calculations (background
            covariance will not be recomputed in each window). Only the
            background mean will be recomputed in each window). If the
            `window` argument is specified, providing `cov` will allow the
            result to be computed *much* faster.

    Returns numpy.ndarray:

        The return value will be the matched filter scores distance) for each
        pixel given.  If `X` has shape (R, C, K), the returned ndarray will
        have shape (R, C).
    '''
    if background is not None and window is not None:
        raise ValueError('`background` and `window` are mutually ' \
                         'exclusive arguments.')
    if window is not None:
        from .spatial import map_outer_window_stats

        def mf_wrapper(bg, x):
            return MatchedFilter(bg, target)(x)

        return map_outer_window_stats(mf_wrapper,
                                      X,
                                      window[0],
                                      window[1],
                                      dim_out=1,
                                      cov=cov)
    else:
        from spectral.algorithms.algorithms import calc_stats
        if background is None:
            background = calc_stats(X)
        return MatchedFilter(background, target)(X)