def writeDiffMeta(o_metaFile, demFile1, demFile2, trans, rmse, proj4,
                  fp_vertices, creation_time):

    demSuffix1 = getDemSuffix(demFile1)
    demSuffix2 = getDemSuffix(demFile2)
    if fp_vertices.dtype != np.int64 and np.array_equal(
            fp_vertices, fp_vertices.astype(np.int64)):
        fp_vertices = fp_vertices.astype(np.int64)

    diff_info = ("""DoD Metadata
Creation Date: {}
DoD creation date: {}
DoD projection (proj4): '{}'

DoD Footprint Vertices
X: {}
Y: {}

Mosaicking Alignment Statistics (meters)
scene, rmse, dz, dx, dy
""".format(
        creation_time,
        creation_time,
        proj4,
        ' '.join(
            np.array_str(fp_vertices[1],
                         max_line_width=float('inf')).strip()[1:-1].split()),
        ' '.join(
            np.array_str(fp_vertices[0],
                         max_line_width=float('inf')).strip()[1:-1].split()),
    ))

    diff_info += "{} {:.2f} {:.4f} {:.4f} {:.4f}\n".format(
        os.path.basename(demFile1), 0, 0, 0, 0)
    diff_info += "{} {:.2f} {:.4f} {:.4f} {:.4f}\n".format(
        os.path.basename(demFile2), rmse, trans[0], trans[1], trans[2])

    diff_info += "\nStrip Registration \n\n"

    demFiles = [demFile1, demFile2]
    strip_info = ""
    for i in range(len(demFiles)):
        demSuffix = getDemSuffix(demFiles[i])

        strip_info += "strip {} name={}\n".format(i + 1, demFiles[i])

        strip_metaFile = demFiles[i].replace(demSuffix, 'reg.txt')
        if os.path.isfile(strip_metaFile):
            strip_metaFile_fp = open(strip_metaFile, 'r')
            strip_info += strip_metaFile_fp.read()
            strip_metaFile_fp.close()
        else:
            strip_info += "{} not found".format(strip_metaFile)
        strip_info += " \n"

    diff_metaFile_fp = open(o_metaFile, 'w')
    diff_metaFile_fp.write(diff_info)
    diff_metaFile_fp.write(strip_info)
    diff_metaFile_fp.close()
Пример #2
0
def saveDBP(demFile):
    demFile = findTestFile(demFile)
    demSuffix = getDemSuffix(demFile)
    shapefileFile = demFile.replace(demSuffix, 'dem_boundary.shp')

    Z, X, Y, proj_ref = rat.extractRasterData(demFile, 'z', 'x', 'y',
                                              'proj_ref')
    poly = rat.getDataBoundariesPoly(Z, X, Y, nodata_val=-9999)
    if not poly:
        raise TestingError("Failed to create data cluster boundaries polygon")

    driver = ogr.GetDriverByName("ESRI Shapefile")
    ds = driver.CreateDataSource(shapefileFile)
    srs = osr.SpatialReference()
    srs.ImportFromWkt(proj_ref)

    layer = ds.CreateLayer("data_clusters", srs, ogr.wkbPolygon)
    feature = ogr.Feature(layer.GetLayerDefn())
    feature.SetGeometry(poly)
    layer.CreateFeature(feature)

    # Dereference datasource to initiate write to disk.
    ds = None
    print("'{}' saved".format(shapefileFile))
Пример #3
0
def scenes2strips(demFiles,
                  maskSuffix=None,
                  filter_options=(),
                  max_coreg_rmse=1,
                  trans_guess=None,
                  trans_err_guess=None,
                  rmse_guess=None,
                  hold_guess=HOLD_GUESS_OFF,
                  check_guess=True,
                  use_second_ortho=False):
    """
    From MATLAB version in Github repo 'setsm_postprocessing', 3.0 branch:

    function [X,Y,Z,M,O,trans,rmse,f]=scenes2strips(varargin)
    %SCENES2STRIPS merge scenes into strips
    %
    %   [x,y,z,m,o,trans,rmse,f]=scenes2strips(demdir,f) merges the
    %   scene geotiffs listed in cellstr f within directory demdir after
    %   ordering them by position. If a break in coverage is detected between
    %   scene n and n+1 only the first 1:n scenes will be merged. The data are
    %   coregistered at overlaps using iterative least squares, starting with
    %   scene n=1.
    %   Outputs are the strip grid coorinates x,y and strip elevation, z,
    %   matchtag, m and orthoimage, o. The 3D translations are given in 3xn
    %   vector trans, along with root-mean-squared of residuals, rmse. The
    %   output f gives the list of filenames in the mosaic. If a break is
    %   detected, the list of output files will be less than the input.
    %
    %   [...]=scenes2strips(...,'maskFileSuffix',value) will apply the mask
    %   identified as the dem filename with the _dem.tif replaced by
    %   _maskSuffix
    %   [...]=scenes2strips(...,'max_coreg_rmse',value) will set a new maximum
    %   coregistration error limit in meters (default=1). Errors above this
    %   limit will result in a segment break.
    %
    % Version 3.1, Ian Howat, Ohio State University, 2015.

    If maskFileSuffix='edgemask', edge and data masks identified as the DEM
    filename with the _dem.tif replaced by _edgemask.tif and _datamask.tif,
    respectively, will be applied.

    """
    from batch_scenes2strips import getDemSuffix, selectBestMatchtag, selectBestOrtho, selectBestOrtho2
    demSuffix = getDemSuffix(demFiles[0])

    cluster_min_px = 1000  # Minimum data cluster area for 2m.
    add_min_px = 50000  # Minimum number of unmasked pixels scene must add to existing segment to not be skipped.

    # Order scenes in north-south or east-west direction by aspect ratio.
    num_scenes = len(demFiles)
    if trans_guess is None and trans_err_guess is None and rmse_guess is None:
        print("Ordering {} scenes".format(num_scenes))
        demFiles_ordered = orderPairs(demFiles)
    elif trans_err_guess is not None and trans_guess is None:
        raise InvalidArgumentError(
            "`trans_guess_err` argument can only be used in conjunction "
            "with `trans_guess` argument")
    elif trans_guess is not None and trans_guess.shape[1] != num_scenes:
        raise InvalidArgumentError(
            "`trans_guess` array must be of shape (3, N) where N is the number "
            "of scenes in `demFiles`, but was {}".format(trans_guess.shape))
    elif rmse_guess is not None and rmse_guess.shape[1] != num_scenes:
        raise InvalidArgumentError(
            "`rmse_guess` array must be of shape (1, N) where N is the number "
            "of scenes in `demFiles`, but was {}".format(rmse_guess.shape))
    else:
        # Files should already be properly ordered if a guess is provided.
        # Running `orderPairs` on them could detrimentally change their order.
        demFiles_ordered = list(demFiles)
    num_scenes = len(demFiles_ordered)

    # Initialize output stats.
    trans = np.zeros((3, num_scenes))
    trans_err = trans.copy()
    rmse = np.zeros((1, num_scenes))
    if check_guess:
        trans_check = np.copy(trans)
        trans_err_check = np.copy(trans_err)
        rmse_check = np.copy(rmse)

    # Get projection reference of the first scene to be used in equality checks
    # with the projection reference of all scenes that follow.
    global __STRIP_SPAT_REF__
    __STRIP_SPAT_REF__ = rat.extractRasterData(demFiles_ordered[0], 'spat_ref')
    if __STRIP_SPAT_REF__.ExportToProj4() == '':
        raise SpatialRefError(
            "DEM '{}' spatial reference ({}) has no PROJ4 representation "
            "and is likely erroneous".format(demFiles_ordered[0],
                                             __STRIP_SPAT_REF__.ExportToWkt()))

    # File loop.
    skipped_scene = False
    segment_break = False
    for i in range(num_scenes + 1):

        if skipped_scene:
            skipped_scene = False
            trans[:, i - 1] = np.nan
            trans_err[:, i - 1] = np.nan
            rmse[0, i - 1] = np.nan
        if i >= num_scenes:
            break
        if ((trans_guess is not None and np.any(np.isnan(trans_guess[:, i])))
                or (trans_err_guess is not None
                    and np.any(np.isnan(trans_err_guess[:, i])))
                or (rmse_guess is not None and np.isnan(rmse_guess[0, i]))):
            # State of scene is somewhere between naturally redundant
            # or redundant by masking, as classified by prior s2s run.
            skipped_scene = True
            continue

        # Construct filenames.
        demFile = demFiles_ordered[i]
        matchFile = selectBestMatchtag(demFile)
        orthoFile = selectBestOrtho(demFile)
        ortho2File = selectBestOrtho2(demFile) if use_second_ortho else None
        metaFile = demFile.replace(demSuffix, 'meta.txt')
        if maskSuffix is None:
            print("No mask applied")
            maskFile = None
        else:
            maskFile = demFile.replace(demSuffix, maskSuffix)

        if use_second_ortho and ortho2File is None:
            raise InvalidArgumentError(
                "`use_second_ortho=True`, but second ortho could not be found")

        print("Scene {} of {}: {}".format(i + 1, len(demFiles_ordered),
                                          demFile))

        # try:
        x, y, z, m, o, o2, md = loadData(demFile, matchFile, orthoFile,
                                         ortho2File, maskFile, metaFile)
        # except:
        #     print("Data read error:")
        #     traceback.print_exc()
        #     print("...skipping")
        #     continue

        # Apply masks.
        x, y, z, m, o, o2, md = applyMasks(x, y, z, m, o, o2, md,
                                           filter_options, maskSuffix)

        # Check for redundant scene.
        if np.count_nonzero(~np.isnan(z)) <= add_min_px:
            print("Not enough (unmasked) data, skipping")
            skipped_scene = True
            continue

        dx = x[1] - x[0]
        dy = y[1] - y[0]

        # Fix grid so that x, y coordinates of
        # pixels in overlapping scenes will match up.
        if ((x[1] / dx) % 1 != 0) or ((y[1] / dy) % 1 != 0):
            x, y, z, m, o, o2, md = regrid(x, y, z, m, o, o2, md)

        # If this is the first scene in strip,
        # set as strip and continue to next scene.
        if 'X' not in vars():
            X, Y, Z, M, O, O2, MD = x, y, z, m, o, o2, md
            del x, y, z, m, o, o2, md
            continue

        # Pad new arrays to stabilize interpolation.
        buff = int(10 * dx + 1)
        z = np.pad(z, buff, 'constant', constant_values=np.nan)
        m = np.pad(m, buff, 'constant', constant_values=0)
        o = np.pad(o, buff, 'constant', constant_values=0)
        o2 = np.pad(o2, buff, 'constant',
                    constant_values=0) if o2 is not None else None
        md = np.pad(md, buff, 'constant', constant_values=1)
        x = np.concatenate((x[0] - dx * np.arange(buff, 0, -1), x,
                            x[-1] + dx * np.arange(1, buff + 1)))
        y = np.concatenate((y[0] + dx * np.arange(buff, 0, -1), y,
                            y[-1] - dx * np.arange(1, buff + 1)))

        # Expand strip coverage to encompass new scene.
        if x[0] < X[0]:
            X1 = np.arange(x[0], X[0], dx)
            X = np.concatenate((X1, X))
            Z, M, O, O2, MD = expandCoverage(Z,
                                             M,
                                             O,
                                             O2,
                                             MD,
                                             X1,
                                             direction='left')
            del X1
        if x[-1] > X[-1]:
            X1 = np.arange(X[-1] + dx, x[-1] + dx, dx)
            X = np.concatenate((X, X1))
            Z, M, O, O2, MD = expandCoverage(Z,
                                             M,
                                             O,
                                             O2,
                                             MD,
                                             X1,
                                             direction='right')
            del X1
        if y[0] > Y[0]:
            Y1 = np.arange(y[0], Y[0], -dx)
            Y = np.concatenate((Y1, Y))
            Z, M, O, O2, MD = expandCoverage(Z,
                                             M,
                                             O,
                                             O2,
                                             MD,
                                             Y1,
                                             direction='up')
            del Y1
        if y[-1] < Y[-1]:
            Y1 = np.arange(Y[-1] - dx, y[-1] - dx, -dx)
            Y = np.concatenate((Y, Y1))
            Z, M, O, O2, MD = expandCoverage(Z,
                                             M,
                                             O,
                                             O2,
                                             MD,
                                             Y1,
                                             direction='down')
            del Y1

        # Map new DEM pixels to swath. These must return integers. If not,
        # interpolation will be required, which is currently not supported.
        c0 = np.where(x[0] == X)[0][0]
        c1 = np.where(x[-1] == X)[0][0] + 1
        r0 = np.where(y[0] == Y)[0][0]
        r1 = np.where(y[-1] == Y)[0][0] + 1

        # Crop to overlap.
        Xsub = np.copy(X[c0:c1])
        Ysub = np.copy(Y[r0:r1])
        Zsub = np.copy(Z[r0:r1, c0:c1])
        Msub = np.copy(M[r0:r1, c0:c1])
        Osub = np.copy(O[r0:r1, c0:c1])
        O2sub = np.copy(O2[r0:r1, c0:c1]) if O2 is not None else None
        MDsub = np.copy(MD[r0:r1, c0:c1])

        # NEW MOSAICKING CODE

        # Crop to just region of overlap.
        A = (~np.isnan(Zsub) & ~np.isnan(z))

        # Check for segment break.
        if np.count_nonzero(A) <= cluster_min_px:
            print("Not enough overlap, segment break")
            segment_break = True
            break

        r, c = cropBorder(A, 0, buff)

        # Make overlap mask removing isolated pixels.
        strip_nodata = np.isnan(Zsub[r[0]:r[1], c[0]:c[1]])
        scene_data = ~np.isnan(z[r[0]:r[1], c[0]:c[1]])
        strip_mask_water_and_cloud = (MDsub[r[0]:r[1], c[0]:c[1]] > 1)

        # Nodata in strip and data in scene is a one.
        A = rat.bwareaopen(strip_nodata & scene_data,
                           cluster_min_px,
                           in_place=True).astype(np.float32)

        # Check for redundant scene.
        num_px_to_add = np.count_nonzero((A == 1)
                                         & ~strip_mask_water_and_cloud)
        print("Number of unmasked pixels to add to strip: {}".format(
            num_px_to_add))
        if num_px_to_add <= add_min_px:
            print("Redundant scene, skipping")
            skipped_scene = True
            continue

        # Data in strip and nodata in scene is a two.
        A[rat.bwareaopen(~strip_nodata & ~scene_data,
                         cluster_min_px,
                         in_place=True)] = 2

        del strip_nodata, scene_data

        Ar = rat.imresize(A, 0.1, 'nearest')

        # Check for redundant scene.
        if not np.any(Ar):
            print("Redundant scene, skipping")
            skipped_scene = True
            continue

        # Locate pixels on outside of boundary of overlap region.
        Ar_nonzero = (Ar != 0)
        B = np.where(rat.bwboundaries_array(Ar_nonzero, noholes=True))

        cz_rows, cz_cols = [], []
        for cc in [[0, 0], [0, Ar.shape[1] - 1],
                   [Ar.shape[0] - 1, Ar.shape[1] - 1], [Ar.shape[0] - 1, 0]]:
            if Ar[tuple(cc)] == 0:
                cz_rows.append(cc[0])
                cz_cols.append(cc[1])

        if len(cz_rows) > 0:
            # Pixels outside of the convex hull of input points for interpolate.griddata
            # currently can't be extrapolated linear-ly (by default they are filled with NaN).
            # Let this region be filled with NaN, but we get a better edge on the convex hull
            # by changing corner pixels that are zero to NaN.
            corner_zeros = (np.array(cz_rows), np.array(cz_cols))
            Ar[corner_zeros] = np.nan

            # Add the corner coordinates to the list of boundary coordinates,
            # which will be used for interpolation.
            By = np.concatenate((B[0], corner_zeros[0]))
            Bx = np.concatenate((B[1], corner_zeros[1]))
            B = (By, Bx)

            del corner_zeros, By, Bx
        del cz_rows, cz_cols

        # Use the coordinates and values of boundary pixels
        # to interpolate values for pixels with zero value.
        Ar_zero_coords = np.where(~Ar_nonzero)
        Ar_interp = interpolate.griddata(B, Ar[B], Ar_zero_coords, 'linear')
        Ar[Ar_zero_coords] = Ar_interp

        del Ar_nonzero, Ar_zero_coords, Ar_interp

        # Fill in the regions outside the convex hull of the boundary points
        # using a nearest extrapolation of all points on the boundary of the
        # overlap region (including the gaps that were just interpolated).
        Ar_outer = np.isnan(Ar)
        Ar_outer_coords = np.where(Ar_outer)
        B = np.where(rat.bwboundaries_array(~Ar_outer))
        Ar_extrap = interpolate.griddata(B, Ar[B], Ar_outer_coords, 'nearest')
        Ar[Ar_outer_coords] = Ar_extrap
        # Nearest extrapolation is granular, so it is smoothed.
        Ar_smooth = rat.moving_average(Ar, 5, zero_border=False)
        Ar[Ar_outer] = Ar_smooth[Ar_outer]

        del Ar_outer, Ar_outer_coords, Ar_extrap

        Ar = rat.imresize(Ar, A.shape, 'bilinear')
        Ar[(A == 1) & (Ar != 1)] = 1
        Ar[(A == 2) & (Ar != 2)] = 2
        A = np.clip(Ar - 1, 0, 1)
        del Ar

        W = (~np.isnan(Zsub)).astype(np.float32)
        W[r[0]:r[1], c[0]:c[1]] = A
        del A
        W[np.isnan(Zsub) & np.isnan(z)] = np.nan

        # Shift weights so that more of the reference layer is kept.
        f0 = 0.25  # overlap fraction where ref z weight goes to zero
        f1 = 0.55  # overlap fraction where ref z weight goes to one

        W = np.clip((1 / (f1 - f0)) * W - f0 / (f1 - f0), 0, 1)

        # Remove <25% edge of coverage from each in pair.
        strip_nodata = (W == 0)
        Zsub[strip_nodata] = np.nan
        Msub[strip_nodata] = 0
        Osub[strip_nodata] = 0
        if O2sub is not None:
            O2sub[strip_nodata] = 0
        MDsub[strip_nodata] = 0

        scene_nodata = (W == 1)
        z[scene_nodata] = np.nan
        m[scene_nodata] = 0
        o[scene_nodata] = 0
        if o2 is not None:
            o2[scene_nodata] = 0
        md[scene_nodata] = 0

        del strip_nodata, scene_nodata

        # Coregistration

        P0 = getDataDensityMap(Msub[r[0]:r[1], c[0]:c[1]]) > 0.9

        # Check for segment break.
        if not np.any(P0):
            print("Not enough data overlap, segment break")
            segment_break = True
            break

        P1 = getDataDensityMap(m[r[0]:r[1], c[0]:c[1]]) > 0.9

        # Check for redundant scene.
        if not np.any(P1):
            print("Redundant scene, skipping")
            skipped_scene = True
            continue

        # Coregister this scene to the strip mosaic.
        if (hold_guess == HOLD_GUESS_ALL and not check_guess
                and (trans_guess is not None and trans_err_guess is not None
                     and rmse_guess is not None)):
            trans[:, i] = trans_guess[:, i]
            trans_err[:, i] = trans_err_guess[:, i]
            rmse[0, i] = rmse_guess[0, i]
        else:
            trans[:, i], trans_err[:, i], rmse[0, i] = coregisterdems(
                Xsub[c[0]:c[1]], Ysub[r[0]:r[1]], Zsub[r[0]:r[1], c[0]:c[1]],
                x[c[0]:c[1]], y[r[0]:r[1]], z[r[0]:r[1], c[0]:c[1]], P0, P1,
                (trans_guess[:,
                             i] if trans_guess is not None else trans_guess),
                hold_guess != HOLD_GUESS_OFF)[[1, 2, 3]]

            if check_guess:
                error_tol = 10**-2
                if trans_guess is not None:
                    trans_check[:, i] = trans[:, i]
                    if not np.allclose(trans_check[:, i],
                                       trans_guess[:, i],
                                       rtol=0,
                                       atol=error_tol,
                                       equal_nan=True):
                        print(
                            "`trans_check` vector out of `coregisterdems` does not match `trans_guess` within error tol ({})"
                            .format(error_tol))
                        print("`trans_guess`:")
                        print(
                            np.array2string(trans_guess,
                                            precision=4,
                                            max_line_width=np.inf))
                        print("`trans_check`:")
                        print(
                            np.array2string(trans_check,
                                            precision=4,
                                            max_line_width=np.inf))
                if rmse_guess is not None:
                    rmse_check[0, i] = rmse[0, i]
                    if not np.allclose(rmse_check[0, i],
                                       rmse_guess[0, i],
                                       rtol=0,
                                       atol=error_tol,
                                       equal_nan=True):
                        print(
                            "`rmse_check` out of `coregisterdems` does not match `rmse_guess` within error tol ({})"
                            .format(error_tol))
                        print("`rmse_guess`:")
                        print(
                            np.array2string(rmse_guess,
                                            precision=4,
                                            max_line_width=np.inf))
                        print("`rmse_check`:")
                        print(
                            np.array2string(rmse_check,
                                            precision=4,
                                            max_line_width=np.inf))

            if hold_guess != HOLD_GUESS_OFF:
                if trans_guess is not None:
                    trans[:, i] = trans_guess[:, i]
                if trans_err_guess is not None:
                    trans_err[:, i] = trans_err_guess[:, i]
                if rmse_guess is not None and hold_guess == HOLD_GUESS_ALL:
                    rmse[0, i] = rmse_guess[0, i]

        # Check for segment break.
        if np.isnan(rmse[0, i]):
            print("Unable to coregister, segment break")
            segment_break = True
        elif rmse[0, i] > max_coreg_rmse:
            print(
                "Final RMSE is greater than cutoff value ({} > {}), segment break"
                .format(rmse[0, i], max_coreg_rmse))
            segment_break = True
        else:
            pass
        if segment_break:
            break

        # Interpolation grid
        xi = x - trans[1, i]
        yi = y - trans[2, i]

        # Check that uniform spacing is maintained (sometimes rounding errors).
        if len(np.unique(np.diff(xi))) > 1:
            xi = np.round(xi, 4)
        if len(np.unique(np.diff(yi))) > 1:
            yi = np.round(yi, 4)

        # Interpolate floating data to the reference grid.
        zi = rat.interp2_gdal(xi, yi, z - trans[0, i], Xsub, Ysub, 'linear')
        del z

        # Interpolate matchtag to the same grid.
        mi = rat.interp2_gdal(xi, yi, m.astype(np.float32), Xsub, Ysub,
                              'nearest')
        mi[np.isnan(mi)] = 0  # convert back to uint8
        mi = mi.astype(np.bool)
        del m

        # Interpolate ortho to same grid.
        oi = o.astype(np.float32)
        oi[oi == 0] = np.nan  # Set border to NaN so it won't be interpolated.
        oi = rat.interp2_gdal(xi, yi, oi, Xsub, Ysub, 'cubic')
        del o

        if o2 is not None:
            # Interpolate ortho2 to same grid.
            o2i = o2.astype(np.float32)
            o2i[o2i ==
                0] = np.nan  # Set border to NaN so it won't be interpolated.
            o2i = rat.interp2_gdal(xi, yi, o2i, Xsub, Ysub, 'cubic')
            del o2
        else:
            o2i = None

        # Interpolate mask to the same grid.
        mdi = rat.interp2_gdal(xi, yi, md.astype(np.float32), Xsub, Ysub,
                               'nearest')
        mdi[np.isnan(mdi)] = 0  # convert back to uint8
        mdi = mdi.astype(np.uint8)
        del md

        del Xsub, Ysub

        # Remove border 0's introduced by NaN interpolation.
        M3 = ~np.isnan(zi)
        M3 = rat.imerode(M3, 6)  # border cutline
        zi[~M3] = np.nan
        mi[~M3] = 0  # also apply to matchtag
        del M3

        # Remove border on ortho separately.
        M4 = ~np.isnan(oi)
        M4 = rat.imerode(M4, 6)
        oi[~M4] = np.nan
        del M4

        if o2i is not None:
            # Remove border on ortho2 separately.
            M5 = ~np.isnan(o2i)
            M5 = rat.imerode(M5, 6)
            o2i[~M5] = np.nan
            del M5

        # Make weighted elevation grid.
        A = Zsub * W + zi * (1 - W)
        Zsub_only = ~np.isnan(Zsub) & np.isnan(zi)
        zi_only = np.isnan(Zsub) & ~np.isnan(zi)
        A[Zsub_only] = Zsub[Zsub_only]
        A[zi_only] = zi[zi_only]
        del Zsub, zi, Zsub_only, zi_only

        # Put strip subset back into full array.
        Z[r0:r1, c0:c1] = A
        del A

        # For the matchtag, just straight combination.
        M[r0:r1, c0:c1] = (Msub | mi)
        del Msub, mi

        # Make weighted ortho grid.
        Osub = Osub.astype(np.float32)
        Osub[Osub == 0] = np.nan
        A = Osub * W + oi * (1 - W)

        # del W

        Osub_only = ~np.isnan(Osub) & np.isnan(oi)
        oi_only = np.isnan(Osub) & ~np.isnan(oi)
        A[Osub_only] = Osub[Osub_only]
        A[oi_only] = oi[oi_only]
        del Osub, oi, Osub_only, oi_only

        A[np.isnan(A)] = 0  # convert back to uint16
        A = A.astype(np.uint16)

        O[r0:r1, c0:c1] = A
        del A

        if O2sub is not None:
            # Make weighted ortho2 grid.
            O2sub = O2sub.astype(np.float32)
            O2sub[O2sub == 0] = np.nan
            A = O2sub * W + o2i * (1 - W)

            # del W

            O2sub_only = ~np.isnan(O2sub) & np.isnan(o2i)
            o2i_only = np.isnan(O2sub) & ~np.isnan(o2i)
            A[O2sub_only] = O2sub[O2sub_only]
            A[o2i_only] = o2i[o2i_only]
            del O2sub, o2i, O2sub_only, o2i_only

            A[np.isnan(A)] = 0  # convert back to uint16
            A = A.astype(np.uint16)

            O2[r0:r1, c0:c1] = A
            del A

        del W

        # For the mask, bitwise combination.
        MD[r0:r1, c0:c1] = np.bitwise_or(MDsub, mdi)
        del MDsub, mdi

    if segment_break:
        demFiles_ordered = demFiles_ordered[:i]
        trans = trans[:, :i]
        rmse = rmse[:, :i]

    # Crop to data.
    if 'Z' in vars() and ~np.all(np.isnan(Z)):
        rcrop, ccrop = cropBorder(Z, np.nan)
        if rcrop is not None:
            X = X[ccrop[0]:ccrop[1]]
            Y = Y[rcrop[0]:rcrop[1]]
            Z = Z[rcrop[0]:rcrop[1], ccrop[0]:ccrop[1]]
            M = M[rcrop[0]:rcrop[1], ccrop[0]:ccrop[1]]
            O = O[rcrop[0]:rcrop[1], ccrop[0]:ccrop[1]]
            O2 = O2[rcrop[0]:rcrop[1],
                    ccrop[0]:ccrop[1]] if O2 is not None else None
            MD = MD[rcrop[0]:rcrop[1], ccrop[0]:ccrop[1]]
            Z[np.isnan(Z)] = -9999
    else:
        X, Y, Z, M, O, O2, MD = None, None, None, None, None, None, None

    return X, Y, Z, M, O, O2, MD, trans, trans_err, rmse, demFiles_ordered, __STRIP_SPAT_REF__
Пример #4
0
def diff_strips(demFile1, demFile2, diff_demFile, save_match):
    # TODO: Write docstring.

    # Construct filenames.
    demSuffix1 = getDemSuffix(demFile1)
    demSuffix2 = getDemSuffix(demFile2)
    diff_demFile_root, diff_demFile_ext = os.path.splitext(diff_demFile)
    matchFile1 = selectBestMatchtag(demFile1)
    matchFile2 = selectBestMatchtag(demFile2)
    metaFile1 = demFile1.replace(demSuffix1, 'mdf.txt')
    metaFile2 = demFile2.replace(demSuffix2, 'mdf.txt')
    regFile1 = demFile1.replace(demSuffix1, 'reg.txt')
    regFile2 = demFile2.replace(demSuffix2, 'reg.txt')
    diff_matchFile = '{}_matchtag{}'.format(diff_demFile_root,
                                            diff_demFile_ext)
    diff_metaFile = '{}_meta.txt'.format(diff_demFile_root, diff_demFile_ext)

    # Read georeferenced strip geometries.
    x1, y1, spatref1 = rat.extractRasterData(demFile1, 'x', 'y', 'spat_ref')
    x2, y2, spatref2 = rat.extractRasterData(demFile2, 'x', 'y', 'spat_ref')

    # Make sure strips have same projection.
    if spatref2.IsSame(spatref1) != 1:
        raise SpatialRefError(
            "Base strip '{}' spatial reference ({}) mismatch with "
            "compare strip spatial reference ({})".format(
                demFile1, spatref1.ExportToWkt(), spatref2.ExportToWkt()))
    spat_ref = spatref1

    # Find area of overlap.
    z1_c0, z1_r0 = 0, 0
    z1_c1, z1_r1 = None, None
    z2_c0, z2_r0 = 0, 0
    z2_c1, z2_r1 = None, None
    try:
        if x1[0] < x2[0]:
            overlap_ind = np.where(x1 == x2[0])[0]
            if overlap_ind.size == 0:
                raise NoOverlapError("")
            z1_c0 = overlap_ind[0]
        else:
            overlap_ind = np.where(x1[0] == x2)[0]
            if overlap_ind.size == 0:
                raise NoOverlapError("")
            z2_c0 = overlap_ind[0]
        if x1[-1] > x2[-1]:
            overlap_ind = np.where(x1 == x2[-1])[0]
            if overlap_ind.size == 0:
                raise NoOverlapError("")
            z1_c1 = overlap_ind[0] + 1
        else:
            overlap_ind = np.where(x1[-1] == x2)[0]
            if overlap_ind.size == 0:
                raise NoOverlapError("")
            z2_c1 = overlap_ind[0] + 1
        if y1[0] > y2[0]:
            overlap_ind = np.where(y1 == y2[0])[0]
            if overlap_ind.size == 0:
                raise NoOverlapError("")
            z1_r0 = overlap_ind[0]
        else:
            overlap_ind = np.where(y1[0] == y2)[0]
            if overlap_ind.size == 0:
                raise NoOverlapError("")
            z2_r0 = overlap_ind[0]
        if y1[-1] < y2[-1]:
            overlap_ind = np.where(y1 == y2[-1])[0]
            if overlap_ind.size == 0:
                raise NoOverlapError("")
            z1_r1 = overlap_ind[0] + 1
        else:
            overlap_ind = np.where(y1[-1] == y2)[0]
            if overlap_ind.size == 0:
                raise NoOverlapError("")
            z2_r1 = overlap_ind[0] + 1
    except NoOverlapError:
        raise NoOverlapError("Strip geometries do not overlap")

    if save_match:
        # Load matchtag data into arrays.
        print("Loading matchtag data")
        m1 = rat.extractRasterData(matchFile1, 'array')
        m2 = rat.extractRasterData(matchFile2, 'array')
        m1 = m1[z1_r0:z1_r1, z1_c0:z1_c1]
        m2 = m2[z2_r0:z2_r1, z2_c0:z2_c1]
        r0, r1, c0, c1 = crop_strip(m1, m2, method='data_density')
        # del m1, m2

    # Load DEM data into arrays.
    print("Loading raster data")
    z1 = rat.extractRasterData(demFile1, 'z')
    z2 = rat.extractRasterData(demFile2, 'z')
    z1[z1 == -9999] = np.nan
    z2[z2 == -9999] = np.nan

    # Crop arrays to area of overlap.
    x1 = x1[z1_c0:z1_c1]
    y1 = y1[z1_r0:z1_r1]
    x2 = x2[z2_c0:z2_c1]
    y2 = y2[z2_r0:z2_r1]
    z1 = z1[z1_r0:z1_r1, z1_c0:z1_c1]
    z2 = z2[z2_r0:z2_r1, z2_c0:z2_c1]

    # Crop arrays further to decrease memory use.
    if 'r0' not in vars():
        # r0, r1, c0, c1 = crop_strip(z1, method='center')
        r0, r1, c0, c1 = crop_strip(rat.getDataArray(z1, np.nan),
                                    rat.getDataArray(z2, np.nan),
                                    method='data_density')
    x1_crop = x1[c0:c1]
    y1_crop = y1[r0:r1]
    x2_crop = x2[c0:c1]
    y2_crop = y2[r0:r1]
    z1_crop = z1[r0:r1, c0:c1]
    z2_crop = z2[r0:r1, c0:c1]

    # Get initial guess of translation vector to
    # hopefully speed up coregistration...
    trans1 = get_trans_vector(regFile1)
    trans2 = get_trans_vector(regFile2)
    trans_guess = trans2 - trans1

    # Coregister the two DEMs.
    print("Beginning coregistration")
    _, trans, _, rmse = coregisterdems(x1_crop,
                                       y1_crop,
                                       z1_crop,
                                       x2_crop,
                                       y2_crop,
                                       z2_crop,
                                       trans_guess=trans_guess)
    dz, dx, dy = trans

    # Interpolate comparison DEM to reference DEM.
    print("Interpolating dem2 to dem1")
    z2i = rat.interp2_gdal(x2 - dx, y2 - dy, z2 - dz, x1, y1, 'linear')
    del z2

    # Difference DEMs and save result.
    print("Saving difference DEM")
    z_diff = z2i - z1
    z_diff[np.isnan(z_diff)] = -9999
    del z1, z2i
    rat.saveArrayAsTiff(z_diff,
                        diff_demFile,
                        x1,
                        y1,
                        spat_ref,
                        nodata_val=-9999,
                        dtype_out='float32')

    print("Extracting footprint vertices for metadata")
    fp_vertices = rat.getFPvertices(z_diff,
                                    x1,
                                    y1,
                                    label=-9999,
                                    label_type='nodata',
                                    replicate_matlab=True,
                                    dtype_out_int64_if_equal=True)
    del z_diff

    if save_match:
        if 'm2' not in vars():
            print("Loading match2")
            m2 = rat.extractRasterData(matchFile2, 'array').astype(np.float32)
            m2 = m2[z2_r0:z2_r1, z2_c0:z2_c1]
        elif m2.dtype != np.float32:
            m2 = m2.astype(np.float32)

        print("Interpolating match2 to match1")
        m2i = rat.interp2_gdal(x2 - dx, y2 - dy, m2, x1, y1, 'nearest')
        del m2
        m2i[np.isnan(m2i)] = 0  # convert back to uint8
        m2i = m2i.astype(np.bool)

        if 'm1' not in vars():
            print("Loading match1")
            m1 = rat.extractRasterData(matchFile1, 'array').astype(np.bool)
            m1 = m1[z1_r0:z1_r1, z1_c0:z1_c1]
        elif m1.dtype != np.bool:
            m1 = m1.astype(np.bool)

        print("Saving difference matchtag")
        m_diff = (m1 & m2i)
        del m1
        rat.saveArrayAsTiff(m_diff,
                            diff_matchFile,
                            x1,
                            y1,
                            spat_ref,
                            nodata_val=0,
                            dtype_out='uint8')
        del m_diff

    # Write metadata for difference image.
    proj4 = spat_ref.ExportToProj4()
    time = datetime.today().strftime("%d-%b-%Y %H:%M:%S")
    writeDiffMeta(diff_metaFile, demFile1, demFile2, trans, rmse, proj4,
                  fp_vertices, time)