コード例 #1
0
ファイル: test_rpc.py プロジェクト: zhhongsh/Danesfield
def test_rpc_multi_back_projection():
    model = rpc_from_gdal_dict(rpc_md)
    img_pts = model.project(points)
    print("Running multi-point back projection")
    bp = model.back_project(img_pts, [p[2] for p in points])
    print("diff: ", bp - points)
    assert numpy.max(numpy.abs(bp - points)) < 1e-16
コード例 #2
0
def main(args):
    parser = argparse.ArgumentParser(
        description='Projects source_points onto a source_image'
        ' using an RPC projection read from source_image or from raytheon_rpc')
    parser.add_argument("source_image", help="Source image file name")
    parser.add_argument("source_points", help="Source points file name")
    parser.add_argument("destination_image",
                        help="Destination image file name")
    parser.add_argument("--raytheon-rpc",
                        type=str,
                        help="Raytheon RPC file name. If not provided, "
                        "the RPC is read from the source_image")
    parser.add_argument(
        "--type",
        choices=["uint8", "uint16", "float32"],
        help="Specify the type for the height band, default is float32.")
    args = parser.parse_args(args)

    # open the GDAL file
    sourceImage = gdal.Open(args.source_image, gdal.GA_ReadOnly)
    if not sourceImage:
        raise RuntimeError("Error: Failed to open source image {}".format(
            args.source_image))
    model = None
    if (args.raytheon_rpc):
        # read the RPC from raytheon file
        print("Reading RPC from Raytheon file: {}".format(args.raytheon_rpc))
        model = raytheon_rpc.read_raytheon_rpc_file(args.raytheon_rpc)
    else:
        # read the RPC from RPC Metadata in the image file
        print("Reading RPC Metadata from {}".format(args.source_image))
        rpcMetaData = sourceImage.GetMetadata('RPC')
        model = rpc.rpc_from_gdal_dict(rpcMetaData)

    driver = sourceImage.GetDriver()
    driverMetadata = driver.GetMetadata()
    destImage = None
    if driverMetadata.get(gdal.DCAP_CREATE) == "YES":
        print("Create destination image (height is {}), "
              "size:({}, {}) ...".format(
                  "float32" if not args.type else args.type,
                  sourceImage.RasterXSize, sourceImage.RasterYSize))
        # georeference information
        projection = sourceImage.GetProjection()
        transform = sourceImage.GetGeoTransform()
        gcpProjection = sourceImage.GetGCPProjection()
        gcps = sourceImage.GetGCPs()
        options = []
        # ensure that space will be reserved for geographic corner coordinates
        # (in DMS) to be set later
        if (driver.ShortName == "NITF" and not projection):
            options.append("ICORDS=G")
        if (args.type == "uint8"):
            eType = gdal.GDT_Byte
            dtype = numpy.uint8
            MAX_VALUE = 255
        elif (args.type == "uint16"):
            eType = gdal.GDT_UInt16
            dtype = numpy.uint16
            MAX_VALUE = 65535
        else:
            eType = gdal.GDT_Float32
            dtype = numpy.float32
        destImage = driver.Create(args.destination_image,
                                  xsize=sourceImage.RasterXSize,
                                  ysize=sourceImage.RasterYSize,
                                  bands=1,
                                  eType=eType,
                                  options=options)
        if (projection):
            # georeference through affine geotransform
            destImage.SetProjection(projection)
            destImage.SetGeoTransform(transform)
        else:
            # georeference through GCPs
            destImage.SetGCPs(gcps, gcpProjection)
        raster = numpy.zeros(
            (sourceImage.RasterYSize, sourceImage.RasterXSize), dtype=dtype)
    else:
        raise RuntimeError(
            "Error: driver {} does not supports Create().".format(driver))

    # read the pdal file and project the points
    json = u"""
    {
      "pipeline": [
        "%s",
        {
            "type":"filters.reprojection",
            "out_srs":"EPSG:4326"
        }
      ]
    }"""
    print("Loading Point Cloud")
    json = json % args.source_points
    pipeline = pdal.Pipeline(json)
    pipeline.validate()  # check if our JSON and options were good
    # this causes a segfault at the end of the program
    # pipeline.loglevel = 8  # really noisy
    pipeline.execute()
    arrays = pipeline.arrays
    arrayX = arrays[0]['X']
    arrayY = arrays[0]['Y']
    arrayZ = arrays[0]['Z']
    pipeline = None

    # Sort the points by height so that higher points project last
    print("Sorting by Height")
    heightIdx = numpy.argsort(arrayZ)
    arrayX = arrayX[heightIdx]
    arrayY = arrayY[heightIdx]
    arrayZ = arrayZ[heightIdx]

    minZ = numpy.amin(arrayZ)
    maxZ = numpy.amax(arrayZ)
    # project points to get image indexes and save their height into the image
    print("Project {} points to destination image ...".format(len(arrayX)))
    print("Points min/max Z: {}/{}  ...".format(minZ, maxZ))

    print("Projecting Points")
    imgPoints = model.project(
        numpy.array([arrayX, arrayY, arrayZ]).transpose())
    intImgPoints = imgPoints.astype(numpy.int).transpose()

    # find indicies of points that fall inside the image bounds
    validIdx = numpy.logical_and.reduce(
        (intImgPoints[1] < raster.shape[0], intImgPoints[1] >= 0,
         intImgPoints[0] < raster.shape[1], intImgPoints[0] >= 0))

    # keep only the points that are in the image
    numOut = numpy.size(validIdx) - numpy.count_nonzero(validIdx)
    if (numOut > 0):
        print("Skipped {} points outside of image".format(numOut))
    intImgPoints = intImgPoints[:, validIdx]
    if (args.type == "uint16" or args.type == "uint8"):
        quantizedZ = ((arrayZ - minZ) * MAX_VALUE / (maxZ - minZ)).astype(
            numpy.int)
        quantizedZ = quantizedZ[validIdx]
        print("Rendering Image")
        raster[intImgPoints[1], intImgPoints[0]] = quantizedZ
    else:
        arrayZ = arrayZ[validIdx]
        print("Rendering Image")
        raster[intImgPoints[1], intImgPoints[0]] = arrayZ

    # Write the image
    print("Write destination image ...")
    destImage.GetRasterBand(1).WriteArray(raster)

    # close files
    print("Close files ...")
    destImage = None
    sourceImage = None
コード例 #3
0
ファイル: ortho.py プロジェクト: zhhongsh/Danesfield
def orthorectify(args_source_image, args_dsm, args_destination_image,
                 args_occlusion_thresh=1.0, args_denoise_radius=2,
                 args_raytheon_rpc=None, args_dtm=None):
    """
    Orthorectify an image given the DSM

    Args:
        source_image: Source image file name
        dsm: Digital surface model (DSM) image file name
        destination_image: Orthorectified image file name
        occlusion-thresh: Threshold on height difference for detecting
                          and masking occluded regions (in meters)
        denoise-radius: Apply morphological operations with this radius
                        to the DSM reduce speckled noise
        raytheon-rpc: Raytheon RPC file name. If not provided
                      the RPC is read from the source_image

    Returns:
        COMPLETE_DSM_INTERSECTION = 0
        PARTIAL_DSM_INTERSECTION = 1
        EMPTY_DSM_INTERSECTION = 2
        ERROR = 10
    """
    returnValue = COMPLETE_DSM_INTERSECTION
    # open the source image
    sourceImage = gdal.Open(args_source_image, gdal.GA_ReadOnly)
    if not sourceImage:
        return ERROR
    sourceBand = sourceImage.GetRasterBand(1)

    if (args_raytheon_rpc):
        # read the RPC from raytheon file
        print("Reading RPC from Raytheon file: {}".format(args_raytheon_rpc))
        model = raytheon_rpc.read_raytheon_rpc_file(args_raytheon_rpc)
    else:
        # read the RPC from RPC Metadata in the image file
        print("Reading RPC Metadata from {}".format(args_source_image))
        rpcMetaData = sourceImage.GetMetadata('RPC')
        model = rpc.rpc_from_gdal_dict(rpcMetaData)
    if model is None:
        print("Error reading the RPC")
        return ERROR

    # open the DSM
    dsm = gdal.Open(args_dsm, gdal.GA_ReadOnly)
    if not dsm:
        return ERROR
    band = dsm.GetRasterBand(1)
    dsmRaster = band.ReadAsArray(
        xoff=0, yoff=0,
        win_xsize=dsm.RasterXSize, win_ysize=dsm.RasterYSize)
    dsm_nodata_value = band.GetNoDataValue()
    print("DSM raster shape {}".format(dsmRaster.shape))

    if args_dtm:
        dtm = gdal.Open(args_dtm, gdal.GA_ReadOnly)
        if not dtm:
            return ERROR
        band = dtm.GetRasterBand(1)
        dtmRaster = band.ReadAsArray(
            xoff=0, yoff=0,
            win_xsize=dtm.RasterXSize, win_ysize=dtm.RasterYSize)
        newRaster = numpy.where(dsmRaster != dsm_nodata_value, dsmRaster, dtmRaster)
        dsmRaster = newRaster

    # apply morphology to denoise the DSM
    if (args_denoise_radius > 0):
        morph_struct = circ_structure(args_denoise_radius)
        dsmRaster = morphology.grey_opening(dsmRaster, structure=morph_struct)
        dsmRaster = morphology.grey_closing(dsmRaster, structure=morph_struct)

    # create the rectified image
    driver = dsm.GetDriver()
    driverMetadata = driver.GetMetadata()
    destImage = None
    arrayX = None
    arrayY = None
    arrayZ = None
    if driverMetadata.get(gdal.DCAP_CREATE) == "YES":
        print("Create destination image of "
              "size:({}, {}) ...".format(dsm.RasterXSize, dsm.RasterYSize))
        # georeference information
        projection = dsm.GetProjection()
        transform = dsm.GetGeoTransform()
        gcpProjection = dsm.GetGCPProjection()
        gcps = dsm.GetGCPs()
        options = ["COMPRESS=DEFLATE"]
        # ensure that space will be reserved for geographic corner coordinates
        # (in DMS) to be set later
        if (driver.ShortName == "NITF" and not projection):
            options.append("ICORDS=G")
        # If I try to use AddBand with GTiff I get:
        # Dataset does not support the AddBand() method.
        # So I create all bands using the same type at the begining
        destImage = driver.Create(
            args_destination_image, xsize=dsm.RasterXSize,
            ysize=dsm.RasterYSize,
            bands=sourceImage.RasterCount, eType=sourceBand.DataType,
            options=options)

        if (projection):
            # georeference through affine geotransform
            destImage.SetProjection(projection)
            destImage.SetGeoTransform(transform)
            pixels = numpy.arange(0, dsm.RasterXSize)
            pixels = numpy.tile(pixels, dsm.RasterYSize)
            lines = numpy.arange(0, dsm.RasterYSize)
            lines = numpy.repeat(lines, dsm.RasterXSize)
            arrayX = transform[0] + pixels * transform[1] + lines * transform[2]
            arrayY = transform[3] + pixels * transform[4] + lines * transform[5]
            arrayZ = dsmRaster[lines, pixels]
            validIdx = arrayZ != dsm_nodata_value
            pixels = pixels[validIdx]
            lines = lines[validIdx]
            arrayX = arrayX[validIdx]
            arrayY = arrayY[validIdx]
            arrayZ = arrayZ[validIdx]

        else:
            # georeference through GCPs
            destImage.SetGCPs(gcps, gcpProjection)
            # not implemented: compute arrayX, arrayY, arrayZ
            print("Not implemented yet")
            return ERROR
    else:
        print("Driver {} does not supports Create().".format(driver))
        return ERROR

    # convert coordinates to Long/Lat
    srs = osr.SpatialReference(wkt=projection)
    proj_srs = srs.ExportToProj4()
    inProj = pyproj.Proj(proj_srs)
    outProj = pyproj.Proj('+proj=longlat +datum=WGS84')
    arrayX, arrayY = pyproj.transform(inProj, outProj, arrayX, arrayY)

    # Sort the points by height so that higher points project last
    if (args_occlusion_thresh > 0):
        print("Sorting by Height")
        heightIdx = numpy.argsort(arrayZ)
        arrayX = arrayX[heightIdx]
        arrayY = arrayY[heightIdx]
        arrayZ = arrayZ[heightIdx]
        lines = lines[heightIdx]
        pixels = pixels[heightIdx]

    # project the points
    minZ = numpy.amin(arrayZ)
    maxZ = numpy.amax(arrayZ)
    # project points to get image indexes and save their height into the image
    print("Project {} points to destination image ...".format(len(arrayX)))
    print("Points min/max Z: {}/{}  ...".format(minZ, maxZ))

    print("Projecting Points")
    imgPoints = model.project(numpy.array([arrayX, arrayY, arrayZ]).transpose())
    intImgPoints = imgPoints.astype(numpy.int).transpose()

    # coumpute the bound of the relevant AOI in the source image
    print("Source Image size: ", [sourceImage.RasterXSize, sourceImage.RasterYSize])
    minPoint = numpy.maximum([0, 0], numpy.min(intImgPoints, 1))
    print("AOI min: ", minPoint)
    maxPoint = numpy.minimum(numpy.max(intImgPoints, 1),
                             [sourceImage.RasterXSize,
                              sourceImage.RasterYSize])
    print("AOI max: ", maxPoint)
    cropSize = maxPoint - minPoint
    if numpy.any(cropSize < 1):
        print("DSM does not intersect source image")
        returnValue = EMPTY_DSM_INTERSECTION

    # shift the projected image point to the cropped AOI space
    intImgPoints[0] -= minPoint[0]
    intImgPoints[1] -= minPoint[1]

    # find indicies of points that fall inside the image bounds
    print("Source raster shape {}".format(cropSize))
    validIdx = numpy.logical_and.reduce((intImgPoints[1] < cropSize[1],
                                         intImgPoints[1] >= 0,
                                         intImgPoints[0] < cropSize[0],
                                         intImgPoints[0] >= 0))
    intImgPoints = intImgPoints[:, validIdx]

    # keep only the points that are in the image
    numOut = numpy.size(validIdx) - numpy.count_nonzero(validIdx)
    if (numOut > 0 and not returnValue == EMPTY_DSM_INTERSECTION):
        print("Skipped {} points outside of image".format(numOut))
        returnValue = PARTIAL_DSM_INTERSECTION

    # use a height map to test for occlusion
    if (args_occlusion_thresh > 0):
        print("Mapping occluded points")
        valid_arrayZ = arrayZ[validIdx]
        # render a height map in the source image space
        height_map = numpy.full(cropSize[::-1], -numpy.inf, dtype=numpy.float32)
        height_map[intImgPoints[1], intImgPoints[0]] = valid_arrayZ

        # get a mask of points that locally are (approximately)
        # the highest point in the map
        is_max_height = height_map[intImgPoints[1], intImgPoints[0]] \
            <= valid_arrayZ + args_occlusion_thresh
        num_occluded = numpy.size(is_max_height) - numpy.count_nonzero(is_max_height)
        print("Skipped {} occluded points".format(num_occluded))

        # keep only non-occluded image points
        intImgPoints = intImgPoints[:, is_max_height]
        # disable occluded points in the valid pixel mask
        validIdx[numpy.nonzero(validIdx)[0][numpy.logical_not(is_max_height)]] = False

    for bandIndex in range(1, sourceImage.RasterCount + 1):
        print("Processing band {} ...".format(bandIndex))
        sourceBand = sourceImage.GetRasterBand(bandIndex)
        nodata_value = sourceBand.GetNoDataValue()
        # for now use zero as a no-data value if one is not specified
        # it would probably be better to add a mask (alpha) band instead
        if nodata_value is None:
            nodata_value = 0
        if numpy.any(cropSize < 1):
            # read one value for data type
            sourceRaster = sourceBand.ReadAsArray(
                xoff=0, yoff=0, win_xsize=1, win_ysize=1)
            destRaster = numpy.full(
                (dsm.RasterYSize, dsm.RasterXSize), nodata_value,
                dtype=sourceRaster.dtype)
        else:
            sourceRaster = sourceBand.ReadAsArray(
                xoff=int(minPoint[0]), yoff=int(minPoint[1]),
                win_xsize=int(cropSize[0]), win_ysize=int(cropSize[1]))

            print("Copying colors ...")
            destRaster = numpy.full(
                (dsm.RasterYSize, dsm.RasterXSize), nodata_value,
                dtype=sourceRaster.dtype)
            destRaster[lines[validIdx], pixels[validIdx]] = sourceRaster[
                intImgPoints[1], intImgPoints[0]]

        print("Write band ...")
        destBand = destImage.GetRasterBand(bandIndex)
        destBand.SetNoDataValue(nodata_value)
        destBand.WriteArray(destRaster)
    return returnValue
コード例 #4
0
def main(args):
    parser = argparse.ArgumentParser(
        description="Crop out images for each of the CORE3D AOIs")
    parser.add_argument("aoi",
                        help="dataset AOI: D1 (WPAFB), D2 (WPAFB), "
                        "D3 (USCD), D4 (Jacksonville) or "
                        "DSM used to get the cropping bounds and elevation")
    parser.add_argument(
        "dest_dir",
        help="Destination directory for writing crops. Crop files have "
        "the same name as source images + an optional postifx.")
    parser.add_argument("src_root",
                        help="Source imagery root directory or list of images",
                        nargs="+")
    parser.add_argument(
        "--dest_file_postfix",
        help="Postfix added to destination files, before the extension")
    parser.add_argument("--rpc_dir",
                        help="Source directory for RPCs or list of RPC files",
                        nargs="+")
    args = parser.parse_args(args)

    useDSM = False
    if os.path.isfile(args.aoi):
        useDSM = True
    if os.path.isfile(args.src_root[0]):
        src_root = args.src_root
        print('Cropping a list of {} images'.format(len(args.src_root)))
    else:
        src_root = os.path.join(args.src_root[0], '')
        print('Cropping all images from directory: {}'.format(args.src_root))

    dest_dir = os.path.join(args.dest_dir, '')
    if (not args.dest_file_postfix):
        dest_file_postfix = "_crop"
    else:
        dest_file_postfix = args.dest_file_postfix

    print('Writing crops in directory: ' + dest_dir)
    print('Cropping to AOI: ' + args.aoi)

    rpc_dir = None
    if args.rpc_dir:
        if os.path.isfile(args.rpc_dir[0]):
            rpc_dir = args.rpc_dir
            print('Using a list of {} RPCs.'.format(len(args.rpc_dir)))
        else:
            rpc_dir = os.path.join(args.rpc_dir[0], '')
            print("Using all RPCs from directory: {}".format(rpc_dir))
    else:
        print('Using RPCs from image metadata.')

    if useDSM:
        data_dsm = gdal_utils.gdal_open(args.aoi)
        # Elevation
        dsm = data_dsm.GetRasterBand(1).ReadAsArray(0,
                                                    0,
                                                    data_dsm.RasterXSize,
                                                    data_dsm.RasterYSize,
                                                    buf_type=gdal.GDT_Float32)
        no_data_value = data_dsm.GetRasterBand(1).GetNoDataValue()
        dsm_without_no_data = dsm[dsm != no_data_value]
        elevations = np.array([[dsm_without_no_data.min()],
                               [dsm_without_no_data.max()]])
        # Cropping bounds from DSM
        [minX, minY, maxX, maxY] = gdal_utils.gdal_bounding_box(
            data_dsm, pyproj.Proj('+proj=longlat +datum=WGS84'))
        latlong_corners = np.array([[minX, minY, elevations[0]],
                                    [maxX, minY, elevations[0]],
                                    [maxX, maxY, elevations[0]],
                                    [minX, maxY, elevations[0]],
                                    [minX, minY, elevations[1]],
                                    [maxX, minY, elevations[1]],
                                    [maxX, maxY, elevations[1]],
                                    [minX, maxY, elevations[1]]])
        print("Cropping bounds extracted from DSM")
    else:
        elevation_range = 100
        # WPAFB AOI D1
        if args.aoi == 'D1':
            elevation = 240
            ul_lon = -84.11236693243779
            ul_lat = 39.77747025512961

            ur_lon = -84.10530109439955
            ur_lat = 39.77749705975315

            lr_lon = -84.10511182729961
            lr_lat = 39.78290042788092

            ll_lon = -84.11236485416471
            ll_lat = 39.78287156225952

        # WPAFB AOI D2
        if args.aoi == 'D2':
            elevation = 300
            ul_lon = -84.08847226672408
            ul_lat = 39.77650841377968

            ur_lon = -84.07992142333644
            ur_lat = 39.77652166058358

            lr_lon = -84.07959205694203
            lr_lat = 39.78413758747398

            ll_lon = -84.0882028871317
            ll_lat = 39.78430009793551

        # UCSD AOI D3
        if args.aoi == 'D3':
            elevation = 120
            ul_lon = -117.24298768132505
            ul_lat = 32.882791370856857

            ur_lon = -117.24296375496185
            ur_lat = 32.874021450913411

            lr_lon = -117.2323749640905
            lr_lat = 32.874041569804469

            ll_lon = -117.23239784772379
            ll_lat = 32.882811496466012

        # Jacksonville AOI D4
        if args.aoi == 'D4':
            elevation = 2
            ul_lon = -81.67078466333165
            ul_lat = 30.31698808384777

            ur_lon = -81.65616946309449
            ur_lat = 30.31729872444624

            lr_lon = -81.65620275072482
            lr_lat = 30.329923847788603

            ll_lon = -81.67062242425624
            ll_lat = 30.32997669492018

    for src_img_file, dst_img_file in filesFromArgs(src_root, dest_dir,
                                                    dest_file_postfix):
        dst_file_no_ext = os.path.splitext(dst_img_file)[0]
        dst_img_file = dst_file_no_ext + ".tif"

        print('Converting img: ' + src_img_file)
        src_image = gdal.Open(src_img_file, gdalconst.GA_ReadOnly)

        nodata_values = []
        nodata = 0
        for i in range(src_image.RasterCount):
            nodata_value = src_image.GetRasterBand(i + 1).GetNoDataValue()
            if not nodata_value:
                nodata_value = nodata
            nodata_values.append(nodata_value)

        if useDSM:
            poly = latlong_corners.copy()
            elevation = np.median(dsm)
        else:
            poly = np.array([[ul_lon, ul_lat, elevation + elevation_range],
                             [ur_lon, ur_lat, elevation + elevation_range],
                             [lr_lon, lr_lat, elevation + elevation_range],
                             [ll_lon, ll_lat, elevation + elevation_range],
                             [ul_lon, ul_lat, elevation + elevation_range],
                             [ul_lon, ul_lat, elevation - elevation_range],
                             [ur_lon, ur_lat, elevation - elevation_range],
                             [lr_lon, lr_lat, elevation - elevation_range],
                             [ll_lon, ll_lat, elevation - elevation_range],
                             [ul_lon, ul_lat, elevation - elevation_range]])
        if rpc_dir:
            print("Using file RPC: {}".format(rpc_dir))
            model = read_raytheon_RPC(rpc_dir, src_img_file)
            if model is None:
                print('No RPC file exists using image metadata RPC: ' +
                      src_img_file + '\n')
                rpc_md = src_image.GetMetadata('RPC')
                model = rpc.rpc_from_gdal_dict(rpc_md)
            else:
                rpc_md = rpc.rpc_to_gdal_dict(model)
        else:
            print("Using image RPC.")
            rpc_md = src_image.GetMetadata('RPC')
            model = rpc.rpc_from_gdal_dict(rpc_md)

        # Project the world point locations into the image
        pixel_poly = model.project(poly)

        ul_x, ul_y = map(int, pixel_poly.min(0))
        lr_x, lr_y = map(int, pixel_poly.max(0))
        min_x, min_y, z = poly.min(0)
        max_x, max_y, z = poly.max(0)

        ul_x = max(0, ul_x)
        ul_y = max(0, ul_y)
        lr_x = min(src_image.RasterXSize - 1, lr_x)
        lr_y = min(src_image.RasterYSize - 1, lr_y)

        samp_off = rpc_md['SAMP_OFF']
        samp_off = float(samp_off) - ul_x
        rpc_md['SAMP_OFF'] = str(samp_off)

        line_off = rpc_md['LINE_OFF']
        line_off = float(line_off) - ul_y
        rpc_md['LINE_OFF'] = str(line_off)

        model.image_offset[0] -= ul_x
        model.image_offset[1] -= ul_y

        # Calculate the pixel size of the new image
        # Constrain the width and height to the bounds of the image
        px_width = int(lr_x - ul_x + 1)
        if px_width + ul_x > src_image.RasterXSize - 1:
            px_width = int(src_image.RasterXSize - ul_x - 1)

        px_height = int(lr_y - ul_y + 1)
        if px_height + ul_y > src_image.RasterYSize - 1:
            px_height = int(src_image.RasterYSize - ul_y - 1)

        # We've constrained x & y so they are within the image.
        # If the width or height ends up negative at this point,
        # the AOI is completely outside the image
        if px_width < 0 or px_height < 0:
            print('AOI out of range, skipping\n')
            continue

        corners = [[0, 0], [px_width, 0], [px_width, px_height],
                   [0, px_height]]
        corner_names = ['UpperLeft', 'UpperRight', 'LowerRight', 'LowerLeft']
        world_corners = model.back_project(corners, elevation)

        corner_gcps = []
        for (p, l), (x, y, h), n in zip(corners, world_corners, corner_names):
            corner_gcps.append(gdal.GCP(x, y, h, p, l, "", n))

        # Load the source data as a gdalnumeric array
        clip = src_image.ReadAsArray(ul_x, ul_y, px_width, px_height)

        # create output raster
        raster_band = src_image.GetRasterBand(1)
        output_driver = gdal.GetDriverByName('MEM')

        # In the event we have multispectral images,
        # shift the shape dimesions we are after,
        # since position 0 will be the number of bands
        try:
            clip_shp_0 = clip.shape[0]
            clip_shp_1 = clip.shape[1]
            if clip.ndim > 2:
                clip_shp_0 = clip.shape[1]
                clip_shp_1 = clip.shape[2]
        except (AttributeError):
            print('Error decoding image, skipping\n')
            continue

        output_dataset = output_driver.Create('', clip_shp_1, clip_shp_0,
                                              src_image.RasterCount,
                                              raster_band.DataType)

        # Copy All metadata data from src to dst
        domains = src_image.GetMetadataDomainList()
        for tag in domains:
            md = src_image.GetMetadata(tag)
            if md:
                output_dataset.SetMetadata(md, tag)

        # Rewrite the rpc_md that we modified above.
        output_dataset.SetMetadata(rpc_md, 'RPC')
        output_dataset.SetGeoTransform(gdal.GCPsToGeoTransform(corner_gcps))
        output_dataset.SetProjection(gdal_get_projection(src_image))

        # End logging, print blank line for clarity
        print('')
        bands = src_image.RasterCount
        if bands > 1:
            for i in range(bands):
                outBand = output_dataset.GetRasterBand(i + 1)
                outBand.SetNoDataValue(nodata_values[i])
                outBand.WriteArray(clip[i])
        else:
            outBand = output_dataset.GetRasterBand(1)
            outBand.SetNoDataValue(nodata_values[0])
            outBand.WriteArray(clip)

        if dst_img_file:
            output_driver = gdal.GetDriverByName('GTiff')
            output_driver.CreateCopy(dst_img_file, output_dataset, False)
コード例 #5
0
ファイル: test_rpc.py プロジェクト: zhhongsh/Danesfield
def test_rpc_back_projection():
    model = rpc_from_gdal_dict(rpc_md)
    img_pt = model.project(points[0])
    bp = model.back_project(img_pt, points[0][2])
    print("diff: ", bp - points[0])
    assert numpy.max(numpy.abs(bp - points[0])) < 1e-16
コード例 #6
0
ファイル: test_rpc.py プロジェクト: zhhongsh/Danesfield
def test_rpc_multi_projection():
    model = rpc_from_gdal_dict(rpc_md)
    print(model.project(points))
コード例 #7
0
ファイル: test_rpc.py プロジェクト: zhhongsh/Danesfield
def test_rpc_from_gdal_dict():
    rpc_from_gdal_dict(rpc_md)