Beispiel #1
0
def isBandAllZeroes(filename, band=0):
    """
    Checks the specified band within a file to see if it is all zeroes.
    band should be 0 based.
    
    Returns True if all zeroes, False otherwise.
    
    This function firstly checks the stats if present and uses this
    and assumes that they are correct.
    
    If they are not present, then the band is read and the values determined.
    
    """

    info = fileinfo.ImageFileStats(filename)
    maxVal = info[band].max
    if maxVal is not None:
        # we have valid stats
        return maxVal == 0

    # otherwise read the thing with rios
    infiles = applier.FilenameAssociations()
    infiles.input = filename

    outfiles = applier.FilenameAssociations()

    otherArgs = applier.OtherInputs()
    otherArgs.nonZeroFound = False
    otherArgs.band = band

    applier.apply(riosAllZeroes, infiles, outfiles, otherArgs)

    return not otherArgs.nonZeroFound
Beispiel #2
0
def makeSaturationMask(fmaskConfig, radiancefile, outMask):
    """
    Checks the radianceFile and creates a mask with
    1's where there is saturation in one of more visible bands.
    0 otherwise. 
    
    The fmaskConfig parameter should be an instance of
    :class:`fmask.config.FmaskConfig`. This is used to determine
    which bands are visible.
    
    This mask is advisible since the whiteness test Eqn 2. 
    and Equation 6 are affected by saturated pixels and
    may determine a pixel is not cloud when it is.
    
    The format of outMask will be the current 
    RIOS default format.
    
    It is assumed that the input radianceFile has values in the
    range 0-255 and saturated pixels are set to 255.
    
    """
    inputs = applier.FilenameAssociations()
    inputs.radiance = radiancefile
    
    outputs = applier.FilenameAssociations()
    outputs.mask = outMask
    
    otherargs = applier.OtherInputs()
    otherargs.radianceBands = fmaskConfig.bands
    
    controls = applier.ApplierControls()
    controls.progress = cuiprogress.GDALProgressBar()
    
    applier.apply(riosSaturationMask, inputs, outputs, 
                otherargs, controls=controls)
Beispiel #3
0
def runCorrection(insigma, inlinc, inpix, outsigma, thetaref=39.0, nFactor=1.0, filterSize=None):

    controls = applier.ApplierControls()
    
    # Set up input images
    infiles = applier.FilenameAssociations()
    infiles.insigma = insigma
    infiles.inlinc = inlinc
    infiles.inpix = inpix
    
    # Set up output image
    outfiles = applier.FilenameAssociations()
    outfiles.outimage = outsigma

    # Set format for output image
    outControls = getOutDriver(outsigma)

    # Set options
    controls.setOutputDriverName(outControls['gdalFormat'])
    controls.setCreationOptions(outControls['gdalCOOptions'])
    controls.setCalcStats(outControls['calcStats'])

    # Set up parameters
    otherargs = applier.OtherInputs()
    otherargs.thetaref = thetaref
    otherargs.nFactor = nFactor
    otherargs.filterSize = filterSize
    
    # Run correction
    controls.progress = cuiprogress.CUIProgressBar()
    applier.apply(castelCorrection, infiles, outfiles, otherargs, controls=controls)
Beispiel #4
0
def makeTOAReflectance(infile, mtlFile, anglesfile, outfile):
    """
    Main routine - does the calculation

    The eqn for TOA reflectance, p, is
    p = pi * L * d^2 / E * cos(theta)
    
    d = earthSunDistance(date)
    L = image pixel (radiance)
    E = exoatmospheric irradiance for the band, and 
    theta = solar zenith angle.
    
    Assumes infile is radiance values in DN from USGS.
    mtlFile is the .mtl file.
    outfile will be created in the default format that RIOS
    is configured to use and will be top of atmosphere 
    reflectance values *10000. Also assumes that the 
    angles image file is scaled as radians*100, and has layers for
    satAzimuth, satZenith, sunAzimuth, sunZenith, in that order. 
    
    """
    mtlInfo = config.readMTLFile(mtlFile)
    spaceCraft = mtlInfo['SPACECRAFT_ID']
    date = mtlInfo['DATE_ACQUIRED']
    date = date.replace('-', '')

    inputs = applier.FilenameAssociations()
    inputs.infile = infile
    inputs.angles = anglesfile

    outputs = applier.FilenameAssociations()
    outputs.outfile = outfile

    otherinputs = applier.OtherInputs()
    otherinputs.earthSunDistance = earthSunDistance(date)
    otherinputs.earthSunDistanceSq = otherinputs.earthSunDistance * otherinputs.earthSunDistance
    otherinputs.esun = ESUN_LOOKUP[spaceCraft]
    gains, offsets = readGainsOffsets(mtlInfo)
    otherinputs.gains = gains
    otherinputs.offsets = offsets
    otherinputs.anglesToRadians = 0.01
    otherinputs.outNull = 32767
    imginfo = fileinfo.ImageInfo(infile)
    otherinputs.inNull = imginfo.nodataval[0]

    controls = applier.ApplierControls()
    if platform.system() in ["Linux", "Darwin"]:
        controls.setNumThreads(multiprocessing.cpu_count())
        controls.setJobManagerType("multiprocessing")

    controls.progress = cuiprogress.GDALProgressBar()
    controls.setStatsIgnore(otherinputs.outNull)
    controls.setCalcStats(False)

    applier.apply(riosTOA, inputs, outputs, otherinputs, controls=controls)

    # Explicitly set the null value in the output
    ds = gdal.Open(outfile, gdal.GA_Update)
    for i in range(ds.RasterCount):
        ds.GetRasterBand(i + 1).SetNoDataValue(otherinputs.outNull)
Beispiel #5
0
def main():
    metadataFile = sys.argv[1]
    imgFile = sys.argv[2]
    toaFile = sys.argv[3]
    d = float(sys.argv[4])
    outfile = "%s_envi.exp" % (metadataFile.split('.')[0])

    if os.path.exists(toaFile):
        os.remove(toaFile)

    (calFactors, solarZenithAngle, eSun, layerNames) = getParams(metadataFile)

    infiles = applier.FilenameAssociations()
    outfiles = applier.FilenameAssociations()
    otherargs = applier.OtherInputs()
    controls = applier.ApplierControls()

    infiles.raw = imgFile
    outfiles.toaFile = toaFile

    otherargs.calFactors = calFactors
    otherargs.solarZenithAngle = solarZenithAngle
    otherargs.pi = 3.14159265358979323846
    otherargs.d = d
    otherargs.eSun = eSun

    info = fileinfo.ImageInfo(imgFile)
    xMin = np.floor(info.xMin)
    xMax = np.ceil(info.xMax)
    yMin = np.floor(info.yMin)
    yMax = np.ceil(info.yMax)
    proj = info.projection
    transform = info.transform
    xRes = info.xRes
    yRes = info.yRes
    otherargs.outNull = 0
    print(otherargs.outNull)

    controls.setStatsIgnore(otherargs.outNull)
    controls.setOutputDriverName('GTiff')
    controls.setCreationOptions(['COMPRESS=LZW'])
    controls.setCreationOptions(['BIGTIFF=IF_SAFER'])

    pixgrid = pixelgrid.PixelGridDefn(geotransform=transform,
                                      xMin=xMin,
                                      xMax=xMax,
                                      yMin=yMin,
                                      yMax=yMax,
                                      xRes=xRes,
                                      yRes=yRes,
                                      projection=proj)
    print(pixgrid)
    controls.setReferencePixgrid(pixgrid)
    controls.setLayerNames(layerNames)
    controls.setWindowXsize(20)
    controls.setWindowYsize(20)
    progress = cuiprogress.GDALProgressBar()
    controls.setProgress(progress)

    applier.apply(doTOA, infiles, outfiles, otherargs, controls=controls)
Beispiel #6
0
def run(data):
    # Load the machine learning estimators
    (greenEstimator,nonGreenEstimator,bareEstimator) = load_estimators()
    # Read in the FC ML Models
    otherargs = applier.OtherInputs()
    otherargs.greenEstimator = greenEstimator
    otherargs.nonGreenEstimator = nonGreenEstimator
    otherargs.bareEstimator = bareEstimator
    # Setup file name associations
    infiles = applier.FilenameAssociations()
    outfiles = applier.FilenameAssociations()

    # Loop for each image
    for feature in data.get("features"):
        print("Found GeoJSON feature:\n%s" % feature)
        # Find the filename
        rel_image_path = feature["properties"].get(AOICLIPPED)
        print("Processing %s" % rel_image_path)
        infiles.nbar = "/tmp/input/%s" % rel_image_path
        outfiles.fc = os.path.splitext("/tmp/output/%s" % rel_image_path)[0] + "_fc.tif"
        # Set up processing controls
        controls = applier.ApplierControls()
        controls.setStatsIgnore(0)
        controls.setOutputDriverName("GTIFF")
        controls.setCreationOptions(["COMPRESS=DEFLATE",
                                     "ZLEVEL=9",
                                     "BIGTIFF=YES",
                                     "TILED=YES",
                                     "INTERLEAVE=BAND",
                                     "NUM_THREADS=ALL_CPUS"])
        # Run the model
        applier.apply(unmixfc, infiles, outfiles, otherargs, controls=controls)
        print("Feature has an FC image at %s" % outfiles.fc)

    return data
def makeAnglesImage(templateimg, outfile, nadirLine, extentSunAngles,
                    satAzimuth, imgInfo):
    """
    Make a single output image file of the sun and satellite angles for every
    pixel in the template image.

    """
    imgInfo = fileinfo.ImageInfo(templateimg)

    infiles = applier.FilenameAssociations()
    outfiles = applier.FilenameAssociations()
    otherargs = applier.OtherInputs()
    controls = applier.ApplierControls()

    infiles.img = templateimg
    outfiles.angles = outfile

    (ctrLat, ctrLong) = getCtrLatLong(imgInfo)
    otherargs.R = localRadius(ctrLat)
    otherargs.nadirLine = nadirLine
    otherargs.xMin = imgInfo.xMin
    otherargs.xMax = imgInfo.xMax
    otherargs.yMin = imgInfo.yMin
    otherargs.yMax = imgInfo.yMax
    otherargs.extentSunAngles = extentSunAngles
    otherargs.satAltitude = 705000  # Landsat nominal altitude in metres
    otherargs.satAzimuth = satAzimuth
    otherargs.radianScale = 100  # Store pixel values as (radians * radianScale)
    controls.setStatsIgnore(500)

    applier.apply(makeAngles, infiles, outfiles, otherargs, controls=controls)
Beispiel #8
0
def run():
    """
    Run the test
    """
    allOK = True
    
    riostestutils.reportStart(TESTNAME)

    ramp1 = 'ramp1.img'
    ramp2 = 'ramp2.img'
    riostestutils.genRampImageFile(ramp1)

    # Second file is same as first, but shifted 100 pixels right and down. 
    xLeft = riostestutils.DEFAULT_XLEFT + OFFSET_2ND_IMAGE
    yTop = riostestutils.DEFAULT_YTOP - OFFSET_2ND_IMAGE
    riostestutils.genRampImageFile(ramp2, xLeft=xLeft, yTop=yTop)
    
    # Set up some RIOS calls
    infiles = applier.FilenameAssociations()
    outfiles = applier.FilenameAssociations()
    otherargs = applier.OtherInputs()
    controls = applier.ApplierControls()

    # Simplest check. Can we get back the coordinates from a single input file.     
    infiles.img = ramp1
    otherargs.tstPixList = []
    otherargs.centresList = []
    applier.apply(getCoords, infiles, outfiles, otherargs, controls=controls)
    ok = checkCoords('1 file, overlap=0', otherargs, TSTPIX_1FILE_NOOVERLAP, CENTRES_1FILE_NOOVERLAP)
    if not ok: allOK = False

    # Single input file, with an overlap set
    otherargs.tstPixList = []
    otherargs.centresList = []
    controls.setOverlap(OLAP)
    applier.apply(getCoords, infiles, outfiles, otherargs, controls=controls)
    ok = checkCoords('1 file, overlap=2', otherargs, TSTPIX_1FILE_OVERLAP2, CENTRES_1FILE_OVERLAP2)
    if not ok: allOK = False

    # Two input files, with an overlap set
    infiles.img = [ramp1, ramp2]
    otherargs.tstPixList = []
    otherargs.centresList = []
    controls.setOverlap(OLAP)
    applier.apply(getCoords, infiles, outfiles, otherargs, controls=controls)
    ok = checkCoords('2 files, overlap=2', otherargs, TSTPIX_2FILE_OVERLAP2, CENTRES_2FILE_OVERLAP2)
    if not ok: allOK = False
    
    # Clean up
    for filename in [ramp1, ramp2]:
        os.remove(filename)
    
    if allOK:
        riostestutils.report(TESTNAME, "Passed")

    
    return allOK
def update_uid_image(uid_img, chng_img, nxt_scr5_img, clrsky_img,
                     obs_day_since_base, tmp_uid_tile):
    from rios import applier
    try:
        import tqdm
        progress_bar = rsgislib.TQDMProgressBar()
    except:
        from rios import cuiprogress
        progress_bar = cuiprogress.GDALProgressBar()

    infiles = applier.FilenameAssociations()
    infiles.uid_img = uid_img
    infiles.chng_img = chng_img
    infiles.nxt_scr5_img = nxt_scr5_img
    infiles.clrsky_img = clrsky_img
    outfiles = applier.FilenameAssociations()
    outfiles.uid_img_out = tmp_uid_tile
    otherargs = applier.OtherInputs()
    otherargs.obs_day_since_base = obs_day_since_base
    aControls = applier.ApplierControls()
    aControls.progress = progress_bar
    aControls.omitPyramids = True
    aControls.calcStats = False

    def _update_uid_img(info, inputs, outputs, otherargs):
        """
        This is an internal rios function
        """
        uid_img_arr = numpy.array(inputs.uid_img,
                                  dtype=numpy.uint32,
                                  copy=True)
        start_year = inputs.uid_img[0]
        chng_feats = inputs.chng_img[0]
        new_chng_pxls = numpy.zeros_like(start_year)
        new_chng_pxls[(start_year == 0) & (chng_feats == 1)] = 1

        chng_scr5_year = inputs.uid_img[4]
        new_scr5_pxls = numpy.zeros_like(chng_scr5_year)
        new_scr5_pxls[(chng_scr5_year == 0)
                      & (inputs.nxt_scr5_img[0] == 1)] = 1

        uid_img_arr[0, new_chng_pxls == 1] = 1970
        uid_img_arr[1, new_chng_pxls == 1] = otherargs.obs_day_since_base
        uid_img_arr[2, inputs.clrsky_img[0] == 1] = 1970
        uid_img_arr[3,
                    inputs.clrsky_img[0] == 1] = otherargs.obs_day_since_base
        uid_img_arr[4, new_scr5_pxls == 1] = 1970
        uid_img_arr[5, new_scr5_pxls == 1] = otherargs.obs_day_since_base

        outputs.uid_img_out = uid_img_arr

    applier.apply(_update_uid_img,
                  infiles,
                  outfiles,
                  otherargs,
                  controls=aControls)
Beispiel #10
0
def calcImgsPxlMode(inputImgs, outputImg, gdalformat, no_data_val=0):
    """
Function which calculates the mode of a group of images.

Warning, this function can be very slow. Use rsgislib.imagecalc.imagePixelColumnSummary

:param inputImgs: the list of images
:param outputImg: the output image file name and path (will be same dimensions as the input)
:param gdalformat: the GDAL image file format of the output image file.

"""
    import scipy.stats
    from rios import applier

    rsgis_utils = rsgislib.RSGISPyUtils()

    datatype = rsgis_utils.getRSGISLibDataTypeFromImg(inputImgs[0])
    numpyDT = rsgis_utils.getNumpyDataType(datatype)

    try:
        import tqdm
        progress_bar = rsgislib.TQDMProgressBar()
    except:
        from rios import cuiprogress
        progress_bar = cuiprogress.GDALProgressBar()

    infiles = applier.FilenameAssociations()
    infiles.images = inputImgs
    outfiles = applier.FilenameAssociations()
    outfiles.outimage = outputImg
    otherargs = applier.OtherInputs()
    otherargs.no_data_val = no_data_val
    otherargs.numpyDT = numpyDT
    aControls = applier.ApplierControls()
    aControls.progress = progress_bar
    aControls.drivername = gdalformat
    aControls.omitPyramids = True
    aControls.calcStats = False

    def _applyCalcMode(info, inputs, outputs, otherargs):
        """
        This is an internal rios function
        """
        image_data = numpy.concatenate(inputs.images,
                                       axis=0).astype(numpy.float32)
        image_data[image_data == otherargs.no_data_val] = numpy.nan
        mode_arr, count_arr = scipy.stats.mode(image_data,
                                               axis=0,
                                               nan_policy='omit')
        outputs.outimage = mode_arr.astype(otherargs.numpyDT)

    applier.apply(_applyCalcMode,
                  infiles,
                  outfiles,
                  otherargs,
                  controls=aControls)
Beispiel #11
0
def predict_for_date(date,
                     input_path,
                     output_path,
                     output_driver='KEA',
                     num_processes=1):
    """Main function to generate the predicted image. Given an input image containing
    per-band model coefficients, outputs a multi-band predicted image over the same area.
    Opening/closing of files, generation of blocks and use of multiprocessing is 
    all handled by RIOS.
    
    date:          The date to predict in YYYY-MM-DD format. 
    input_path:    Path to the input image generated by get_model_coeffs.py.
    output_path:   Path for the output image.
    output_driver: Short driver name for GDAL, e.g. KEA, GTiff.
    num_processes: Number of concurrent processes to use."""

    # Create object to hold input files
    infile = applier.FilenameAssociations()
    infile.coeff_img = input_path

    # Create object to hold output file
    outfile = applier.FilenameAssociations()
    outfile.output_img = output_path

    # ApplierControls object holds details on how processing should be done
    app = applier.ApplierControls()

    # Set output file type
    app.setOutputDriverName(output_driver)

    # Use Python's multiprocessing module
    app.setJobManagerType('multiprocessing')
    app.setNumThreads(num_processes)

    # Convert provided date to ordinal
    ordinal_date = datetime.strptime(date, '%Y-%m-%d').toordinal()

    # Additional arguments - have to be passed as a single object
    other_args = applier.OtherInputs()
    other_args.date_to_predict = ordinal_date

    # Get band names
    try:
        input_img = fileinfo.ImageInfo(infile.coeff_img)
    except:
        sys.exit('Could not find input image.')

    layer_names = np.unique([name.split('_')[0] for name in input_img.lnames])
    app.setLayerNames(layer_names)

    applier.apply(gen_prediction,
                  infile,
                  outfile,
                  otherArgs=other_args,
                  controls=app)
Beispiel #12
0
def run():
    """
    Run the test
    """
    riostestutils.reportStart(TESTNAME)

    # Create a multi-band file with some data in it.
    tstfile = 'multilayer.img'
    numBands = 5
    ds = riostestutils.createTestFile(tstfile, numBands=numBands)

    onelayerArr = riostestutils.genRampArray()
    lyrList = []
    for i in range(numBands):
        lyr = (onelayerArr + 1)
        band = ds.GetRasterBand(i + 1)
        band.WriteArray(lyr)
        lyrList.append(lyr)
    del ds

    stack = numpy.array(lyrList)

    # Sum of all pixels in bands 2 & 4
    layerList = [2, 4]
    correctSum = sum([(stack[i - 1].astype(numpy.float64)).sum()
                      for i in layerList])

    # Now do it using RIOS
    infiles = applier.FilenameAssociations()
    outfiles = applier.FilenameAssociations()
    otherargs = applier.OtherInputs()
    controls = applier.ApplierControls()

    infiles.img = tstfile
    controls.selectInputImageLayers(layerList)
    otherargs.total = 0
    # We will use this to check the number of layers being read
    otherargs.numLayers = len(layerList)
    otherargs.numLayersIsOK = True

    applier.apply(doSum, infiles, outfiles, otherargs, controls=controls)

    if correctSum != otherargs.total:
        riostestutils.report(
            TESTNAME,
            "Totals do not match: %s != %s" % (correctSum, otherargs.total))
        ok = False
    else:
        riostestutils.report(TESTNAME, "Passed")
        ok = True

    os.remove(tstfile)

    return ok
Beispiel #13
0
def apply_gain_to_img(input_img, output_img, gdal_format, gain, np_dtype,
                      in_no_data, out_no_data):
    """
    Apply a gain scale factor to an input image and save as an integer dataset.

    :param input_img: Input image file
    :param output_img: Output image file
    :param gdal_format: GDAL image format for output image
    :param gain: scale factor to be applied to the input image
    :param np_dtype: the numpy datatype for the output data (e.g., numpy.int16 or numpy.uint16)
    :param in_no_data: the input image no data value
    :param out_no_data: the no data value to be used for the output image

    """
    try:
        import tqdm
        progress_bar = TQDMProgressBar()
    except:
        progress_bar = cuiprogress.GDALProgressBar()

    def _apply_img_gain(info, inputs, outputs, otherargs):
        # Internal Function...
        out_img_arr = numpy.zeros_like(inputs.image, dtype=otherargs.np_dtype)
        out_img_arr[...] = numpy.around((inputs.image * otherargs.gain), 0)
        out_img_arr[inputs.image ==
                    otherargs.in_no_data] = otherargs.out_no_data
        outputs.outimage = out_img_arr

    infiles = applier.FilenameAssociations()
    infiles.image = input_img

    outfiles = applier.FilenameAssociations()
    outfiles.outimage = output_img

    otherargs = applier.OtherInputs()
    otherargs.gain = gain
    otherargs.np_dtype = np_dtype
    otherargs.in_no_data = in_no_data
    otherargs.out_no_data = out_no_data

    aControls = applier.ApplierControls()
    aControls.progress = progress_bar
    aControls.drivername = gdal_format
    aControls.omitPyramids = True
    aControls.calcStats = False
    if gdal_format == 'GTIFF':
        aControls.creationoptions = GTIFF_CREATION_OPTS

    applier.apply(_apply_img_gain,
                  infiles,
                  outfiles,
                  otherargs,
                  controls=aControls)
Beispiel #14
0
def calcWSG84PixelArea(img, out_img, scale=10000, gdalformat='KEA'):
    """
A function which calculates the area (in metres) of the pixel projected in WGS84.

:param img: input image, for which the per-pixel area will be calculated.
:param out_img: output image file.
:param scale: scale the output area to unit of interest. Scale=10000(Ha), Scale=1(sq m), Scale=1000000(sq km), Scale=4046.856(Acre), Scale=2590000(sq miles), Scale=0.0929022668(sq feet)

"""
    import rsgislib.tools
    from rios import applier

    try:
        import tqdm
        progress_bar = rsgislib.TQDMProgressBar()
    except:
        from rios import cuiprogress
        progress_bar = cuiprogress.GDALProgressBar()

    rsgis_utils = rsgislib.RSGISPyUtils()
    x_res, y_res = rsgis_utils.getImageRes(img)

    infiles = applier.FilenameAssociations()
    infiles.img = img
    outfiles = applier.FilenameAssociations()
    outfiles.outimage = out_img
    otherargs = applier.OtherInputs()
    otherargs.x_res = x_res
    otherargs.y_res = y_res
    otherargs.scale = float(scale)
    aControls = applier.ApplierControls()
    aControls.progress = progress_bar
    aControls.drivername = gdalformat
    aControls.omitPyramids = False
    aControls.calcStats = False

    def _calcPixelArea(info, inputs, outputs, otherargs):
        xBlock, yBlock = info.getBlockCoordArrays()

        x_res_arr = numpy.zeros_like(yBlock, dtype=float)
        x_res_arr[...] = otherargs.x_res
        y_res_arr = numpy.zeros_like(yBlock, dtype=float)
        y_res_arr[...] = otherargs.y_res
        x_res_arr_m, y_res_arr_m = rsgislib.tools.degrees_to_metres(
            yBlock, x_res_arr, y_res_arr)
        outputs.outimage = numpy.expand_dims(
            (x_res_arr_m * y_res_arr_m) / otherargs.scale, axis=0)

    applier.apply(_calcPixelArea,
                  infiles,
                  outfiles,
                  otherargs,
                  controls=aControls)
Beispiel #15
0
def call_min_max_filter(infile,
                        outfile,
                        min=-1,
                        max=1,
                        block_size=512,
                        n_threads=5):
    """
    Function caller to min_max_filter which set values below the minimum or above the maximum to nan
    Args:
        infile: full path to the input file
        outfile: full path to the output file
        min: minimum allowed value
        max: maximum allowed value
        block_size: block size for RIOS block wise processing
        n_threads: number of threads

    Returns: GeoTiff with extreme values set to nan

    """

    # inputs
    inputs = applier.FilenameAssociations()
    inputs.image = infile

    # parameters
    otherargs = applier.OtherInputs()
    otherargs.min = min
    otherargs.max = max

    # controls
    controls = applier.ApplierControls()
    controls.setWindowXsize(block_size)
    controls.setWindowYsize(block_size)
    controls.progress = cuiprogress.CUIProgressBar()
    controls.setOutputDriverName("GTiff")
    controls.setCreationOptions(["COMPRESS=NONE"])
    controls.setCreationOptions(["INTERLEAVE=PIXEL"])

    # parallelization currently not working due to issues with pickeling
    if n_threads > 1:
        # parallel.jobmanager.getAvailableJobManagerTypes()
        controls.setNumThreads(n_threads)
        controls.setJobManagerType('subproc')

    # output file
    outfiles = applier.FilenameAssociations()
    outfiles.outimage = outfile

    applier.apply(min_max_filter,
                  inputs,
                  outfiles,
                  otherargs,
                  controls=controls)
def findminclumpval(clumpsImg, valsImg, valBand, out_col):
    import rsgislib.rastergis
    import rsgislib.rastergis.ratutils
    from rios import applier
    import numpy
    try:
        import tqdm
        progress_bar = rsgislib.TQDMProgressBar()
    except:
        from rios import cuiprogress
        progress_bar = cuiprogress.GDALProgressBar()

    n_clumps = rsgislib.rastergis.getRATLength(clumpsImg)
    min_vals = numpy.zeros(n_clumps, dtype=int)

    infiles = applier.FilenameAssociations()
    infiles.clumpsImg = clumpsImg
    infiles.valsImg = valsImg
    outfiles = applier.FilenameAssociations()
    otherargs = applier.OtherInputs()
    otherargs.min_vals = min_vals
    otherargs.valBand = valBand - 1
    aControls = applier.ApplierControls()
    aControls.progress = progress_bar
    aControls.omitPyramids = True
    aControls.calcStats = False

    def _findMinVals(info, inputs, outputs, otherargs):
        """
        This is an internal rios function
        """
        unqClumpVals = numpy.unique(inputs.clumpsImg)
        clumpValsFlat = inputs.clumpsImg.flatten()
        for clump in unqClumpVals:
            pxl_vals = inputs.valsImg[otherargs.valBand].flatten()[
                clumpValsFlat == clump]
            pxl_vals = pxl_vals[pxl_vals > 0]
            if pxl_vals.shape[0] > 0:
                clump_min_val = pxl_vals.min()
                if otherargs.min_vals[clump] == 0:
                    otherargs.min_vals[clump] = clump_min_val
                else:
                    if clump_min_val < otherargs.min_vals[clump]:
                        otherargs.min_vals[clump] = clump_min_val

    applier.apply(_findMinVals,
                  infiles,
                  outfiles,
                  otherargs,
                  controls=aControls)

    rsgislib.rastergis.ratutils.setColumnData(clumpsImg, out_col, min_vals)
Beispiel #17
0
def rescale_unmixing_results(input_img,
                             output_img,
                             gdalformat,
                             scale_factor=1000):
    """
    A function which rescales an output from a spectral unmixing
    (e.g., rsgislib.imagecalc.specunmixing.calc_unconstrained_unmixing) so that
    negative values are removed and each pixel sums to 1.

    :param inputImg: Input image with the spectral unmixing result (pixels need to range from 0-1)
    :param outputImg: Output image with the result of the rescaling (pixel values will be in range 0-1)
    :param gdalformat: the file format of the output file.

    """
    try:
        import tqdm
        progress_bar = rsgislib.TQDMProgressBar()
    except:
        progress_bar = cuiprogress.GDALProgressBar()

    infiles = applier.FilenameAssociations()
    infiles.image = input_img
    outfiles = applier.FilenameAssociations()
    outfiles.outimage = output_img
    otherargs = applier.OtherInputs()
    otherargs.scale_factor = scale_factor
    aControls = applier.ApplierControls()
    aControls.progress = progress_bar
    aControls.drivername = gdalformat
    aControls.omitPyramids = True
    aControls.calcStats = False

    def _applyUnmixRescale(info, inputs, outputs, otherargs):
        """
        This is an internal rios function
        """
        inputs.image[inputs.image < 0] = 0
        if otherargs.scale_factor == 1:
            outputs.outimage = numpy.zeros_like(inputs.image,
                                                dtype=numpy.float32)
        else:
            outputs.outimage = numpy.zeros_like(inputs.image,
                                                dtype=numpy.uint16)
        for idx in range(inputs.image.shape[0]):
            outputs.outimage[idx] = (inputs.image[idx] / numpy.sum(
                inputs.image, axis=0)) * otherargs.scale_factor

    applier.apply(_applyUnmixRescale,
                  infiles,
                  outfiles,
                  otherargs,
                  controls=aControls)
Beispiel #18
0
def exec(input_dir, model_filepath, output_filepath):

    ts_utils.mkdirp(ts_utils.basedir(output_filepath))

    images = ts_utils.get_filenames(input_dir, \
     filter_prefix='ts_b', filter_suffix='.vrt')

    model = load_model(model_filepath)

    infiles = applier.FilenameAssociations()
    outfiles = applier.FilenameAssociations()
    otherargs = applier.OtherInputs()

    otherargs.n_images = len(images)

    for i in range(0, otherargs.n_images):
        key = 'img' + str(i)
        setattr(infiles, key, images[i])

    outfiles.result = output_filepath
    otherargs.model = model

    def genmap(info, inputs, outputs, otherargs):
        size_x, size_y = info.getBlockSize()
        outputs.result = np.empty((1, size_y, size_x), dtype=np.uint16)

        print("Processing status " + str(info.getPercent()) + "%")

        input_ts = []
        for i in range(0, otherargs.n_images):
            key = 'img' + str(i)
            input_img = getattr(inputs, key)
            input_img = np.transpose(input_img)

            shape = input_img.shape
            input_img = input_img.reshape(shape[0] * shape[1], shape[2])

            input_ts.append(input_img)

        input_ts = np.dstack(input_ts)

        predicted = np.argmax(otherargs.model.predict(input_ts),
                              axis=1).astype(np.uint16)

        outputs.result = np.transpose(
            np.reshape(predicted, (size_x, size_y, 1)))

    controls = applier.ApplierControls()
    controls.setNumThreads(1)
    controls.setJobManagerType('multiprocessing')
    applier.apply(genmap, infiles, outfiles, otherargs, controls=controls)
Beispiel #19
0
def calc_ratio_img(vv_img, vh_img, out_img, gdal_format):
    """
    A function which calculates the ratio image of the VV/HV polarisations.

    :param vv_img: GDAL image with VV polarisation
    :param vh_img: GDAL image with VH polarisation
    :param out_img: Output image file.
    :param gdal_format: Output image file format.

    """
    try:
        import tqdm
        progress_bar = TQDMProgressBar()
    except:
        progress_bar = cuiprogress.GDALProgressBar()

    def _apply_calc_pol_ratio(info, inputs, outputs, otherargs):
        # Internal Function...
        ratio_img_arr = numpy.where(
            (numpy.isfinite(inputs.vv_img) &
             (inputs.vv_img > 0.0) & numpy.isfinite(inputs.vh_img) &
             (inputs.vh_img > 0.0)), inputs.vv_img / inputs.vh_img, 0.0)
        ratio_img_arr[numpy.isnan(ratio_img_arr)] = 0.0
        ratio_img_arr[numpy.isinf(ratio_img_arr)] = 0.0
        outputs.outimage = ratio_img_arr

    infiles = applier.FilenameAssociations()
    infiles.vv_img = vv_img
    infiles.vh_img = vh_img

    outfiles = applier.FilenameAssociations()
    outfiles.outimage = out_img

    otherargs = applier.OtherInputs()

    aControls = applier.ApplierControls()
    aControls.progress = progress_bar
    aControls.drivername = gdal_format
    aControls.omitPyramids = True
    aControls.calcStats = False
    if gdal_format == 'GTIFF':
        aControls.creationoptions = GTIFF_CREATION_OPTS

    applier.apply(_apply_calc_pol_ratio,
                  infiles,
                  outfiles,
                  otherargs,
                  controls=aControls)
    logger.debug("Created ratio output image file: {}".format(out_img))
Beispiel #20
0
def calc_valid_msk(input_img, output_img, gdal_format, no_data_val):
    """
    A function to create a valid data mask image.

    :param input_img: Input image file
    :param output_img: Output image file
    :param gdal_format: GDAL image format for output image
    :param no_data_val: the input image no data value

    """
    try:
        import tqdm
        progress_bar = TQDMProgressBar()
    except:
        progress_bar = cuiprogress.GDALProgressBar()

    def _calc_valid_msk(info, inputs, outputs, otherargs):
        # Internal Function...
        input_shp = inputs.image.shape
        outputs.output_img = numpy.zeros((1, input_shp[1], input_shp[2]),
                                         dtype=numpy.uint8)
        for n in range(input_shp[0]):
            outputs.output_img[0] = numpy.where(
                inputs.image[n] != otherargs.no_data_val, 1,
                outputs.output_img[0])

    infiles = applier.FilenameAssociations()
    infiles.image = input_img

    outfiles = applier.FilenameAssociations()
    outfiles.output_img = output_img

    otherargs = applier.OtherInputs()
    otherargs.no_data_val = no_data_val

    aControls = applier.ApplierControls()
    aControls.progress = progress_bar
    aControls.drivername = gdal_format
    aControls.omitPyramids = True
    aControls.calcStats = False
    if gdal_format == 'GTIFF':
        aControls.creationoptions = GTIFF_CREATION_OPTS
    applier.apply(_calc_valid_msk,
                  infiles,
                  outfiles,
                  otherargs,
                  controls=aControls)
Beispiel #21
0
def apply_rf_image(in_data_stack, out_image, rf_model, nodata_vals):
    """
    Apply Random Forests model generated by scikit-learn
    to an input data stack and output image

    Requires:

    * in_data_stack - stack of all layers
    * out_image - output image
    * rf_model - model produced by scikit-learn
    * nodata_vals - array with a no-data value for each band

    Returns the mean and standard deviation of the output (predicted)
    image.

    """
    # Apply to image
    infiles = applier.FilenameAssociations()
    infiles.inimage = in_data_stack

    outfiles = applier.FilenameAssociations()
    outfiles.outimage = out_image

    otherargs = applier.OtherInputs()
    otherargs.rf = rf_model
    otherargs.predict_sm = None  # Array to store output SM
    # Pass in list of no data values for each layer
    otherargs.nodata_vals_list = nodata_vals
    controls = applier.ApplierControls()
    controls.setOutputDriverName(
        upscaling_utilities.get_gdal_format(out_image))
    controls.setCalcStats(False)
    controls.progress = cuiprogress.CUIProgressBar()
    applier.apply(_rios_apply_rf_image,
                  infiles,
                  outfiles,
                  otherargs,
                  controls=controls)

    average_sm_predict = otherargs.predict_sm.mean()
    sd_sm_predict = otherargs.predict_sm.std()

    return average_sm_predict, sd_sm_predict
def createPlots(imageA,
                imageB,
                outPlot,
                bandA=1,
                bandB=1,
                labelA=None,
                labelB=None,
                plotMin=None,
                plotMax=None,
                scale=1,
                independentXY=False):

    controls = applier.ApplierControls()

    # Set up input images
    infiles = applier.FilenameAssociations()
    infiles.imageA = imageA
    infiles.imageB = imageB

    outfiles = applier.FilenameAssociations()

    # Set up parameters
    otherargs = applier.OtherInputs()
    otherargs.bandA = bandA - 1
    otherargs.bandB = bandB - 1
    otherargs.outdataA = numpy.array([], dtype=numpy.float32)
    otherargs.outdataB = numpy.array([], dtype=numpy.float32)
    otherargs.scale = scale

    # Get data
    print('Extracting data')
    controls.progress = cuiprogress.CUIProgressBar()
    # If necessary reproject image B to image A
    controls.setReferenceImage(infiles.imageA)
    controls.setResampleMethod('near')
    applier.apply(getData, infiles, outfiles, otherargs, controls=controls)

    # Produce plot
    print('Saving plot')
    plotData(otherargs.outdataA, otherargs.outdataB, outPlot, labelA, labelB,
             plotMin, plotMax, independentXY)
Beispiel #23
0
def run_s2cloudless(input_img, out_prob_img, out_cloud_msk, gdalformat):
    """
Function which runs the S2Cloudless methods in 256 x 256 pixel blocks 
across an image.

:param input_img: input sentinel-2 image with all 13 bands.
:param output_img: the output image cloud mask
:param gdalformat: the GDAL image file format of the output image file.

"""
    s2_pxl_cloud_detect = S2PixelCloudDetector(all_bands=True)

    infiles = applier.FilenameAssociations()
    infiles.s2image = input_img
    outfiles = applier.FilenameAssociations()
    outfiles.out_prob_img = out_prob_img
    outfiles.out_cloud_msk = out_cloud_msk
    otherargs = applier.OtherInputs()
    otherargs.s2_pxl_cloud_detect = s2_pxl_cloud_detect
    aControls = applier.ApplierControls()
    aControls.progress = cuiprogress.CUIProgressBar()
    aControls.drivername = gdalformat
    aControls.omitPyramids = True
    aControls.calcStats = False

    def _applyS2Cloudless(info, inputs, outputs, otherargs):
        """
        This is an internal rios function
        """
        # Current shape is: [13 x n x m]
        # Image data needs to be in shape [1 x n x m x 13]
        s2img_reshp = numpy.expand_dims(numpy.stack([inputs.s2image[0], inputs.s2image[1], inputs.s2image[2], inputs.s2image[3], inputs.s2image[4], inputs.s2image[5], inputs.s2image[6], inputs.s2image[7], inputs.s2image[8], inputs.s2image[9], inputs.s2image[10], inputs.s2image[11], inputs.s2image[12]], axis=2), axis=0)
        s2img_reshp_toa = s2img_reshp/10000.0
        outputs.out_prob_img = otherargs.s2_pxl_cloud_detect.get_cloud_probability_maps(s2img_reshp_toa)
        outputs.out_cloud_msk = otherargs.s2_pxl_cloud_detect.get_mask_from_prob(outputs.out_prob_img)

    applier.apply(_applyS2Cloudless, infiles, outfiles, otherargs, controls=aControls)
Beispiel #24
0
def findImgCorners(img, imgInfo):
    """
    Find the corners of the data within the given template image
    Return a numpy array of (x, y) coordinates. The array has 2 columns, for X and Y.
    Each row is a corner, in the order:

    top-left, top-right, bottom-left, bottom-right.

    Uses RIOS to pass through the image searching for non-null data,
    and find the extremes. Assumes we are working with a full-swathe Landsat
    image.

    Each list element is a numpy array of (x, y)

    """
    infiles = applier.FilenameAssociations()
    outfiles = applier.FilenameAssociations()
    otherargs = applier.OtherInputs()

    infiles.img = img
    otherargs.tl = None
    otherargs.tr = None
    otherargs.bl = None
    otherargs.br = None
    otherargs.nullVal = imgInfo.nodataval[0]
    if otherargs.nullVal is None:
        otherargs.nullVal = 0

    applier.apply(findCorners, infiles, outfiles, otherargs)

    corners = numpy.array([
        otherargs.tl,
        otherargs.tr,
        otherargs.bl,
        otherargs.br,
    ])
    return corners
Beispiel #25
0
def rescaleUnmixingResults(inputImg, outputImg, gdalformat):
    """
A function which rescales an output from a spectral unmixing
(e.g., rsgislib.imagecalc.conSum1LinearSpecUnmix) so that
negative values are removed and each pixel sums to 1.

:param inputImg: Input image with the spectral unmixing result (pixels need to range from 0-1)
:param outputImg: Output image with the result of the rescaling (pixel values will be in range 0-1)
:param gdalformat: the file format of the output file.

"""
    infiles = applier.FilenameAssociations()
    infiles.image = inputImg
    outfiles = applier.FilenameAssociations()
    outfiles.outimage = outputImg
    otherargs = applier.OtherInputs()
    aControls = applier.ApplierControls()
    aControls.progress = cuiprogress.CUIProgressBar()
    aControls.drivername = gdalformat
    aControls.omitPyramids = True
    aControls.calcStats = False

    def _applyUnmixRescale(info, inputs, outputs, otherargs):
        """
        This is an internal rios function
        """
        inputs.image[inputs.image < 0] = 0
        outputs.outimage = numpy.zeros_like(inputs.image, dtype=numpy.float32)
        for idx in range(inputs.image.shape[0]):
            outputs.outimage[idx] = inputs.image[idx] / numpy.sum(inputs.image,
                                                                  axis=0)

    applier.apply(_applyUnmixRescale,
                  infiles,
                  outfiles,
                  otherargs,
                  controls=aControls)
Beispiel #26
0
def calcMeanWithRiosApplier(imgfile, vecfile):
    """
    Use RIOS's vector facilities, through the applier, to calculate the
    mean of the image within the vector
    """
    infiles = applier.FilenameAssociations()
    outfiles = applier.FilenameAssociations()
    controls = applier.ApplierControls()
    otherargs = applier.OtherInputs()
    infiles.img = imgfile
    infiles.vec = vecfile
    controls.setBurnValue(-1)
    controls.setVectorDatatype(numpy.int16)
    otherargs.total = 0
    otherargs.count = 0

    applier.apply(meanWithinVec,
                  infiles,
                  outfiles,
                  otherargs,
                  controls=controls)

    mean = otherargs.total / otherargs.count
    return mean
Beispiel #27
0
def get_ST_model_coeffs(json_fp, output_fp, gdalformat='KEA', bands=None, num_processes=1, model_type='Lasso',
                        alpha=20, cv=False):
    """
Main function to run to generate the output image. Given an input JSON file
and an output file path, generates a multi-band output image where each pixel
contains the model details for that pixel. Opening/closing of files, generation
of blocks and use of multiprocessing is all handled by RIOS.

:param json_fp:       Path to JSON file of date/filepath pairs.
:param output_fp:     Path for output file.
:param gdalformat:    Short driver name for GDAL, e.g. KEA, GTiff.
:param bands:         List of GDAL band numbers to use in the analysis, e.g. [2, 5, 7].
:param num_processes: Number of concurrent processes to use.
:param model_type:    Either 'Lasso' or 'OLS'. The type of model fitting to use. OLS will
                      be faster, but more likely to overfit. Both types will adjust the number of model
                      coefficients depending on the number of observations.
:param alpha:         If using Lasso fitting, the alpha value controls the degree of
                      penalization of the coefficients. The lower the value, the closer
                      the model will fit the data. For surface reflectance, a value of
                      around 20 (the default) is usually OK.
:param cv:            If using Lasso fitting, you can use cross validation to choose
                      the value of alpha by setting cv=True. However, this is not recommended and will
                      substantially increase run time.
"""
    paths = []
    dates = []

    try:
        # Open and read JSON file containing date:filepath pairs
        with open(json_fp) as json_file:
            image_list = json.load(json_file)

            for date, img_path in image_list.items():
                dates.append(datetime.strptime(date, '%Y-%m-%d').toordinal())
                paths.append(img_path)
    except FileNotFoundError:
        print('Could not find the provided JSON file.')
        sys.exit()
    except json.decoder.JSONDecodeError as e:
        print('There is an error in the provided JSON file: {}'.format(e))
        sys.exit()

    # Create object to hold input files
    infiles = applier.FilenameAssociations()
    infiles.images = paths

    # Create object to hold output file
    outfiles = applier.FilenameAssociations()
    outfiles.outimage = output_fp

    # ApplierControls object holds details on how processing should be done
    app = applier.ApplierControls()

    # Set window size to 1 because we are working per-pixel
    app.setWindowXsize(1)
    app.setWindowYsize(1)

    # Set output file type
    app.setOutputDriverName(gdalformat)
    
    # Set progress
    try:
        import tqdm
        progress_bar = rsgislib.TQDMProgressBar()
    except:
        progress_bar = cuiprogress.GDALProgressBar()
    app.progress = progress_bar

    # Set that pyramids and statistics are not calculated.
    app.omitPyramids = True
    app.calcStats = False

    # Use Python's multiprocessing module
    app.setJobManagerType('multiprocessing')
    app.setNumThreads(num_processes)

    # Open first image in list to use as a template
    template_image = fileinfo.ImageInfo(infiles.images[0])

    # Get no data value
    nodata_val = template_image.nodataval[0]

    if not bands:  # No bands specified - default to all
        num_bands = template_image.rasterCount
        bands = [i for i in range(1, num_bands + 1)]

    else:  # If a list of bands is provided
        # Number of bands determines things like the size of the output array
        num_bands = len(bands)

        # Need to tell the applier to only use the specified bands
        app.selectInputImageLayers(bands)

    # Create list of actual names
    full_names = [template_image.layerNameFromNumber(i) for i in bands]
    template_image = None

    # Set up output layer names based on band numbers
    layer_names = gen_layer_names(full_names)
    app.setLayerNames(layer_names)

    # Additional arguments - have to be passed as a single object
    other_args = applier.OtherInputs()
    other_args.dates = dates
    other_args.num_bands = num_bands
    other_args.nodata_val = nodata_val
    other_args.model_type = model_type
    other_args.alpha = alpha
    other_args.cv = cv

    try:
        applier.apply(gen_per_band_models, infiles, outfiles, otherArgs=other_args, controls=app)
    except RuntimeError as e:
        print('There was an error processing the images: {}'.format(e))
        print('Do all images in the JSON file exist?')
Beispiel #28
0
def apply_sklearn_classifer(classTrainInfo,
                            skClassifier,
                            imgMask,
                            imgMaskVal,
                            imgFileInfo,
                            outputImg,
                            gdalformat,
                            classClrNames=True):
    """
This function uses a trained classifier and applies it to the provided input image.

:param classTrainInfo: dict (where the key is the class name) of rsgislib.classification.ClassSimpleInfoObj
                       objects which will be used to train the classifier (i.e., train_sklearn_classifier()),
                       provide pixel value id and RGB class values.
:param skClassifier: a trained instance of a scikit-learn classifier
                     (e.g., use train_sklearn_classifier or train_sklearn_classifer_gridsearch)
:param imgMask: is an image file providing a mask to specify where should be classified. Simplest mask is all
                the valid data regions (rsgislib.imageutils.genValidMask)
:param imgMaskVal: the pixel value within the imgMask to limit the region to which the classification is applied.
                   Can be used to create a heirachical classification.
:param imgFileInfo: a list of rsgislib.imageutils.ImageBandInfo objects (also used within
                    rsgislib.imageutils.extractZoneImageBandValues2HDF) to identify which images and bands are to
                    be used for the classification so it adheres to the training data.
:param outputImg: output image file with the classification. Note. by default a colour table and class names column
                  is added to the image. If an error is produced use HFA or KEA formats.
:param gdalformat: is the output image format - all GDAL supported formats are supported.
:param classClrNames: default is True and therefore a colour table will the colours specified in classTrainInfo
                      and a ClassName column (from imgFileInfo) will be added to the output file.

    """
    infiles = applier.FilenameAssociations()
    infiles.imageMask = imgMask
    numClassVars = 0
    for imgFile in imgFileInfo:
        infiles.__dict__[imgFile.name] = imgFile.fileName
        numClassVars = numClassVars + len(imgFile.bands)

    outfiles = applier.FilenameAssociations()
    outfiles.outimage = outputImg
    otherargs = applier.OtherInputs()
    otherargs.classifier = skClassifier
    otherargs.mskVal = imgMaskVal
    otherargs.numClassVars = numClassVars
    otherargs.imgFileInfo = imgFileInfo

    try:
        import tqdm
        progress_bar = rsgislib.TQDMProgressBar()
    except:
        progress_bar = cuiprogress.GDALProgressBar()

    aControls = applier.ApplierControls()
    aControls.progress = progress_bar
    aControls.drivername = gdalformat
    aControls.omitPyramids = True
    aControls.calcStats = False

    # RIOS function to apply classifer
    def _applySKClassifier(info, inputs, outputs, otherargs):
        """
        Internal function for rios applier. Used within applyClassifer.
        """
        outClassVals = numpy.zeros_like(inputs.imageMask, dtype=numpy.uint32)
        if numpy.any(inputs.imageMask == otherargs.mskVal):
            outClassVals = outClassVals.flatten()
            imgMaskVals = inputs.imageMask.flatten()
            classVars = numpy.zeros(
                (outClassVals.shape[0], otherargs.numClassVars),
                dtype=numpy.float)
            # Array index which can be used to populate the output array following masking etc.
            ID = numpy.arange(imgMaskVals.shape[0])
            classVarsIdx = 0
            for imgFile in otherargs.imgFileInfo:
                imgArr = inputs.__dict__[imgFile.name]
                for band in imgFile.bands:
                    classVars[..., classVarsIdx] = imgArr[(band - 1)].flatten()
                    classVarsIdx = classVarsIdx + 1
            classVars = classVars[imgMaskVals == otherargs.mskVal]
            ID = ID[imgMaskVals == otherargs.mskVal]
            predClass = otherargs.classifier.predict(classVars)
            outClassVals[ID] = predClass
            outClassVals = numpy.expand_dims(outClassVals.reshape(
                (inputs.imageMask.shape[1], inputs.imageMask.shape[2])),
                                             axis=0)
        outputs.outimage = outClassVals

    print("Applying the Classifier")
    applier.apply(_applySKClassifier,
                  infiles,
                  outfiles,
                  otherargs,
                  controls=aControls)
    print("Completed")
    rsgislib.rastergis.populateStats(clumps=outputImg,
                                     addclrtab=True,
                                     calcpyramids=True,
                                     ignorezero=True)

    if classClrNames:
        ratDataset = gdal.Open(outputImg, gdal.GA_Update)
        red = rat.readColumn(ratDataset, 'Red')
        green = rat.readColumn(ratDataset, 'Green')
        blue = rat.readColumn(ratDataset, 'Blue')
        ClassName = numpy.empty_like(red, dtype=numpy.dtype('a255'))

        for classKey in classTrainInfo:
            print("Apply Colour to class \'" + classKey + "\'")
            red[classTrainInfo[classKey].id] = classTrainInfo[classKey].red
            green[classTrainInfo[classKey].id] = classTrainInfo[classKey].green
            blue[classTrainInfo[classKey].id] = classTrainInfo[classKey].blue
            ClassName[classTrainInfo[classKey].id] = classKey

        rat.writeColumn(ratDataset, "Red", red)
        rat.writeColumn(ratDataset, "Green", green)
        rat.writeColumn(ratDataset, "Blue", blue)
        rat.writeColumn(ratDataset, "ClassName", ClassName)
        ratDataset = None
Beispiel #29
0
        print(
            "Warning: the script used to generate the model couldn't be saved onto datasource."
        )
elif mode == 'predict':
    ### TODO: generalize predict process
    try:
        model = load_model(fname_acc)
        print("Loaded model from disk.")
    except OSError:
        print(
            "Error: cannot load model's files! Have you ever perform training?"
        )
        exit(0)
    infiles = applier.FilenameAssociations()
    outfiles = applier.FilenameAssociations()
    otherargs = applier.OtherInputs()
    infiles.raster = fname_raster
    outfiles.map = fname_output
    otherargs.model = model

    def genmap(info, inputs, outputs, otherargs):
        size_x, size_y = info.getBlockSize()
        outputs.map = np.empty((1, size_y, size_x), dtype=np.uint16)
        inputs.raster = np.transpose(inputs.raster)
        inputs.raster = inputs.raster.reshape(
            inputs.raster.shape[0] * inputs.raster.shape[1],
            inputs.raster.shape[2])
        tensor = np.dstack([
            inputs.raster,
        ])
        predict = np.argmax(otherargs.model.predict(tensor),
Beispiel #30
0
def apply_keras_pixel_classifier(classTrainInfo,
                                 keras_cls_mdl,
                                 imgMask,
                                 imgMaskVal,
                                 imgFileInfo,
                                 outClassImg,
                                 gdalformat,
                                 pred_batch_size=32,
                                 classClrNames=True):
    """
This function applies a trained single pixel keras model to an image. The function train_keras_pixel_classifer
can be used to train such as model. The output image will contain the hard membership of the predicted class. 

:param classTrainInfo: dict (where the key is the class name) of rsgislib.classification.ClassInfoObj
                       objects which will be used to train the classifier (i.e., train_keras_pixel_classifer()),
                       provide pixel value id and RGB class values.
:param keras_cls_mdl: a trained keras model object, with a input dimensions equivlent to the number of image
                      bands specified in the imgFileInfo input and output layer which provides an output array
                      of the length of the number of classes.
:param imgMask: is an image file providing a mask to specify where should be classified. Simplest mask is all the
                valid data regions (rsgislib.imageutils.genValidMask)
:param imgMaskVal: the pixel value within the imgMask to limit the region to which the classification is applied.
                   Can be used to create a heirachical classification.
:param imgFileInfo: a list of rsgislib.imageutils.ImageBandInfo objects (also used within
                    rsgislib.imageutils.extractZoneImageBandValues2HDF) to identify which images and bands are to
                    be used for the classification so it adheres to the training data.
:param outClassImg: Output image which will contain the hard classification.
:param gdalformat: is the output image format - all GDAL supported formats are supported.
:param pred_batch_size: the batch size used for the classification.
:param classClrNames: default is True and therefore a colour table will the colours specified in ClassInfoObj
                      and a ClassName (from classTrainInfo) column will be added to the output file.

    """
    def _applyKerasPxlClassifier(info, inputs, outputs, otherargs):
        outClassIdVals = numpy.zeros_like(inputs.imageMask, dtype=numpy.uint16)
        if numpy.any(inputs.imageMask == otherargs.mskVal):
            n_pxls = inputs.imageMask.shape[1] * inputs.imageMask.shape[2]
            outClassIdVals = outClassIdVals.flatten()
            imgMaskVals = inputs.imageMask.flatten()
            classVars = numpy.zeros((n_pxls, otherargs.numClassVars),
                                    dtype=numpy.float)
            # Array index which can be used to populate the output array following masking etc.
            ID = numpy.arange(imgMaskVals.shape[0])
            classVarsIdx = 0
            for imgFile in otherargs.imgFileInfo:
                imgArr = inputs.__dict__[imgFile.name]
                for band in imgFile.bands:
                    classVars[..., classVarsIdx] = imgArr[(band - 1)].flatten()
                    classVarsIdx = classVarsIdx + 1
            classVars = classVars[imgMaskVals == otherargs.mskVal]
            ID = ID[imgMaskVals == otherargs.mskVal]
            preds_idxs = numpy.argmax(otherargs.classifier.predict(
                classVars, batch_size=otherargs.pred_batch_size),
                                      axis=1)
            preds_cls_ids = numpy.zeros_like(preds_idxs, dtype=numpy.uint16)
            for cld_id, idx in zip(otherargs.cls_id_lut,
                                   numpy.arange(0, len(otherargs.cls_id_lut))):
                preds_cls_ids[preds_idxs == idx] = cld_id

            outClassIdVals[ID] = preds_cls_ids
            outClassIdVals = numpy.expand_dims(outClassIdVals.reshape(
                (inputs.imageMask.shape[1], inputs.imageMask.shape[2])),
                                               axis=0)
        outputs.outclsimage = outClassIdVals

    infiles = applier.FilenameAssociations()
    infiles.imageMask = imgMask
    numClassVars = 0
    for imgFile in imgFileInfo:
        infiles.__dict__[imgFile.name] = imgFile.fileName
        numClassVars = numClassVars + len(imgFile.bands)

    n_classes = len(classTrainInfo)
    cls_id_lut = numpy.zeros(n_classes)
    for clsname in classTrainInfo:
        if classTrainInfo[clsname].id >= n_classes:
            raise (
                "ClassInfoObj '{}' id ({}) is not consecutive starting from 0."
                .format(clsname, classTrainInfo[clsname].id))
        cls_id_lut[classTrainInfo[clsname].id] = classTrainInfo[clsname].out_id

    outfiles = applier.FilenameAssociations()
    outfiles.outclsimage = outClassImg
    otherargs = applier.OtherInputs()
    otherargs.classifier = keras_cls_mdl
    otherargs.pred_batch_size = pred_batch_size
    otherargs.mskVal = imgMaskVal
    otherargs.numClassVars = numClassVars
    otherargs.imgFileInfo = imgFileInfo
    otherargs.n_classes = n_classes
    otherargs.cls_id_lut = cls_id_lut

    try:
        import tqdm
        progress_bar = rsgislib.TQDMProgressBar()
    except:
        progress_bar = cuiprogress.GDALProgressBar()

    aControls = applier.ApplierControls()
    aControls.progress = progress_bar
    aControls.drivername = gdalformat
    aControls.omitPyramids = True
    aControls.calcStats = False
    print("Applying the Classifier")
    applier.apply(_applyKerasPxlClassifier,
                  infiles,
                  outfiles,
                  otherargs,
                  controls=aControls)
    print("Completed Classification")

    if classClrNames:
        rsgislib.rastergis.populateStats(outClassImg,
                                         addclrtab=True,
                                         calcpyramids=True,
                                         ignorezero=True)
        ratDataset = gdal.Open(outClassImg, gdal.GA_Update)
        red = rat.readColumn(ratDataset, 'Red')
        green = rat.readColumn(ratDataset, 'Green')
        blue = rat.readColumn(ratDataset, 'Blue')
        ClassName = numpy.empty_like(red, dtype=numpy.dtype('a255'))
        ClassName[...] = ""

        for classKey in classTrainInfo:
            print("Apply Colour to class \'" + classKey + "\'")
            red[classTrainInfo[classKey].out_id] = classTrainInfo[classKey].red
            green[classTrainInfo[classKey].
                  out_id] = classTrainInfo[classKey].green
            blue[classTrainInfo[classKey].
                 out_id] = classTrainInfo[classKey].blue
            ClassName[classTrainInfo[classKey].out_id] = classKey

        rat.writeColumn(ratDataset, "Red", red)
        rat.writeColumn(ratDataset, "Green", green)
        rat.writeColumn(ratDataset, "Blue", blue)
        rat.writeColumn(ratDataset, "ClassName", ClassName)
        ratDataset = None