Exemplo n.º 1
0
    def testCreateGdalGeoTiffDatasetGeoreferenced(self):
        destPath = os.path.join(self.dir, 'test-create-gdal-dataset-georeferenced.tif')
        destPath2 = os.path.join(self.dir, 'test-create-gdal-dataset-georeferenced2.tif')

        image = Image.open(self.file)
        
        ndarray = maskImage(image, self.testData)
        offset = getOffsetValues(self.testData, image)
        driver = gdal.GetDriverByName("GTiff")
        if driver is None:
            raise ValueError("Can't find GeoTiff Driver")
        
        response = createGdalDataset(image, ndarray, driver, None, destPath)
        response1 = createGdalDataset(image, ndarray, driver, offset, destPath2)
        
        print '====================='
        print 'Test if testCreateGdalGeoTiffDataset ...'
        print 'Response: %s'%response
        print '====================='
         
        
        geoTransform = gdal.GCPsToGeoTransform(self.testGcp)
        geoTransform1 = gdal.GCPsToGeoTransform(correctGCPOffset(self.testGcp, offset))
        geoProj = SRC_DICT_WKT[4314]
        response.SetProjection(geoProj)
        response.SetGeoTransform(geoTransform)
        response1.SetProjection(geoProj)
        response1.SetGeoTransform(geoTransform1)        
        response.FlushCache() 
        response1.FlushCache()
        # clear up
        del image
        del ndarray
        del response
        del response1
        
        # create vrt
        dst_path = os.path.join(self.dir, 'test_createVrt.vrt')
        dataset = gdal.Open(self.file, GA_ReadOnly)
        vrt = createVrt(dataset, dst_path)
        vrt.SetProjection(geoProj)
        vrt.SetGeoTransform(geoTransform)
        vrt.FlushCache()
        del vrt
        
        # create georef classic
        dst_path2 = os.path.join(self.dir, 'test-mtb-georef.tif')
        logger = createLogger('GeoreferenceTest', logging.DEBUG)
        georeference(self.file, dst_path2, self.dir, 
                geoTransform, 4314, 'polynom', logger)
#         if os.path.exists(destPath):
#             os.remove(destPath)

        # create georef clipped 
        dst_path3 = os.path.join(self.dir, 'test-mtb-georef-clipped.tif')
        clipPath = createClipShapefile(self.bbox, os.path.join(self.dir, 'test_shp'), 4314)
        response = georeference(self.file, dst_path3, self.dir, 
                                geoTransform, 4314, 'polynom', logger, clipPath)
Exemplo n.º 2
0
    def testGeoreferenceMtbWithClip(self):
        dstPath = os.path.join(self.dir, 'mtb-georef-clipped.tif')
        geoTransform = gdal.GCPsToGeoTransform(self.testData1['mtb']['gcps'])
        clipPath = createClipShapefile(self.testData1['mtb']['bbox'], os.path.join(self.dir, 'test_shp'), self.testData1['mtb']['srs'])
        response = georeference(self.testData1['mtb']['srcFile'], dstPath, self.dir, 
                                geoTransform, self.testData1['mtb']['srs'], 'polynom', self.logger, clipPath)
        
        print '====================='
        print 'Test if testGeoreferenceMtb ...'
        print 'Response: %s'%response
        print '====================='

        self.assertTrue(os.path.exists(dstPath), 'Could not find created vrt file ...')
        self.assertEqual(response, dstPath, 'Response is not like expected ...')
                    
        responseDataset = gdal.Open(response, GA_ReadOnly)
        self.assertTrue(responseDataset.GetProjection() == 'GEOGCS["DHDN",DATUM["Deutsches_Hauptdreiecksnetz",SPHEROID["Bessel 1841",6377397.155,299.1528128000008,AUTHORITY["EPSG","7004"]],TOWGS84[598.1,73.7,418.2,0.202,0.045,-2.455,6.7],AUTHORITY["EPSG","6314"]],PRIMEM["Greenwich",0],UNIT["degree",0.0174532925199433],AUTHORITY["EPSG","4314"]]', 'Response has not expected coordinate system ...')
         
        # clear up
        del responseDataset
        if os.path.exists(dstPath):
            os.remove(dstPath)
        if os.path.exists(clipPath):
            os.remove('%s.shp'%os.path.join(self.dir, 'test_shp'))
            os.remove('%s.dbf'%os.path.join(self.dir, 'test_shp'))
            os.remove('%s.prj'%os.path.join(self.dir, 'test_shp'))
            os.remove('%s.shx'%os.path.join(self.dir, 'test_shp'))
Exemplo n.º 3
0
    def testCreateGdalGeoTiffDatasetGeoreferencedSimple(self):
        destPath = os.path.join(self.dir, 'test-create-gdal-dataset-georeferenced-simple.tif')

        image = Image.open(self.file)
        
        ndarray = maskImage(image, self.testData)
        offset = getOffsetValues(self.testData, image)
        driver = gdal.GetDriverByName("GTiff")
        if driver is None:
            raise ValueError("Can't find GeoTiff Driver")
        
        response = createGdalDataset(image, ndarray, driver, offset, destPath)
        
        print '====================='
        print 'Test if testCreateGdalGeoTiffDatasetGeoreferencedSimple ...'
        print 'Response: %s'%response
        print '====================='
         
        geoTransform = gdal.GCPsToGeoTransform(correctGCPOffset(self.testGcp, offset))
        geoProj = SRC_DICT_WKT[4314]
        response.SetProjection(geoProj)
        response.SetGeoTransform(geoTransform)
        response.SetProjection(geoProj)    
        response.FlushCache() 
        
        # clear up
        del image
        del ndarray
        del response
        if os.path.exists(destPath):
            os.remove(destPath)
 def settinGeotransformation(self, file):
     file = file.split('.')[0] + '.tiff'
     fn = self.TIFF_PATH + file
     ds = gdal.Open(fn, gdal.GA_Update)
     gcps = ds.GetGCPs()
     gt = gdal.GCPsToGeoTransform(gcps)
     return gt
Exemplo n.º 5
0
def gdal_bounding_box(raster, outProj=None):
    """
    Computes the bounding box for an open GDAL raster file.

    The format is [minX, minY, maxX, maxY] in outProj coordinates.
    For instance outProj for lat/lon is pyproj.Proj('+proj=longlat +datum=WGS84')
    Returns None in case of an error.
    """
    projection = raster.GetProjection()
    if (projection):
        transform = raster.GetGeoTransform()
    else:
        projection = raster.GetGCPProjection()
        gcps = raster.GetGCPs()
        transform = gdal.GCPsToGeoTransform(gcps)
        if transform is None:
            print("Unable to extract a geotransform from GCPs")
            return None
    lines = numpy.array([0, 0, raster.RasterYSize, raster.RasterYSize])
    pixels = numpy.array([0, raster.RasterXSize, raster.RasterXSize, 0])
    arrayX = transform[0] + pixels * transform[1] + lines * transform[2]
    arrayY = transform[3] + pixels * transform[4] + lines * transform[5]

    if outProj:
        srs = osr.SpatialReference(wkt=projection)
        proj_srs = srs.ExportToProj4()
        inProj = pyproj.Proj(proj_srs)
        arrayX, arrayY = pyproj.transform(inProj, outProj, arrayX, arrayY)

    minX = numpy.amin(arrayX)
    minY = numpy.amin(arrayY)
    maxX = numpy.amax(arrayX)
    maxY = numpy.amax(arrayY)
    return [minX, minY, maxX, maxY]
Exemplo n.º 6
0
    def testTransformClipPolygon(self):
        geoTransform = gdal.GCPsToGeoTransform(self.testData1['mtb']['gcps'])
        response = transformClipPolygon(self.testData1['mtb']['clip'], geoTransform)
        
        print '====================='
        print 'Test if testTransformClipPolygon ...'
        print 'Response: %s'%response
        print '====================='

        self.assertTrue(isinstance(response, list), 'Response is not of type list ...')
Exemplo n.º 7
0
def rectifyImageAffine(srcFile, dstFile, clipPolygon, gcps, srs, logger):
    """ Functions generates clips an image and adds a geotransformation matrix to it

    :type srcFile: str
    :type dstFile: str
    :type clipPolygon: List.<Tuple.<int>>
    :type gcps: List.<gdal.GCP>
    :type srs: int Right now the function only supports 4314 as spatial reference system
    :type logger: logging.logger
    :return: str
    :raise: ValueError """
    logger.debug('Open image ...')
    srcImage = Image.open(srcFile)

    logger.debug('Mask image ...')
    ndarray = maskImage(srcImage, clipPolygon)

    logger.debug('Calculate offset ...')
    offset = {'left': 0, 'top': 0, 'right': 0, 'bottom': 0}
    if len(clipPolygon) > 0:
        offset = getOffsetValues(clipPolygon, srcImage)

    # create an output geotiff
    newDataset = createGeotiff(srcImage, ndarray, offset, dstFile, logger)

    logger.debug('Do georeferencing based on an affine transformation ...')
    geoTransform = gdal.GCPsToGeoTransform(correctGCPOffset(gcps, offset))
    geoProj = SRC_DICT_WKT[srs]
    if geoProj is None:
        raise ValueError("SRS with id - %s - is not supported" % srs)
    newDataset.SetProjection(geoProj)
    newDataset.SetGeoTransform(geoTransform)
    newDataset.FlushCache()

    # clear up
    del srcImage
    del newDataset
    del ndarray

    return dstFile
Exemplo n.º 8
0
    def testResampleGeoreferencedImageSimple(self):
        destPath = os.path.join(self.dir, 'test-create-gdal-dataset-resample-simple.tif')
        image = Image.open(self.file)
        ndarray = maskImage(image, self.testData)
        offset = getOffsetValues(self.testData, image)
        driver = gdal.GetDriverByName("MEM")
        if driver is None:
            raise ValueError("Can't find Mem Driver")
        srcDataset = createGdalDataset(image, ndarray, driver, offset)

        
        outputDriver = gdal.GetDriverByName('GTiff')
        if outputDriver is None: 
            raise ValueError("Can't find GTiff Driver")
        
        geoTransform = gdal.GCPsToGeoTransform(correctGCPOffset(self.testGcp, offset))
        geoProj = SRC_DICT_WKT[4314]
        srcDataset.SetProjection(geoProj)
        srcDataset.SetGeoTransform(geoTransform)
        response = resampleGeoreferencedImage(srcDataset, geoTransform, geoProj, outputDriver, destPath)
        
        print '====================='
        print 'Test if testResampleGeoreferencedImageSimple ...'
        print 'Response: %s'%response
        print '====================='
        
        response.FlushCache() 
        
        self.assertTrue(isinstance(response, gdal.Dataset), "Response is not a gdal.Dataset.")
        
        # clear up
        del image
        del ndarray
        del response
        if os.path.exists(destPath):
            os.remove(destPath)
Exemplo n.º 9
0
def main(args):
    parser = argparse.ArgumentParser(
        description=
        'Render a DSM from a DTM and polygons representing buildings.')
    parser.add_argument("--input_vtp_path",
                        type=str,
                        help="Input buildings polygonal file (.vtp)")
    parser.add_argument(
        "--input_obj_paths",
        nargs="*",
        help="List of input building (.obj) file paths.  "
        "Building object files start "
        "with a digit, road object files start with \"Road\". "
        "All obj files start with comments specifying the offsets "
        "that are added the coordinats. There are three comment lines, "
        "one for each coordinate: \"#c offset: value\" where c is x, y and z.")
    parser.add_argument("input_dtm", help="Input digital terain model (DTM)")
    parser.add_argument("output_dsm",
                        help="Output digital surface model (DSM)")
    parser.add_argument("--render_png",
                        action="store_true",
                        help="Do not save the DSM, render into a PNG instead.")
    parser.add_argument(
        "--render_cls",
        action="store_true",
        help="Render a buildings mask: render buildings label (6), "
        "background (2) and no DTM.")
    parser.add_argument("--buildings_only",
                        action="store_true",
                        help="Do not use the DTM, use only the buildings.")
    parser.add_argument("--debug",
                        action="store_true",
                        help="Save intermediate results")
    args = parser.parse_args(args)

    # open the DTM
    dtm = gdal.Open(args.input_dtm, gdal.GA_ReadOnly)
    if not dtm:
        raise RuntimeError("Error: Failed to open DTM {}".format(
            args.input_dtm))

    dtmDriver = dtm.GetDriver()
    dtmDriverMetadata = dtmDriver.GetMetadata()
    dsm = None
    dtmBounds = [0.0, 0.0, 0.0, 0.0]
    if dtmDriverMetadata.get(gdal.DCAP_CREATE) == "YES":
        print("Create destination image "
              "size:({}, {}) ...".format(dtm.RasterXSize, dtm.RasterYSize))
        # georeference information
        projection = dtm.GetProjection()
        transform = dtm.GetGeoTransform()
        gcpProjection = dtm.GetGCPProjection()
        gcps = dtm.GetGCPs()
        options = ["COMPRESS=DEFLATE"]
        # ensure that space will be reserved for geographic corner coordinates
        # (in DMS) to be set later
        if (dtmDriver.ShortName == "NITF" and not projection):
            options.append("ICORDS=G")
        if args.render_cls:
            eType = gdal.GDT_Byte
        else:
            eType = gdal.GDT_Float32
        dsm = dtmDriver.Create(args.output_dsm,
                               xsize=dtm.RasterXSize,
                               ysize=dtm.RasterYSize,
                               bands=1,
                               eType=eType,
                               options=options)
        if (projection):
            # georeference through affine geotransform
            dsm.SetProjection(projection)
            dsm.SetGeoTransform(transform)
        else:
            # georeference through GCPs
            dsm.SetGCPs(gcps, gcpProjection)
            gdal.GCPsToGeoTransform(gcps, transform)
        corners = [[0, 0], [0, dtm.RasterYSize],
                   [dtm.RasterXSize, dtm.RasterYSize], [dtm.RasterXSize, 0]]
        geoCorners = numpy.zeros((4, 2))
        for i, corner in enumerate(corners):
            geoCorners[i] = [
                transform[0] + corner[0] * transform[1] +
                corner[1] * transform[2], transform[3] +
                corner[0] * transform[4] + corner[1] * transform[5]
            ]
        dtmBounds[0] = numpy.min(geoCorners[:, 0])
        dtmBounds[1] = numpy.max(geoCorners[:, 0])
        dtmBounds[2] = numpy.min(geoCorners[:, 1])
        dtmBounds[3] = numpy.max(geoCorners[:, 1])

        if args.render_cls:
            # label for no building
            dtmRaster = numpy.full([dtm.RasterYSize, dtm.RasterXSize], 2)
            nodata = 0
        else:
            print("Reading the DTM {} size: ({}, {})\n"
                  "\tbounds: ({}, {}), ({}, {})...".format(
                      args.input_dtm, dtm.RasterXSize, dtm.RasterYSize,
                      dtmBounds[0], dtmBounds[1], dtmBounds[2], dtmBounds[3]))
            dtmRaster = dtm.GetRasterBand(1).ReadAsArray()
            nodata = dtm.GetRasterBand(1).GetNoDataValue()
        print("Nodata: {}".format(nodata))
    else:
        raise RuntimeError(
            "Driver {} does not supports Create().".format(dtmDriver))

    # read the buildings polydata, set Z as a scalar and project to XY plane
    print("Reading the buildings ...")
    # labels for buildings and elevated roads
    labels = [6, 17]
    if (args.input_vtp_path and os.path.isfile(args.input_vtp_path)):
        polyReader = vtk.vtkXMLPolyDataReader()
        polyReader.SetFileName(args.input_vtp_path)
        polyReader.Update()
        polyVtkList = [polyReader.GetOutput()]
    elif (args.input_obj_paths):
        # buildings start with numbers
        # optional elevated roads start with Road*.obj
        bldg_re = re.compile(".*/?[0-9][^/]*\\.obj")
        bldg_files = [f for f in args.input_obj_paths if bldg_re.match(f)]
        print(bldg_files)
        road_re = re.compile(".*/?Road[^/]*\\.obj")
        road_files = [f for f in args.input_obj_paths if road_re.match(f)]
        files = [bldg_files, road_files]
        files = [x for x in files if x]
        print(road_files)
        if len(files) >= 2:
            print("Found {} buildings and {} roads".format(
                len(files[0]), len(files[1])))
        elif len(files) == 1:
            print("Found {} buildings".format(len(files[0])))
        else:
            raise RuntimeError("No OBJ files found in {}".format(
                args.input_obj_paths))
        polyVtkList = []
        for category in range(len(files)):
            append = vtk.vtkAppendPolyData()
            for i, fileName in enumerate(files[category]):
                offset = [0.0, 0.0, 0.0]
                gdal_utils.read_offset(fileName, offset)
                print("Offset: {}".format(offset))
                transform = vtk.vtkTransform()
                transform.Translate(offset[0], offset[1], offset[2])

                objReader = vtk.vtkOBJReader()
                objReader.SetFileName(fileName)
                transformFilter = vtk.vtkTransformFilter()
                transformFilter.SetTransform(transform)
                transformFilter.SetInputConnection(objReader.GetOutputPort())
                append.AddInputConnection(transformFilter.GetOutputPort())
            append.Update()
            polyVtkList.append(append.GetOutput())
    else:
        raise RuntimeError(
            "Must provide either --input_vtp_path, or --input_obj_paths")

    arrayName = "Elevation"
    append = vtk.vtkAppendPolyData()
    for category in range(len(polyVtkList)):
        poly = dsa.WrapDataObject(polyVtkList[category])
        polyElevation = poly.Points[:, 2]
        if args.render_cls:
            # label for buildings
            polyElevation[:] = labels[category]
        polyElevationVtk = numpy_support.numpy_to_vtk(polyElevation)
        polyElevationVtk.SetName(arrayName)
        poly.PointData.SetScalars(polyElevationVtk)
        append.AddInputDataObject(polyVtkList[category])
    append.Update()

    # Create the RenderWindow, Renderer
    ren = vtk.vtkRenderer()
    renWin = vtk.vtkRenderWindow()
    renWin.OffScreenRenderingOn()
    renWin.SetSize(dtm.RasterXSize, dtm.RasterYSize)
    renWin.SetMultiSamples(0)
    renWin.AddRenderer(ren)

    # show the buildings
    trisBuildingsFilter = vtk.vtkTriangleFilter()
    trisBuildingsFilter.SetInputDataObject(append.GetOutput())
    trisBuildingsFilter.Update()

    p2cBuildings = vtk.vtkPointDataToCellData()
    p2cBuildings.SetInputConnection(trisBuildingsFilter.GetOutputPort())
    p2cBuildings.PassPointDataOn()
    p2cBuildings.Update()
    buildingsScalarRange = p2cBuildings.GetOutput().GetCellData().GetScalars(
    ).GetRange()

    if (args.debug):
        polyWriter = vtk.vtkXMLPolyDataWriter()
        polyWriter.SetFileName("p2c.vtp")
        polyWriter.SetInputConnection(p2cBuildings.GetOutputPort())
        polyWriter.Write()

    buildingsMapper = vtk.vtkPolyDataMapper()
    buildingsMapper.SetInputDataObject(p2cBuildings.GetOutput())

    buildingsActor = vtk.vtkActor()
    buildingsActor.SetMapper(buildingsMapper)
    ren.AddActor(buildingsActor)

    if (args.render_png):
        print("Render into a PNG ...")
        # Show the terrain.
        print("Converting the DTM into a surface ...")
        # read the DTM as a VTK object
        dtmReader = vtk.vtkGDALRasterReader()
        dtmReader.SetFileName(args.input_dtm)
        dtmReader.Update()
        dtmVtk = dtmReader.GetOutput()

        # Convert the terrain into a polydata.
        surface = vtk.vtkImageDataGeometryFilter()
        surface.SetInputDataObject(dtmVtk)

        # Make sure the polygons are planar, so need to use triangles.
        tris = vtk.vtkTriangleFilter()
        tris.SetInputConnection(surface.GetOutputPort())

        # Warp the surface by scalar values
        warp = vtk.vtkWarpScalar()
        warp.SetInputConnection(tris.GetOutputPort())
        warp.SetScaleFactor(1)
        warp.UseNormalOn()
        warp.SetNormal(0, 0, 1)
        warp.Update()
        dsmScalarRange = warp.GetOutput().GetPointData().GetScalars().GetRange(
        )

        dtmMapper = vtk.vtkPolyDataMapper()
        dtmMapper.SetInputConnection(warp.GetOutputPort())
        dtmActor = vtk.vtkActor()
        dtmActor.SetMapper(dtmMapper)
        ren.AddActor(dtmActor)

        ren.ResetCamera()
        camera = ren.GetActiveCamera()
        camera.ParallelProjectionOn()
        camera.SetParallelScale((dtmBounds[3] - dtmBounds[2]) / 2)

        if (args.buildings_only):
            scalarRange = buildingsScalarRange
        else:
            scalarRange = [
                min(dsmScalarRange[0], buildingsScalarRange[0]),
                max(dsmScalarRange[1], buildingsScalarRange[1])
            ]
        lut = vtk.vtkColorTransferFunction()
        lut.AddRGBPoint(scalarRange[0], 0.23, 0.30, 0.75)
        lut.AddRGBPoint((scalarRange[0] + scalarRange[1]) / 2, 0.86, 0.86,
                        0.86)
        lut.AddRGBPoint(scalarRange[1], 0.70, 0.02, 0.15)

        dtmMapper.SetLookupTable(lut)
        dtmMapper.SetColorModeToMapScalars()
        buildingsMapper.SetLookupTable(lut)
        if (args.buildings_only):
            ren.RemoveActor(dtmActor)

        renWin.Render()
        windowToImageFilter = vtk.vtkWindowToImageFilter()
        windowToImageFilter.SetInput(renWin)
        windowToImageFilter.SetInputBufferTypeToRGBA()
        windowToImageFilter.ReadFrontBufferOff()
        windowToImageFilter.Update()

        writerPng = vtk.vtkPNGWriter()
        writerPng.SetFileName(args.output_dsm + ".png")
        writerPng.SetInputConnection(windowToImageFilter.GetOutputPort())
        writerPng.Write()
    else:
        print("Render into a floating point buffer ...")

        ren.ResetCamera()
        camera = ren.GetActiveCamera()
        camera.ParallelProjectionOn()
        camera.SetParallelScale((dtmBounds[3] - dtmBounds[2]) / 2)
        distance = camera.GetDistance()
        focalPoint = [(dtmBounds[0] + dtmBounds[1]) * 0.5,
                      (dtmBounds[3] + dtmBounds[2]) * 0.5,
                      (buildingsScalarRange[0] + buildingsScalarRange[1]) * 0.5
                      ]
        position = [focalPoint[0], focalPoint[1], focalPoint[2] + distance]
        camera.SetFocalPoint(focalPoint)
        camera.SetPosition(position)

        valuePass = vtk.vtkValuePass()
        valuePass.SetRenderingMode(vtk.vtkValuePass.FLOATING_POINT)
        # use the default scalar for point data
        valuePass.SetInputComponentToProcess(0)
        valuePass.SetInputArrayToProcess(
            vtk.VTK_SCALAR_MODE_USE_POINT_FIELD_DATA, arrayName)
        passes = vtk.vtkRenderPassCollection()
        passes.AddItem(valuePass)
        sequence = vtk.vtkSequencePass()
        sequence.SetPasses(passes)
        cameraPass = vtk.vtkCameraPass()
        cameraPass.SetDelegatePass(sequence)
        ren.SetPass(cameraPass)
        # We have to render the points first, otherwise we get a segfault.
        renWin.Render()
        valuePass.SetInputArrayToProcess(
            vtk.VTK_SCALAR_MODE_USE_CELL_FIELD_DATA, arrayName)
        renWin.Render()
        elevationFlatVtk = valuePass.GetFloatImageDataArray(ren)
        valuePass.ReleaseGraphicsResources(renWin)

        print("Writing the DSM ...")
        elevationFlat = numpy_support.vtk_to_numpy(elevationFlatVtk)
        # VTK X,Y corresponds to numpy cols,rows. VTK stores arrays
        # in Fortran order.
        elevationTranspose = numpy.reshape(elevationFlat,
                                           [dtm.RasterXSize, dtm.RasterYSize],
                                           "F")
        # changes from cols, rows to rows,cols.
        elevation = numpy.transpose(elevationTranspose)
        # numpy rows increase as you go down, Y for VTK images increases as you go up
        elevation = numpy.flip(elevation, 0)
        if args.buildings_only:
            dsmElevation = elevation
        else:
            # elevation has nans in places other than buildings
            dsmElevation = numpy.fmax(dtmRaster, elevation)
        dsm.GetRasterBand(1).WriteArray(dsmElevation)
        if nodata:
            dsm.GetRasterBand(1).SetNoDataValue(nodata)
Exemplo n.º 10
0
import os.path

if len(sys.argv) < 2:
    print "Usage: gcps2wld.py source_file"
    sys.exit(1)

filename = sys.argv[1]
dataset = gdal.Open(filename)
if dataset is None:
    print 'Unable to open ', filename
    sys.exit(1)

gcps = dataset.GetGCPs()

if gcps is None or len(gcps) == 0:
    print 'No GCPs found on file ' + filename
    sys.exit(1)

geotransform = gdal.GCPsToGeoTransform(gcps)

if geotransform is None:
    print 'Unable to extract a geotransform.'
    sys.exit(1)

print geotransform[1]
print geotransform[4]
print geotransform[2]
print geotransform[5]
print geotransform[0] + 0.5 * geotransform[1] + 0.5 * geotransform[2]
print geotransform[3] + 0.5 * geotransform[4] + 0.5 * geotransform[5]
Exemplo n.º 11
0
def get_spatial_extent(raster_path, target_EPSG=4326, tol=0.1):
    """ Get the spatial extent of a raster file. 
    
    If the file is not georeferenced (e.g. for raw radarsat 2), this function 
    attempts to use the GCPs in the image . Howver, this doesn't always
    produce exact results, so it is advisable to use an extra buffer tolerance
    in your spatial extent (maybe ~0.1 decimal degrees) 
    
    *Parameters*
    
    raster_path : str
        Path to raster for which a spatial extent is desired
    target_EPSG : int
        EPSG code specifying coordinate system for output file
    tol : float 
        By how many decimal degrees to buffer spatial extent
        
    *Returns*
    
    dict
        Dictionary with the following keys: {xmin, xmax, ymin, ymax} corresponding
        to the spatial extent in WGS84 decimal degrees 
    
    """

    # open file
    src = gdal.Open(raster_path)
    prj = src.GetProjection()

    # check if georeferencing information is available
    if (sum(src.GetGeoTransform()) == 2) and src.GetGCPCount() > 3:
        gt = gdal.GCPsToGeoTransform(src.GetGCPs())
        prj = src.GetGCPProjection()
    else:
        gt = src.GetGeoTransform()

    # get untransformed upper left and lower right corner coordinates
    ulx, xres, xskew, uly, yskew, yres = gt
    lrx = ulx + (src.RasterXSize * xres)
    lry = uly + (src.RasterYSize * yres)

    # Setup the source projection - you can also import from epsg, proj4...
    source = osr.SpatialReference()
    source.ImportFromWkt(prj)

    # The target projection
    target = osr.SpatialReference()
    target.ImportFromEPSG(target_EPSG)

    # set up transform
    transform = osr.CoordinateTransformation(source, target)

    # transform coordinates
    upper = transform.TransformPoint(ulx, uly)
    lower = transform.TransformPoint(lrx, lry)

    ext = {
        'xmin': min(upper[0], lower[0]) - tol,
        'xmax': max(upper[0], lower[0]) + tol,
        'ymin': min(upper[1], lower[1]) - tol,
        'ymax': max(upper[1], lower[1]) + tol
    }

    return (ext)
Exemplo n.º 12
0
        # 创建坐标系
        srs = osr.SpatialReference()
        srs.SetWellKnownGeogCS('WGS84')
        # 相关信息
        rows = ds.RasterYSize  # 行数
        cols = ds.RasterXSize  # 列数
        # 创建地面控制点:经度、纬度、z,照片列数,照片行数
        gcps = [
            gdal.GCP(y1, x2, 0, 0, 0),  # 左上
            gdal.GCP(y2, x2, 0, cols - 1, 0),  # 右上
            gdal.GCP(y1, x1, 0, 0, rows - 1),  # 左下
            gdal.GCP(y2, x1, 0, cols - 1, rows - 1)  # 右下
        ]
        ds.SetGCPs(gcps, srs.ExportToWkt())
        # 确保在数据集上设置了地理变化和投影信息
        ds.SetProjection(srs.ExportToWkt() )
        ds.SetGeoTransform(gdal.GCPsToGeoTransform(gcps) )
        subimgs.append(tif_fp) #加入到subimgs,准备拼接
        del ds

    # 对registration_dir内的数据进行拼接
    out_fn = os.path.join(mosaic_dir, "out.tif")
    params = {
        "-o": out_fn,
        "input_files": subimgs
    }
    from gdal_merge import main_by_params
    main_by_params(params)

    pass
Exemplo n.º 13
0
def projectImage(inputPatch, x0, y0, x1, y1, cornerPoints, rpcInformation):
    invCornerPoints = np.zeros(cornerPoints.shape)
    invCornerPoints[0, :] = inverseLookup(cornerPoints[0, :],
                                          (x0, y0) + (-1, 1), rpcInformation)
    invCornerPoints[1, :] = inverseLookup(cornerPoints[1, :],
                                          (x0, y1) + (1, 1), rpcInformation)
    invCornerPoints[2, :] = inverseLookup(cornerPoints[2, :],
                                          (x1, y1) + (1, -1), rpcInformation)
    invCornerPoints[3, :] = inverseLookup(cornerPoints[3, :],
                                          (x1, y0) + (-1, -1), rpcInformation)
    xySource = np.mgrid[y0:y1:1, x0:x1:1]
    inputPatch = inputPatch.transpose(1, 0, 2)
    plotCoordinates = xySource[:, 0:inputPatch.shape[0], 0:inputPatch.shape[1]]
    pixelPoints = np.ones((4, 2))
    pixelPoints[0, 0] = y0
    pixelPoints[0, 1] = x0
    pixelPoints[1, 0] = y1
    pixelPoints[1, 1] = x0
    pixelPoints[2, 0] = y1
    pixelPoints[2, 1] = x1
    pixelPoints[3, 0] = y0
    pixelPoints[3, 1] = x1

    gcp_list = []  #List of Ground Control Points

    for i in range(0, 4):
        pixel = pixelPoints[i, 0].item()
        line = pixelPoints[i, 1].item()
        x = invCornerPoints[i, 0].item()
        y = invCornerPoints[i, 1].item()
        z = 0

        gcp = gdal.GCP(x, y, z, pixel, line)
        gcp_list.append(gcp)
    #polygon = Polygon(cornerPoints)
    #for i in range(0,25):
    a = 1  #np.random.uniform(.8,1,1)[0]
    b = 1  #np.random.uniform(.8,1,1)[0]
    x = (a * invCornerPoints[0, 0] + (2 - a) * invCornerPoints[2, 0]) / 2
    y = (b * invCornerPoints[0, 1] + (2 - b) * invCornerPoints[2, 1]) / 2
    #point = Point(x,y)
    #if(polygon.contains(point)):
    line, pixel = getCorrespondingPixel((y, x), rpcInformation)
    z = 0
    gcp = gdal.GCP(x, y, z, pixel, line)
    gcp_list.append(gcp)
    # Generating the Geo Transform:
    gt2 = gdal.GCPsToGeoTransform(gcp_list)
    fwd = Affine.from_gdal(*gt2)
    long, lat = fwd * plotCoordinates

    cornerPoints3 = np.zeros((4, 2))
    cornerPoints3[0, :] = [long[0, 0], lat[0, 0]]
    cornerPoints3[3, :] = [long[0, -1], lat[0, -1]]
    cornerPoints3[2, :] = [long[-1, -1], lat[-1, -1]]
    cornerPoints3[1, :] = [long[-1, 0], lat[-1, 0]]
    transformMatrix = solve_affine(cornerPoints3, invCornerPoints)

    input = np.vstack(
        (long.flatten(), lat.flatten(), np.ones((1, np.prod(long.shape)))))
    updatedPerspective = transformMatrix * input
    long = updatedPerspective[0].reshape(long.shape)
    lat = updatedPerspective[1].reshape(lat.shape)
    print("error", np.sum(pow(cornerPoints3 - invCornerPoints, 2)))

    return long, lat, inputPatch
Exemplo n.º 14
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)
Exemplo n.º 15
0
 def gcps_to_geotransform(self):
     '''
     Transforms ground control points into geotransform using gdal.
     '''
     return gdal.GCPsToGeoTransform(self.gcps())