Ejemplo n.º 1
0
    #dem1_fwd_obs = np.ma.empty_like(dem1)
    #dem1_fwd_obs[fwd_idx] = dem2[disp_y_abs_fwd.compressed(),disp_x_abs_fwd.compressed()]

    #Extract values from dem2 for new positions
    dem1_fwd_obs = dem2[np.ma.filled(disp_y_abs_fwd, 0),
                        np.ma.filled(disp_x_abs_fwd, 0)]
    dem1_fwd_obs = np.ma.masked_equal(dem1_fwd_obs, dem2.fill_value)
    #This is necessary b/c we are filling index arrays with 0, so existing nodata pixels will have valid values

    #NOTE: this was changed on 9/25/15 due to error in the Jak datset, but it didn't cause problems with earlier PIG data

    disp_m = np.percentile(np.sqrt(disp_x**2 + disp_y**2), 98)
    #disp_m = 59
    disp_m = 29

    dem1_smooth = filtlib.gauss_fltr_astropy(dem1, 2 * disp_m)
    dem2_smooth = filtlib.gauss_fltr_astropy(dem2, 2 * disp_m)

    #dem1_fwd_obs.mask[:] = disp_x_abs_fwd.mask
    dem1_fwd_obs = np.ma.array(dem1_fwd_obs, mask=disp_x_abs_fwd.mask)
    #Expected elevation values assuming steady-state advection along dem1 surface
    #dem1_fwd_exp = dem1[np.ma.filled(disp_y_abs_fwd,0),np.ma.filled(disp_x_abs_fwd,0)]
    dem1_fwd_exp = dem1_smooth[np.ma.filled(disp_y_abs_fwd, 0),
                               np.ma.filled(disp_x_abs_fwd, 0)]
    dem1_fwd_exp = np.ma.masked_equal(dem1_fwd_exp, dem1.fill_value)
    #dem1_fwd_exp.mask[:] = disp_x_abs_fwd.mask
    dem1_fwd_exp = np.ma.array(dem1_fwd_exp, mask=disp_x_abs_fwd.mask)

    #This stores indices for expected feature locations in dem1
    disp_x_abs_inv = np.ma.masked_outside(idx[1] - disp_x, 0,
                                          dem1.shape[1] - 1)
Ejemplo n.º 2
0
def warp(src_ds, res=None, extent=None, t_srs=None, r='cubic', driver=mem_drv, dst_fn=None, dst_ndv=None, verbose=True):
    """Warp an input dataset with predetermined arguments specifying output res/extent/srs

    This is the function that actually calls gdal.ReprojectImage
    
    Parameters
    ----------
    src_ds : gdal.Dataset object
        Dataset to be warped
    res : float
        Desired output resolution
    extent : list of float
        Desired output extent in t_srs coordinate system
    t_srs : osr.SpatialReference()
        Desired output spatial reference
    r : str
        Desired resampling algorithm
    driver : GDAL Driver to use for warp 
        Either MEM or GTiff
    dst_fn : str
        Output filename (for disk warp)
    dst_ndv : float
        Desired output NoData Value

    Returns
    -------
    dst_ds : gdal.Dataset object
        Warped dataset (either in memory or on disk)

    """
    src_srs = geolib.get_ds_srs(src_ds)
    
    if t_srs is None:
        t_srs = geolib.get_ds_srs(src_ds)
    
    src_gt = src_ds.GetGeoTransform()
    #Note: get_res returns [x_res, y_res]
    #Could just use gt here and average x_res and y_res
    src_res = geolib.get_res(src_ds, t_srs=t_srs, square=True)[0]

    if res is None:
        res = src_res

    if extent is None:
        extent = geolib.ds_geom_extent(src_ds, t_srs=t_srs)
    
    #Note: GDAL Lanczos creates block artifacts
    #Wait for gdalwarp to support gaussian resampling
    #Want to use Lanczos for downsampling
    #if src_res < res:
    #    gra = gdal.GRA_Lanczos
    #See http://blog.codinghorror.com/better-image-resizing/
    # Suggests cubic for downsampling, bilinear for upsampling
    #    gra = gdal.GRA_Cubic
    #Cubic for upsampling
    #elif src_res >= res:
    #    gra = gdal.GRA_Bilinear

    gra = parse_rs_alg(r)

    #At this point, the resolution and extent values must be float
    #Extent must be list
    res = float(res)
    extent = [float(i) for i in extent]

    #Might want to move this to memwarp_multi, keep memwarp basic w/ gdal.GRA types

    #Create progress function
    prog_func = None
    if verbose:
        prog_func = gdal.TermProgress
    
    if dst_fn is None:
        #This is a dummy fn if only in mem, but can be accessed later via GetFileList()
        #Actually, no, doesn't look like the filename survivies
        dst_fn = ''
    
    #Compute output image dimensions
    dst_nl = int(round((extent[3] - extent[1])/res))
    dst_ns = int(round((extent[2] - extent[0])/res))
    #dst_nl = int(math.ceil((extent[3] - extent[1])/res))
    #dst_ns = int(math.ceil((extent[2] - extent[0])/res))
    #dst_nl = int(math.floor((extent[3] - extent[1])/res))
    #dst_ns = int(math.floor((extent[2] - extent[0])/res))
    if verbose:
        print('nl: %i ns: %i res: %0.3f' % (dst_nl, dst_ns, res))
    #Create output dataset
    src_b = src_ds.GetRasterBand(1)
    src_dt = src_b.DataType
    src_nl = src_ds.RasterYSize
    src_ns = src_ds.RasterXSize

    dst_ds = driver.Create(dst_fn, dst_ns, dst_nl, src_ds.RasterCount, src_dt) 

    dst_ds.SetProjection(t_srs.ExportToWkt())
    #Might be an issue to use src_gt rotation terms here with arbitrary extent/res
    dst_gt = [extent[0], res, src_gt[2], extent[3], src_gt[4], -res]
    dst_ds.SetGeoTransform(dst_gt)
   
    #This will smooth the input before downsampling to prevent aliasing, fill gaps
    #Pretty inefficent, as we need to create another intermediate dataset
    gauss = False 

    for n in range(1, src_ds.RasterCount+1):
        if dst_ndv is None:
            src_b = src_ds.GetRasterBand(n)
            src_ndv = iolib.get_ndv_b(src_b)
            dst_ndv = src_ndv
        b = dst_ds.GetRasterBand(n)
        b.SetNoDataValue(dst_ndv)
        b.Fill(dst_ndv)

        if gauss:
            from pygeotools.lib import filtlib
            #src_a = src_b.GetVirtualMemArray()
            #Compute resampling ratio to determine filter window size
            res_ratio = float(res)/src_res
            if verbose:
                print("Resampling factor: %0.3f" % res_ratio)
            #Might be more efficient to do iterative gauss filter with size 3, rather than larger windows
            f_size = math.floor(res_ratio/2.)*2+1
            #This is conservative to avoid filling holes with noise
            #f_size = math.floor(res_ratio/2.)*2-1
            if f_size <= 1:
                continue

            if verbose:
                print("Smoothing window size: %i" % f_size)
            #Create temp dataset to store filtered array - avoid overwriting original
            temp_ds = driver.Create('', src_ns, src_nl, src_ds.RasterCount, src_dt) 
            temp_ds.SetProjection(src_srs.ExportToWkt())
            temp_ds.SetGeoTransform(src_gt)
            temp_b = temp_ds.GetRasterBand(n)
            temp_b.SetNoDataValue(dst_ndv)
            temp_b.Fill(dst_ndv)

            src_a = iolib.b_getma(src_b)
            src_a = filtlib.gauss_fltr_astropy(src_a, size=f_size)
            #Want to run with maskfill, so only fills gaps, without expanding isolated points
            temp_b.WriteArray(src_a)
            src_ds = temp_ds
            
            #In theory, NN should be fine since we already smoothed.  In practice, cubic still provides slightly better results
            #gra = gdal.GRA_NearestNeighbour
    
    """
    if not verbose:
        #Suppress GDAL progress bar
        orig_stdout = sys.stdout
        sys.stdout = open(os.devnull, 'w')
    """

    #Note: default maxerror=0.0, second 0.0 argument
    gdal.ReprojectImage(src_ds, dst_ds, src_srs.ExportToWkt(), t_srs.ExportToWkt(), gra, 0.0, 0.0, prog_func)

    """
    if not verbose:
        sys.stdout.close()
        sys.stdout = orig_stdout
    """

    #Note: this is now done in diskwarp
    #Write out to disk
    #if driver != mem_drv:
    #    dst_ds.FlushCache()

    #Return GDAL dataset object in memory
    return dst_ds
Ejemplo n.º 3
0
def main():
    parser = getparser()
    args = parser.parse_args()

    fn = args.fn
    if not iolib.fn_check(fn):
        sys.exit("Unable to locate input file: %s" % fn)

    #Need some checks on these
    param = args.param

    print("Loading input raster into masked array")
    ds = iolib.fn_getds(fn)
    #Currently supports only single band operations
    r = iolib.ds_getma(ds, 1)

    #May need to cast input ma as float32 so np.nan filling works
    #r = r.astype(np.float32)
    #Want function that checks and returns float32 if necessary
    #Should filter, then return original dtype

    r_fltr = r

    #Loop through all specified input filters
    #for filt in args.filt:
    filt = args.filt[0]

    if len(param) == 1:
        param = param[0]
    param_str = ''

    if filt == 'range':
        #Range filter
        param = [float(i) for i in param[1:]]
        r_fltr = filtlib.range_fltr(r_fltr, param)
        param_str = '_{0:0.2f}-{1:0.2f}'.format(*param)
    elif filt == 'absrange':
        #Range filter of absolute values
        param = [float(i) for i in param[1:]]
        r_fltr = filtlib.absrange_fltr(r_fltr, param)
        param_str = '_{0:0.2f}-{1:0.2f}'.format(*param)
    elif filt == 'perc':
        #Percentile filter
        param = [float(i) for i in param[1:]]
        r_fltr = filtlib.perc_fltr(r, perc=param)
        param_str = '_{0:0.2f}-{1:0.2f}'.format(*param)
    elif filt == 'med':
        #Median filter
        param = int(param)
        r_fltr = filtlib.rolling_fltr(r_fltr, f=np.nanmedian, size=param)
        #r_fltr = filtlib.median_fltr(r_fltr, fsize=param, origmask=True)
        #r_fltr = filtlib.median_fltr_skimage(r_fltr, radius=4, origmask=True)
        param_str = '_%ipx' % param
    elif filt == 'gauss':
        #Gaussian filter (default)
        param = int(param)
        r_fltr = filtlib.gauss_fltr_astropy(r_fltr,
                                            size=param,
                                            origmask=False,
                                            fill_interior=False)
        param_str = '_%ipx' % param
    elif filt == 'highpass':
        #High pass filter
        param = int(param)
        r_fltr = filtlib.highpass(r_fltr, size=param)
        param_str = '_%ipx' % param
    elif filt == 'sigma':
        #n*sigma filter, remove outliers
        param = int(param)
        r_fltr = filtlib.sigma_fltr(r_fltr, n=param)
        param_str = '_n%i' % param
    elif filt == 'mad':
        #n*mad filter, remove outliers
        #Maybe better to use a percentile filter
        param = int(param)
        r_fltr = filtlib.mad_fltr(r_fltr, n=param)
        param_str = '_n%i' % param
    elif filt == 'dz':
        #Difference filter, need to specify ref_fn and range
        #Could let the user compute their own dz, then just run a standard range or absrange filter
        ref_fn = param[0]
        ref_ds = warplib.memwarp_multi_fn([
            ref_fn,
        ],
                                          res=ds,
                                          extent=ds,
                                          t_srs=ds)[0]
        ref = iolib.ds_getma(ref_ds)
        param = [float(i) for i in param[1:]]
        r_fltr = filtlib.dz_fltr_ma(r, ref, rangelim=param)
        #param_str = '_{0:0.2f}-{1:0.2f}'.format(*param)
        param_str = '_{0:0.0f}_{1:0.0f}'.format(*param)
    else:
        sys.exit("No filter type specified")

    #Compute and print stats before/after
    if args.stats:
        print("Input stats:")
        malib.print_stats(r)
        print("Filtered stats:")
        malib.print_stats(r_fltr)

    #Write out
    dst_fn = os.path.splitext(fn)[0] + '_%sfilt%s.tif' % (filt, param_str)
    if args.outdir is not None:
        outdir = args.outdir
        if not os.path.exists(outdir):
            os.makedirs(outdir)
        dst_fn = os.path.join(outdir, os.path.split(dst_fn)[-1])
    print("Writing out filtered raster: %s" % dst_fn)
    iolib.writeGTiff(r_fltr, dst_fn, ds)
Ejemplo n.º 4
0
    #Attempt to extract from nearby SNOTEL sites for dem_ts
    #Attempt to use model
    #Last resort, use constant value
    rho_s = 0.5
    #rho_s = 0.4
    #rho_s = 0.36

#Convert snow depth to swe
swe = dz * rho_s

if args.filter:
    print("Filtering SWE map")
    #Median filter to remove artifacts
    swe_f = filtlib.rolling_fltr(swe, size=5)
    #Gaussian filter to smooth over gaps
    swe_f = filtlib.gauss_fltr_astropy(swe, size=9)
    swe = swe_f

swe_clim = list(malib.calcperc(swe, (1,99)))
swe_clim[0] = 0
swe_clim = (0, 8)

prism = None
nax = 2
figsize = (8, 4)
if args.prism:
    #This is PRISM 30-year normal winter PRECIP
    prism_fn = '/Users/dshean/data/PRISM_ppt_30yr_normal_800mM2_10-05_winter_cum.tif'
    if os.path.exists(prism_fn):
        prism_ds = warplib.memwarp_multi_fn([prism_fn,], extent=dem1_ds, res=dem1_ds, t_srs=dem1_ds, r='cubicspline')[0]
        #Values are mm, convert to meters
Ejemplo n.º 5
0
Archivo: vmap.py Proyecto: whigg/vmap
def main():
    parser = getparser()
    args = parser.parse_args()
    if args.seedmode == 'existing_velocity':
        if args.vx_fn is None or args.vy_fn is None:
            parser.error('"-seedmode existing_velocity" requires "-vx_fn" and "-vy_fn"')

    print('\n%s' % datetime.now())
    print('%s UTC\n' % datetime.utcnow())

    align = args.align
    seedmode = args.seedmode
    spr = args.refinement
    erode = args.erode
    #Correlator tile timeout
    #With proper seeding, correlation should be very fast
    #timeout = 360 
    timeout = 1200 
    threads = args.threads

    kernel = (args.kernel, args.kernel)
    #SGM correlator
    if spr > 3:
        #kernel = (7,7)
        kernel = (11,11)
        erode = 0

    #Smooth the output F.tif 
    smoothF = args.filter 

    res = args.tr
    #Resample input to something easier to work with
    #res = 4.0

    #Open input files
    fn1 = args.fn1
    fn2 = args.fn2 

    if not iolib.fn_check(fn1) or not iolib.fn_check(fn2):
        sys.exit("Unable to locate input files")

    if args.outdir is not None:
        outdir = args.outdir
    else:
        outdir = '%s__%s_vmap_%sm_%ipx_spm%i' % (os.path.splitext(os.path.split(fn1)[1])[0], \
                os.path.splitext(os.path.split(fn2)[1])[0], res, kernel[0], spr)

    #Note, can encounter filename length issues in boost, just use vmap prefix
    outprefix = '%s/vmap' % (outdir)
    if not os.path.exists(outdir):
        os.makedirs(outdir)

    #Check to see if inputs have geolocation and projection information
    ds1 = iolib.fn_getds(fn1)
    ds2 = iolib.fn_getds(fn2)

    if geolib.srs_check(ds1) and geolib.srs_check(ds2):
        ds1_clip_fn = os.path.join(outdir, os.path.splitext(os.path.basename(fn1))[0]+'_warp.tif')
        ds2_clip_fn = os.path.join(outdir, os.path.splitext(os.path.basename(fn2))[0]+'_warp.tif')

        if not os.path.exists(ds1_clip_fn) or not os.path.exists(ds2_clip_fn):
            #This should write out files to new subdir
            ds1_clip, ds2_clip = warplib.diskwarp_multi_fn([fn1, fn2], extent='intersection', res=res, r='average', outdir=outdir)
            ds1_clip = None
            ds2_clip = None
            #However, if inputs have identical extent/res/proj, then link to original files
            if not os.path.exists(ds1_clip_fn):
                os.symlink(os.path.abspath(fn1), ds1_clip_fn)
            if not os.path.exists(ds2_clip_fn):
                os.symlink(os.path.abspath(fn2), ds2_clip_fn)
            align = 'None'

        #Mask support - limit correlation only to rock/ice surfaces, no water/veg
        #This masks input images - guarantee we won't waste time correlating over vegetation
        #TODO: Add support to load arbitrary raster or shp mask
        if args.mask_input:
            ds1_masked_fn = os.path.splitext(ds1_clip_fn)[0]+'_masked.tif'
            ds2_masked_fn = os.path.splitext(ds2_clip_fn)[0]+'_masked.tif'

            if not os.path.exists(ds1_masked_fn) or not os.path.exists(ds2_masked_fn):
                #Load NLCD or bareground mask
                from demcoreg.dem_mask import get_lulc_mask

                ds1_clip = iolib.fn_getds(ds1_clip_fn)
                lulc_mask_fn = os.path.join(outdir, 'lulc_mask.tif')
                #if not os.path.exists(nlcd_mask_fn):
                lulc_mask = get_lulc_mask(ds1_clip, mask_glaciers=False, filter='not_forest')
                iolib.writeGTiff(lulc_mask, lulc_mask_fn, ds1_clip) 
                ds1_clip = None

                #Now apply to original images 
                #This could be problematic for huge inputs, see apply_mask.py
                #lulc_mask = lulc_mask.astype(int)
                for fn in (ds1_clip_fn, ds2_clip_fn):
                    ds = iolib.fn_getds(fn)
                    a = iolib.ds_getma(ds)
                    a = np.ma.array(a, mask=~(lulc_mask))
                    if a.count() > 0:
                        out_fn = os.path.splitext(fn)[0]+'_masked.tif'
                        iolib.writeGTiff(a,out_fn,ds)
                        a = None
                    else:
                        sys.exit("No unmasked pixels over bare earth")
            ds1_clip_fn = ds1_masked_fn
            ds2_clip_fn = ds2_masked_fn
    else:
        ds1_clip_fn = fn1
        ds2_clip_fn = fn2
        #Now let user specify alignment methods as option - don't hardcode
        #align = 'Homography'
        #align = 'AffineEpipolar'
    ds1 = None
    ds2 = None

    #Should have extra kwargs option here
    stereo_opt = get_stereo_opt(threads=threads, kernel=kernel, timeout=timeout, \
            erode=erode, spr=spr, align=align)
    
    #Stereo arguments
    #Latest version of ASP should accept tif without camera models
    #stereo_args = [ds1_clip_fn, ds2_clip_fn, outprefix]
    #Nope - still need to provide dummy camera models, and they must be unique files
    #Use the dummy.tsai file bundled in the vmap repo
    dummy_tsai = os.path.join(os.path.split(os.path.realpath(__file__))[0], 'dummy.tsai')
    dummy_tsai2 = os.path.splitext(dummy_tsai)[0]+'2.tsai'
    if not os.path.exists(dummy_tsai2):
        dummy_tsai2 = os.symlink(dummy_tsai, os.path.splitext(dummy_tsai)[0]+'2.tsai')
    stereo_args = [ds1_clip_fn, ds2_clip_fn, dummy_tsai, dummy_tsai2, outprefix]

    #Run stereo_pprc
    if not os.path.exists(outprefix+'-R_sub.tif'):
        run_cmd('stereo_pprc', stereo_opt+stereo_args, msg='0: Preprocessing')
        #Copy proj info to outputs, this should happen automatically now?
        for ext in ('L', 'R', 'L_sub', 'R_sub', 'lMask', 'rMask', 'lMask_sub', 'rMask_sub'):
            geolib.copyproj(ds1_clip_fn, '%s-%s.tif' % (outprefix,ext))

    #Prepare seeding for stereo_corr
    #TODO: these are untested after refactoring
    if not os.path.exists(outprefix+'_D_sub.tif'):
        #Don't need to do anything for default seed-mode 1
        if seedmode == 'sparse_disp':
            #Sparse correlation of full-res images
            stereo_opt.extend(['--corr-seed-mode', '3'])
            sparse_disp_opt = []
            sparse_disp_opt.extend(['--Debug', '--coarse', '512', '--fine', '256', '--no_epipolar_fltr']) 
            sparse_disp_opt.extend(['-P', str(threads)])
            sparse_disp_args = [outprefix+'-L.tif', outprefix+'-R.tif', outprefix]
            run_cmd('sparse_disp', sparse_disp_opt+sparse_disp_args, msg='0.5: D_sub generation')
        elif seedmode == 'existing_velocity':
            #User-input low-res velocity maps for seeding
            #TODO: Add functions that fetch best available velocities for Ant/GrIS or user-defined low-res velocities
            #Automatically query GoLive velocities here
            vx_fn = args.vx_fn 
            vy_fn = args.vy_fn 
            #Check for existence

            #HMA seeding
            vdir = '/nobackup/deshean/rpcdem/hma/velocity_jpl_amaury_2013-2015'
            vx_fn = os.path.join(vdir, 'PKH_WRS2_B8_2013_2015_snr5_n1_r170_res12.x_vel.TIF')
            vy_fn = os.path.join(vdir, 'PKH_WRS2_B8_2013_2015_snr5_n1_r170_res12.y_vel.TIF')

            if os.path.exists(vx_fn) and os.path.exists(vy_fn):
                ds1_clip = iolib.fn_getds(ds1_clip_fn)
                ds1_res = geolib.get_res(ds1_clip, square=True)[0]

                #Compute L_sub res - use this for output dimensions
                L_sub_fn = outprefix+'-L_sub.tif' 
                L_sub_ds = gdal.Open(L_sub_fn)
                L_sub_x_scale = float(ds1_clip.RasterXSize) / L_sub_ds.RasterXSize
                L_sub_y_scale = float(ds1_clip.RasterYSize) / L_sub_ds.RasterYSize
                L_sub_scale = np.max([L_sub_x_scale, L_sub_y_scale])
                L_sub_res = ds1_res * L_sub_scale

                #Since we are likely upsampling here, use cubicspline
                vx_ds_clip, vy_ds_clip = warplib.memwarp_multi_fn([vx_fn, vy_fn], extent=ds1_clip, \
                        t_srs=ds1_clip, res=L_sub_res, r='cubicspline')

                ds1_clip = None

                #Get vx and vy arrays
                vx = iolib.ds_getma(vx_ds_clip)
                vy = iolib.ds_getma(vy_ds_clip)

                #Determine time interval between inputs
                #Use to scaling of known low-res velocities
                t_factor = get_t_factor_fn(ds1_clip_fn, ds2_clip_fn, ds=vx_ds_clip)

                if t_factor is not None:
                    #Compute expected offset in scaled pixels 
                    dx = (vx*t_factor)/L_sub_res
                    dy = (vy*t_factor)/L_sub_res
                    #Note: Joughin and Rignot's values are positive y up!
                    #ASP is positive y down, so need to multiply these values by -1
                    #dy = -(vy*t_factor)/L_sub_res

                    #Should smooth/fill dx and dy

                    #If absolute search window is only 30x30
                    #Don't seed, just use fixed search window 
                    #search_window_area_thresh = 900
                    search_window_area_thresh = 0 
                    search_window = np.array([dx.min(), dy.min(), dx.max(), dy.max()])
                    dx_p = calcperc(dx, perc=(0.5, 99.5))
                    dy_p = calcperc(dy, perc=(0.5, 99.5))
                    search_window = np.array([dx_p[0], dy_p[0], dx_p[1], dy_p[1]])
                    search_window_area = (search_window[2]-search_window[0]) * (search_window[3]-search_window[1])
                    if search_window_area < search_window_area_thresh:
                        stereo_opt.extend(['--corr-seed-mode', '0'])
                        stereo_opt.append('--corr-search')
                        stereo_opt.extend([str(x) for x in search_window])
                        #pad_perc=0.1
                        #stereo_opt.extend(['--corr-sub-seed-percent', str(pad_perc)]
                    #Otherwise, generate a D_sub map from low-res velocity
                    else:
                        stereo_opt.extend(['--corr-seed-mode', '3'])
                        #This is relative to the D_sub scaled disparities
                        d_sub_fn = L_sub_fn.split('-L_sub')[0]+'-D_sub.tif' 
                        gen_d_sub(d_sub_fn, dx, dy)

    #If the above didn't generate a D_sub.tif for seeding, run stereo_corr to generate Low-res D_sub.tif
    if not os.path.exists(outprefix+'-D_sub.tif'):
        newopt = ['--compute-low-res-disparity-only',]
        run_cmd('stereo_corr', newopt+stereo_opt+stereo_args, msg='1.1: Low-res Correlation')
    #Copy projection info to D_sub
    geolib.copyproj(outprefix+'-L_sub.tif', outprefix+'-D_sub.tif')
      
    #Mask D_sub to limit correlation over bare earth surfaces
    #This _should_ be a better approach than masking input images, but stereo_corr doesn't honor D_sub
    #Still need to mask input images before stereo_pprc
    #Left this in here for reference, or if this changes in ASP
    if False:
        D_sub_ds = gdal.Open(outprefix+'-D_sub.tif', gdal.GA_Update)

        #Mask support - limit correlation only to rock/ice surfaces, no water/veg
        from demcoreg.dem_mask import get_nlcd, mask_nlcd
        nlcd_fn = get_nlcd()
        nlcd_ds = warplib.diskwarp_multi_fn([nlcd_fn,], extent=D_sub_ds, res=D_sub_ds, t_srs=D_sub_ds, r='near', outdir=outdir)[0]
        #validmask = mask_nlcd(nlcd_ds, valid='rock+ice')
        validmask = mask_nlcd(nlcd_ds, valid='not_forest', mask_glaciers=False)
        nlcd_mask_fn = os.path.join(outdir, 'nlcd_validmask.tif')
        iolib.writeGTiff(validmask, nlcd_mask_fn, nlcd_ds) 

        #Now apply to D_sub (band 3 is valid mask)
        #validmask = validmask.astype(int)
        for b in (1,2,3):
            dsub = iolib.ds_getma(D_sub_ds, b)
            dsub = np.ma.array(dsub, mask=~(validmask))
            D_sub_ds.GetRasterBand(b).WriteArray(dsub.filled())
        D_sub_ds = None

    #OK, finally run stereo_corr full-res integer correlation with appropriate seeding
    if not os.path.exists(outprefix+'-D.tif'):
        run_cmd('stereo_corr', stereo_opt+stereo_args, msg='1: Correlation')
        geolib.copyproj(ds1_clip_fn, outprefix+'-D.tif')

    #Run stereo_rfne
    if spr > 0:
        if not os.path.exists(outprefix+'-RD.tif'):
            run_cmd('stereo_rfne', stereo_opt+stereo_args, msg='2: Refinement')
            geolib.copyproj(ds1_clip_fn, outprefix+'-RD.tif')
        d_fn = make_ln(outdir, outprefix, '-RD.tif')
    else:
        ln_fn = outprefix+'-RD.tif'
        if os.path.lexists(ln_fn):
            os.remove(ln_fn)
        os.symlink(os.path.split(outprefix)[1]+'-D.tif', ln_fn)

    #Run stereo_fltr
    if not os.path.exists(outprefix+'-F.tif'):
        run_cmd('stereo_fltr', stereo_opt+stereo_args, msg='3: Filtering')
        geolib.copyproj(ds1_clip_fn, outprefix+'-F.tif')

    d_fn = make_ln(outdir, outprefix, '-F.tif')

    if smoothF and not os.path.exists(outprefix+'-F_smooth.tif'):
        print('Smoothing F.tif')
        from pygeotools.lib import filtlib 
        #Fill holes and smooth F
        F_fill_fn = outprefix+'-F_smooth.tif'
        F_ds = gdal.Open(outprefix+'-F.tif', gdal.GA_ReadOnly)
        #import dem_downsample_fill
        #F_fill_ds = dem_downsample_fill.gdalfill_ds(F_fill_ds)
        print('Creating F_smooth.tif')
        F_fill_ds = iolib.gtif_drv.CreateCopy(F_fill_fn, F_ds, 0, options=iolib.gdal_opt)
        F_ds = None
        for n in (1, 2):
            print('Smoothing band %i' % n)
            b = F_fill_ds.GetRasterBand(n)
            b_fill_bma = iolib.b_getma(b)
            #b_fill_bma = iolib.b_getma(dem_downsample_fill.gdalfill(b))
            #Filter extreme values (careful, could lose areas of valid data with fastest v)
            #b_fill_bma = filtlib.perc_fltr(b_fill_bma, perc=(0.01, 99.99))
            #These filters remove extreme values and fill data gaps
            #b_fill_bma = filtlib.median_fltr_skimage(b_fill_bma, radius=7, erode=0)
            #b_fill_bma = filtlib.median_fltr(b_fill_bma, fsize=7, origmask=True)
            #Gaussian filter
            b_fill_bma = filtlib.gauss_fltr_astropy(b_fill_bma, size=9)
            b.WriteArray(b_fill_bma)
        F_fill_ds = None
        d_fn = make_ln(outdir, outprefix, '-F_smooth.tif')

    print('\n%s' % datetime.now())
    print('%s UTC\n' % datetime.utcnow())

    #If time interval is specified, convert pixel displacements to rates
    if args.dt != 'none':
        #Check if vm.tif already exists
        #Should probably just overwrite by default
        #if os.path.exists(os.path.splitext(d_fn)[0]+'_vm.tif'):
        #    print("\nFound existing velocity magnitude map!\n"
        #else:
        #Generate output velocity products and figure
        #Requires that vmap repo is in PATH
        cmd = ['disp2v.py', d_fn]
        #Note: this will attempt to automatically determine control surfaces
        #disp2v.py will accept arbitrary mask, could pass through here
        if args.remove_offsets:
            cmd.append('-remove_offsets')
        cmd.extend(['-dt', args.dt])
        print("Converting disparities to velocities")
        print(cmd)
        subprocess.call(cmd)
Ejemplo n.º 6
0
    #trend_filt = filtlib.sigma_fltr(trend, n=3)
    #print("Output pixel count: %s" % trend_filt.count())

    #Remove islands
    #trend_filt = filtlib.remove_islands(trend, iterations=1)
    #Erode edges near nodata 
    trend_filt = filtlib.erode_edge(trend, iterations=1)
    print("Output pixel count: %s" % trend_filt.count())

    #Rolling median filter (remove noise) - can use a slightly larger window here
    trend_filt = filtlib.rolling_fltr(trend_filt, size=size, circular=True, origmask=True)
    print("Output pixel count: %s" % trend_filt.count())

    #Gaussian filter (smooth)
    #trend_filt = filtlib.gauss_fltr_astropy(trend_filt, size=size, origmask=True, fill_interior=True)
    trend_filt = filtlib.gauss_fltr_astropy(trend_filt, size=size)
    print("Output pixel count: %s" % trend_filt.count())

    trend_fn=out_fn+'_trend_%spx_filt.tif' % size
    print("Writing out: %s" % trend_fn)
    iolib.writeGTiff(trend_filt*365.25, trend_fn, trend_ds)

    #Update intercept using new filtered slope values
    #Need to update for different periods?
    #dt_pivot = timelib.mean_date(datetime(2000,5,31), datetime(2009,5,31))
    #dt_pivot = timelib.mean_date(datetime(2009,5,31), datetime(2018,5,31))
    dt_pivot = timelib.dt2o(datetime(2009, 5, 31))
    intercept_filt = dt_pivot * (trend - trend_filt) + intercept
    intercept_fn=out_fn+'_intercept_%spx_filt.tif' % size
    print("Writing out: %s" % intercept_fn)
    iolib.writeGTiff(intercept_filt*365.25, intercept_fn, trend_ds)
Ejemplo n.º 7
0
def main():
    #This is defualt filter size (pixels) 
    size = 19
    #Compute and print stats before/after
    stats = False 

    #Need to clean up with argparse
    #Accept filter list, filter size as argument

    if len(sys.argv) == 2:
        dem_fn = sys.argv[1]
    elif len(sys.argv) == 3:
        dem_fn = sys.argv[1]
        size = int(sys.argv[2])
    else:
        sys.exit("Usage is %s dem [size]" % sys.argv[0])
   
    print("Loading DEM into masked array")
    dem_ds = iolib.fn_getds(dem_fn)
    dem = iolib.ds_getma(dem_ds, 1)
    #Cast input ma as float32 so np.nan filling works
    #dem = dem.astype(np.float32)

    dem_fltr = dem

    #Should accept arbitrary number of ordered filter operations as cli argument
    #filt_list = ['gauss_fltr_astropy',]
    #for filt in filt_list:
    #    dem_fltr = filtlib.filt(dem_fltr, size=size, kwargs)

    #Percentile filter
    #dem_fltr = filtlib.perc_fltr(dem, perc=(15.865, 84.135))
    #dem_fltr = filtlib.perc_fltr(dem, perc=(2.275, 97.725))
    #dem_fltr = filtlib.perc_fltr(dem, perc=(0.135, 99.865))
    #dem_fltr = filtlib.perc_fltr(dem, perc=(0, 99.73))
    #dem_fltr = filtlib.perc_fltr(dem, perc=(0, 95.45))
    #dem_fltr = filtlib.perc_fltr(dem, perc=(0, 68.27))

    #Difference filter, need to specify refdem_fn
    #dem_fltr = filtlib.dz_fltr(dem_fn, refdem_fn, abs_dz_lim=(0,30))

    #Absolute range filter
    #dem_fltr = filtlib.range_fltr(dem_fltr, (15, 9999))

    #Median filter
    #dem_fltr = filtlib.rolling_fltr(dem_fltr, f=np.nanmedian, size=size)
    #dem_fltr = filtlib.median_fltr(dem_fltr, fsize=size, origmask=True)
    #dem_fltr = filtlib.median_fltr_skimage(dem_fltr, radius=4, origmask=True)

    #High pass filter
    #dem_fltr = filtlib.highpass(dem_fltr, size=size)

    #Gaussian filter (default)
    dem_fltr = filtlib.gauss_fltr_astropy(dem_fltr, size=size, origmask=True, fill_interior=False)

    if stats:
        print("Input DEM stats:")
        malib.print_stats(dem)
        print("Filtered DEM stats:")
        malib.print_stats(dem_fltr)
    
    dst_fn = os.path.splitext(dem_fn)[0]+'_filt%ipx.tif' % size
    print("Writing out filtered DEM: %s" % dst_fn)
    #Note: writeGTiff writes dem_fltr.filled()
    iolib.writeGTiff(dem_fltr, dst_fn, dem_ds)