예제 #1
0
def main():
    parser = getparser()
    args = parser.parse_args()

    dem_fn = args.dem_fn

    # Write out because they will be used to mask CHM
    writeall = True

    # Auto compute min TOA with gaussian mixture model
    auto_min_toa = args.auto_min_toa

    dirname, demname = os.path.split(dem_fn)

    # The subdir in which the DEM.tif sits will be the pairname
    pairname = os.path.split(dirname)[1]
    print("Pairname:", pairname)

    if args.out_dir is not None:

        # Create symlink in out_dir to: (1) original out-DEM_4m (2) *_ortho_4m.tif (3) All *.xml files
        # This should look like <out_dir>/<pairname>_out-DEM_4m
        dem_fn_lnk = os.path.join(args.out_dir, pairname + '_' +  demname)
        force_symlink(dem_fn, dem_fn_lnk)
        force_symlink(os.path.join(dirname, pairname + '_ortho_4m.tif'), os.path.join(args.out_dir, pairname + '_ortho_4m.tif') )
        xml_list = [f for f in os.listdir(dirname) if f.endswith('r100.xml')]

        print("\nSymlinks made for:")
        for x in xml_list:
            print(x)
            shutil.copy2(os.path.join(dirname,x), args.out_dir)

        out_fn_base = os.path.splitext(dem_fn_lnk)[0]

        dem_fn = dem_fn_lnk
    else:
        out_fn_base = os.path.splitext(dem_fn)[0]

    print("\nBasename for output files:")
    print(out_fn_base)

    #Max Threshold value for LiDAR datset; Valid pixels under this value
    lidar_fn=args.lidar_fn
    max_thresh=args.max_thresh

    #Need some checks on these
    param = args.filt_param
    if param is not None and len(param) == 1:
        param = param[0]
    # Get original DEM
    dem = iolib.fn_getma(dem_fn)

    print("\nLoading input DEM into masked array")
    dem_ds = iolib.fn_getds(dem_fn)

    toa_mask = None
    toa_tri_mask = None # probably not used by itself; done as part of toa_mask
    rough_mask = None
    slope_mask = None
    mask_list = [toa_tri_mask, toa_mask, rough_mask, slope_mask]

    if args.filtdz:
        print("\nFilter with dz from ref DEM to remove cloud returns and blunders (shadows)...")
        print("Reference DEM: %s" % os.path.split(param[0])[1] )
        print("Absolute dz (+/-): %s \n" % param[2] )
        #May need to cast input ma as float32 so np.nan filling works
        dem = dem.astype(np.float32)

        #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=dem_ds, extent=dem_ds, t_srs=dem_ds)[0]
        ref = iolib.ds_getma(ref_ds)
        param = map(float, param[1:])

        # A dem that has been masked based on the dz filter
        dem = filtlib.dz_fltr_ma(dem, ref, rangelim=param)

        if writeall:
            #out_fn = os.path.splitext(dem_fn)[0]+'_dzfilt.tif'
            out_fn = os.path.join(out_fn_base +'_dzfilt.tif')
            print("Writing out %s\n" % out_fn)
            iolib.writeGTiff(dem, out_fn, src_ds=dem_ds, ndv=args.ndv)

    #Initialize a control mask that we'll update
    #True (1) represents "valid" unmasked pixel, False (0) represents "invalid" pixel to be masked
    controlmask = ~(np.ma.getmaskarray(dem))

    # DEM masking: Each block returns a masked output (not a mask)
    #    TOA: mask dark and/or smooth areas (shadows and/or water)
    #    Roughness
    #    Slope

    if args.toamask or args.toatrimask:
        #try:
            print("\nCompute TOA from ortho...\n")
            toa_fn = get_toa_fn(out_fn_base + '.tif') ##--->dem_fn
            print(toa_fn)
            print("\nWarp TOA to DEM...\n")

            toa_ds = warplib.memwarp_multi_fn([toa_fn,], res=dem_ds, extent=dem_ds, t_srs=dem_ds)[0]

            if args.toamask:

                if auto_min_toa:

                    # Compute a good min TOA value
                    m,s = get_min_gaus(toa_fn, 50, 4)
                    min_toa = m + s
                    min_toa = m
                else:
                    min_toa = args.min_toa

                with open(os.path.join(os.path.split(toa_fn)[0], "min_toa_" + pairname + ".txt"), "w") as text_file:
                    text_file.write(os.path.basename(__file__))
                    text_file.write("\nMinimum TOA used for mask:\n{0}".format(min_toa))

                # Should mask dark areas and dilate
                toa_mask = get_toa_mask(toa_ds, min_toa)

                #Dilate the mask
                if args.dilate_toa is not None:
                    niter = args.dilate_toa
                    print("Dilating TOA mask with %i iterations" % niter)
                    from scipy import ndimage
                    toa_mask = ~(ndimage.morphology.binary_dilation(~toa_mask, iterations=niter))

                controlmask = np.logical_and(toa_mask, controlmask)

                # Mask islands here
                controlmask = malib.mask_islands(controlmask, 5)

                if writeall:
                    #out_fn = out_fn_base+'_toamask.tif'
                    out_fn = os.path.join(out_fn_base +'_toamask.tif')
                    print("Writing out %s\n" % out_fn)
                    iolib.writeGTiff(toa_mask, out_fn, src_ds=dem_ds)

            if args.toatrimask:
                # Should mask smooth areas (measures local variance)
                toa_tri_mask = get_tri_mask(toa_ds, args.min_toatri)
                controlmask = np.logical_and(toa_tri_mask, controlmask)

                if writeall:
                    #out_fn = out_fn_base+'_toatrimask.tif'
                    out_fn = os.path.join(out_fn_base +'_toatrimask.tif')
                    print("Writing out %s\n" % out_fn)
                    iolib.writeGTiff(toa_tri_mask, out_fn, src_ds=dem_ds)

        #except Exception, e:
            #print "\tFailed to apply TOA masking.\n"

    if args.slopemask:
        slope_mask = get_slope_mask(dem_ds, args.max_slope)
        controlmask = np.logical_and(slope_mask, controlmask)

        #if args.slopemaskcoarse:

            #dem_fn2 = args.dem_coarscomp_fn

            #print("\nLoading input coarse DEM into masked array")
            #dem2_ds = iolib.fn_getds(dem_fn2)
            #slope_mask = get_slope_mask(dem2_ds, args.max_slope)
            #controlmask = np.logical_and(slope_mask, controlmask)

        if writeall:
            #out_fn = out_fn_base+'_slopemask.tif'
            out_fn = os.path.join(out_fn_base +'_slopemask.tif')
            print("Writing out %s\n" % out_fn)
            iolib.writeGTiff(slope_mask, out_fn, src_ds=dem_ds)

    if args.lidar_fn:
        try:
            print("Masking DEM file based on Lidar Dataset\n")
            print("\nWarp Lidar Raster to DEM...\n")
            lidar_ds=warplib.memwarp_multi_fn([lidar_fn,],r='near', res=dem_ds, extent=dem_ds, t_srs=dem_ds)[0]

            lidarmask = get_lidar_mask(dem_ds, lidar_ds, max_thresh)

            controlmask = np.logical_and(lidarmask, controlmask)

            if writeall:
                out_fn=out_fn_base+'_lidarmask.tif'
                print("Writing out %s\n" % out_fn)
                iolib.writeGTiff(lidarmask, out_fn, src_ds=dem_ds)
        except Exception as e:
            print("\tFailed to Apply Lidar Mask")

    # CHM mask will be a subset of the Control mask; slope_mask, toa_mask, toa_tri_mask
    chmmask = controlmask
    print("Generating final CHM mask to apply later")
    #out_fn = out_fn_base+'_chmmask.tif'
    out_fn = os.path.join(out_fn_base +'_chmmask.tif')
    print("Writing out %s\n" % out_fn)
    iolib.writeGTiff(chmmask, out_fn, src_ds=dem_ds)

    if args.roughmask:

        rough_mask = get_rough_mask(dem_ds, args.max_rough)
        controlmask = np.logical_and(rough_mask, controlmask)

        if writeall:
            out_fn = os.path.join(out_fn_base +'_roughmask.tif')
            print("Writing out %s\n" % out_fn)
            iolib.writeGTiff(rough_mask, out_fn, src_ds=dem_ds)

    print("Generating final mask to use for reference surfaces, and applying to input DEM")

    #Now invert to use to create final masked array
    # This steps results in the areas to be removed being set to a valid value
    controlmask = ~controlmask

    #Dilate the mask
    if args.dilate_con is not None:
        niter = args.dilate_con
        print("Dilating control mask with %i iterations" % niter)
        from scipy import ndimage
        #
        # So, this should work too.... controlmask = ndimage.morphology.binary_dilation(controlmask, iterations=niter))
        controlmask = ~(ndimage.morphology.binary_dilation(~controlmask, iterations=niter)) # This steps results in the areas to be removed being set to a valid value, again

    print("\nApply mask to original DEM - use these control surfaces for co-registration...")
    newdem = np.ma.array(dem, mask=controlmask) # This sets the valid values of the controlmask to the 'mask' of the DEM, which turns them into NaN values

    if True:
        print("\nStats of valid DEM with masks applied:")
        valid_stats = malib.print_stats(newdem)
        valid_stats_med = valid_stats[5]

    print("\nWriting DEM control surfaces:")
    #if args.out_dir is not None:
    #    dst_fn = os.path.join(args.out_dir, os.path.split(dirname)[1] + os.path.splitext(demname)[0]+'_control.tif')
    #else:
    #    dst_fn = os.path.splitext(dem_fn)[0]+'_control.tif'
    dst_fn = os.path.join(out_fn_base +'_control.tif')
    print(dst_fn)
    iolib.writeGTiff(newdem, dst_fn, dem_ds)

    return dst_fn
예제 #2
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)
예제 #3
0
def main():
    parser = getparser()
    args = parser.parse_args()

    dem_fn = args.dem_fn

    # Write out because they will be used to mask CHM
    writeall = True

    # Auto compute min TOA with gaussian mixture model
    compute_min_toa = True

    #Basename for output files
    out_fn_base = os.path.splitext(dem_fn)[0]

    #Need some checks on these
    param = args.filt_param
    if param is not None and len(param) == 1:
        param = param[0]
    # Get original DEM
    dem = iolib.fn_getma(dem_fn)

    print("\nLoading input DEM into masked array")
    dem_ds = iolib.fn_getds(dem_fn)

    toa_mask = None
    toa_tri_mask = None  # probably not used by itself; done as part of toa_mask
    rough_mask = None
    slope_mask = None
    mask_list = [toa_tri_mask, toa_mask, rough_mask, slope_mask]

    if args.filtdz:
        print(
            "\nFilter with dz from ref DEM to remove cloud returns and blunders (shadows)..."
        )
        print("Reference DEM: %s" % os.path.split(param[0])[1])
        print("Absolute dz (+/-): %s \n" % param[2])
        #May need to cast input ma as float32 so np.nan filling works
        dem = dem.astype(np.float32)

        #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=dem_ds,
                                          extent=dem_ds,
                                          t_srs=dem_ds)[0]
        ref = iolib.ds_getma(ref_ds)
        param = map(float, param[1:])

        # A dem that has been masked based on the dz filter
        dem = filtlib.dz_fltr_ma(dem, ref, rangelim=param)

        if writeall:
            out_fn = os.path.splitext(dem_fn)[0] + '_dzfilt.tif'
            print("Writing out %s\n" % out_fn)
            iolib.writeGTiff(dem, out_fn, src_ds=dem_ds, ndv=args.ndv)

    #Initialize a control mask that we'll update
    #True (1) represents "valid" unmasked pixel, False (0) represents "invalid" pixel to be masked
    controlmask = ~(np.ma.getmaskarray(dem))

    # DEM masking: Each block returns a masked output (not a mask)
    #    TOA: mask dark and/or smooth areas (shadows and/or water)
    #    Roughness
    #    Slope

    if args.toamask or args.toatrimask:

        print("\nCompute TOA from ortho...\n")
        toa_fn = get_toa_fn(dem_fn)
        print("\nWarp TOA to DEM...\n")
        toa_ds = warplib.memwarp_multi_fn([
            toa_fn,
        ],
                                          res=dem_ds,
                                          extent=dem_ds,
                                          t_srs=dem_ds)[0]

        if args.toamask:

            if compute_min_toa:

                # Compute a good min TOA value
                m, s = get_min_gaus(toa_fn, 50, 4)
                min_toa = m + s
                min_toa = m
            else:
                min_toa = args.min_toa

            with open(os.path.join(os.path.split(toa_fn)[0], "min_toa.txt"),
                      "w") as text_file:
                text_file.write(os.path.basename(__file__))
                text_file.write(
                    "\nMinimum TOA used for mask:\n{0}".format(min_toa))

            # Should mask dark areas and dilate
            toa_mask = get_toa_mask(toa_ds, min_toa)

            #Dilate the mask
            if args.dilate_toa is not None:
                niter = args.dilate_toa
                print("Dilating TOA mask with %i iterations" % niter)
                from scipy import ndimage
                toa_mask = ~(ndimage.morphology.binary_dilation(
                    ~toa_mask, iterations=niter))

            controlmask = np.logical_and(toa_mask, controlmask)

            # Mask islands here
            controlmask = malib.mask_islands(controlmask, 5)

            if writeall:
                out_fn = out_fn_base + '_toamask.tif'
                print("Writing out %s\n" % out_fn)
                iolib.writeGTiff(toa_mask, out_fn, src_ds=dem_ds)

        if args.toatrimask:
            # Should mask smooth areas (measures local variance)
            toa_tri_mask = get_tri_mask(toa_ds, args.min_toatri)
            controlmask = np.logical_and(toa_tri_mask, controlmask)

            if writeall:
                out_fn = out_fn_base + '_toatrimask.tif'
                print("Writing out %s\n" % out_fn)
                iolib.writeGTiff(toa_tri_mask, out_fn, src_ds=dem_ds)

    if args.slopemask:
        slope_mask = get_slope_mask(dem_ds, args.max_slope)
        controlmask = np.logical_and(slope_mask, controlmask)
        if writeall:
            out_fn = out_fn_base + '_slopemask.tif'
            print("Writing out %s\n" % out_fn)
            iolib.writeGTiff(slope_mask, out_fn, src_ds=dem_ds)

    # CHM mask will be a subset of the Control mask; slope_mask, toa_mask, toa_tri_mask
    chmmask = controlmask
    print("Generating final CHM mask to apply later")
    out_fn = out_fn_base + '_chmmask.tif'
    print("Writing out %s\n" % out_fn)
    iolib.writeGTiff(chmmask, out_fn, src_ds=dem_ds)

    if args.roughmask:
        rough_mask = get_rough_mask(dem_ds, args.max_rough)
        controlmask = np.logical_and(rough_mask, controlmask)
        if writeall:
            out_fn = out_fn_base + '_roughmask.tif'
            print("Writing out %s\n" % out_fn)
            iolib.writeGTiff(rough_mask, out_fn, src_ds=dem_ds)

    print(
        "Generating final mask to use for reference surfaces, and applying to input DEM"
    )
    #Now invert to use to create final masked array
    controlmask = ~controlmask

    #Dilate the mask
    if args.dilate_con is not None:
        niter = args.dilate_con
        print("Dilating control mask with %i iterations" % niter)
        from scipy import ndimage
        controlmask = ~(ndimage.morphology.binary_dilation(~controlmask,
                                                           iterations=niter))

    #Apply mask to original DEM - use these surfaces for co-registration
    newdem = np.ma.array(dem, mask=controlmask)

    if True:
        print("\nStats of valid DEM with maskes applied:")
        valid_stats = malib.print_stats(newdem)
        valid_stats_med = valid_stats[5]

    print("\nWriting DEM control surfaces:")
    dst_fn = os.path.splitext(dem_fn)[0] + '_control.tif'
    print(dst_fn)
    iolib.writeGTiff(newdem, dst_fn, dem_ds)

    return dst_fn