Ejemplo n.º 1
0
def resample_setsm(raster, dstdir, args):

    for suffix in suffixes:

        srcdir, srcfn = os.path.split(raster)
        component = os.path.join(srcdir, srcfn.replace('dem.tif', suffix))
        new_raster = os.path.join(dstdir, srcfn.replace('dem.tif', suffix))

        if not os.path.isfile(new_raster):

            logger.info("Reprojecting {}".format(component))
            #print new_raster
            if suffix == 'dem.tif':
                cmd = (
                    'gdalwarp -q -tap -t_srs EPSG:{0} -tr {3} {3} -r bilinear -co tiled=yes -co compress=lzw '
                    '-co bigtiff=if_safer "{1}" "{2}"'.format(
                        args.epsg, component, new_raster, args.resolution))
                if not args.dryrun:
                    taskhandler.exec_cmd(cmd)
            elif suffix == 'meta.txt':
                resample_stripmeta(component, new_raster, args.epsg)
            else:
                cmd = (
                    'gdalwarp -q -tap -t_srs EPSG:{0} -tr {3} {3} -r near -co tiled=yes -co compress=lzw '
                    '-co bigtiff=if_safer "{1}" "{2}"'.format(
                        args.epsg, component, new_raster, args.resolution))
                if not args.dryrun:
                    taskhandler.exec_cmd(cmd)
    logger.info('Done')
Ejemplo n.º 2
0
def resample_setsm(dem, args):
    low_res_dem = "{}.tif".format(os.path.splitext(dem)[0])
    low_res_dem = os.path.join(os.path.dirname(low_res_dem),os.path.basename(low_res_dem.replace("_2m","_{}m".format(args.resolution))))
                    
    if not os.path.isfile(low_res_dem) or args.overwrite is True:
        logger.info("Resampling {}".format(dem))
        #print low_res_dem
        resampling_method = 'bilinear' if args.component == 'dem' else 'near'
        cmd = 'gdalwarp -q -co tiled=yes -co compress=lzw -r {3} -tr {0} {0} "{1}" "{2}"'.format(args.resolution, dem, low_res_dem, resampling_method)
        #print cmd
        if not args.dryrun:
            taskhandler.exec_cmd(cmd)
def resample_setsm(dem, args):
    ext = get_extension(args.format)
    if args.dstdir:
        tempfile = "{}_temp.tif".format(
            os.path.join(args.dstdir,
                         os.path.basename(os.path.splitext(dem)[0])))
        low_res_dem = "{}_browse.{}".format(
            os.path.join(args.dstdir,
                         os.path.basename(os.path.splitext(dem)[0])), ext)
    else:
        tempfile = "{}_temp.tif".format(os.path.splitext(dem)[0])
        low_res_dem = "{}_browse.{}".format(os.path.splitext(dem)[0], ext)

    deletables = []
    deletables.append(tempfile)

    if not os.path.isfile(low_res_dem) or args.overwrite is True:
        logger.info("Resampling {}".format(dem))
        #print low_res_dem
        if args.component == 'dem':
            cmd = 'gdalwarp -tap -q -tr {0} {0} -r bilinear -dstnodata -9999 "{1}" "{2}"'.format(
                args.resolution, dem, tempfile)
            cmd2 = 'gdaldem hillshade -q -z 3 -compute_edges -of {2} -co TILED=YES -co BIGTIFF=IF_SAFER -co COMPRESS=LZW "{0}" "{1}"'.format(
                tempfile, low_res_dem, args.format)

        elif args.component == 'matchtag':
            cmd = 'gdal_translate -q -tr {0} {0} -of {3} -r near -a_nodata 0 "{1}" "{2}"'.format(
                args.resolution, dem, low_res_dem, args.format)
            cmd2 = None

        else:
            cmd = 'gdal_translate -tap -q -ot Byte -scale -tr {0} {0} -of {3} -r cubic -a_nodata 0 "{1}" "{2}"'.format(
                args.resolution, dem, low_res_dem, args.format)
            cmd2 = None

        #print cmd
        if not args.dryrun:
            taskhandler.exec_cmd(cmd)
            if cmd2:
                taskhandler.exec_cmd(cmd2)

        if not args.dryrun:
            for f in deletables:
                if os.path.isfile(f):
                    try:
                        os.remove(f)
                    except:
                        print "Cannot remove %s" % f
Ejemplo n.º 4
0
def resample_setsm(dem, args):
    low_res_dem = "{}_{}m.tif".format(
        os.path.splitext(dem)[0], args.resolution)

    if not os.path.isfile(low_res_dem) or args.overwrite is True:
        logger.info("Resampling {}".format(dem))
        #print low_res_dem
        resampling_method = 'bilinear' if args.component == 'dem' else 'near'
        cmd = 'gdalwarp -q -co tiled=yes -co compress=lzw -r {3} -tr {0} {0} "{1}" "{2}"'.format(
            args.resolution, dem, low_res_dem, resampling_method)
        #print cmd
        if not args.dryrun:
            taskhandler.exec_cmd(cmd)

        if os.path.isfile(low_res_dem):
            cmd = 'gdaladdo -q "{}" 2 4 8 16'.format(low_res_dem)
            #print cmd
            if not args.dryrun:
                taskhandler.exec_cmd(cmd)
Ejemplo n.º 5
0
def main():
    
    #########################################################
    ####  Handle args
    #########################################################

    #### Set Up Arguments 
    parser = argparse.ArgumentParser(
        description="Create mosaic subtile"
    )
    
    parser.add_argument("tile", help="output tile name")
    parser.add_argument("src", help="textfile of input rasters (tif only)")
    
    parser.add_argument("-r", "--resolution", nargs=2, type=float,
                        help="output pixel resolution -- xres yres (default is same as first input file)")
    parser.add_argument("-e", "--extent", nargs=4, type=float,
                        help="extent of output mosaic -- xmin xmax ymin ymax (default is union of all inputs)")
    parser.add_argument("-t", "--tilesize", nargs=2, type=float,
                        help="tile size in coordinate system units -- xsize ysize (default is 40,000 times output "
                             "resolution)")
    parser.add_argument("--force-pan-to-multi", action="store_true", default=False,
                        help="if output is multiband, force script to also use 1 band images")
    parser.add_argument("-b", "--bands", type=int,
                        help="number of output bands( default is number of bands in the first image)")
    parser.add_argument("--median-remove", action="store_true", default=False,
                        help="subtract the median from each input image before forming the mosaic in order to correct "
                             "for contrast")
    parser.add_argument("--wd",
                        help="scratch space (default is mosaic directory)")
    parser.add_argument("--gtiff-compression", choices=mosaic.GTIFF_COMPRESSIONS, default="lzw",
                        help="GTiff compression type. Default=lzw ({})".format(','.join(mosaic.GTIFF_COMPRESSIONS)))
    parser.add_argument("--version", action='version', version="imagery_utils v{}".format(utils.package_version))

    
    #### Parse Arguments
    args = parser.parse_args()

    status = 0
        
    bands = args.bands
    inpath = args.src
    tile = args.tile
    ref_xres, ref_yres = args.resolution
    xmin, xmax, ymin, ymax = args.extent
    dims = "-tr {} {} -te {} {} {} {}".format(ref_xres, ref_yres, xmin, ymin, xmax, ymax)
    
    ##### Configure Logger
    logfile = os.path.splitext(tile)[0] + ".log"
    lfh = logging.FileHandler(logfile)
    lfh.setLevel(logging.DEBUG)
    formatter = logging.Formatter('%(asctime)s %(levelname)s- %(message)s', '%m-%d-%Y %H:%M:%S')
    lfh.setFormatter(formatter)
    logger.addHandler(lfh) 
    
    #### get working directory
    if args.wd:
        if os.path.isdir(args.wd):
            localpath = args.wd
        else:
            parser.error("scratch space directory does not exist: {0}".format(args.wd))
    else:
        localpath = os.path.dirname(tile)
    
    intersects = []
    
    if os.path.isfile(inpath):
        t = open(inpath, 'r')
        for line in t.readlines():
            line = line.strip('\n').strip('\r')
            
            if ',' in line:
                image, median_string = line.split(',')
                iinfo = mosaic.ImageInfo(image, "IMAGE")
                median = {}
                for stat in median_string.split(";"):
                    k, v = stat.split(":")
                    median[int(k)] = float(v)
                if len(median) == iinfo.bands:
                    iinfo.set_raster_median(median)
                else:
                    logger.warning("Median dct length (%i) does not match band count (%i)", len(median), iinfo.bands)
            
            else:
                iinfo = mosaic.ImageInfo(line, "IMAGE")
            
            intersects.append(iinfo)
        t.close()
    else:
        logger.error("Intersecting image file does not exist: %i", inpath)

    logger.info(tile)

    logger.info("Number of image found in source file: %i", len(intersects))
    
    wd = os.path.join(localpath, os.path.splitext(os.path.basename(tile))[0])
    if not os.path.isdir(wd):
        os.makedirs(wd)
    localtile2 = os.path.join(wd, os.path.basename(tile))
    localtile1 = localtile2.replace(".tif", "_temp.tif")
    
    del_images = []
    images = {}
        
    #### Get Extent geometry 
    poly_wkt = 'POLYGON (( {} {}, {} {}, {} {}, {} {}, {} {} ))'.format(xmin, ymin, xmin, ymax, xmax, ymax, xmax, ymin,
                                                                        xmin, ymin)
    
    c = 0
    for iinfo in intersects:
            
        #### Check if bands number is correct
        mergefile = iinfo.srcfp

        if args.force_pan_to_multi and iinfo.bands > 1:
            if iinfo.bands == 1:
                mergefile = os.path.join(wd, os.path.basename(iinfo.srcfp)[:-4]) + "_merge.tif"
                cmd = 'gdal_merge.py -ps {} {} -separate -o "{}" "{}"'.format(ref_xres,
                                                                              ref_yres,
                                                                              mergefile,
                                                                              '" "'.join([iinfo.srcfp] * iinfo.bands))
                taskhandler.exec_cmd(cmd)
        srcnodata = " ".join([str(ndv) for ndv in iinfo.nodatavalue])

        if args.median_remove:
            dst = os.path.join(wd, os.path.basename(mergefile)[:-4]) + "_median_removed.tif"
            status = BandSubtractMedian(iinfo, dst)
            if status == 1:
                logger.error("BandSubtractMedian() failed on %s", mergefile)
                sys.exit(1)
            ds = gdal.Open(dst)
            if ds:
                srcnodata_val = ds.GetRasterBand(1).GetNoDataValue()
                srcnodata = " ".join([str(srcnodata_val)] * bands)
                mergefile = dst
            else:
                logger.error("BandSubtractMedian() failed at gdal.Open(%s)", dst)
                sys.exit(1)
            
        if c == 0:
            if os.path.isfile(localtile1):
                logger.info("localtile1 already exists")
                status = 1
                break
            cmd = 'gdalwarp {} -srcnodata "{}" -dstnodata "{}" "{}" "{}"'.format(dims, srcnodata, srcnodata, mergefile,
                                                                                 localtile1)
            taskhandler.exec_cmd(cmd)
            
        else:
            cmd = 'gdalwarp -srcnodata "{}" "{}" "{}"'.format(srcnodata, mergefile, localtile1)
            taskhandler.exec_cmd(cmd)
            
        c += 1
       
        if not mergefile == iinfo.srcfp:
            del_images.append(mergefile)
            
    del_images.append(localtile1)        
    
    if status == 0:
        ####  Write to Compressed file
        if os.path.isfile(localtile1):
            if args.gtiff_compression == 'lzw':
                compress_option = '-co "compress=lzw"'
            elif args.gtiff_compression == 'jpeg95':
                compress_option = '-co "compress=jpeg" -co "jpeg_quality=95"'
                
            cmd = 'gdal_translate -stats -of GTiff {} -co "PHOTOMETRIC=MINISBLACK" -co "TILED=YES" -co ' \
                  '"BIGTIFF=IF_SAFER" "{}" "{}"'.format(compress_option, localtile1, localtile2)
            taskhandler.exec_cmd(cmd)
        
        ####  Build Pyramids        
        if os.path.isfile(localtile2):
            cmd = 'gdaladdo "{}" 2 4 8 16 30'.format(localtile2)
            taskhandler.exec_cmd(cmd)
        
        #### Copy tile to destination
        if os.path.isfile(localtile2):
            logger.info("Copying output files to destination dir")
            mosaic.copyall(localtile2, os.path.dirname(tile))
            
        del_images.append(localtile2)
    
    
    #### Delete temp files
    utils.delete_temp_files(del_images)
    shutil.rmtree(wd)
   
    logger.info("Done")
Ejemplo n.º 6
0
def exec_pansharpen(image_pair, pansh_dstfp, args):

    dstdir = os.path.dirname(pansh_dstfp)

    #### Get working dir
    if args.wd is not None:
        wd = args.wd
    else:
        wd = dstdir
    if not os.path.isdir(wd):
        try:
            os.makedirs(wd)
        except OSError:
            pass
    logger.info("Working Dir: %s" % wd)

    ####  Identify name pattern
    print "Multispectral image: %s" % image_pair.mul_srcfp
    print "Panchromatic image: %s" % image_pair.pan_srcfp

    if args.dem is not None:
        dem_arg = '-d "%s" ' % args.dem
    else:
        dem_arg = ""

    bittype = utils.get_bit_depth(args.outtype)
    pan_basename = os.path.splitext(image_pair.pan_srcfn)[0]
    mul_basename = os.path.splitext(image_pair.mul_srcfn)[0]
    pan_local_dstfp = os.path.join(
        wd, "{}_{}{}{}.tif".format(pan_basename, bittype, args.stretch,
                                   args.epsg))
    mul_local_dstfp = os.path.join(
        wd, "{}_{}{}{}.tif".format(mul_basename, bittype, args.stretch,
                                   args.epsg))
    pan_dstfp = os.path.join(
        dstdir, "{}_{}{}{}.tif".format(pan_basename, bittype, args.stretch,
                                       args.epsg))
    mul_dstfp = os.path.join(
        dstdir, "{}_{}{}{}.tif".format(mul_basename, bittype, args.stretch,
                                       args.epsg))
    pansh_tempfp = os.path.join(
        wd, "{}_{}{}{}_pansh_temp.tif".format(mul_basename, bittype,
                                              args.stretch, args.epsg))
    pansh_local_dstfp = os.path.join(
        wd, "{}_{}{}{}_pansh.tif".format(mul_basename, bittype, args.stretch,
                                         args.epsg))
    pansh_xmlfp = os.path.join(
        dstdir, "{}_{}{}{}_pansh.xml".format(mul_basename, bittype,
                                             args.stretch, args.epsg))
    mul_xmlfp = os.path.join(
        dstdir, "{}_{}{}{}.xml".format(mul_basename, bittype, args.stretch,
                                       args.epsg))

    if not os.path.isdir(wd):
        os.makedirs(wd)

    ####  Ortho pan
    logger.info("Orthorectifying panchromatic image")
    if not os.path.isfile(pan_dstfp) and not os.path.isfile(pan_local_dstfp):
        ortho_functions.process_image(image_pair.pan_srcfp, pan_dstfp, args,
                                      image_pair.intersection_geom)

    if not os.path.isfile(pan_local_dstfp) and os.path.isfile(pan_dstfp):
        shutil.copy2(pan_dstfp, pan_local_dstfp)

    logger.info("Orthorectifying multispectral image")
    ####  Ortho multi
    if not os.path.isfile(mul_dstfp) and not os.path.isfile(mul_local_dstfp):
        ## If resolution is specified in the command line, assume it's intended for the pansharpened image
        ##    and multiply the multi by 4
        if args.resolution:
            args.resolution = args.resolution * 4.0
        ortho_functions.process_image(image_pair.mul_srcfp, mul_dstfp, args,
                                      image_pair.intersection_geom)

    if not os.path.isfile(mul_local_dstfp) and os.path.isfile(mul_dstfp):
        shutil.copy2(mul_dstfp, mul_local_dstfp)

    ####  Pansharpen
    logger.info("Pansharpening multispectral image")
    if os.path.isfile(pan_local_dstfp) and os.path.isfile(mul_local_dstfp):
        if not os.path.isfile(pansh_local_dstfp):
            cmd = 'gdal_pansharpen.py -co BIGTIFF=IF_SAFER -co COMPRESS=LZW -co TILED=YES "{}" "{}" "{}"'.format(
                pan_local_dstfp, mul_local_dstfp, pansh_local_dstfp)
            taskhandler.exec_cmd(cmd)
    else:
        print "Pan or Multi warped image does not exist\n\t%s\n\t%s" % (
            pan_local_dstfp, mul_local_dstfp)

    #### Make pyramids
    if os.path.isfile(pansh_local_dstfp):
        cmd = 'gdaladdo "%s" 2 4 8 16' % (pansh_local_dstfp)
        taskhandler.exec_cmd(cmd)

    ## Copy warped multispectral xml to pansharpened output
    shutil.copy2(mul_xmlfp, pansh_xmlfp)

    #### Copy pansharpened output
    if wd <> dstdir:
        for local_path, dst_path in [(pansh_local_dstfp, pansh_dstfp),
                                     (pan_local_dstfp, pan_dstfp),
                                     (mul_local_dstfp, mul_dstfp)]:
            if os.path.isfile(local_path) and not os.path.isfile(dst_path):
                shutil.copy2(local_path, dst_path)

    #### Delete Temp Files
    wd_files = [pansh_local_dstfp, pan_local_dstfp, mul_local_dstfp]

    if not args.save_temps:
        if wd <> dstdir:
            for f in wd_files:
                try:
                    os.remove(f)
                except Exception, e:
                    logger.warning('Could not remove %s: %s' %
                                   (os.path.basename(f), e))
def exec_pansharpen(image_pair, pansh_dstfp, args):

    dstdir = os.path.dirname(pansh_dstfp)

    #### Get working dir
    if args.wd is not None:
        wd = args.wd
    else:
        wd = dstdir
    if not os.path.isdir(wd):
        try:
            os.makedirs(wd)
        except OSError:
            pass
    logger.info("Working Dir: %s", wd)

    ####  Identify name pattern
    print("Multispectral image: {}".format(image_pair.mul_srcfp))
    print("Panchromatic image: {}".format(image_pair.pan_srcfp))

    if args.dem is not None:
        dem_arg = '-d "{}" '.format(args.dem)
    else:
        dem_arg = ""

    bittype = utils.get_bit_depth(args.outtype)
    pan_basename = os.path.splitext(image_pair.pan_srcfn)[0]
    mul_basename = os.path.splitext(image_pair.mul_srcfn)[0]
    pan_local_dstfp = os.path.join(wd, "{}_{}{}{}.tif".format(pan_basename, bittype, args.stretch, args.epsg))
    mul_local_dstfp = os.path.join(wd, "{}_{}{}{}.tif".format(mul_basename, bittype, args.stretch, args.epsg))
    pan_dstfp = os.path.join(dstdir, "{}_{}{}{}.tif".format(pan_basename, bittype, args.stretch, args.epsg))
    mul_dstfp = os.path.join(dstdir, "{}_{}{}{}.tif".format(mul_basename, bittype, args.stretch, args.epsg))
    pansh_tempfp = os.path.join(wd, "{}_{}{}{}_pansh_temp.tif".format(mul_basename, bittype, args.stretch, args.epsg))
    pansh_local_dstfp = os.path.join(wd, "{}_{}{}{}_pansh.tif".format(mul_basename, bittype, args.stretch, args.epsg))
    pansh_xmlfp = os.path.join(dstdir, "{}_{}{}{}_pansh.xml".format(mul_basename, bittype, args.stretch, args.epsg))
    mul_xmlfp = os.path.join(dstdir, "{}_{}{}{}.xml".format(mul_basename, bittype, args.stretch, args.epsg))
    
    if not os.path.isdir(wd):
        os.makedirs(wd)

    ####  Ortho pan
    logger.info("Orthorectifying panchromatic image")
    if not os.path.isfile(pan_dstfp) and not os.path.isfile(pan_local_dstfp):
        ortho_functions.process_image(image_pair.pan_srcfp, pan_dstfp, args, image_pair.intersection_geom)

    if not os.path.isfile(pan_local_dstfp) and os.path.isfile(pan_dstfp):
        shutil.copy2(pan_dstfp, pan_local_dstfp)

    logger.info("Orthorectifying multispectral image")
    ####  Ortho multi
    if not os.path.isfile(mul_dstfp) and not os.path.isfile(mul_local_dstfp):
        ## If resolution is specified in the command line, assume it's intended for the pansharpened image
        ##    and multiply the multi by 4
        if args.resolution:
            args.resolution = args.resolution * 4.0
        ortho_functions.process_image(image_pair.mul_srcfp, mul_dstfp, args, image_pair.intersection_geom)

    if not os.path.isfile(mul_local_dstfp) and os.path.isfile(mul_dstfp):
        shutil.copy2(mul_dstfp, mul_local_dstfp)

    ####  Pansharpen
    ## get system info for program extension
    if platform.system() == 'Windows':
        py_ext = ''
    else:
        py_ext = '.py'
    
    logger.info("Pansharpening multispectral image")
    if os.path.isfile(pan_local_dstfp) and os.path.isfile(mul_local_dstfp):
        if not os.path.isfile(pansh_local_dstfp):
            cmd = 'gdal_pansharpen{} -co BIGTIFF=IF_SAFER -co COMPRESS=LZW -co TILED=YES "{}" "{}" "{}"'.\
                format(py_ext, pan_local_dstfp, mul_local_dstfp, pansh_local_dstfp)
            taskhandler.exec_cmd(cmd)
    else:
        print("Pan or Multi warped image does not exist\n\t{}\n\t{}").format(pan_local_dstfp, mul_local_dstfp)

    #### Make pyramids
    if os.path.isfile(pansh_local_dstfp):
        cmd = 'gdaladdo -r {} "{}" 2 4 8 16'.format(args.pyramid_type, pansh_local_dstfp)
        taskhandler.exec_cmd(cmd)
       
    ## Copy warped multispectral xml to pansharpened output
    shutil.copy2(mul_xmlfp, pansh_xmlfp)

    #### Copy pansharpened output
    if wd != dstdir:
        for local_path, dst_path in [(pansh_local_dstfp, pansh_dstfp), (pan_local_dstfp, pan_dstfp),
                                     (mul_local_dstfp, mul_dstfp)]:
            if os.path.isfile(local_path) and not os.path.isfile(dst_path):
                shutil.copy2(local_path, dst_path)

    #### Delete Temp Files
    wd_files = [
        pansh_local_dstfp,
        pan_local_dstfp,
        mul_local_dstfp
    ]

    if not args.save_temps:
        if wd != dstdir:
            for f in wd_files:
                try:
                    os.remove(f)
                except Exception as e:
                    logger.warning('Could not remove %s: %s', os.path.basename(f), e)
    
    if os.path.isfile(pansh_dstfp):
        return 0
    else:
        return 0
def calc_ndvi(srcfp, dstfp, args):

    # ndvi nodata value
    ndvi_nodata = -9999

    # tolerance for floating point equality
    tol = 0.00001

    # get basenames for src and dst files, get xml metadata filenames
    srcdir, srcfn = os.path.split(srcfp)
    dstdir, dstfn = os.path.split(dstfp)
    bn, ext = os.path.splitext(srcfn)
    src_xml = os.path.join(srcdir, bn + '.xml')
    dst_xml = os.path.join(dstdir, bn + '_ndvi.xml')

    #### Get working dir
    if args.wd is not None:
        wd = args.wd
    else:
        wd = dstdir
    if not os.path.isdir(wd):
        try:
            os.makedirs(wd)
        except OSError:
            pass
    logger.info("Working Dir: %s", wd)

    print("Image: {}".format(srcfn))
   
    ## copy source image to working directory
    srcfp_local = os.path.join(wd, srcfn)
    if not os.path.isfile(srcfp_local):
        shutil.copy2(srcfp, srcfp_local)

    ## open image and get band numbers
    ds = gdal.Open(srcfp_local)
    if ds:
        bands = ds.RasterCount
        if bands == 8:
            red_band_num = 5
            nir_band_num = 7
        elif bands == 4:
            red_band_num = 3
            nir_band_num = 4
        else:
            logger.error("Cannot calculate NDVI from a %i band image: %s", bands, srcfp_local)
            return 1
    else:
        logger.error("Cannot open target image: %s", srcfp_local)
        return 1

    ## check for input data type - must be float or int
    datatype = ds.GetRasterBand(1).DataType
    if datatype not in [1, 2, 3, 4, 5, 6, 7]:
        logger.error("Invalid input data type %s", datatype)
        return 1 

    ## get the raster dimensions
    nx = ds.RasterXSize
    ny = ds.RasterYSize

    ## open output file for write and copy proj/geotransform info
    if not os.path.isfile(dstfp):
        dstfp_local = os.path.join(wd, os.path.basename(dstfp))
        gtiff_options = ['TILED=YES', 'COMPRESS=LZW', 'BIGTIFF=IF_SAFER']
        driver = gdal.GetDriverByName('GTiff')
        out_ds = driver.Create(dstfp_local, nx, ny, 1, gdal.GetDataTypeByName(args.outtype), gtiff_options)
        if out_ds:
            out_ds.SetGeoTransform(ds.GetGeoTransform())
            out_ds.SetProjection(ds.GetProjection())
            ndvi_band = out_ds.GetRasterBand(1)
            ndvi_band.SetNoDataValue(float(ndvi_nodata))
        else:
            logger.error("Couldn't open for write: %s", dstfp_local)
            return 1

        ## for red and nir bands, get band data, nodata values, and natural block size
        ## if NoData is None default it to zero.
        red_band = ds.GetRasterBand(red_band_num)
        if red_band is None:
            logger.error("Can't load band %i from %s", red_band_num, srcfp_local)
            return 1
        red_nodata = red_band.GetNoDataValue()
        if red_nodata is None:
            logger.info("Defaulting red band nodata to zero")
            red_nodata = 0.0
        (red_xblocksize, red_yblocksize) = red_band.GetBlockSize()
    
        nir_band = ds.GetRasterBand(nir_band_num)
        if nir_band is None:
            logger.error("Can't load band %i from %s", nir_band_num, srcfp_local)
            return 1
        nir_nodata = nir_band.GetNoDataValue()
        if nir_nodata is None:
            logger.info("Defaulting nir band nodata to zero")
            nir_nodata = 0.0
        (nir_xblocksize, nir_yblocksize) = nir_band.GetBlockSize()

        ## if different block sizes choose the smaller of the two
        xblocksize = min([red_xblocksize, nir_xblocksize])
        yblocksize = min([red_yblocksize, nir_yblocksize])

        ## calculate the number of x and y blocks to read/write
        nxblocks = int(math.floor(nx + xblocksize - 1) / xblocksize)
        nyblocks = int(math.floor(ny + yblocksize - 1) / yblocksize)

        ## blocks loop
        yblockrange = range(nyblocks)
        xblockrange = range(nxblocks)
        for yblock in yblockrange:
            ## y offset for ReadAsArray
            yoff = yblock * yblocksize

            ## get block actual y size in case of partial block at edge
            if yblock < nyblocks - 1:
                block_ny = yblocksize
            else:
                block_ny = ny - (yblock * yblocksize)

            for xblock in xblockrange:
                ## x offset for ReadAsArray
                xoff = xblock * xblocksize

                ## get block actual x size in case of partial block at edge
                if xblock < (nxblocks - 1):
                    block_nx = xblocksize
                else:
                    block_nx = nx - (xblock * xblocksize)

                ## read a block from each band
                red_array = red_band.ReadAsArray(xoff, yoff, block_nx, block_ny)
                nir_array = nir_band.ReadAsArray(xoff, yoff, block_nx, block_ny)

                ## generate mask for red nodata, nir nodata, and 
                ## (red+nir) less than tol away from zero
                red_mask = (red_array == red_nodata)
                if red_array[red_mask] != []:
                    nir_mask = (nir_array == nir_nodata)
                    if nir_array[nir_mask] != []:
                        divzero_mask = abs(nir_array + red_array) < tol
                        if red_array[divzero_mask] != []:
                            ndvi_mask = red_mask | nir_mask | divzero_mask
                        else:
                            ndvi_mask = red_mask | nir_mask
                    else:
                        divzero_mask = abs(nir_array + red_array) < tol
                        if red_array[divzero_mask] != []:
                            ndvi_mask = red_mask | divzero_mask
                        else:
                            ndvi_mask = red_mask
                else:
                    nir_mask = (nir_array == nir_nodata)
                    if nir_array[nir_mask] != []:
                        divzero_mask = abs(nir_array + red_array) < tol
                        if red_array[divzero_mask] != []:
                            ndvi_mask = nir_mask | divzero_mask
                        else:
                            ndvi_mask = nir_mask
                    else:
                        divzero_mask = abs(nir_array + red_array) < tol
                        if red_array[divzero_mask] != []:
                            ndvi_mask = divzero_mask
                        else:
                            ndvi_mask = numpy.full_like(red_array, fill_value=0, dtype=numpy.bool)

                ## declare ndvi array, init to nodata value
                ndvi_array = numpy.full_like(red_array, fill_value=ndvi_nodata, dtype=numpy.float32)
                ## cast bands to float for calc
                red_asfloat = numpy.array(red_array, dtype=numpy.float32)
                red_array = None
                nir_asfloat = numpy.array(nir_array, dtype=numpy.float32)
                nir_array = None

                ## calculate ndvi
                if ndvi_array[~ndvi_mask] != []:
                    ndvi_array[~ndvi_mask] = numpy.divide(numpy.subtract(nir_asfloat[~ndvi_mask],
                                                                         red_asfloat[~ndvi_mask]),
                                                          numpy.add(nir_asfloat[~ndvi_mask],
                                                                    red_asfloat[~ndvi_mask]))
                red_asfloat = None
                nir_asfloat = None
 
                ## scale and cast to int if outtype integer
                if args.outtype == 'Int16':
                    ndvi_scaled = numpy.full_like(ndvi_array, fill_value=ndvi_nodata, dtype=numpy.int16)
                    if ndvi_scaled[~ndvi_mask] != []:
                        ndvi_scaled[~ndvi_mask] = numpy.array(ndvi_array[~ndvi_mask]*1000.0, dtype=numpy.int16)
                    ndvi_array = ndvi_scaled
                    ndvi_scaled = None

                ndvi_mask = None
               
                ## write valid portion of ndvi array to output file
                ndvi_band.WriteArray(ndvi_array, xoff, yoff)
                ndvi_array = None

        out_ds = None
        ds = None
        
        if os.path.isfile(dstfp_local):
            ## add pyramids
            cmd = 'gdaladdo "{}" 2 4 8 16'.format(dstfp_local)
            taskhandler.exec_cmd(cmd)

            ## copy to dst
            if wd != dstdir:
                shutil.copy2(dstfp_local, dstfp)

            ## copy xml to dst
            if os.path.isfile(src_xml):
                shutil.copy2(src_xml, dst_xml)
            else:
                logger.warning("xml %s not found", src_xml)
        
            ## Delete Temp Files
            temp_files = [srcfp_local]
            wd_files = [dstfp_local]
            if not args.save_temps:
                for f in temp_files:
                    try:
                        os.remove(f)
                    except Exception as e:
                        logger.warning('Could not remove %s: %s', os.path.basename(f), e)
            if wd != dstdir:
                for f in wd_files:
                    try:
                        os.remove(f)
                    except Exception as e:
                        logger.warning('Could not remove %s: %s', os.path.basename(f), e)
        else:
            logger.error("pgc_ndvi.py: %s was not created", dstfp_local)
            return 1 
            
    else:
        logger.info("pgc_ndvi.py: file %s already exists", dstfp)
        
        ## copy xml to dst if missing
        if not os.path.isfile(dst_xml):
            shutil.copy2(src_xml, dst_xml)
            
    return 0
Ejemplo n.º 9
0
def exec_pansharpen(image_pair, pansh_dstfp, args):

    dstdir = os.path.dirname(pansh_dstfp)

    #### Get working dir
    if args.wd is not None:
        wd = args.wd
    else:
        wd = dstdir
    if not os.path.isdir(wd):
        try:
            os.makedirs(wd)
        except OSError:
            pass
    logger.info("Working Dir: %s", wd)

    ####  Identify name pattern
    print("Multispectral image: {}".format(image_pair.mul_srcfp))
    print("Panchromatic image: {}".format(image_pair.pan_srcfp))

    if args.dem is not None:
        dem_arg = '-d "{}" '.format(args.dem)
    else:
        dem_arg = ""

    bittype = utils.get_bit_depth(args.outtype)
    pan_basename = os.path.splitext(image_pair.pan_srcfn)[0]
    mul_basename = os.path.splitext(image_pair.mul_srcfn)[0]
    pan_local_dstfp = os.path.join(
        wd, "{}_{}{}{}.tif".format(pan_basename, bittype, args.stretch,
                                   args.epsg))
    mul_local_dstfp = os.path.join(
        wd, "{}_{}{}{}.tif".format(mul_basename, bittype, args.stretch,
                                   args.epsg))
    pan_dstfp = os.path.join(
        dstdir, "{}_{}{}{}.tif".format(pan_basename, bittype, args.stretch,
                                       args.epsg))
    mul_dstfp = os.path.join(
        dstdir, "{}_{}{}{}.tif".format(mul_basename, bittype, args.stretch,
                                       args.epsg))
    pansh_tempfp = os.path.join(
        wd, "{}_{}{}{}_pansh_temp.tif".format(mul_basename, bittype,
                                              args.stretch, args.epsg))
    pansh_local_dstfp = os.path.join(
        wd, "{}_{}{}{}_pansh.tif".format(mul_basename, bittype, args.stretch,
                                         args.epsg))
    pansh_xmlfp = os.path.join(
        dstdir, "{}_{}{}{}_pansh.xml".format(mul_basename, bittype,
                                             args.stretch, args.epsg))
    mul_xmlfp = os.path.join(
        dstdir, "{}_{}{}{}.xml".format(mul_basename, bittype, args.stretch,
                                       args.epsg))

    if not os.path.isdir(wd):
        os.makedirs(wd)

    ####  Ortho pan
    logger.info("Orthorectifying panchromatic image")
    if not os.path.isfile(pan_dstfp) and not os.path.isfile(pan_local_dstfp):
        ortho_functions.process_image(image_pair.pan_srcfp, pan_dstfp, args,
                                      image_pair.intersection_geom)

    if not os.path.isfile(pan_local_dstfp) and os.path.isfile(pan_dstfp):
        shutil.copy2(pan_dstfp, pan_local_dstfp)

    logger.info("Orthorectifying multispectral image")
    ####  Ortho multi
    if not os.path.isfile(mul_dstfp) and not os.path.isfile(mul_local_dstfp):
        ## If resolution is specified in the command line, assume it's intended for the pansharpened image
        ##    and multiply the multi by 4
        if args.resolution:
            args.resolution = args.resolution * 4.0
        ortho_functions.process_image(image_pair.mul_srcfp, mul_dstfp, args,
                                      image_pair.intersection_geom)

    if not os.path.isfile(mul_local_dstfp) and os.path.isfile(mul_dstfp):
        shutil.copy2(mul_dstfp, mul_local_dstfp)

    ####  Pansharpen
    ## get system info for program extension
    if platform.system() == 'Windows':
        py_ext = ''
    else:
        py_ext = '.py'

    pan_threading = ''
    if hasattr(args, 'threads'):
        if args.threads != 1:
            pan_threading = '-threads {}'.format(args.threads)

    logger.info("Pansharpening multispectral image")
    if os.path.isfile(pan_local_dstfp) and os.path.isfile(mul_local_dstfp):
        if not os.path.isfile(pansh_local_dstfp):
            cmd = 'gdal_pansharpen{} -co BIGTIFF=IF_SAFER -co COMPRESS=LZW -co TILED=YES {} "{}" "{}" "{}"'.\
                format(py_ext, pan_threading, pan_local_dstfp, mul_local_dstfp, pansh_local_dstfp)
            taskhandler.exec_cmd(cmd)
    else:
        logger.warning(
            "Pan or Multi warped image does not exist\n\t{}\n\t{}".format(
                pan_local_dstfp, mul_local_dstfp))

    #### Make pyramids
    if os.path.isfile(pansh_local_dstfp):
        cmd = 'gdaladdo -r {} "{}" 2 4 8 16'.format(args.pyramid_type,
                                                    pansh_local_dstfp)
        taskhandler.exec_cmd(cmd)

    ## Copy warped multispectral xml to pansharpened output
    shutil.copy2(mul_xmlfp, pansh_xmlfp)

    #### Copy pansharpened output
    if wd != dstdir:
        for local_path, dst_path in [(pansh_local_dstfp, pansh_dstfp),
                                     (pan_local_dstfp, pan_dstfp),
                                     (mul_local_dstfp, mul_dstfp)]:
            if os.path.isfile(local_path) and not os.path.isfile(dst_path):
                shutil.copy2(local_path, dst_path)

    #### Delete Temp Files
    wd_files = [pansh_local_dstfp, pan_local_dstfp, mul_local_dstfp]

    if not args.save_temps:
        if wd != dstdir:
            for f in wd_files:
                try:
                    os.remove(f)
                except Exception as e:
                    logger.warning('Could not remove %s: %s',
                                   os.path.basename(f), e)

    if os.path.isfile(pansh_dstfp):
        return 0
    else:
        return 0