def single_band_calculator(self, rlist, expression): """ Raster calculator """ logging.debug('Starting single_band_calculator... ') array_list = [GdalReader().ds2array(gdal_import.src2ds(r))[0] if np.array(r).ndim is 2 else GdalReader().ds2array(gdal_import.src2ds(r)) for r in rlist] calculation = tools.array_calculator(array_list, expression) return self._array2raster(calculation, name=str(expression), mask=rlist[0])
def histogram_matching(self, input_raster, reference, output='histogram_matching'): logging.debug('Starting histogram_matching... ') src_ds = gdal_import.src2ds(input_raster) raster_array = GdalReader().ds2array(src_ds) ref_ds = gdal_import.src2ds(reference) ref_array = GdalReader().ds2array(ref_ds) nodata = ref_ds.GetRasterBand(1).GetNoDataValue() matched_array= tools.histogram_matching(raster_array, ref_array, nodata=nodata) return self._array2raster(matched_array, name=output, mask=input_raster)
def src2ds(src): logging.debug("Importing file tiles " + str(src)) if GdalReader().isvalid(src): return src else: try: GdalReader().isvalid(src.ds) return src.ds except: logging.exception(" Unknown source.")
def raster2file(raster, file_path): ds = src2ds(raster) GdalReader().gdal2file(ds, file_path, driver_name='GTiff') if os.path.exists(file_path): return file_path
def raster_stats(input_raster, output=None): logging.debug('Starting histogram_matching... ') src_ds = gdal_import.src2ds(input_raster) raster_array = GdalReader().ds2array(src_ds) return numpy_tools.array_stats(raster_array)
def py2gdal(py_raster): """ Convert python format to gdal""" if GdalReader().isvalid(py_raster.ds): return py_raster.ds else: geotransform = (py_raster.extent[0], py_raster.xres, 0, py_raster.extent[3], 0, py_raster.yres) return GdalReader().array2ds(src_array=py_raster.array, output=py_raster.filename, geotransform=geotransform, projection=py_raster.projection, nodata=py_raster.nodata)
def zonal_stats(self, raster, zones, resize=True): logging.debug('Starting zonal_stats... ') src_ds = gdal_import.src2ds(raster) raster_array = GdalReader().ds2array(src_ds) zones_ds = gdal_import.src2ds(zones) zones_array = GdalReader().ds2array(zones_ds) outputs = tools.zonal_stats(valuesarr=raster_array[0], zonesarr=zones_array[0], resize=resize) outputs_dict = {} name = 'stats' for stat in ['count', 'mean', 'stdev']: outputs_dict[str(stat)] = (self._array2raster(outputs[stat], name=str(name + '_' + str(stat)), mask=raster)) return outputs_dict
def rgb_intensity(self, input_raster): """ Intensity for rgb images :param input_raster dictionary with the RGB bands """ logging.debug('Starting rgb_intensity... ') src_ds = gdal_import.src2ds(input_raster) raster_array = GdalReader().ds2array(src_ds) intensity = tools.rgb_intensity(raster_array) return self._array2raster(intensity, name='intensity', mask=input_raster)
def equalization(self, input_raster): """Equalization of a 2D array with finite values :param input_raster 2D array""" logging.debug('Starting equalization... ') src_ds = gdal_import.src2ds(input_raster) raster_arrays = GdalReader().ds2array(src_ds) d_bands = tools.equalization(bands_list=raster_arrays) # return gdal_import.gdal_import(toolbox.raster.gdal_utils.poly_clip(raster, polygons, output)) return self._array2raster(d_bands, name='equalization', mask=input_raster)
def normalisation(self, input_raster): """Normalisation of a 2D array to 0-255 :param input_raster 2D array""" logging.debug('Starting normalisation... ') src_ds = gdal_import.src2ds(input_raster) raster_arrays = GdalReader().ds2array(src_ds) nodata = src_ds.GetRasterBand(1).GetNoDataValue() d_bands = tools.normalisation(raster_arrays, nodata=nodata) return self._array2raster(d_bands, name="normalization", mask=input_raster)
def single_bands_to_multiband(gdal_bands_list, output=None): """ Convert several gdal single file to a single gdal datasource""" # Get mask # src_ds = gdal.OpenShared(gdal_bands_list[0]) src_ds = GdalReader().gdal2ds(gdal_bands_list[0]) # src_ds.SetMetadataItem('FilePath', gdal_bands_list[0]) # Get output if not output: output = 'image_multiband' # Create new ds # tmp_ds = gdal.GetDriverByName('MEM').CreateCopy('', src_ds, 0) out_ds = gdalr.GdalReader().create_ds(output, src_ds.RasterXSize, src_ds.RasterYSize, len(gdal_bands_list), src_ds.GetRasterBand(1).DataType) out_ds.SetProjection(src_ds.GetProjection()) out_ds.SetGeoTransform(src_ds.GetGeoTransform()) i = 0 for band_dataset in gdal_bands_list: i = i + 1 band_ds = GdalReader().gdal2ds(band_dataset) # mask_ds = gdal.OpenShared(band_dataset) array_i = band_ds.GetRasterBand(1).ReadAsArray() out_ds.GetRasterBand(i).WriteArray(array_i) band_ds = None del array_i if GdalReader().isvalid(out_ds): return out_ds
def vegetation_index(self, input_raster): """ Vegetation Index (GRVI, NDVI) for rgb/rgbnir images :param input_raster dictionary with the RGB bands """ logging.debug('Starting vegetation_index... ') src_ds = gdal_import.src2ds(input_raster) raster_bands = GdalReader().ds2array(src_ds) if len(raster_bands) == 3: vi = tools.vegetation_index(red=raster_bands[0], green=raster_bands[1]) elif len(raster_bands) >= 4: vi = tools.vegetation_index(red=raster_bands[0], green=raster_bands[1], nir=raster_bands[3]) else: logging.warning('Not enough bands to create vegetation index.') return return self._array2raster(vi, name='vi', mask=input_raster)
def poly_clip(raster, polygons, outuput): """Clip raster with polygons""" src_ds = gdal_import.src2ds(raster) poly_ds = ogr_import.src2ogr(polygons) # 1.- Reproject vector geometry to same projection as raster projection = src_ds.GetProjection() poly_reprojected = ogr_utils.reproject(poly_ds, wtk_projection=projection, outname='polygons_reprojected') poly_ds = ogr_import.src2ogr(poly_reprojected) poly_lyr = poly_ds.GetLayer() # Bound box (debbuging code) # geom_type = poly_lyr.GetGeomType() # outDataSource = ogrr.create_layer('bound_box', geom_type=geom_type, wkt_proj=projection, file_path=None) # outLayer = outDataSource.GetLfpayer() # outLayerDefn = outLayer.GetLayerDefn() # outFeature = ogr.Feature(outLayerDefn) # outFeature.SetGeometry(geom) # outLayer.CreateFeature(outFeature) # outFeature = None # outDataSource = None # 2.- Filter and extract features # Get Raster Extent nodata = src_ds.GetRasterBand(1).GetNoDataValue() r_min_x, r_max_x, r_min_y, r_max_y = GdalReader().get_extent(src_ds) wkt = 'POLYGON((' + ','.join([ ' '.join([str(r_min_x), str(r_max_y)]), ' '.join([ str(r_min_x), str(r_min_y) ]), ' '.join([str(r_max_x), str(r_min_y)]), ' '.join([ str(r_max_x), str(r_max_y) ]), ' '.join([str(r_min_x), str(r_max_y)]) ]) + '))' geom = ogr.CreateGeometryFromWkt(wkt) poly_lyr.SetSpatialFilter(geom) mem_driver = ogr.GetDriverByName('MEMORY') filtered_poly_ds = mem_driver.CreateDataSource('filered_polygons') # Open the memory datasource with write access and copy content mem_driver = ogr.GetDriverByName('MEMORY') mem_driver.Open('filered_polygons', 1) filtered_poly_ds.CopyLayer(poly_lyr, 'filered_polygons', ['OVERWRITE=YES']) poly_lyr.SetSpatialFilter(None) # Intersect geometries with boundary box geom_type = poly_lyr.GetGeomType() clipped_poly_ds = ogrr.create_layer('clipped_polygons', geom_type=geom_type, wkt_proj=projection, file_path=None) clipped_poly_lyr = clipped_poly_ds.GetLayer() filtered_poly_lyr = filtered_poly_ds.GetLayer() clipped_lyr_defn = clipped_poly_lyr.GetLayerDefn() infeature = filtered_poly_lyr.GetNextFeature() while infeature: feat_geom = infeature.GetGeometryRef() intersection_geom = feat_geom.Intersection(geom) out_feature = ogr.Feature(clipped_lyr_defn) out_feature.SetGeometry(intersection_geom) clipped_poly_lyr.CreateFeature(out_feature) out_feature = None infeature = filtered_poly_lyr.GetNextFeature() filtered_poly_lyr.ResetReading() filtered_poly_lyr = None # Bound box (debbuging code) # geom_type = poly_lyr.GetGeomType() # filtered_poly_ds = ogrr.create_layer('filered_polygons', geom_type=geom_type, wkt_proj=projection, # file_path=None) # Clip raster to layer extent lyr = clipped_poly_lyr extent = lyr.GetExtent() # Convert the _vector extent to image pixel coordinates geo_trans = src_ds.GetGeoTransform() # projection = rds.GetProjection() ul_x, ul_y = GdalReader().world2pixel(geo_trans, extent[0], extent[3]) lr_x, lr_y = GdalReader().world2pixel(geo_trans, extent[1], extent[2]) # Create a new geomatrix for the _raster geo_trans = list(geo_trans) geo_trans[0] = extent[0] geo_trans[3] = extent[3] # Get the new array to layer extent rarray = gdal_array.DatasetReadAsArray(src_ds) if len(rarray.shape) == 3: clip = rarray[:, ul_y:lr_y, ul_x:lr_x] elif len(rarray.shape) == 2: clip = rarray[ul_y:lr_y, ul_x:lr_x] else: return logging.error('Error in array shape.') new_array = clip_raster_array(vds=filtered_poly_ds, raster_array=clip, geotransform=geo_trans, nodata=nodata) return GdalReader().array2ds(src_array=np.array(new_array), output=outuput, geotransform=geo_trans, projection=projection, nodata=nodata)
def nir(self, input_raster): src_ds = gdal_import.src2ds(input_raster) raster_array = GdalReader().ds2array(src_ds) return self._array2raster(raster_array[3], name="nir", mask=input_raster)
def _array2raster(self, src_array, name, mask): """ Provide the right format to PY/GDAL outputs""" return GdalReader().array2ds(src_array, name, mask_ds=mask)
def clip_raster_array(vds, raster_array, geotransform, nodata=0): if len(raster_array.shape) == 3: nbands = raster_array.shape[0] else: nbands = 1 new_array = [] layer = vds.GetLayer(0) layer.ResetReading() for band in xrange(nbands): if len(raster_array.shape) == 3: raster_array_i = raster_array[band] else: raster_array_i = raster_array ysize, xsize = raster_array_i.shape # Create data mask rasterpoly = Image.new("L", (xsize, ysize), 1) raster_im = ImageDraw.Draw(rasterpoly) inner_ring_im = ImageDraw.Draw(rasterpoly) # for fid in xrange(layer.GetFeatureCount()): # feature = layer.GetFeature(fid) for feature in layer: geoms = feature.GetGeometryRef() if geoms.GetGeometryName().lower() == "multipolygon": for geom in geoms: pts = geom.GetGeometryRef(0) points = [(pts.GetX(p), pts.GetY(p)) for p in range(pts.GetPointCount())] pixels = [ GdalReader().world2pixel(geotransform, p[0], p[1]) for p in points ] raster_im.polygon(pixels, 0) if geom.GetGeometryCount() > 1: for i in xrange(1, geom.GetGeometryCount()): pts = geom.GetGeometryRef(i) points1 = [(pts.GetX(p), pts.GetY(p)) for p in range(pts.GetPointCount())] pixels1 = [ GdalReader().world2pixel( geotransform, p[0], p[1]) for p in points1 ] inner_ring_im.polygon(pixels1, 1) elif geoms.GetGeometryName().lower() == "polygon": pts = geoms.GetGeometryRef(0) points = [(pts.GetX(p), pts.GetY(p)) for p in range(pts.GetPointCount())] pixels = [ GdalReader().world2pixel(geotransform, p[0], p[1]) for p in points ] raster_im.polygon(pixels, 0) del feature layer.ResetReading() # Image to array try: # old version mask = np.fromstring(rasterpoly.tostring(), 'b') except: # new version mask = np.fromstring(rasterpoly.tobytes(), 'b') mask.shape = rasterpoly.im.size[1], rasterpoly.im.size[0] # Clip the image using the mask (Note that np.uint8 does not allow nan values new_array.append( np.choose(mask, (raster_array_i, nodata)).astype(np.float)) return np.array(new_array)
def gdal2tiles(src, tile_size=500, tile_id_y=None, tile_id_x=None): """ Load a gdal file to local python instance :param src: source gdal dataset :param tile_size: Tile size :param tile_id_y: Single tile ID for Y :param tile_id_x: Single tile ID for X """ src_ds = gdal_import.src2ds(src) xsize = src_ds.RasterXSize ysize = src_ds.RasterYSize bands = src_ds.RasterCount nxtiles, nytiles = get_number_tiles(src_ds) # Read raster as arrays dtype = [ key for key, value in GdalReader().np2gdal.iteritems() if value == src_ds.GetRasterBand(1).DataType ][0] if tile_id_x and str(tile_id_x).isdigit() and tile_id_y and str( tile_id_y).isdigit(): x_tile_range = [tile_id_x] y_tile_range = [tile_id_y] else: x_tile_range = range(nxtiles + 1) y_tile_range = range(nytiles + 1) tiles = {} for xtile in x_tile_range: for ytile in y_tile_range: # DatasetReadAsArray(ds, xoff=0, yoff=0, win_xsize=None, win_ysize=None) if (tile_size * xtile + tile_size) < xsize and (tile_size * ytile + tile_size) < ysize: # arr_i = np.array(gdal_array.DatasetReadAsArray(src_ds, xoff=tile_size * xtile, yoff=tile_size * ytile, # win_xsize=tile_size, win_ysize=tile_size)).astype(dtype) arr_i = np.array( gdal_array.DatasetReadAsArray(src_ds, tile_size * xtile, tile_size * ytile, tile_size, tile_size)).astype(dtype) else: win_xsize = min(tile_size, xsize - tile_size * xtile) win_ysize = min(tile_size, ysize - tile_size * ytile) if win_xsize < 0 or win_ysize < 0: # Not square shape continue # arr_src = np.array(gdal_array.DatasetReadAsArray(src_ds, xoff=tile_size * xtile, # yoff=tile_size * ytile, win_xsize=win_xsize, win_ysize=win_ysize)).astype(dtype) arr_src = np.array( gdal_array.DatasetReadAsArray(src_ds, tile_size * xtile, tile_size * ytile, win_xsize, win_ysize)).astype(dtype) arr_i = np.zeros((bands, win_ysize, win_xsize), dtype=dtype) arr_i[:, 0:arr_src.shape[1], 0:arr_src.shape[2]] = arr_src # Create raster # Geotransform geotransform = src_ds.GetGeoTransform() top_left_x = geotransform[0] + geotransform[ 1] * tile_size * xtile + geotransform[2] * tile_size * ytile top_left_y = geotransform[3] + geotransform[ 5] * tile_size * ytile + geotransform[4] * tile_size * xtile new_geotransform = [ top_left_x, geotransform[1], geotransform[2], top_left_y, geotransform[4], geotransform[5] ] projection = src_ds.GetProjection() nodata = src_ds.GetRasterBand(1).GetNoDataValue() name = src_ds.GetMetadataItem('FilePath') tiles[str(xtile) + '_' + str(ytile)] = GdalReader().array2ds( arr_i, name + '_' + str(xtile) + '_' + str(ytile), geotransform=new_geotransform, projection=projection) return tiles
def merge(src_ds_list, outname, smooth_edges=False): # First layer metadata src_ds = GdalReader().gdal2ds(src_ds_list[0]) src_ds_list = [GdalReader().gdal2ds(r) for r in src_ds_list] geotransform = src_ds.GetGeoTransform() xres = geotransform[1] yres = geotransform[5] projection = src_ds.GetProjection() nodata = src_ds.GetRasterBand(1).GetNoDataValue() # Get common extent xmin, xmax, ymin, ymax = GdalReader().get_extent(src_ds) bands = src_ds.RasterCount for src_i in src_ds_list: xmin_i, xmax_i, ymin_i, ymax_i = GdalReader().get_extent(src_i) xmax = max(xmax, xmax_i) xmin = min(xmin, xmin_i) ymax = max(ymax, ymax_i) ymin = min(ymin, ymin_i) bands = max(bands, src_i.RasterCount) # Aligne Pixels xmin = math.floor(xmin / xres) * xres xmax = math.ceil(xmax / xres) * xres ymin = math.floor(ymin / -yres) * -yres ymax = math.ceil(ymax / -yres) * -yres # Create output if it does not already exist. geotransform = [xmin, xres, 0, ymax, 0, yres] xsize = int(math.ceil((xmax - xmin) / xres)) ysize = int(math.ceil((ymin - ymax) / yres)) # Copy data from source files into output file 1. out_array = np.empty((ysize, xsize)) out_array[:] = np.nan borders = [] for src_i in src_ds_list: for band in xrange(1, src_ds.RasterCount + 1): geotransform_i = src_i.GetGeoTransform() if not int(xres) == int(geotransform_i[1]) or not int(yres) == int( geotransform_i[5]): logging.error( 'Merge cannot be performed because the layer resolution are different: ' + str(xres) + ',' + str(yres) + ' vs. ' + str(geotransform_i[1]) + ',' + str(geotransform_i[5])) continue xmin_i, xmax_i, ymin_i, ymax_i = GdalReader().get_extent(src_i) xoff = int(math.ceil((xmin_i - xmin) / xres)) yoff = int(math.ceil((ymax_i - ymax) / yres)) x_size_i = src_i.RasterXSize y_size_i = src_i.RasterYSize array_i = GdalReader().ds2array(src_i) out_array[yoff:yoff + y_size_i, xoff:xoff + x_size_i] = array_i #slice_i = out_array[yoff:yoff + y_size_i, xoff:xoff + x_size_i] #out_array[yoff:yoff + y_size_i, xoff:xoff + x_size_i] = np.where( # np.ma.getmask(np.ma.masked_invalid(array_i[band - 1])), slice_i, array_i[band - 1]) # Edges smoothing if smooth_edges: mask = np.where( np.ma.getmask(np.ma.masked_invalid(array_i[band - 1])), np.nan, 1) if smooth_edges: borders_i = [ ([i + yoff, j + xoff] if 0 < [ mask[i - 1, j], mask[i + 1, j], mask[i, j - 1], mask[i, j + 1] ].count(1) < 4 else None) if (1 <= i < mask.shape[0] - 1) and (1 <= j < mask.shape[1] - 1) else None # ([i+yoff, j+xoff] if mask[i, j] == 1 else None) for i, j in np.ndindex(mask.shape) ] borders = borders + borders_i # Edges smoothing if smooth_edges: for k in borders: if k: out_array[k[0], k[1]] = np.nanmean(out_array[k[0] - 1:k[0] + 1, k[1] - 1:k[1] + 1]) return GdalReader().array2ds(src_array=out_array, output=outname, projection=projection, geotransform=geotransform, nodata=nodata)